Commit 1d2ef5901483004d74947bbf78d5146c24038fe7
Committed by
Linus Torvalds
1 parent
003f6c9df5
Exists in
master
and in
20 other branches
restore pinning the victim dentry in vfs_rmdir()/vfs_rename_dir()
We used to get the victim pinned by dentry_unhash() prior to commit 64252c75a219 ("vfs: remove dget() from dentry_unhash()") and ->rmdir() and ->rename() instances relied on that; most of them don't care, but ones that used d_delete() themselves do. As the result, we are getting rmdir() oopses on NFS now. Just grab the reference before locking the victim and drop it explicitly after unlocking, same as vfs_rename_other() does. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Tested-by: Simon Kirby <sim@hostway.ca> Cc: stable@kernel.org (3.0.x) Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 4 additions and 0 deletions Side-by-side Diff
fs/namei.c
... | ... | @@ -2616,6 +2616,7 @@ |
2616 | 2616 | if (!dir->i_op->rmdir) |
2617 | 2617 | return -EPERM; |
2618 | 2618 | |
2619 | + dget(dentry); | |
2619 | 2620 | mutex_lock(&dentry->d_inode->i_mutex); |
2620 | 2621 | |
2621 | 2622 | error = -EBUSY; |
... | ... | @@ -2636,6 +2637,7 @@ |
2636 | 2637 | |
2637 | 2638 | out: |
2638 | 2639 | mutex_unlock(&dentry->d_inode->i_mutex); |
2640 | + dput(dentry); | |
2639 | 2641 | if (!error) |
2640 | 2642 | d_delete(dentry); |
2641 | 2643 | return error; |
... | ... | @@ -3025,6 +3027,7 @@ |
3025 | 3027 | if (error) |
3026 | 3028 | return error; |
3027 | 3029 | |
3030 | + dget(new_dentry); | |
3028 | 3031 | if (target) |
3029 | 3032 | mutex_lock(&target->i_mutex); |
3030 | 3033 | |
... | ... | @@ -3045,6 +3048,7 @@ |
3045 | 3048 | out: |
3046 | 3049 | if (target) |
3047 | 3050 | mutex_unlock(&target->i_mutex); |
3051 | + dput(new_dentry); | |
3048 | 3052 | if (!error) |
3049 | 3053 | if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) |
3050 | 3054 | d_move(old_dentry,new_dentry); |