ycrfs.c 38.38 KiB
#include <linux/buffer_head.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mpage.h>
#include <linux/slab.h>
#include <linux/statfs.h>
#include <linux/version.h>
#include "ycrfs.h"
struct ycrfs_inode_info {
	uint32_t iblock;
	char i_data[32];
	struct inode vfs_inode;
static const struct inode_operations ycrfs_inode_ops;
static const struct inode_operations ycrfs_symlink_inode_ops;
static const struct file_operations ycrfs_dir_ops;
static const struct file_operations ycrfs_file_ops;
static const struct address_space_operations ycrfs_aops;
static inline uint32_t idiv_ceil(uint32_t a, uint32_t b)
	uint32_t ret = a / b;
	if (a % b) {
		return ret + 1;
	return ret;
static inline uint32_t get_first_free_bits(unsigned long *freemap,
					   unsigned long size, uint32_t len)
	uint32_t bit, prev = 0, count = 0;
	for_each_set_bit(bit, freemap, size) {
		if (prev != bit - 1) {
			count = 0;
		prev = bit;
		if (++count == len) {
			bitmap_clear(freemap, bit - len + 1, len);
			return bit - len + 1;
	return 0;
static inline uint32_t get_free_inode(struct ycrfs_sb_info *sbi)
	uint32_t ret =
		get_first_free_bits(sbi->bfree_bitmap, sbi->nr_blocks, 1);
	if (ret) {
		sbi->nr_free_inodes--;
	return ret;
static inline uint32_t get_free_blocks(struct ycrfs_sb_info *sbi, uint32_t len)
	uint32_t ret =
		get_first_free_bits(sbi->bfree_bitmap, sbi->nr_blocks, len);
	if (ret) {
		sbi->nr_free_blocks -= len;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
return ret; } static inline uint32_t put_free_bits(unsigned long *freemap, unsigned long size, uint32_t i, uint32_t len) { if (i + len - 1 > size) { return -1; } bitmap_set(freemap, i, len); return 0; } static inline void put_inode(struct ycrfs_sb_info *sbi, uint32_t ino) { if (put_free_bits(sbi->ifree_bitmap, sbi->nr_inodes, ino, 1)) { return; } sbi->nr_free_inodes++; } static inline void put_blocks(struct ycrfs_sb_info *sbi, uint32_t bno, uint32_t len) { if (put_free_bits(sbi->ifree_bitmap, sbi->nr_blocks, bno, len)) { return; } sbi->nr_free_blocks += len; } static struct kmem_cache *ycrfs_inode_cache; int ycrfs_init_inode_cache(void) { ycrfs_inode_cache = kmem_cache_create( "ycrfs_cache", sizeof(struct ycrfs_inode_info), 0, 0, NULL); if (!ycrfs_inode_cache) { return -ENOMEM; } return 0; } void ycrfs_destroy_inode_cache(void) { kmem_cache_destroy(ycrfs_inode_cache); } struct inode *ycrfs_alloc_inode(struct super_block *sb) { struct ycrfs_inode_info *zi = kmem_cache_alloc(ycrfs_inode_cache, GFP_KERNEL); if (!zi) return NULL; inode_init_once(&zi->vfs_inode); return &zi->vfs_inode; } void ycrfs_destroy_inode(struct inode *inode) { struct ycrfs_inode_info *zi = container_of(inode, struct ycrfs_inode_info, vfs_inode); kmem_cache_free(ycrfs_inode_cache, zi); } static int ycrfs_write_inode(struct inode *inode, struct writeback_control *wbc) { struct ycrfs_inode *disk_inode; struct super_block *sb = inode->i_sb;