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