Second/last part of fix for rcfs inode leak seen if classes are repeatedly 
created and deleted. Several changes:
- in some cases, a directory needs to be empty of all files, including 
magic ones and in others, only user created subdirectories should be freed. 
Distinguish these two cases.
- do a better cleanup of files & directories rather than use 
simple_rmdir, simple_unlink 


Signed-off-by: Shailabh Nagar <[EMAIL PROTECTED]>
Signed-off-by: Gerrit Huizenga <[EMAIL PROTECTED]>
-------------


 fs/rcfs/dir.c        |   28 ++++++++++++---
 fs/rcfs/inode.c      |   93 ++++++++++++++++++++++++++++++++++++++++++---------
 fs/rcfs/magic.c      |    8 +++-
 include/linux/rcfs.h |    3 +
 4 files changed, 109 insertions(+), 23 deletions(-)

Index: linux-2.6.13-ckrm2/fs/rcfs/dir.c
===================================================================
--- linux-2.6.13-ckrm2.orig/fs/rcfs/dir.c       2005-09-09 21:41:36.000000000 
-0700
+++ linux-2.6.13-ckrm2/fs/rcfs/dir.c    2005-09-09 21:43:22.000000000 -0700
@@ -31,8 +31,6 @@
 #include <linux/rcfs.h>
 #include <asm/uaccess.h>
 
-#define rcfs_positive(dentry)  ((dentry)->d_inode && !d_unhashed((dentry)))
-
 int rcfs_empty(struct dentry *dentry)
 {
        struct dentry *child;
@@ -40,6 +38,21 @@ int rcfs_empty(struct dentry *dentry)
 
        spin_lock(&dcache_lock);
        list_for_each_entry(child, &dentry->d_subdirs, d_child)
+           if (rcfs_positive(child))
+               goto out;
+       ret = 1;
+out:
+       spin_unlock(&dcache_lock);
+       return ret;
+}
+
+static int rcfs_empty_with_magic(struct dentry *dentry)
+{
+       struct dentry *child;
+       int ret = 0;
+
+       spin_lock(&dcache_lock);
+       list_for_each_entry(child, &dentry->d_subdirs, d_child)
            if (!rcfs_is_magic(child) && rcfs_positive(child))
                goto out;
        ret = 1;
@@ -48,6 +61,9 @@ out:
        return ret;
 }
 
+
+
+
 /* Directory inode operations */
 
 int rcfs_create_coredir(struct inode *dir, struct dentry *dentry)
