From abd988c41bb537a6ab20fbe421d0bd280972c0f4 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 2 Jul 2002 01:37:41 -0700 Subject: [PATCH] Make ramfs/driverfs maintain directory nlink counts. Make dcache filesystems export directory entry types to readdir. --- fs/driverfs/inode.c | 26 ++++++++++++++++++-------- fs/libfs.c | 8 +++++++- fs/ramfs/inode.c | 32 +++++++++++++++++++++++--------- include/linux/fs.h | 3 +++ 4 files changed, 51 insertions(+), 18 deletions(-) diff --git a/fs/driverfs/inode.c b/fs/driverfs/inode.c index 73ad5c1f6adb..2fd9126199b2 100644 --- a/fs/driverfs/inode.c +++ b/fs/driverfs/inode.c @@ -149,6 +149,10 @@ static int driverfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) lock_kernel(); dentry->d_op = &driverfs_dentry_dir_ops; res = driverfs_mknod(dir, dentry, mode | S_IFDIR, 0); + if (!res) { + dir->i_nlink++; + dentry->d_inode->i_nlink++; + } unlock_kernel(); return res; } @@ -205,23 +209,29 @@ static int driverfs_empty(struct dentry *dentry) } static int driverfs_unlink(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + + lock_kernel(); + inode->i_nlink--; + unlock_kernel(); + dput(dentry); + return 0; +} + +static int driverfs_rmdir(struct inode *dir, struct dentry *dentry) { int error = -ENOTEMPTY; if (driverfs_empty(dentry)) { - struct inode *inode = dentry->d_inode; - - lock_kernel(); - inode->i_nlink--; - unlock_kernel(); - dput(dentry); + dentry->d_inode->i_nlink--; + driverfs_unlink(dir, dentry); + dir->i_nlink--; error = 0; } return error; } -#define driverfs_rmdir driverfs_unlink - /** * driverfs_read_file - "read" data from a file. * @file: file pointer diff --git a/fs/libfs.c b/fs/libfs.c index f4b12699b37a..be9a8f7963e8 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -83,6 +83,12 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) return offset; } +/* Relationship between i_mode and the DT_xxx types */ +static inline unsigned char dt_type(struct inode *inode) +{ + return (inode->i_mode >> 12) & 15; +} + /* * Directory is locked and all positive dentries in it are safe, since * for ramfs-type trees they can't go away without unlink() or rmdir(), @@ -125,7 +131,7 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir) continue; spin_unlock(&dcache_lock); - if (filldir(dirent, next->d_name.name, next->d_name.len, filp->f_pos, next->d_inode->i_ino, DT_UNKNOWN) < 0) + if (filldir(dirent, next->d_name.name, next->d_name.len, filp->f_pos, next->d_inode->i_ino, dt_type(next->d_inode)) < 0) return 0; spin_lock(&dcache_lock); /* next is still alive */ diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index d3edc3128ec0..7d41fc6389f2 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -130,7 +130,12 @@ static int ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int d static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) { - return ramfs_mknod(dir, dentry, mode | S_IFDIR, 0); + int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0); + if (!retval) { + dir->i_nlink++; + dentry->d_inode->i_nlink++; + } + return retval; } static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode) @@ -186,25 +191,30 @@ static int ramfs_empty(struct dentry *dentry) } /* - * This works for both directories and regular files. - * (non-directories will always have empty subdirs) + * Unlink a ramfs entry */ static int ramfs_unlink(struct inode * dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + + inode->i_nlink--; + dput(dentry); /* Undo the count from "create" - this does all the work */ + return 0; +} + +static int ramfs_rmdir(struct inode * dir, struct dentry *dentry) { int retval = -ENOTEMPTY; if (ramfs_empty(dentry)) { - struct inode *inode = dentry->d_inode; - - inode->i_nlink--; - dput(dentry); /* Undo the count from "create" - this does all the work */ + dentry->d_inode->i_nlink--; + ramfs_unlink(dir, dentry); + dir->i_nlink--; retval = 0; } return retval; } -#define ramfs_rmdir ramfs_unlink - /* * The VFS layer already does all the dentry stuff for rename, * we just have to decrement the usage count for the target if @@ -221,6 +231,10 @@ static int ramfs_rename(struct inode * old_dir, struct dentry *old_dentry, struc inode->i_nlink--; dput(new_dentry); } + if (S_ISDIR(old_dentry->d_inode->i_mode)) { + old_dir->i_nlink--; + new_dir->i_nlink++; + } error = 0; } return error; diff --git a/include/linux/fs.h b/include/linux/fs.h index 322e644060cf..002e02289155 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -701,6 +701,9 @@ extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct de /* * File types + * + * NOTE! These match bits 12..15 of stat.st_mode + * (ie "(i_mode >> 12) & 15"). */ #define DT_UNKNOWN 0 #define DT_FIFO 1 -- 2.39.5