static struct dentry *simplefs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { struct inode *inode = NULL; struct page *pagep = NULL; struct simplefs_dentry *raw_de; long ino; dentry->d_op = dir->i_sb->s_root->d_op; if (dentry->d_name.len > SIMPLEFS_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); raw_de = simplefs_find_dentry(dir, dentry, &pagep); if (raw_de) { ino = raw_de->inode; simplefs_put_page(pagep); inode = simplefs_iget(dir->i_sb, ino); if (IS_ERR(inode)) return ERR_CAST(inode); } //dentry->d_op = &d_op; if (inode) { printk(KERN_INFO "simplefs_lookup: dentry %d", dentry->d_count.counter); printk(KERN_INFO "simplefs_lookup: inode %ld %ld %d %d", inode->i_ino, inode->i_state, inode->i_count.counter, inode->i_nlink); } return d_splice_alias(inode, dentry); }
static int simplefs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) { struct inode *inode = NULL; long ino; int err = 0; ino = bitmap_alloc_inode(dir->i_sb); if (ino < 0) return -EIO; inode = simplefs_iget(dir->i_sb, ino); if (IS_ERR(inode)) return -EIO; inode->i_state = 0; inode->i_mode = mode | S_IFREG; inode->i_nlink = 1; inode->i_size = inode->i_blocks = inode->i_bytes = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); err = simplefs_insert_dentry(dentry, inode); if (!err) { //dentry->d_op = &d_op; d_instantiate(dentry, inode); if (inode) { printk(KERN_INFO "simplefs_create: dentry %d", dentry->d_count.counter); printk(KERN_INFO "simplefs_create: inode %ld %ld %d %d", inode->i_ino, inode->i_state, inode->i_count.counter, inode->i_nlink); } return 0; } inode_dec_link_count(inode); iput(inode); return err; }
struct dentry *simplefs_lookup(struct inode *parent_inode, struct dentry *child_dentry, unsigned int flags) { struct simplefs_inode *parent = SIMPLEFS_INODE(parent_inode); struct super_block *sb = parent_inode->i_sb; struct buffer_head *bh; struct simplefs_dir_record *record; int i; bh = sb_bread(sb, parent->data_block_number); BUG_ON(!bh); sfs_trace("Lookup in: ino=%llu, b=%llu\n", parent->inode_no, parent->data_block_number); record = (struct simplefs_dir_record *)bh->b_data; for (i = 0; i < parent->dir_children_count; i++) { sfs_trace("Have file: '%s' (ino=%llu)\n", record->filename, record->inode_no); if (!strcmp(record->filename, child_dentry->d_name.name)) { /* FIXME: There is a corner case where if an allocated inode, * is not written to the inode store, but the inodes_count is * incremented. Then if the random string on the disk matches * with the filename that we are comparing above, then we * will use an invalid uninitialized inode */ struct inode *inode = simplefs_iget(sb, record->inode_no); inode_init_owner(inode, parent_inode, SIMPLEFS_INODE(inode)->mode); d_add(child_dentry, inode); return NULL; } record++; } printk(KERN_ERR "No inode found for the filename [%s]\n", child_dentry->d_name.name); return NULL; }
static int simplefs_mkdir(struct inode *dir, struct dentry *dentry, int mode) { struct inode *inode = NULL; long ino; int err = 0; printk(KERN_INFO "simplefs_mkdir: %s %d\n", dentry->d_name.name, mode); inode_inc_link_count(dir); ino = bitmap_alloc_inode(dir->i_sb); if (ino < 0) return -EIO; inode = simplefs_iget(dir->i_sb, ino); if (IS_ERR(inode)) return -EIO; // set inode operations inode->i_op = &simplefs_file_inode_operations; inode->i_fop = &simplefs_file_operations; inode->i_mapping->a_ops = &simplefs_aops; inode->i_mode = mode | S_IFDIR; inode->i_nlink = 2; inode->i_size = inode->i_blocks = inode->i_bytes = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); err = simplefs_insert_dentry(dentry, inode); if (!err) { d_instantiate(dentry, inode); return 0; } inode_dec_link_count(inode); inode_dec_link_count(inode); iput(inode); inode_dec_link_count(dir); return err; }
/* This function, as the name implies, Makes the super_block valid and * fills filesystem specific information in the super block */ int simplefs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *root_inode; struct buffer_head *bh; struct simplefs_super_block *sb_disk; int ret = -EPERM; bh = sb_bread(sb, SIMPLEFS_SUPERBLOCK_BLOCK_NUMBER); BUG_ON(!bh); sb_disk = (struct simplefs_super_block *)bh->b_data; printk(KERN_INFO "The magic number obtained in disk is: [%llu]\n", sb_disk->magic); if (unlikely(sb_disk->magic != SIMPLEFS_MAGIC)) { printk(KERN_ERR "The filesystem that you try to mount is not of type simplefs. Magicnumber mismatch."); goto release; } if (unlikely(sb_disk->block_size != SIMPLEFS_DEFAULT_BLOCK_SIZE)) { printk(KERN_ERR "simplefs seem to be formatted using a non-standard block size."); goto release; } /** XXX: Avoid this hack, by adding one more sb wrapper, but non-disk */ sb_disk->journal = NULL; printk(KERN_INFO "simplefs filesystem of version [%llu] formatted with a block size of [%llu] detected in the device.\n", sb_disk->version, sb_disk->block_size); /* A magic number that uniquely identifies our filesystem type */ sb->s_magic = SIMPLEFS_MAGIC; /* For all practical purposes, we will be using this s_fs_info as the super block */ sb->s_fs_info = sb_disk; sb->s_maxbytes = SIMPLEFS_DEFAULT_BLOCK_SIZE; sb->s_op = &simplefs_sops; root_inode = new_inode(sb); root_inode->i_ino = SIMPLEFS_ROOTDIR_INODE_NUMBER; inode_init_owner(root_inode, NULL, S_IFDIR); root_inode->i_sb = sb; root_inode->i_op = &simplefs_inode_ops; root_inode->i_fop = &simplefs_dir_operations; root_inode->i_atime = root_inode->i_mtime = root_inode->i_ctime = CURRENT_TIME; root_inode->i_private = simplefs_get_inode(sb, SIMPLEFS_ROOTDIR_INODE_NUMBER); /* TODO: move such stuff into separate header. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) sb->s_root = d_make_root(root_inode); #else sb->s_root = d_alloc_root(root_inode); if (!sb->s_root) iput(root_inode); #endif if (!sb->s_root) { ret = -ENOMEM; goto release; } if ((ret = simplefs_parse_options(sb, data))) goto release; if (!sb_disk->journal) { struct inode *journal_inode; journal_inode = simplefs_iget(sb, SIMPLEFS_JOURNAL_INODE_NUMBER); ret = simplefs_sb_load_journal(sb, journal_inode); goto release; } ret = jbd2_journal_load(sb_disk->journal); release: brelse(bh); return ret; }
static int simplefs_fill_super(struct super_block *sb, void *data, int silent) { struct buffer_head *bh; struct simplefs_super *rsb; struct simplefs_super_info *sbi; struct inode *root; int i, j, cnt, ret = 0; printk(KERN_INFO "simplefs_fill_super\n"); if (!(bh = sb_bread(sb, SIMPLEFS_SUPER_BNO))) { printk(KERN_ERR "Simplefs: unable to read superblock\n"); return -ENOMEM; } sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) { ret = -ENOMEM; goto out; } sbi->s_sb = bh; memcpy(&sbi->raw_super, bh->b_data, sizeof(sbi->raw_super)); sb->s_fs_info = sbi; sb->s_blocksize = SIMPLEFS_BLOCKSIZE; sb->s_flags = sb->s_flags & ~MS_POSIXACL; /* * set up enough so that it can read an inode */ sb->s_op = &simplefs_super_operations; root = simplefs_iget(sb, SIMPLEFS_ROOT_INO); if (!root) { printk(KERN_ERR "Simplefs: corrupt root inode\n"); ret = -EINVAL; goto failed_root; } printk(KERN_INFO "simplefs_fill_super -> simplefs_iget ok: %ld\n", root->i_ino); sb->s_root = d_alloc_root(root); if (!sb->s_root) { iput(root); printk(KERN_ERR "Simplefs: get root dentry failed\n"); ret = -ENOMEM; goto failed_root; } printk(KERN_INFO "simplefs_fill_super -> d_alloc_root ok\n"); cnt = sbi->raw_super.s_inode_bitmap_blknr + sbi->raw_super.s_block_bitmap_blknr; if (!(sbi->s_bitmaps = kzalloc(sizeof(struct buffer_head *) * cnt, GFP_KERNEL))) goto failed_bitmap; for (i = 0, j = 0; i < cnt; i++) { if (!(bh = bitmap_load(sb, SIMPLEFS_SUPER_BNO + 1 + i))) goto failed_load; sbi->s_bitmaps[j++] = bh; printk(KERN_INFO "simplefs_fill_super bitmap ok:%d -> %d\n", cnt, i); } rsb = &sbi->raw_super; printk("fill super ok: (inode %d %d %d) (block %d %d %d)\n", rsb->s_inode_bitmap_blknr, rsb->s_inode_blknr, rsb->s_free_inodes_count, rsb->s_block_bitmap_blknr, rsb->s_block_blknr, rsb->s_free_blocks_count); return 0; failed_load: for (i = 0; i < j; i++) { brelse(sbi->s_bitmaps[i]); } failed_bitmap: dput(sb->s_root); failed_root: kfree(sbi); out: brelse(bh); sbi->s_sb = NULL; printk("simplefs get sb failed.\n"); return ret; }