From: Al Viro <v...@zeniv.linux.org.uk>

3.4.108-rc1 review patch.  If anyone has any objections, please let me know.

------------------


commit 0db59e59299f0b67450c5db21f7f316c8fb04e84 upstream.

As it is, we have debugfs_remove() racing with symlink traversals.
Supply ->evict_inode() and do freeing there - inode will remain
pinned until we are done with the symlink body.

And rip the idiocy with checking if dentry is positive right after
we'd verified debugfs_positive(), which is a stronger check...

Signed-off-by: Al Viro <v...@zeniv.linux.org.uk>
[lizf: Backported to 3.4:
 - call end_writeback() instead of clear_inode()
 - call truncate_inode_pages() instead of truncate_inode_pages_final()]
Signed-off-by: Zefan Li <lize...@huawei.com>
---
 fs/debugfs/inode.c | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 47d64e9..7b65755 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -238,10 +238,19 @@ static int debugfs_show_options(struct seq_file *m, 
struct dentry *root)
        return 0;
 }
 
+static void debugfs_evict_inode(struct inode *inode)
+{
+       truncate_inode_pages(&inode->i_data, 0);
+       end_writeback(inode);
+       if (S_ISLNK(inode->i_mode))
+               kfree(inode->i_private);
+}
+
 static const struct super_operations debugfs_super_operations = {
        .statfs         = simple_statfs,
        .remount_fs     = debugfs_remount,
        .show_options   = debugfs_show_options,
+       .evict_inode    = debugfs_evict_inode,
 };
 
 static int debug_fill_super(struct super_block *sb, void *data, int silent)
@@ -459,23 +468,14 @@ static int __debugfs_remove(struct dentry *dentry, struct 
dentry *parent)
        int ret = 0;
 
        if (debugfs_positive(dentry)) {
-               if (dentry->d_inode) {
-                       dget(dentry);
-                       switch (dentry->d_inode->i_mode & S_IFMT) {
-                       case S_IFDIR:
-                               ret = simple_rmdir(parent->d_inode, dentry);
-                               break;
-                       case S_IFLNK:
-                               kfree(dentry->d_inode->i_private);
-                               /* fall through */
-                       default:
-                               simple_unlink(parent->d_inode, dentry);
-                               break;
-                       }
-                       if (!ret)
-                               d_delete(dentry);
-                       dput(dentry);
-               }
+               dget(dentry);
+               if (S_ISDIR(dentry->d_inode->i_mode))
+                       ret = simple_rmdir(parent->d_inode, dentry);
+               else
+                       simple_unlink(parent->d_inode, dentry);
+               if (!ret)
+                       d_delete(dentry);
+               dput(dentry);
        }
        return ret;
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to