diff --git a/mkfs-simplefs.c b/mkfs-simplefs.c index 16d5f07..c201b52 100644 --- a/mkfs-simplefs.c +++ b/mkfs-simplefs.c @@ -12,6 +12,7 @@ int main(int argc, char *argv[]) int fd; ssize_t ret; struct simplefs_super_block sb; + struct simplefs_inode root_inode; if (argc != 2) { printf("Usage: mkfs-simplefs \n"); @@ -27,24 +28,39 @@ int main(int argc, char *argv[]) sb.version = 1; sb.magic = SIMPLEFS_MAGIC; sb.block_size = SIMPLEFS_DEFAULT_BLOCK_SIZE; - sb.free_blocks = ~0; - sb.root_inode.mode = S_IFDIR; - sb.root_inode.inode_no = SIMPLEFS_ROOT_INODE_NUMBER; - sb.root_inode.data_block_number = SIMPLEFS_ROOTDIR_DATABLOCK_NUMBER; - sb.root_inode.dir_children_count = 0; + /* Only the root dir will have an inode now */ + sb.inodes_count = 1; + sb.free_blocks = ~0; ret = write(fd, (char *)&sb, sizeof(sb)); - /* Just a redundant check. Not required ideally. */ - if (ret != SIMPLEFS_DEFAULT_BLOCK_SIZE) + if (ret != SIMPLEFS_DEFAULT_BLOCK_SIZE) { printf ("bytes written [%d] are not equal to the default block size\n", (int)ret); - else - printf("Super block written succesfully\n"); + ret = -1; + goto exit; + } + printf("Super block written succesfully\n"); + + root_inode.mode = S_IFDIR; + root_inode.inode_no = SIMPLEFS_ROOTDIR_INODE_NUMBER; + root_inode.data_block_number = SIMPLEFS_ROOTDIR_DATABLOCK_NUMBER; + root_inode.dir_children_count = 0; + + ret = write(fd, (char *)&root_inode, sizeof(root_inode)); + + if (ret != sizeof(root_inode)) { + printf("The inode store was not written properly. Retry your mkfs\n"); + ret = -1; + goto exit; + } + printf("inode store written succesfully\n"); + ret = 0; + +exit: close(fd); - - return 0; + return ret; } diff --git a/simple.c b/simple.c index 900deb8..746639f 100644 --- a/simple.c +++ b/simple.c @@ -28,7 +28,7 @@ static int simplefs_readdir(struct file *filp, void *dirent, filldir_t filldir) sfs_inode = inode->i_private; if (unlikely(!S_ISDIR(sfs_inode->mode))) { - printk(KERN_ERR "inode %u not a directory", sfs_inode->inode_no); + printk(KERN_ERR "inode %llu not a directory", sfs_inode->inode_no); return -ENOTDIR; } @@ -63,39 +63,31 @@ static struct inode_operations simplefs_inode_ops = { .lookup = simplefs_lookup, }; -/* This function creates, configures and returns an inode, - * for the asked file (or) directory (differentiated by the mode param), - * under the directory specified by the dir param - * on the device dev, managed by the superblock sb param) */ -struct inode *simplefs_get_inode(struct super_block *sb, - const struct inode *dir, umode_t mode, - dev_t dev) +/* This functions returns a simplefs_inode with the given inode_no + * from the inode store, if it exists. */ +struct simplefs_inode * simplefs_get_inode(struct super_block *sb, uint64_t inode_no) { - struct inode *inode = new_inode(sb); + struct simplefs_super_block *sfs_sb = sb->s_fs_info; + struct simplefs_inode *sfs_inode = NULL; - if (inode) { - inode->i_ino = get_next_ino(); - inode_init_owner(inode, dir, mode); + int i; + struct buffer_head *bh; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + /* The inode store can be read once and kept in memory permanently while mounting. + * But such a model will not be scalable in a filesystem with + * millions or billions of files (inodes) */ + bh = (struct buffer_head *)sb_bread(sb, SIMPLEFS_INODESTORE_BLOCK_NUMBER); + sfs_inode = (struct simplefs_inode *) bh->b_data; - switch (mode & S_IFMT) { - case S_IFDIR: - /* i_nlink will be initialized to 1 in the inode_init_always function - * (that gets called inside the new_inode function), - * We change it to 2 for directories, for covering the "." entry */ - inc_nlink(inode); - break; - case S_IFREG: - case S_IFLNK: - default: - printk(KERN_ERR - "simplefs can create meaningful inode for only root directory at the moment\n"); - return NULL; - break; + for (i=0;i < sfs_sb->inodes_count; i++) { + if (sfs_inode->inode_no == inode_no) { + /* FIXME: bh->b_data is probably leaking */ + return sfs_inode; } + sfs_inode++; } - return inode; + + return NULL; } /* This function, as the name implies, Makes the super_block valid and @@ -106,11 +98,12 @@ int simplefs_fill_super(struct super_block *sb, void *data, int silent) struct buffer_head *bh; struct simplefs_super_block *sb_disk; - bh = (struct buffer_head *)sb_bread(sb, 0); + bh = (struct buffer_head *)sb_bread(sb, SIMPLEFS_SUPERBLOCK_BLOCK_NUMBER); sb_disk = (struct simplefs_super_block *)bh->b_data; + /* FIXME: bh->b_data is probably leaking */ - printk(KERN_INFO "The magic number obtained in disk is: [%d]\n", + printk(KERN_INFO "The magic number obtained in disk is: [%llu]\n", sb_disk->magic); if (unlikely(sb_disk->magic != SIMPLEFS_MAGIC)) { @@ -126,7 +119,7 @@ int simplefs_fill_super(struct super_block *sb, void *data, int silent) } printk(KERN_INFO - "simplefs filesystem of version [%d] formatted with a block size of [%d] detected in the device.\n", + "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 */ @@ -136,14 +129,14 @@ int simplefs_fill_super(struct super_block *sb, void *data, int silent) sb->s_fs_info = sb_disk; root_inode = new_inode(sb); - root_inode->i_ino = SIMPLEFS_ROOT_INODE_NUMBER; + 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 = &(sb_disk->root_inode); + root_inode->i_private = simplefs_get_inode(sb, SIMPLEFS_ROOTDIR_INODE_NUMBER); sb->s_root = d_make_root(root_inode); if (!sb->s_root) diff --git a/simple.h b/simple.h index 5c9afe7..a25aee8 100644 --- a/simple.h +++ b/simple.h @@ -3,7 +3,7 @@ #define SIMPLEFS_FILENAME_MAXLEN 255 /* Hard-coded inode number for the root directory */ -const int SIMPLEFS_ROOT_INODE_NUMBER = 1; +const int SIMPLEFS_ROOTDIR_INODE_NUMBER = 1; /* The disk block where super block is stored */ const int SIMPLEFS_SUPERBLOCK_BLOCK_NUMBER = 0; @@ -19,27 +19,26 @@ const int SIMPLEFS_ROOTDIR_DATABLOCK_NUMBER = 2; * This gets stored as the data for a directory */ struct simplefs_dir_record { char filename[SIMPLEFS_FILENAME_MAXLEN]; - uint32_t inode_no; + uint64_t inode_no; }; struct simplefs_inode { mode_t mode; - uint32_t inode_no; - uint32_t data_block_number; + uint64_t inode_no; + uint64_t data_block_number; union { - uint32_t file_size; - uint32_t dir_children_count; + uint64_t file_size; + uint64_t dir_children_count; }; }; struct simplefs_super_block { - uint32_t version; - uint32_t magic; - uint32_t block_size; - uint32_t free_blocks; + uint64_t version; + uint64_t magic; + uint64_t block_size; + uint64_t inodes_count; + uint64_t free_blocks; - struct simplefs_inode root_inode; - - char padding[SIMPLEFS_DEFAULT_BLOCK_SIZE - (4 * sizeof(uint32_t)) - sizeof(struct simplefs_inode)]; + char padding[SIMPLEFS_DEFAULT_BLOCK_SIZE - (5 * sizeof(uint64_t))]; };