diff options
Diffstat (limited to 'fs/nfs/dir.c')
| -rw-r--r-- | fs/nfs/dir.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 3e64b98f3a93..e35c8199f82f 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -799,6 +799,9 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
| 799 | goto out_bad; | 799 | goto out_bad; |
| 800 | } | 800 | } |
| 801 | 801 | ||
| 802 | if (nfs_have_delegation(inode, FMODE_READ)) | ||
| 803 | goto out_set_verifier; | ||
| 804 | |||
| 802 | /* Force a full look up iff the parent directory has changed */ | 805 | /* Force a full look up iff the parent directory has changed */ |
| 803 | if (!nfs_is_exclusive_create(dir, nd) && nfs_check_verifier(dir, dentry)) { | 806 | if (!nfs_is_exclusive_create(dir, nd) && nfs_check_verifier(dir, dentry)) { |
| 804 | if (nfs_lookup_verify_inode(inode, nd)) | 807 | if (nfs_lookup_verify_inode(inode, nd)) |
| @@ -817,6 +820,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
| 817 | if ((error = nfs_refresh_inode(inode, &fattr)) != 0) | 820 | if ((error = nfs_refresh_inode(inode, &fattr)) != 0) |
| 818 | goto out_bad; | 821 | goto out_bad; |
| 819 | 822 | ||
| 823 | out_set_verifier: | ||
| 820 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 824 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
| 821 | out_valid: | 825 | out_valid: |
| 822 | dput(parent); | 826 | dput(parent); |
| @@ -973,7 +977,7 @@ struct dentry_operations nfs4_dentry_operations = { | |||
| 973 | * Use intent information to determine whether we need to substitute | 977 | * Use intent information to determine whether we need to substitute |
| 974 | * the NFSv4-style stateful OPEN for the LOOKUP call | 978 | * the NFSv4-style stateful OPEN for the LOOKUP call |
| 975 | */ | 979 | */ |
| 976 | static int is_atomic_open(struct inode *dir, struct nameidata *nd) | 980 | static int is_atomic_open(struct nameidata *nd) |
| 977 | { | 981 | { |
| 978 | if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0) | 982 | if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0) |
| 979 | return 0; | 983 | return 0; |
| @@ -996,7 +1000,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
| 996 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | 1000 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); |
| 997 | 1001 | ||
| 998 | /* Check that we are indeed trying to open this file */ | 1002 | /* Check that we are indeed trying to open this file */ |
| 999 | if (!is_atomic_open(dir, nd)) | 1003 | if (!is_atomic_open(nd)) |
| 1000 | goto no_open; | 1004 | goto no_open; |
| 1001 | 1005 | ||
| 1002 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) { | 1006 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) { |
| @@ -1047,10 +1051,10 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 1047 | struct inode *dir; | 1051 | struct inode *dir; |
| 1048 | int openflags, ret = 0; | 1052 | int openflags, ret = 0; |
| 1049 | 1053 | ||
| 1054 | if (!is_atomic_open(nd)) | ||
| 1055 | goto no_open; | ||
| 1050 | parent = dget_parent(dentry); | 1056 | parent = dget_parent(dentry); |
| 1051 | dir = parent->d_inode; | 1057 | dir = parent->d_inode; |
| 1052 | if (!is_atomic_open(dir, nd)) | ||
| 1053 | goto no_open; | ||
| 1054 | /* We can't create new files in nfs_open_revalidate(), so we | 1058 | /* We can't create new files in nfs_open_revalidate(), so we |
| 1055 | * optimize away revalidation of negative dentries. | 1059 | * optimize away revalidation of negative dentries. |
| 1056 | */ | 1060 | */ |
| @@ -1062,11 +1066,11 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 1062 | 1066 | ||
| 1063 | /* NFS only supports OPEN on regular files */ | 1067 | /* NFS only supports OPEN on regular files */ |
| 1064 | if (!S_ISREG(inode->i_mode)) | 1068 | if (!S_ISREG(inode->i_mode)) |
| 1065 | goto no_open; | 1069 | goto no_open_dput; |
| 1066 | openflags = nd->intent.open.flags; | 1070 | openflags = nd->intent.open.flags; |
| 1067 | /* We cannot do exclusive creation on a positive dentry */ | 1071 | /* We cannot do exclusive creation on a positive dentry */ |
| 1068 | if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) | 1072 | if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) |
| 1069 | goto no_open; | 1073 | goto no_open_dput; |
| 1070 | /* We can't create new files, or truncate existing ones here */ | 1074 | /* We can't create new files, or truncate existing ones here */ |
| 1071 | openflags &= ~(O_CREAT|O_TRUNC); | 1075 | openflags &= ~(O_CREAT|O_TRUNC); |
| 1072 | 1076 | ||
| @@ -1081,10 +1085,9 @@ out: | |||
| 1081 | if (!ret) | 1085 | if (!ret) |
| 1082 | d_drop(dentry); | 1086 | d_drop(dentry); |
| 1083 | return ret; | 1087 | return ret; |
| 1084 | no_open: | 1088 | no_open_dput: |
| 1085 | dput(parent); | 1089 | dput(parent); |
| 1086 | if (inode != NULL && nfs_have_delegation(inode, FMODE_READ)) | 1090 | no_open: |
| 1087 | return 1; | ||
| 1088 | return nfs_lookup_revalidate(dentry, nd); | 1091 | return nfs_lookup_revalidate(dentry, nd); |
| 1089 | } | 1092 | } |
| 1090 | #endif /* CONFIG_NFSV4 */ | 1093 | #endif /* CONFIG_NFSV4 */ |
| @@ -1794,7 +1797,8 @@ static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, str | |||
| 1794 | cache = nfs_access_search_rbtree(inode, cred); | 1797 | cache = nfs_access_search_rbtree(inode, cred); |
| 1795 | if (cache == NULL) | 1798 | if (cache == NULL) |
| 1796 | goto out; | 1799 | goto out; |
| 1797 | if (!time_in_range(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo)) | 1800 | if (!nfs_have_delegation(inode, FMODE_READ) && |
| 1801 | !time_in_range_open(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo)) | ||
| 1798 | goto out_stale; | 1802 | goto out_stale; |
| 1799 | res->jiffies = cache->jiffies; | 1803 | res->jiffies = cache->jiffies; |
| 1800 | res->cred = cache->cred; | 1804 | res->cred = cache->cred; |
