Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 926

kernel-2.6.18-238.el5.src.rpm

From: Josef Bacik <jbacik@redhat.com>
Date: Thu, 22 May 2008 11:29:35 -0400
Subject: [fs] debugfs: fix dentry reference count bug
Message-id: 20080522152935.GA2449@unused.rdu.redhat.com
O-Subject: [RHEL5.3 PATCH] debugfs: fix dentry reference count bug
Bugzilla: 445787
RH-Acked-by: Jeff Moyer <jmoyer@redhat.com>

Hello,

This is in reference to 445787.  Apparently oracle has a case where they can
call debugfs_create_by_name twice, and when they do debugfs_remove() won't
remove the file because the dentry was dget()'ed twice, and only dput()'ed once.
This patch is a backport of commits

29a7f3ada7fea5510504c5359c3f70d109aeb055
65c333367b1aea57d58168ad3dc1df27b0227401

The second one moves the dput() to the creation path, as lookup_one_len() will
do a dget and debugfs_mknod will also do a dget.  The first commit fixes a
remove bug that was reported in the same code that I figured I'd go ahead and
backport while I was there.  Thank you,

Josef

diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 0388882..6ad1b27 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -152,6 +152,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
 			error = debugfs_mkdir(parent->d_inode, *dentry, mode);
 		else 
 			error = debugfs_create(parent->d_inode, *dentry, mode);
+		dput(*dentry);
 	} else
 		error = PTR_ERR(dentry);
 	mutex_unlock(&parent->d_inode->i_mutex);
@@ -197,13 +198,15 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode,
 
 	pr_debug("debugfs: creating file '%s'\n",name);
 
-	error = simple_pin_fs(&debug_fs_type, &debugfs_mount, &debugfs_mount_count);
+	error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
+			      &debugfs_mount_count);
 	if (error)
 		goto exit;
 
 	error = debugfs_create_by_name(name, mode, parent, &dentry);
 	if (error) {
 		dentry = NULL;
+		simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 		goto exit;
 	}
 
@@ -264,7 +267,8 @@ EXPORT_SYMBOL_GPL(debugfs_create_dir);
 void debugfs_remove(struct dentry *dentry)
 {
 	struct dentry *parent;
-	
+	int ret = 0;
+
 	if (!dentry)
 		return;
 
@@ -275,11 +279,14 @@ void debugfs_remove(struct dentry *dentry)
 	mutex_lock(&parent->d_inode->i_mutex);
 	if (debugfs_positive(dentry)) {
 		if (dentry->d_inode) {
+			dget(dentry);
 			if (S_ISDIR(dentry->d_inode->i_mode))
-				simple_rmdir(parent->d_inode, dentry);
+				ret = simple_rmdir(parent->d_inode, dentry);
 			else
 				simple_unlink(parent->d_inode, dentry);
-		dput(dentry);
+			if (!ret)
+				d_delete(dentry);
+			dput(dentry);
 		}
 	}
 	mutex_unlock(&parent->d_inode->i_mutex);