diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-08-10 17:51:46 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-08-24 15:50:42 -0400 |
commit | 68adb0af51ebccb72ffb14d49cb8121b1afc4259 (patch) | |
tree | cfe18744aa4a96680cf344092cff9a741fe152c3 /net/sunrpc | |
parent | dff02cc1a34fcb60904a2c57cb351857cc11219e (diff) |
SUNRPC: rpc_unlink() must check for unhashed dentries
A prior call to rpc_depopulate() by rpc_rmdir() on the parent directory may
have already called simple_unlink() on this entry.
Add the same check to rpc_rmdir(). Also remove a redundant call to
rpc_close_pipes() in rpc_rmdir.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
(cherry picked from 0bbfb9d20f6437c4031aa3bf9b4d311a053e58e3 commit)
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 9c355e1ae61a..0b1a1ac8a4bc 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -539,6 +539,7 @@ repeat: | |||
539 | rpc_close_pipes(dentry->d_inode); | 539 | rpc_close_pipes(dentry->d_inode); |
540 | simple_unlink(dir, dentry); | 540 | simple_unlink(dir, dentry); |
541 | } | 541 | } |
542 | inode_dir_notify(dir, DN_DELETE); | ||
542 | dput(dentry); | 543 | dput(dentry); |
543 | } while (n); | 544 | } while (n); |
544 | goto repeat; | 545 | goto repeat; |
@@ -610,8 +611,8 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry) | |||
610 | int error; | 611 | int error; |
611 | 612 | ||
612 | shrink_dcache_parent(dentry); | 613 | shrink_dcache_parent(dentry); |
613 | if (dentry->d_inode) | 614 | if (d_unhashed(dentry)) |
614 | rpc_close_pipes(dentry->d_inode); | 615 | return 0; |
615 | if ((error = simple_rmdir(dir, dentry)) != 0) | 616 | if ((error = simple_rmdir(dir, dentry)) != 0) |
616 | return error; | 617 | return error; |
617 | if (!error) { | 618 | if (!error) { |
@@ -747,13 +748,15 @@ rpc_unlink(struct dentry *dentry) | |||
747 | parent = dget_parent(dentry); | 748 | parent = dget_parent(dentry); |
748 | dir = parent->d_inode; | 749 | dir = parent->d_inode; |
749 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 750 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
750 | d_drop(dentry); | 751 | if (!d_unhashed(dentry)) { |
751 | if (dentry->d_inode) { | 752 | d_drop(dentry); |
752 | rpc_close_pipes(dentry->d_inode); | 753 | if (dentry->d_inode) { |
753 | error = simple_unlink(dir, dentry); | 754 | rpc_close_pipes(dentry->d_inode); |
755 | error = simple_unlink(dir, dentry); | ||
756 | } | ||
757 | inode_dir_notify(dir, DN_DELETE); | ||
754 | } | 758 | } |
755 | dput(dentry); | 759 | dput(dentry); |
756 | inode_dir_notify(dir, DN_DELETE); | ||
757 | mutex_unlock(&dir->i_mutex); | 760 | mutex_unlock(&dir->i_mutex); |
758 | dput(parent); | 761 | dput(parent); |
759 | return error; | 762 | return error; |