@@ -84,7 +100,8 @@ int rcfs_mkdir(struct inode *dir, struct
        int retval = 0;
        struct ckrm_classtype *clstype;
 
-       if (rcfs_mknod(dir, dentry, mode | S_IFDIR, 0)) {
+       retval = rcfs_mknod(dir, dentry, mode | S_IFDIR, 0) ;
+       if (retval) {
                printk(KERN_ERR "rcfs_mkdir: error in rcfs_mknod\n");
                return retval;
        }
@@ -108,10 +125,9 @@ int rcfs_rmdir(struct inode *dir, struct
 {
        struct rcfs_inode_info *ri = rcfs_get_inode_info(dentry->d_inode);
 
-       if (!rcfs_empty(dentry)) {
-               printk(KERN_ERR "rcfs_rmdir: directory not empty\n");
+       if (!rcfs_empty_with_magic(dentry))
                return -ENOTEMPTY;
-       }
+
        /* Core class removal  */
 
        if (ri->core == NULL) {
Index: linux-2.6.13-ckrm2/fs/rcfs/inode.c
===================================================================
--- linux-2.6.13-ckrm2.orig/fs/rcfs/inode.c     2005-09-09 21:43:04.000000000 
-0700
+++ linux-2.6.13-ckrm2/fs/rcfs/inode.c  2005-09-09 21:43:22.000000000 -0700
@@ -133,26 +133,89 @@ struct dentry *rcfs_create_internal(stru
 
        return mfdentry;
 }
+static int rcfs_unlink (struct inode *dir, struct dentry *dentry)
+{
+       struct inode *inode = dentry->d_inode;
+       down(&inode->i_sem);
+       dentry->d_inode->i_nlink--;
+       dput(dentry);
+       up(&inode->i_sem);
+       d_delete(dentry);
+       return 0;
+}
 
-int rcfs_delete_internal(struct dentry *mfdentry)
+/* Copy of fs:namei.c:d_unhash/dentry_unhash.
+   Remove and use dentry_unhash instead on post-2.6.9 kernels */
+void rcfs_unhash(struct dentry *dentry)
 {
-       struct dentry *parent;
+       dget(dentry);
+       spin_lock(&dcache_lock);
+       switch (atomic_read(&dentry->d_count)) {
+       default:
+               spin_unlock(&dcache_lock);
+               shrink_dcache_parent(dentry);
+               spin_lock(&dcache_lock);
+               if (atomic_read(&dentry->d_count) != 2)
+                       break;
+       case 2:
+               __d_drop(dentry);
+       }
+       spin_unlock(&dcache_lock);
+}
 
-       if (!mfdentry || !mfdentry->d_parent)
-               return -EINVAL;
-       parent = mfdentry->d_parent;
-       if (!mfdentry->d_inode) {
-               return 0;
+int rcfs_generic_rmdir(struct inode *dir, struct dentry *dentry)
+{
+       int error = -ENOTEMPTY;
+       struct inode * inode = dentry->d_inode;
+
+       down(&inode->i_sem);
+       rcfs_unhash(dentry);
+       if (rcfs_empty(dentry)) {
+               dentry->d_inode->i_nlink -= 2;
+               dput(dentry);
+               inode->i_flags |= S_DEAD;
+               dir->i_nlink--;
+               error = 0;
        }
-       down(&mfdentry->d_inode->i_sem);
-       if (S_ISDIR(mfdentry->d_inode->i_mode))
-               simple_rmdir(parent->d_inode, mfdentry);
-       else
-               simple_unlink(parent->d_inode, mfdentry);
-       up(&mfdentry->d_inode->i_sem);
-       d_delete(mfdentry);
+       up(&inode->i_sem);
+       if (!error)
+               d_delete(dentry);
+       dput(dentry);
+       return error;
+}
 
-       return 0;
+int __rcfs_delete_internal(struct dentry *dentry)
+{
+       struct dentry *parent = dentry->d_parent;
+       int rc;
+
+       rc = 0;
+       if (rcfs_positive(dentry)) {
+               if (S_ISDIR(dentry->d_inode->i_mode))
+                       rc = rcfs_generic_rmdir(parent->d_inode, dentry);
+               else
+                       rc = rcfs_unlink(parent->d_inode, dentry);
+               dput(dentry);
+       }
+       return rc;
+}
+
+int rcfs_delete_internal(struct dentry *dentry)
+{
+       struct dentry *parent = dentry->d_parent;
+       int rc;
+
+       if (!dentry || !dentry->d_parent)
+               return -EINVAL;
+       parent = dentry->d_parent;
+       if (!parent || !parent->d_inode)
+               return -EINVAL;
+
+       down(&parent->d_inode->i_sem);
+       rc = __rcfs_delete_internal(dentry);
+       up(&parent->d_inode->i_sem);
+
+       return rc;
 }
 
 struct inode_operations rcfs_file_inode_operations = {
Index: linux-2.6.13-ckrm2/fs/rcfs/magic.c
===================================================================
--- linux-2.6.13-ckrm2.orig/fs/rcfs/magic.c     2005-09-09 21:41:57.000000000 
-0700
+++ linux-2.6.13-ckrm2/fs/rcfs/magic.c  2005-09-09 21:43:22.000000000 -0700
@@ -475,15 +475,19 @@ struct file_operations shares_fileops = 
 int rcfs_clear_magic(struct dentry *parent)
 {
        struct dentry *mftmp, *mfdentry;
+       int rc=0;
 
        list_for_each_entry_safe(mfdentry, mftmp, &parent->d_subdirs, d_child) {
                if (!rcfs_is_magic(mfdentry))
                        continue;
-               if (rcfs_delete_internal(mfdentry))
+               rc=__rcfs_delete_internal(mfdentry);
+               if (rc) {
                        printk(KERN_ERR
                               "rcfs_clear_magic: error deleting one\n");
+                       break;
+               }
        }
-       return 0;
+       return rc;
 }
 
 EXPORT_SYMBOL_GPL(rcfs_clear_magic);
Index: linux-2.6.13-ckrm2/include/linux/rcfs.h
===================================================================
--- linux-2.6.13-ckrm2.orig/include/linux/rcfs.h        2005-09-09 
21:41:36.000000000 -0700
+++ linux-2.6.13-ckrm2/include/linux/rcfs.h     2005-09-09 21:43:22.000000000 
-0700
@@ -28,6 +28,7 @@ extern int RCFS_IS_MAGIC;
 #define RCFS_RECLASSIFY_NAME   "reclassify"
 
 #define rcfs_is_magic(dentry)  ((dentry)->d_fsdata == &RCFS_IS_MAGIC)
+#define rcfs_positive(dentry)  ((dentry)->d_inode && !d_unhashed((dentry)))
 
 struct rcfs_inode_info {
        struct ckrm_core_class *core;
@@ -65,6 +66,8 @@ struct dentry *rcfs_create_internal(stru
 int rcfs_delete_internal(struct dentry *);
 int rcfs_create_magic(struct dentry *, struct rcfs_magf *, int);
 int rcfs_clear_magic(struct dentry *);
+extern int rcfs_empty(struct dentry *);
+extern int __rcfs_delete_internal(struct dentry *);
 
 extern struct super_operations rcfs_super_ops;
 extern struct address_space_operations rcfs_aops;

--


-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
ckrm-tech mailing list
https://lists.sourceforge.net/lists/listinfo/ckrm-tech

Reply via email to