diff options
| -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 | ||||
| -rw-r--r-- | net/sunrpc/auth.c | 1 |
6 files changed, 104 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 | ||
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 247e973544bf..f77366717420 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
| @@ -592,6 +592,7 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags) | |||
| 592 | put_group_info(acred.group_info); | 592 | put_group_info(acred.group_info); |
| 593 | return ret; | 593 | return ret; |
| 594 | } | 594 | } |
| 595 | EXPORT_SYMBOL_GPL(rpcauth_lookupcred); | ||
| 595 | 596 | ||
| 596 | void | 597 | void |
| 597 | rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred, | 598 | rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred, |
