Commit 0db59e59299f0b67450c5db21f7f316c8fb04e84

Authored by Al Viro
1 parent dca111782c

debugfs: leave freeing a symlink body until inode eviction

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...

Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 1 changed file with 17 additions and 17 deletions Side-by-side Diff

... ... @@ -169,10 +169,19 @@
169 169 return 0;
170 170 }
171 171  
  172 +static void debugfs_evict_inode(struct inode *inode)
  173 +{
  174 + truncate_inode_pages_final(&inode->i_data);
  175 + clear_inode(inode);
  176 + if (S_ISLNK(inode->i_mode))
  177 + kfree(inode->i_private);
  178 +}
  179 +
172 180 static const struct super_operations debugfs_super_operations = {
173 181 .statfs = simple_statfs,
174 182 .remount_fs = debugfs_remount,
175 183 .show_options = debugfs_show_options,
  184 + .evict_inode = debugfs_evict_inode,
176 185 };
177 186  
178 187 static struct vfsmount *debugfs_automount(struct path *path)
... ... @@ -511,23 +520,14 @@
511 520 int ret = 0;
512 521  
513 522 if (debugfs_positive(dentry)) {
514   - if (dentry->d_inode) {
515   - dget(dentry);
516   - switch (dentry->d_inode->i_mode & S_IFMT) {
517   - case S_IFDIR:
518   - ret = simple_rmdir(parent->d_inode, dentry);
519   - break;
520   - case S_IFLNK:
521   - kfree(dentry->d_inode->i_private);
522   - /* fall through */
523   - default:
524   - simple_unlink(parent->d_inode, dentry);
525   - break;
526   - }
527   - if (!ret)
528   - d_delete(dentry);
529   - dput(dentry);
530   - }
  523 + dget(dentry);
  524 + if (S_ISDIR(dentry->d_inode->i_mode))
  525 + ret = simple_rmdir(parent->d_inode, dentry);
  526 + else
  527 + simple_unlink(parent->d_inode, dentry);
  528 + if (!ret)
  529 + d_delete(dentry);
  530 + dput(dentry);
531 531 }
532 532 return ret;
533 533 }