diff options
-rw-r--r-- | fs/nfs/dir.c | 19 | ||||
-rw-r--r-- | fs/nfs/unlink.c | 7 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 1 |
3 files changed, 21 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; |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 2c1485d18419..bb939edd4c99 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
@@ -207,6 +207,13 @@ out_free: | |||
207 | return ret; | 207 | return ret; |
208 | } | 208 | } |
209 | 209 | ||
210 | void nfs_wait_on_sillyrename(struct dentry *dentry) | ||
211 | { | ||
212 | struct nfs_inode *nfsi = NFS_I(dentry->d_inode); | ||
213 | |||
214 | wait_event(nfsi->waitqueue, atomic_read(&nfsi->silly_count) <= 1); | ||
215 | } | ||
216 | |||
210 | void nfs_block_sillyrename(struct dentry *dentry) | 217 | void nfs_block_sillyrename(struct dentry *dentry) |
211 | { | 218 | { |
212 | struct nfs_inode *nfsi = NFS_I(dentry->d_inode); | 219 | struct nfs_inode *nfsi = NFS_I(dentry->d_inode); |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 7125cef74164..3ea4cde8701c 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -524,6 +524,7 @@ static inline void nfs4_label_free(void *label) {} | |||
524 | * linux/fs/nfs/unlink.c | 524 | * linux/fs/nfs/unlink.c |
525 | */ | 525 | */ |
526 | extern void nfs_complete_unlink(struct dentry *dentry, struct inode *); | 526 | extern void nfs_complete_unlink(struct dentry *dentry, struct inode *); |
527 | extern void nfs_wait_on_sillyrename(struct dentry *dentry); | ||
527 | extern void nfs_block_sillyrename(struct dentry *dentry); | 528 | extern void nfs_block_sillyrename(struct dentry *dentry); |
528 | extern void nfs_unblock_sillyrename(struct dentry *dentry); | 529 | extern void nfs_unblock_sillyrename(struct dentry *dentry); |
529 | extern int nfs_sillyrename(struct inode *dir, struct dentry *dentry); | 530 | extern int nfs_sillyrename(struct inode *dir, struct dentry *dentry); |