From e0e7618c8ef7e70ee29cbce686908f17bf42e1a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sankar=20=E0=AE=9A=E0=AE=99=E0=AF=8D=E0=AE=95=E0=AE=B0?= =?UTF-8?q?=E0=AF=8D?= Date: Mon, 22 Apr 2013 16:45:25 +0530 Subject: [PATCH] Load inode of the root dir from disk. Support readdir (ls) on root directory. --- mkfs-simplefs.c | 10 +++++++-- simple.c | 54 ++++++++++++++++++++++++++++++++++++++++--------- simple.h | 34 ++++++++++++++++++++++++++++--- super.h | 6 ++++++ 4 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 super.h diff --git a/mkfs-simplefs.c b/mkfs-simplefs.c index f219887..16d5f07 100644 --- a/mkfs-simplefs.c +++ b/mkfs-simplefs.c @@ -1,10 +1,11 @@ -#include "simple.h" - #include #include #include #include #include +#include + +#include "simple.h" int main(int argc, char *argv[]) { @@ -28,6 +29,11 @@ int main(int argc, char *argv[]) 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; + ret = write(fd, (char *)&sb, sizeof(sb)); /* Just a redundant check. Not required ideally. */ diff --git a/simple.c b/simple.c index 5ec21d1..900deb8 100644 --- a/simple.c +++ b/simple.c @@ -9,14 +9,40 @@ #include #include #include +#include -#include "simple.h" +#include "super.h" static int simplefs_readdir(struct file *filp, void *dirent, filldir_t filldir) { - /* ls will list nothing as of now. - * Basic skeleton code to make ls (readdir) work for simplefs */ - return 0; + loff_t pos = filp->f_pos; + struct inode *inode = filp->f_dentry->d_inode; + struct super_block *sb = inode->i_sb; + struct buffer_head *bh; + struct simplefs_inode *sfs_inode; + struct simplefs_dir_record *record; + int i; + + printk(KERN_INFO "We are inside readdir. The pos[%lld], inode number[%lu], superblock magic [%lu]\n", pos, inode->i_ino, sb->s_magic); + + sfs_inode = inode->i_private; + + if (unlikely(!S_ISDIR(sfs_inode->mode))) { + printk(KERN_ERR "inode %u not a directory", sfs_inode->inode_no); + return -ENOTDIR; + } + + bh = (struct buffer_head *)sb_bread(sb, sfs_inode->data_block_number); + + record = (struct simplefs_dir_record *) bh->b_data; + for (i=0; i < sfs_inode->dir_children_count; i++) { + printk(KERN_INFO "Got filename: %s\n", record->filename); + filldir(dirent, record->filename, SIMPLEFS_FILENAME_MAXLEN, pos, record->inode_no, DT_UNKNOWN); + pos += sizeof(struct simplefs_dir_record); + record ++; + } + + return 1; } const struct file_operations simplefs_dir_operations = { @@ -76,7 +102,7 @@ struct inode *simplefs_get_inode(struct super_block *sb, * fills filesystem specific information in the super block */ int simplefs_fill_super(struct super_block *sb, void *data, int silent) { - struct inode *inode; + struct inode *root_inode; struct buffer_head *bh; struct simplefs_super_block *sb_disk; @@ -106,10 +132,20 @@ int simplefs_fill_super(struct super_block *sb, void *data, int silent) /* A magic number that uniquely identifies our filesystem type */ sb->s_magic = SIMPLEFS_MAGIC; - inode = simplefs_get_inode(sb, NULL, S_IFDIR, 0); - inode->i_op = &simplefs_inode_ops; - inode->i_fop = &simplefs_dir_operations; - sb->s_root = d_make_root(inode); + /* For all practical purposes, we will be using this s_fs_info as the super block */ + sb->s_fs_info = sb_disk; + + root_inode = new_inode(sb); + root_inode->i_ino = SIMPLEFS_ROOT_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); + + sb->s_root = d_make_root(root_inode); if (!sb->s_root) return -ENOMEM; diff --git a/simple.h b/simple.h index ba2c5ae..3c37ae8 100644 --- a/simple.h +++ b/simple.h @@ -1,5 +1,25 @@ -const int SIMPLEFS_MAGIC = 0x10032013; -const int SIMPLEFS_DEFAULT_BLOCK_SIZE = 4 * 1024; +#define SIMPLEFS_MAGIC 0x10032013 +#define SIMPLEFS_DEFAULT_BLOCK_SIZE 4096 +#define SIMPLEFS_FILENAME_MAXLEN 255 + +const int SIMPLEFS_ROOT_INODE_NUMBER = 1; +const int SIMPLEFS_ROOTDIR_DATABLOCK_NUMBER = 2; + +struct simplefs_dir_record { + char filename[SIMPLEFS_FILENAME_MAXLEN]; + uint32_t inode_no; +}; + +struct simplefs_inode { + mode_t mode; + uint32_t inode_no; + uint32_t data_block_number; + + union { + uint32_t file_size; + uint32_t dir_children_count; + }; +}; struct simplefs_super_block { uint32_t version; @@ -7,5 +27,13 @@ struct simplefs_super_block { uint32_t block_size; uint32_t free_blocks; - char padding[(4 * 1024) - (4 * sizeof(uint32_t))]; + struct simplefs_inode root_inode; + + char padding[SIMPLEFS_DEFAULT_BLOCK_SIZE - (4 * sizeof(uint32_t)) - sizeof(struct simplefs_inode)]; }; + +/* +struct simplefs_dir_contents { + uint32_t children_count; + struct simplefs_dir_record records[]; +}; */ diff --git a/super.h b/super.h new file mode 100644 index 0000000..b8b3222 --- /dev/null +++ b/super.h @@ -0,0 +1,6 @@ +#include + +static inline struct simplefs_super_block *SIMPLEFS_SB(struct super_block *sb) +{ + return sb->s_fs_info; +}