diff options
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 8ec7fbd8240c..35334539d947 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -562,6 +562,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
562 | nfs_fattr_init(&fattr); | 562 | nfs_fattr_init(&fattr); |
563 | desc->entry = &my_entry; | 563 | desc->entry = &my_entry; |
564 | 564 | ||
565 | nfs_block_sillyrename(dentry); | ||
565 | while(!desc->entry->eof) { | 566 | while(!desc->entry->eof) { |
566 | res = readdir_search_pagecache(desc); | 567 | res = readdir_search_pagecache(desc); |
567 | 568 | ||
@@ -592,6 +593,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
592 | break; | 593 | break; |
593 | } | 594 | } |
594 | } | 595 | } |
596 | nfs_unblock_sillyrename(dentry); | ||
595 | unlock_kernel(); | 597 | unlock_kernel(); |
596 | if (res > 0) | 598 | if (res > 0) |
597 | res = 0; | 599 | res = 0; |
@@ -866,6 +868,7 @@ struct dentry_operations nfs_dentry_operations = { | |||
866 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | 868 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) |
867 | { | 869 | { |
868 | struct dentry *res; | 870 | struct dentry *res; |
871 | struct dentry *parent; | ||
869 | struct inode *inode = NULL; | 872 | struct inode *inode = NULL; |
870 | int error; | 873 | int error; |
871 | struct nfs_fh fhandle; | 874 | struct nfs_fh fhandle; |
@@ -894,26 +897,31 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
894 | goto out_unlock; | 897 | goto out_unlock; |
895 | } | 898 | } |
896 | 899 | ||
900 | parent = dentry->d_parent; | ||
901 | /* Protect against concurrent sillydeletes */ | ||
902 | nfs_block_sillyrename(parent); | ||
897 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); | 903 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); |
898 | if (error == -ENOENT) | 904 | if (error == -ENOENT) |
899 | goto no_entry; | 905 | goto no_entry; |
900 | if (error < 0) { | 906 | if (error < 0) { |
901 | res = ERR_PTR(error); | 907 | res = ERR_PTR(error); |
902 | goto out_unlock; | 908 | goto out_unblock_sillyrename; |
903 | } | 909 | } |
904 | inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr); | 910 | inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr); |
905 | res = (struct dentry *)inode; | 911 | res = (struct dentry *)inode; |
906 | if (IS_ERR(res)) | 912 | if (IS_ERR(res)) |
907 | goto out_unlock; | 913 | goto out_unblock_sillyrename; |
908 | 914 | ||
909 | no_entry: | 915 | no_entry: |
910 | res = d_materialise_unique(dentry, inode); | 916 | res = d_materialise_unique(dentry, inode); |
911 | if (res != NULL) { | 917 | if (res != NULL) { |
912 | if (IS_ERR(res)) | 918 | if (IS_ERR(res)) |
913 | goto out_unlock; | 919 | goto out_unblock_sillyrename; |
914 | dentry = res; | 920 | dentry = res; |
915 | } | 921 | } |
916 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 922 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
923 | out_unblock_sillyrename: | ||
924 | nfs_unblock_sillyrename(parent); | ||
917 | out_unlock: | 925 | out_unlock: |
918 | unlock_kernel(); | 926 | unlock_kernel(); |
919 | out: | 927 | out: |