]> git.hungrycats.org Git - linux/commitdiff
Make ramfs/driverfs maintain directory nlink counts.
authorLinus Torvalds <torvalds@home.transmeta.com>
Tue, 2 Jul 2002 08:37:41 +0000 (01:37 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Tue, 2 Jul 2002 08:37:41 +0000 (01:37 -0700)
Make dcache filesystems export directory entry types
to readdir.

fs/driverfs/inode.c
fs/libfs.c
fs/ramfs/inode.c
include/linux/fs.h

index 73ad5c1f6adbb567ac04d2a62546164d66a6dc2a..2fd9126199b2064758c32f6b6aefa6633d8f1c92 100644 (file)
@@ -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
index f4b12699b37aab2f0219cb097bfca40a99b7b309..be9a8f7963e89966d5344e5b8e03d756d65f0f1e 100644 (file)
@@ -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 */
index d3edc3128ec0f87ba40aa0c3dd0c2cc4725305ac..7d41fc6389f2e6da1c8806c457437f1e0b61352e 100644 (file)
@@ -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;
index 322e644060cf5076a876b3212fb9288e64949fd9..002e022891551375f36b59991fc0af070243a7a5 100644 (file)
@@ -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