aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dir.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-08-30 12:24:25 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-09-03 15:26:29 -0400
commitba6c05928dcafc7e0a0c8e4ee6a293ba47190fd4 (patch)
tree3b32adfdc8fb978f1933d43591e36ed0b14897d6 /fs/nfs/dir.c
parenta5250def7c4549a6a1cd8257900bef9c12ffc2fc (diff)
NFS: Ensure that rmdir() waits for sillyrenames to complete
If an NFS client does mkdir("dir"); fd = open("dir/file"); unlink("dir/file"); close(fd); rmdir("dir"); then the asynchronous nature of the sillyrename operation means that we can end up getting EBUSY for the rmdir() in the above test. Fix that by ensuring that we wait for any in-progress sillyrenames before sending the rmdir() to the server. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r--fs/nfs/dir.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index d8149e916dd7..187caa47dad9 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1694,12 +1694,19 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry)
1694 dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); 1694 dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
1695 1695
1696 trace_nfs_rmdir_enter(dir, dentry); 1696 trace_nfs_rmdir_enter(dir, dentry);
1697 error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); 1697 if (dentry->d_inode) {
1698 /* Ensure the VFS deletes this inode */ 1698 nfs_wait_on_sillyrename(dentry);
1699 if (error == 0 && dentry->d_inode != NULL) 1699 error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
1700 clear_nlink(dentry->d_inode); 1700 /* Ensure the VFS deletes this inode */
1701 else if (error == -ENOENT) 1701 switch (error) {
1702 nfs_dentry_handle_enoent(dentry); 1702 case 0:
1703 clear_nlink(dentry->d_inode);
1704 break;
1705 case -ENOENT:
1706 nfs_dentry_handle_enoent(dentry);
1707 }
1708 } else
1709 error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
1703 trace_nfs_rmdir_exit(dir, dentry, error); 1710 trace_nfs_rmdir_exit(dir, dentry, error);
1704 1711
1705 return error; 1712 return error;