diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/inode.c | 76 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4namespace.c | 102 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/write.c | 4 |
5 files changed, 103 insertions, 83 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index c496f8a74639..9927913c97c2 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -147,6 +147,17 @@ int nfs_sync_mapping(struct address_space *mapping) | |||
147 | return ret; | 147 | return ret; |
148 | } | 148 | } |
149 | 149 | ||
150 | static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags) | ||
151 | { | ||
152 | struct nfs_inode *nfsi = NFS_I(inode); | ||
153 | |||
154 | if (inode->i_mapping->nrpages == 0) | ||
155 | flags &= ~NFS_INO_INVALID_DATA; | ||
156 | nfsi->cache_validity |= flags; | ||
157 | if (flags & NFS_INO_INVALID_DATA) | ||
158 | nfs_fscache_invalidate(inode); | ||
159 | } | ||
160 | |||
150 | /* | 161 | /* |
151 | * Invalidate the local caches | 162 | * Invalidate the local caches |
152 | */ | 163 | */ |
@@ -162,17 +173,16 @@ static void nfs_zap_caches_locked(struct inode *inode) | |||
162 | 173 | ||
163 | memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); | 174 | memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); |
164 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { | 175 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { |
165 | nfs_fscache_invalidate(inode); | 176 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR |
166 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | ||
167 | | NFS_INO_INVALID_DATA | 177 | | NFS_INO_INVALID_DATA |
168 | | NFS_INO_INVALID_ACCESS | 178 | | NFS_INO_INVALID_ACCESS |
169 | | NFS_INO_INVALID_ACL | 179 | | NFS_INO_INVALID_ACL |
170 | | NFS_INO_REVAL_PAGECACHE; | 180 | | NFS_INO_REVAL_PAGECACHE); |
171 | } else | 181 | } else |
172 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | 182 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR |
173 | | NFS_INO_INVALID_ACCESS | 183 | | NFS_INO_INVALID_ACCESS |
174 | | NFS_INO_INVALID_ACL | 184 | | NFS_INO_INVALID_ACL |
175 | | NFS_INO_REVAL_PAGECACHE; | 185 | | NFS_INO_REVAL_PAGECACHE); |
176 | nfs_zap_label_cache_locked(nfsi); | 186 | nfs_zap_label_cache_locked(nfsi); |
177 | } | 187 | } |
178 | 188 | ||
@@ -187,8 +197,7 @@ void nfs_zap_mapping(struct inode *inode, struct address_space *mapping) | |||
187 | { | 197 | { |
188 | if (mapping->nrpages != 0) { | 198 | if (mapping->nrpages != 0) { |
189 | spin_lock(&inode->i_lock); | 199 | spin_lock(&inode->i_lock); |
190 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA; | 200 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA); |
191 | nfs_fscache_invalidate(inode); | ||
192 | spin_unlock(&inode->i_lock); | 201 | spin_unlock(&inode->i_lock); |
193 | } | 202 | } |
194 | } | 203 | } |
@@ -209,7 +218,7 @@ EXPORT_SYMBOL_GPL(nfs_zap_acl_cache); | |||
209 | void nfs_invalidate_atime(struct inode *inode) | 218 | void nfs_invalidate_atime(struct inode *inode) |
210 | { | 219 | { |
211 | spin_lock(&inode->i_lock); | 220 | spin_lock(&inode->i_lock); |
212 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; | 221 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATIME); |
213 | spin_unlock(&inode->i_lock); | 222 | spin_unlock(&inode->i_lock); |
214 | } | 223 | } |
215 | EXPORT_SYMBOL_GPL(nfs_invalidate_atime); | 224 | EXPORT_SYMBOL_GPL(nfs_invalidate_atime); |
@@ -369,7 +378,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st | |||
369 | inode->i_mode = fattr->mode; | 378 | inode->i_mode = fattr->mode; |
370 | if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0 | 379 | if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0 |
371 | && nfs_server_capable(inode, NFS_CAP_MODE)) | 380 | && nfs_server_capable(inode, NFS_CAP_MODE)) |
372 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 381 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); |
373 | /* Why so? Because we want revalidate for devices/FIFOs, and | 382 | /* Why so? Because we want revalidate for devices/FIFOs, and |
374 | * that's precisely what we have in nfs_file_inode_operations. | 383 | * that's precisely what we have in nfs_file_inode_operations. |
375 | */ | 384 | */ |
@@ -415,36 +424,36 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st | |||
415 | if (fattr->valid & NFS_ATTR_FATTR_ATIME) | 424 | if (fattr->valid & NFS_ATTR_FATTR_ATIME) |
416 | inode->i_atime = fattr->atime; | 425 | inode->i_atime = fattr->atime; |
417 | else if (nfs_server_capable(inode, NFS_CAP_ATIME)) | 426 | else if (nfs_server_capable(inode, NFS_CAP_ATIME)) |
418 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 427 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); |
419 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) | 428 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) |
420 | inode->i_mtime = fattr->mtime; | 429 | inode->i_mtime = fattr->mtime; |
421 | else if (nfs_server_capable(inode, NFS_CAP_MTIME)) | 430 | else if (nfs_server_capable(inode, NFS_CAP_MTIME)) |
422 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 431 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); |
423 | if (fattr->valid & NFS_ATTR_FATTR_CTIME) | 432 | if (fattr->valid & NFS_ATTR_FATTR_CTIME) |
424 | inode->i_ctime = fattr->ctime; | 433 | inode->i_ctime = fattr->ctime; |
425 | else if (nfs_server_capable(inode, NFS_CAP_CTIME)) | 434 | else if (nfs_server_capable(inode, NFS_CAP_CTIME)) |
426 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 435 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); |
427 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) | 436 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) |
428 | inode->i_version = fattr->change_attr; | 437 | inode->i_version = fattr->change_attr; |
429 | else if (nfs_server_capable(inode, NFS_CAP_CHANGE_ATTR)) | 438 | else if (nfs_server_capable(inode, NFS_CAP_CHANGE_ATTR)) |
430 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 439 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); |
431 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) | 440 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) |
432 | inode->i_size = nfs_size_to_loff_t(fattr->size); | 441 | inode->i_size = nfs_size_to_loff_t(fattr->size); |
433 | else | 442 | else |
434 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | 443 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR |
435 | | NFS_INO_REVAL_PAGECACHE; | 444 | | NFS_INO_REVAL_PAGECACHE); |
436 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) | 445 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) |
437 | set_nlink(inode, fattr->nlink); | 446 | set_nlink(inode, fattr->nlink); |
438 | else if (nfs_server_capable(inode, NFS_CAP_NLINK)) | 447 | else if (nfs_server_capable(inode, NFS_CAP_NLINK)) |
439 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 448 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); |
440 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) | 449 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) |
441 | inode->i_uid = fattr->uid; | 450 | inode->i_uid = fattr->uid; |
442 | else if (nfs_server_capable(inode, NFS_CAP_OWNER)) | 451 | else if (nfs_server_capable(inode, NFS_CAP_OWNER)) |
443 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 452 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); |
444 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) | 453 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) |
445 | inode->i_gid = fattr->gid; | 454 | inode->i_gid = fattr->gid; |
446 | else if (nfs_server_capable(inode, NFS_CAP_OWNER_GROUP)) | 455 | else if (nfs_server_capable(inode, NFS_CAP_OWNER_GROUP)) |
447 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 456 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR); |
448 | if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) | 457 | if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) |
449 | inode->i_blocks = fattr->du.nfs2.blocks; | 458 | inode->i_blocks = fattr->du.nfs2.blocks; |
450 | if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { | 459 | if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { |
@@ -550,6 +559,9 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset) | |||
550 | 559 | ||
551 | spin_lock(&inode->i_lock); | 560 | spin_lock(&inode->i_lock); |
552 | i_size_write(inode, offset); | 561 | i_size_write(inode, offset); |
562 | /* Optimisation */ | ||
563 | if (offset == 0) | ||
564 | NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA; | ||
553 | spin_unlock(&inode->i_lock); | 565 | spin_unlock(&inode->i_lock); |
554 | 566 | ||
555 | truncate_pagecache(inode, offset); | 567 | truncate_pagecache(inode, offset); |
@@ -578,7 +590,8 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | |||
578 | inode->i_uid = attr->ia_uid; | 590 | inode->i_uid = attr->ia_uid; |
579 | if ((attr->ia_valid & ATTR_GID) != 0) | 591 | if ((attr->ia_valid & ATTR_GID) != 0) |
580 | inode->i_gid = attr->ia_gid; | 592 | inode->i_gid = attr->ia_gid; |
581 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 593 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS |
594 | | NFS_INO_INVALID_ACL); | ||
582 | spin_unlock(&inode->i_lock); | 595 | spin_unlock(&inode->i_lock); |
583 | } | 596 | } |
584 | if ((attr->ia_valid & ATTR_SIZE) != 0) { | 597 | if ((attr->ia_valid & ATTR_SIZE) != 0) { |
@@ -1101,7 +1114,7 @@ static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr | |||
1101 | && inode->i_version == fattr->pre_change_attr) { | 1114 | && inode->i_version == fattr->pre_change_attr) { |
1102 | inode->i_version = fattr->change_attr; | 1115 | inode->i_version = fattr->change_attr; |
1103 | if (S_ISDIR(inode->i_mode)) | 1116 | if (S_ISDIR(inode->i_mode)) |
1104 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 1117 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA); |
1105 | ret |= NFS_INO_INVALID_ATTR; | 1118 | ret |= NFS_INO_INVALID_ATTR; |
1106 | } | 1119 | } |
1107 | /* If we have atomic WCC data, we may update some attributes */ | 1120 | /* If we have atomic WCC data, we may update some attributes */ |
@@ -1117,7 +1130,7 @@ static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr | |||
1117 | && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | 1130 | && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { |
1118 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 1131 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
1119 | if (S_ISDIR(inode->i_mode)) | 1132 | if (S_ISDIR(inode->i_mode)) |
1120 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 1133 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA); |
1121 | ret |= NFS_INO_INVALID_ATTR; | 1134 | ret |= NFS_INO_INVALID_ATTR; |
1122 | } | 1135 | } |
1123 | if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) | 1136 | if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) |
@@ -1128,9 +1141,6 @@ static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr | |||
1128 | ret |= NFS_INO_INVALID_ATTR; | 1141 | ret |= NFS_INO_INVALID_ATTR; |
1129 | } | 1142 | } |
1130 | 1143 | ||
1131 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) | ||
1132 | nfs_fscache_invalidate(inode); | ||
1133 | |||
1134 | return ret; | 1144 | return ret; |
1135 | } | 1145 | } |
1136 | 1146 | ||
@@ -1189,7 +1199,7 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
1189 | invalid |= NFS_INO_INVALID_ATIME; | 1199 | invalid |= NFS_INO_INVALID_ATIME; |
1190 | 1200 | ||
1191 | if (invalid != 0) | 1201 | if (invalid != 0) |
1192 | nfsi->cache_validity |= invalid; | 1202 | nfs_set_cache_invalid(inode, invalid); |
1193 | 1203 | ||
1194 | nfsi->read_cache_jiffies = fattr->time_start; | 1204 | nfsi->read_cache_jiffies = fattr->time_start; |
1195 | return 0; | 1205 | return 0; |
@@ -1402,13 +1412,11 @@ EXPORT_SYMBOL_GPL(nfs_refresh_inode); | |||
1402 | 1412 | ||
1403 | static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr) | 1413 | static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr) |
1404 | { | 1414 | { |
1405 | struct nfs_inode *nfsi = NFS_I(inode); | 1415 | unsigned long invalid = NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
1406 | 1416 | ||
1407 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 1417 | if (S_ISDIR(inode->i_mode)) |
1408 | if (S_ISDIR(inode->i_mode)) { | 1418 | invalid |= NFS_INO_INVALID_DATA; |
1409 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 1419 | nfs_set_cache_invalid(inode, invalid); |
1410 | nfs_fscache_invalidate(inode); | ||
1411 | } | ||
1412 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 1420 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) |
1413 | return 0; | 1421 | return 0; |
1414 | return nfs_refresh_inode_locked(inode, fattr); | 1422 | return nfs_refresh_inode_locked(inode, fattr); |
@@ -1601,6 +1609,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1601 | if ((nfsi->npages == 0) || new_isize > cur_isize) { | 1609 | if ((nfsi->npages == 0) || new_isize > cur_isize) { |
1602 | i_size_write(inode, new_isize); | 1610 | i_size_write(inode, new_isize); |
1603 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1611 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1612 | invalid &= ~NFS_INO_REVAL_PAGECACHE; | ||
1604 | } | 1613 | } |
1605 | dprintk("NFS: isize change on server for file %s/%ld " | 1614 | dprintk("NFS: isize change on server for file %s/%ld " |
1606 | "(%Ld to %Ld)\n", | 1615 | "(%Ld to %Ld)\n", |
@@ -1702,10 +1711,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1702 | invalid &= ~NFS_INO_INVALID_DATA; | 1711 | invalid &= ~NFS_INO_INVALID_DATA; |
1703 | if (!NFS_PROTO(inode)->have_delegation(inode, FMODE_READ) || | 1712 | if (!NFS_PROTO(inode)->have_delegation(inode, FMODE_READ) || |
1704 | (save_cache_validity & NFS_INO_REVAL_FORCED)) | 1713 | (save_cache_validity & NFS_INO_REVAL_FORCED)) |
1705 | nfsi->cache_validity |= invalid; | 1714 | nfs_set_cache_invalid(inode, invalid); |
1706 | |||
1707 | if (invalid & NFS_INO_INVALID_DATA) | ||
1708 | nfs_fscache_invalidate(inode); | ||
1709 | 1715 | ||
1710 | return 0; | 1716 | return 0; |
1711 | out_err: | 1717 | out_err: |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index f63cb87cd730..ba2affa51941 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -230,7 +230,7 @@ int nfs_atomic_open(struct inode *, struct dentry *, struct file *, | |||
230 | extern struct file_system_type nfs4_fs_type; | 230 | extern struct file_system_type nfs4_fs_type; |
231 | 231 | ||
232 | /* nfs4namespace.c */ | 232 | /* nfs4namespace.c */ |
233 | struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); | 233 | struct rpc_clnt *nfs4_negotiate_security(struct rpc_clnt *, struct inode *, struct qstr *); |
234 | struct vfsmount *nfs4_submount(struct nfs_server *, struct dentry *, | 234 | struct vfsmount *nfs4_submount(struct nfs_server *, struct dentry *, |
235 | struct nfs_fh *, struct nfs_fattr *); | 235 | struct nfs_fh *, struct nfs_fattr *); |
236 | int nfs4_replace_transport(struct nfs_server *server, | 236 | int nfs4_replace_transport(struct nfs_server *server, |
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 3d5dbf80d46a..3d83cb1fdc70 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
@@ -139,16 +139,22 @@ static size_t nfs_parse_server_name(char *string, size_t len, | |||
139 | * @server: NFS server struct | 139 | * @server: NFS server struct |
140 | * @flavors: List of security tuples returned by SECINFO procedure | 140 | * @flavors: List of security tuples returned by SECINFO procedure |
141 | * | 141 | * |
142 | * Return the pseudoflavor of the first security mechanism in | 142 | * Return an rpc client that uses the first security mechanism in |
143 | * "flavors" that is locally supported. Return RPC_AUTH_UNIX if | 143 | * "flavors" that is locally supported. The "flavors" array |
144 | * no matching flavor is found in the array. The "flavors" array | ||
145 | * is searched in the order returned from the server, per RFC 3530 | 144 | * is searched in the order returned from the server, per RFC 3530 |
146 | * recommendation. | 145 | * recommendation and each flavor is checked for membership in the |
146 | * sec= mount option list if it exists. | ||
147 | * | ||
148 | * Return -EPERM if no matching flavor is found in the array. | ||
149 | * | ||
150 | * Please call rpc_shutdown_client() when you are done with this rpc client. | ||
151 | * | ||
147 | */ | 152 | */ |
148 | static rpc_authflavor_t nfs_find_best_sec(struct nfs_server *server, | 153 | static struct rpc_clnt *nfs_find_best_sec(struct rpc_clnt *clnt, |
154 | struct nfs_server *server, | ||
149 | struct nfs4_secinfo_flavors *flavors) | 155 | struct nfs4_secinfo_flavors *flavors) |
150 | { | 156 | { |
151 | rpc_authflavor_t pseudoflavor; | 157 | rpc_authflavor_t pflavor; |
152 | struct nfs4_secinfo4 *secinfo; | 158 | struct nfs4_secinfo4 *secinfo; |
153 | unsigned int i; | 159 | unsigned int i; |
154 | 160 | ||
@@ -159,62 +165,73 @@ static rpc_authflavor_t nfs_find_best_sec(struct nfs_server *server, | |||
159 | case RPC_AUTH_NULL: | 165 | case RPC_AUTH_NULL: |
160 | case RPC_AUTH_UNIX: | 166 | case RPC_AUTH_UNIX: |
161 | case RPC_AUTH_GSS: | 167 | case RPC_AUTH_GSS: |
162 | pseudoflavor = rpcauth_get_pseudoflavor(secinfo->flavor, | 168 | pflavor = rpcauth_get_pseudoflavor(secinfo->flavor, |
163 | &secinfo->flavor_info); | 169 | &secinfo->flavor_info); |
164 | /* make sure pseudoflavor matches sec= mount opt */ | 170 | /* does the pseudoflavor match a sec= mount opt? */ |
165 | if (pseudoflavor != RPC_AUTH_MAXFLAVOR && | 171 | if (pflavor != RPC_AUTH_MAXFLAVOR && |
166 | nfs_auth_info_match(&server->auth_info, | 172 | nfs_auth_info_match(&server->auth_info, pflavor)) { |
167 | pseudoflavor)) | 173 | struct rpc_clnt *new; |
168 | return pseudoflavor; | 174 | struct rpc_cred *cred; |
169 | break; | 175 | |
176 | /* Cloning creates an rpc_auth for the flavor */ | ||
177 | new = rpc_clone_client_set_auth(clnt, pflavor); | ||
178 | if (IS_ERR(new)) | ||
179 | continue; | ||
180 | /** | ||
181 | * Check that the user actually can use the | ||
182 | * flavor. This is mostly for RPC_AUTH_GSS | ||
183 | * where cr_init obtains a gss context | ||
184 | */ | ||
185 | cred = rpcauth_lookupcred(new->cl_auth, 0); | ||
186 | if (IS_ERR(cred)) { | ||
187 | rpc_shutdown_client(new); | ||
188 | continue; | ||
189 | } | ||
190 | put_rpccred(cred); | ||
191 | return new; | ||
192 | } | ||
170 | } | 193 | } |
171 | } | 194 | } |
172 | 195 | return ERR_PTR(-EPERM); | |
173 | /* if there were any sec= options then nothing matched */ | ||
174 | if (server->auth_info.flavor_len > 0) | ||
175 | return -EPERM; | ||
176 | |||
177 | return RPC_AUTH_UNIX; | ||
178 | } | 196 | } |
179 | 197 | ||
180 | static rpc_authflavor_t nfs4_negotiate_security(struct inode *inode, struct qstr *name) | 198 | /** |
199 | * nfs4_negotiate_security - in response to an NFS4ERR_WRONGSEC on lookup, | ||
200 | * return an rpc_clnt that uses the best available security flavor with | ||
201 | * respect to the secinfo flavor list and the sec= mount options. | ||
202 | * | ||
203 | * @clnt: RPC client to clone | ||
204 | * @inode: directory inode | ||
205 | * @name: lookup name | ||
206 | * | ||
207 | * Please call rpc_shutdown_client() when you are done with this rpc client. | ||
208 | */ | ||
209 | struct rpc_clnt * | ||
210 | nfs4_negotiate_security(struct rpc_clnt *clnt, struct inode *inode, | ||
211 | struct qstr *name) | ||
181 | { | 212 | { |
182 | struct page *page; | 213 | struct page *page; |
183 | struct nfs4_secinfo_flavors *flavors; | 214 | struct nfs4_secinfo_flavors *flavors; |
184 | rpc_authflavor_t flavor; | 215 | struct rpc_clnt *new; |
185 | int err; | 216 | int err; |
186 | 217 | ||
187 | page = alloc_page(GFP_KERNEL); | 218 | page = alloc_page(GFP_KERNEL); |
188 | if (!page) | 219 | if (!page) |
189 | return -ENOMEM; | 220 | return ERR_PTR(-ENOMEM); |
221 | |||
190 | flavors = page_address(page); | 222 | flavors = page_address(page); |
191 | 223 | ||
192 | err = nfs4_proc_secinfo(inode, name, flavors); | 224 | err = nfs4_proc_secinfo(inode, name, flavors); |
193 | if (err < 0) { | 225 | if (err < 0) { |
194 | flavor = err; | 226 | new = ERR_PTR(err); |
195 | goto out; | 227 | goto out; |
196 | } | 228 | } |
197 | 229 | ||
198 | flavor = nfs_find_best_sec(NFS_SERVER(inode), flavors); | 230 | new = nfs_find_best_sec(clnt, NFS_SERVER(inode), flavors); |
199 | 231 | ||
200 | out: | 232 | out: |
201 | put_page(page); | 233 | put_page(page); |
202 | return flavor; | 234 | return new; |
203 | } | ||
204 | |||
205 | /* | ||
206 | * Please call rpc_shutdown_client() when you are done with this client. | ||
207 | */ | ||
208 | struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *clnt, struct inode *inode, | ||
209 | struct qstr *name) | ||
210 | { | ||
211 | rpc_authflavor_t flavor; | ||
212 | |||
213 | flavor = nfs4_negotiate_security(inode, name); | ||
214 | if ((int)flavor < 0) | ||
215 | return ERR_PTR((int)flavor); | ||
216 | |||
217 | return rpc_clone_client_set_auth(clnt, flavor); | ||
218 | } | 235 | } |
219 | 236 | ||
220 | static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, | 237 | static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, |
@@ -397,11 +414,6 @@ struct vfsmount *nfs4_submount(struct nfs_server *server, struct dentry *dentry, | |||
397 | 414 | ||
398 | if (client->cl_auth->au_flavor != flavor) | 415 | if (client->cl_auth->au_flavor != flavor) |
399 | flavor = client->cl_auth->au_flavor; | 416 | flavor = client->cl_auth->au_flavor; |
400 | else { | ||
401 | rpc_authflavor_t new = nfs4_negotiate_security(dir, name); | ||
402 | if ((int)new >= 0) | ||
403 | flavor = new; | ||
404 | } | ||
405 | mnt = nfs_do_submount(dentry, fh, fattr, flavor); | 417 | mnt = nfs_do_submount(dentry, fh, fattr, flavor); |
406 | out: | 418 | out: |
407 | rpc_shutdown_client(client); | 419 | rpc_shutdown_client(client); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 285ad5334018..4bf3d97cc5a0 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -3247,7 +3247,7 @@ static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, | |||
3247 | err = -EPERM; | 3247 | err = -EPERM; |
3248 | if (client != *clnt) | 3248 | if (client != *clnt) |
3249 | goto out; | 3249 | goto out; |
3250 | client = nfs4_create_sec_client(client, dir, name); | 3250 | client = nfs4_negotiate_security(client, dir, name); |
3251 | if (IS_ERR(client)) | 3251 | if (IS_ERR(client)) |
3252 | return PTR_ERR(client); | 3252 | return PTR_ERR(client); |
3253 | 3253 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 3ee5af4e738e..98ff061ccaf3 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -934,12 +934,14 @@ static bool nfs_write_pageuptodate(struct page *page, struct inode *inode) | |||
934 | 934 | ||
935 | if (nfs_have_delegated_attributes(inode)) | 935 | if (nfs_have_delegated_attributes(inode)) |
936 | goto out; | 936 | goto out; |
937 | if (nfsi->cache_validity & (NFS_INO_INVALID_DATA|NFS_INO_REVAL_PAGECACHE)) | 937 | if (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) |
938 | return false; | 938 | return false; |
939 | smp_rmb(); | 939 | smp_rmb(); |
940 | if (test_bit(NFS_INO_INVALIDATING, &nfsi->flags)) | 940 | if (test_bit(NFS_INO_INVALIDATING, &nfsi->flags)) |
941 | return false; | 941 | return false; |
942 | out: | 942 | out: |
943 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) | ||
944 | return false; | ||
943 | return PageUptodate(page) != 0; | 945 | return PageUptodate(page) != 0; |
944 | } | 946 | } |
945 | 947 | ||