Pull more NFS client updates from Trond Myklebust: "Highlights include: - further attribute cache improvements to make revalidation more fine grained - NFSv4 locking improvements Bugfixes: - nfs4_fl_prepare_ds must be careful about reporting success in files layout - pNFS/flexfiles: Instead of marking a device inactive, remove it from the cache" * tag 'nfs-for-4.10-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv4: Retry the DELEGRETURN if the embedded GETATTR is rejected with EACCES NFS: Retry the CLOSE if the embedded GETATTR is rejected with EACCES NFSv4: Place the GETATTR operation before the CLOSE NFSv4: Also ask for attributes when downgrading to a READ-only state NFS: Don't abuse NFS_INO_REVAL_FORCED in nfs_post_op_update_inode_locked() pNFS: Return RW layouts on OPEN_DOWNGRADE NFSv4: Add encode/decode of the layoutreturn op in OPEN_DOWNGRADE NFS: Don't disconnect open-owner on NFS4ERR_BAD_SEQID NFSv4: ensure __nfs4_find_lock_state returns consistent result. NFSv4.1: nfs4_fl_prepare_ds must be careful about reporting success. pNFS/flexfiles: delete deviceid, don't mark inactive NFS: Clean up nfs_attribute_timeout() NFS: Remove unused function nfs_revalidate_inode_rcu() NFS: Fix and clean up the access cache validity checking NFS: Only look at the change attribute cache state in nfs_weak_revalidate() NFS: Clean up cache validity checking NFS: Don't revalidate the file on close if we hold a delegation NFSv4: Don't discard the attributes returned by asynchronous DELEGRETURN NFSv4: Update the attribute cache info in update_changeattr
Unified · Split
| @@ -1273,8 +1273,8 @@ out_error: · 1272 unmodified lines | |||
| 1273 | */ | 1273 | */ |
| 1274 | static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags) | 1274 | static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags) |
| 1275 | { | 1275 | { |
| 1276 | int error; | ||
| 1277 | struct inode *inode = d_inode(dentry); | 1276 | struct inode *inode = d_inode(dentry); |
| 1277 | int error = 0; | ||
| 1278 | 1278 | ||
| 1279 | /* | 1279 | /* |
| 1280 | * I believe we can only get a negative dentry here in the case of a | 1280 | * I believe we can only get a negative dentry here in the case of a |
| @@ -1293,7 +1293,8 @@ static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags) · 12 unmodified lines | |||
| 1293 | return 0; | 1293 | return 0; |
| 1294 | } | 1294 | } |
| 1295 | 1295 | ||
| 1296 | error = nfs_revalidate_inode(NFS_SERVER(inode), inode); | 1296 | if (nfs_mapping_need_revalidate_inode(inode)) |
| 1297 | error = __nfs_revalidate_inode(NFS_SERVER(inode), inode); | ||
| 1297 | dfprintk(LOOKUPCACHE, "NFS: %s: inode %lu is %s\n", | 1298 | dfprintk(LOOKUPCACHE, "NFS: %s: inode %lu is %s\n", |
| 1298 | __func__, inode->i_ino, error ? "invalid" : "valid"); | 1299 | __func__, inode->i_ino, error ? "invalid" : "valid"); |
| 1299 | return !error; | 1300 | return !error; |
| @@ -2285,8 +2286,7 @@ static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, str · 985 unmodified lines | |||
| 2285 | if (cache == NULL) | 2286 | if (cache == NULL) |
| 2286 | goto out; | 2287 | goto out; |
| 2287 | /* Found an entry, is our attribute cache valid? */ | 2288 | /* Found an entry, is our attribute cache valid? */ |
| 2288 | if (!nfs_attribute_cache_expired(inode) && | 2289 | if (!nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS)) |
| 2289 | !(nfsi->cache_validity & NFS_INO_INVALID_ATTR)) | ||
| 2290 | break; | 2290 | break; |
| 2291 | err = -ECHILD; | 2291 | err = -ECHILD; |
| 2292 | if (!may_block) | 2292 | if (!may_block) |
| @@ -2334,12 +2334,12 @@ static int nfs_access_get_cached_rcu(struct inode *inode, struct rpc_cred *cred, · 41 unmodified lines | |||
| 2334 | cache = NULL; | 2334 | cache = NULL; |
| 2335 | if (cache == NULL) | 2335 | if (cache == NULL) |
| 2336 | goto out; | 2336 | goto out; |
| 2337 | err = nfs_revalidate_inode_rcu(NFS_SERVER(inode), inode); | 2337 | if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS)) |
| 2338 | if (err) | ||
| 2339 | goto out; | 2338 | goto out; |
| 2340 | res->jiffies = cache->jiffies; | 2339 | res->jiffies = cache->jiffies; |
| 2341 | res->cred = cache->cred; | 2340 | res->cred = cache->cred; |
| 2342 | res->mask = cache->mask; | 2341 | res->mask = cache->mask; |
| 2342 | err = 0; | ||
| 2343 | out: | 2343 | out: |
| 2344 | rcu_read_unlock(); | 2344 | rcu_read_unlock(); |
| 2345 | return err; | 2345 | return err; |
| @@ -2491,12 +2491,13 @@ EXPORT_SYMBOL_GPL(nfs_may_open); · 145 unmodified lines | |||
| 2491 | static int nfs_execute_ok(struct inode *inode, int mask) | 2491 | static int nfs_execute_ok(struct inode *inode, int mask) |
| 2492 | { | 2492 | { |
| 2493 | struct nfs_server *server = NFS_SERVER(inode); | 2493 | struct nfs_server *server = NFS_SERVER(inode); |
| 2494 | int ret; | 2494 | int ret = 0; |
| 2495 | 2495 | ||
| 2496 | if (mask & MAY_NOT_BLOCK) | 2496 | if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS)) { |
| 2497 | ret = nfs_revalidate_inode_rcu(server, inode); | 2497 | if (mask & MAY_NOT_BLOCK) |
| 2498 | else | 2498 | return -ECHILD; |
| 2499 | ret = nfs_revalidate_inode(server, inode); | 2499 | ret = __nfs_revalidate_inode(server, inode); |
| 2500 | } | ||
| 2500 | if (ret == 0 && !execute_ok(inode)) | 2501 | if (ret == 0 && !execute_ok(inode)) |
| 2501 | ret = -EACCES; | 2502 | ret = -EACCES; |
| 2502 | return ret; | 2503 | return ret; |
| @@ -101,21 +101,11 @@ EXPORT_SYMBOL_GPL(nfs_file_release); · 100 unmodified lines | |||
| 101 | static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) | 101 | static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) |
| 102 | { | 102 | { |
| 103 | struct nfs_server *server = NFS_SERVER(inode); | 103 | struct nfs_server *server = NFS_SERVER(inode); |
| 104 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 105 | const unsigned long force_reval = NFS_INO_REVAL_PAGECACHE|NFS_INO_REVAL_FORCED; | ||
| 106 | unsigned long cache_validity = nfsi->cache_validity; | ||
| 107 | |||
| 108 | if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ) && | ||
| 109 | (cache_validity & force_reval) != force_reval) | ||
| 110 | goto out_noreval; | ||
| 111 | 104 | ||
| 112 | if (filp->f_flags & O_DIRECT) | 105 | if (filp->f_flags & O_DIRECT) |
| 113 | goto force_reval; | 106 | goto force_reval; |
| 114 | if (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) | 107 | if (nfs_check_cache_invalid(inode, NFS_INO_REVAL_PAGECACHE)) |
| 115 | goto force_reval; | ||
| 116 | if (nfs_attribute_timeout(inode)) | ||
| 117 | goto force_reval; | 108 | goto force_reval; |
| 118 | out_noreval: | ||
| 119 | return 0; | 109 | return 0; |
| 120 | force_reval: | 110 | force_reval: |
| 121 | return __nfs_revalidate_inode(server, inode); | 111 | return __nfs_revalidate_inode(server, inode); |
| @@ -282,7 +282,8 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx) · 281 unmodified lines | |||
| 282 | s->nfs_client->cl_minorversion); | 282 | s->nfs_client->cl_minorversion); |
| 283 | 283 | ||
| 284 | out_test_devid: | 284 | out_test_devid: |
| 285 | if (filelayout_test_devid_unavailable(devid)) | 285 | if (ret->ds_clp == NULL || |
| 286 | filelayout_test_devid_unavailable(devid)) | ||
| 286 | ret = NULL; | 287 | ret = NULL; |
| 287 | out: | 288 | out: |
| 288 | return ret; | 289 | return ret; |
| @@ -1126,7 +1126,8 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task, · 1125 unmodified lines | |||
| 1126 | case -EPIPE: | 1126 | case -EPIPE: |
| 1127 | dprintk("%s DS connection error %d\n", __func__, | 1127 | dprintk("%s DS connection error %d\n", __func__, |
| 1128 | task->tk_status); | 1128 | task->tk_status); |
| 1129 | nfs4_mark_deviceid_unavailable(devid); | 1129 | nfs4_delete_deviceid(devid->ld, devid->nfs_client, |
| 1130 | &devid->deviceid); | ||
| 1130 | rpc_wake_up(&tbl->slot_tbl_waitq); | 1131 | rpc_wake_up(&tbl->slot_tbl_waitq); |
| 1131 | /* fall through */ | 1132 | /* fall through */ |
| 1132 | default: | 1133 | default: |
| @@ -1175,7 +1176,8 @@ static int ff_layout_async_handle_error_v3(struct rpc_task *task, · 42 unmodified lines | |||
| 1175 | default: | 1176 | default: |
| 1176 | dprintk("%s DS connection error %d\n", __func__, | 1177 | dprintk("%s DS connection error %d\n", __func__, |
| 1177 | task->tk_status); | 1178 | task->tk_status); |
| 1178 | nfs4_mark_deviceid_unavailable(devid); | 1179 | nfs4_delete_deviceid(devid->ld, devid->nfs_client, |
| 1180 | &devid->deviceid); | ||
| 1179 | } | 1181 | } |
| 1180 | /* FIXME: Need to prevent infinite looping here. */ | 1182 | /* FIXME: Need to prevent infinite looping here. */ |
| 1181 | return -NFS4ERR_RESET_TO_PNFS; | 1183 | return -NFS4ERR_RESET_TO_PNFS; |
| @@ -177,7 +177,7 @@ out_err: · 176 unmodified lines | |||
| 177 | static void ff_layout_mark_devid_invalid(struct pnfs_layout_segment *lseg, | 177 | static void ff_layout_mark_devid_invalid(struct pnfs_layout_segment *lseg, |
| 178 | struct nfs4_deviceid_node *devid) | 178 | struct nfs4_deviceid_node *devid) |
| 179 | { | 179 | { |
| 180 | nfs4_mark_deviceid_unavailable(devid); | 180 | nfs4_delete_deviceid(devid->ld, devid->nfs_client, &devid->deviceid); |
| 181 | if (!ff_layout_has_available_ds(lseg)) | 181 | if (!ff_layout_has_available_ds(lseg)) |
| 182 | pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode, | 182 | pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode, |
| 183 | lseg); | 183 | lseg); |
| @@ -160,6 +160,43 @@ int nfs_sync_mapping(struct address_space *mapping) · 159 unmodified lines | |||
| 160 | return ret; | 160 | return ret; |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | static int nfs_attribute_timeout(struct inode *inode) | ||
| 164 | { | ||
| 165 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 166 | |||
| 167 | return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); | ||
| 168 | } | ||
| 169 | |||
| 170 | static bool nfs_check_cache_invalid_delegated(struct inode *inode, unsigned long flags) | ||
| 171 | { | ||
| 172 | unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity); | ||
| 173 | |||
| 174 | /* Special case for the pagecache or access cache */ | ||
| 175 | if (flags == NFS_INO_REVAL_PAGECACHE && | ||
| 176 | !(cache_validity & NFS_INO_REVAL_FORCED)) | ||
| 177 | return false; | ||
| 178 | return (cache_validity & flags) != 0; | ||
| 179 | } | ||
| 180 | |||
| 181 | static bool nfs_check_cache_invalid_not_delegated(struct inode *inode, unsigned long flags) | ||
| 182 | { | ||
| 183 | unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity); | ||
| 184 | |||
| 185 | if ((cache_validity & flags) != 0) | ||
| 186 | return true; | ||
| 187 | if (nfs_attribute_timeout(inode)) | ||
| 188 | return true; | ||
| 189 | return false; | ||
| 190 | } | ||
| 191 | |||
| 192 | bool nfs_check_cache_invalid(struct inode *inode, unsigned long flags) | ||
| 193 | { | ||
| 194 | if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ)) | ||
| 195 | return nfs_check_cache_invalid_delegated(inode, flags); | ||
| 196 | |||
| 197 | return nfs_check_cache_invalid_not_delegated(inode, flags); | ||
| 198 | } | ||
| 199 | |||
| 163 | static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags) | 200 | static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags) |
| 164 | { | 201 | { |
| 165 | struct nfs_inode *nfsi = NFS_I(inode); | 202 | struct nfs_inode *nfsi = NFS_I(inode); |
| @@ -795,6 +832,8 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync) · 629 unmodified lines | |||
| 795 | if (!is_sync) | 832 | if (!is_sync) |
| 796 | return; | 833 | return; |
| 797 | inode = d_inode(ctx->dentry); | 834 | inode = d_inode(ctx->dentry); |
| 835 | if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ)) | ||
| 836 | return; | ||
| 798 | nfsi = NFS_I(inode); | 837 | nfsi = NFS_I(inode); |
| 799 | if (inode->i_mapping->nrpages == 0) | 838 | if (inode->i_mapping->nrpages == 0) |
| 800 | return; | 839 | return; |
| @@ -1044,13 +1083,6 @@ out: · 243 unmodified lines | |||
| 1044 | return status; | 1083 | return status; |
| 1045 | } | 1084 | } |
| 1046 | 1085 | ||
| 1047 | int nfs_attribute_timeout(struct inode *inode) | ||
| 1048 | { | ||
| 1049 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 1050 | |||
| 1051 | return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | int nfs_attribute_cache_expired(struct inode *inode) | 1086 | int nfs_attribute_cache_expired(struct inode *inode) |
| 1055 | { | 1087 | { |
| 1056 | if (nfs_have_delegated_attributes(inode)) | 1088 | if (nfs_have_delegated_attributes(inode)) |
| @@ -1073,15 +1105,6 @@ int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) · 16 unmodified lines | |||
| 1073 | } | 1105 | } |
| 1074 | EXPORT_SYMBOL_GPL(nfs_revalidate_inode); | 1106 | EXPORT_SYMBOL_GPL(nfs_revalidate_inode); |
| 1075 | 1107 | ||
| 1076 | int nfs_revalidate_inode_rcu(struct nfs_server *server, struct inode *inode) | ||
| 1077 | { | ||
| 1078 | if (!(NFS_I(inode)->cache_validity & | ||
| 1079 | (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) | ||
| 1080 | && !nfs_attribute_cache_expired(inode)) | ||
| 1081 | return NFS_STALE(inode) ? -ESTALE : 0; | ||
| 1082 | return -ECHILD; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping) | 1108 | static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping) |
| 1086 | { | 1109 | { |
| 1087 | struct nfs_inode *nfsi = NFS_I(inode); | 1110 | struct nfs_inode *nfsi = NFS_I(inode); |
| @@ -1114,17 +1137,8 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map · 26 unmodified lines | |||
| 1114 | 1137 | ||
| 1115 | bool nfs_mapping_need_revalidate_inode(struct inode *inode) | 1138 | bool nfs_mapping_need_revalidate_inode(struct inode *inode) |
| 1116 | { | 1139 | { |
| 1117 | unsigned long cache_validity = NFS_I(inode)->cache_validity; | 1140 | return nfs_check_cache_invalid(inode, NFS_INO_REVAL_PAGECACHE) || |
| 1118 | 1141 | NFS_STALE(inode); | |
| 1119 | if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ)) { | ||
| 1120 | const unsigned long force_reval = | ||
| 1121 | NFS_INO_REVAL_PAGECACHE|NFS_INO_REVAL_FORCED; | ||
| 1122 | return (cache_validity & force_reval) == force_reval; | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | return (cache_validity & NFS_INO_REVAL_PAGECACHE) | ||
| 1126 | || nfs_attribute_timeout(inode) | ||
| 1127 | || NFS_STALE(inode); | ||
| 1128 | } | 1142 | } |
| 1129 | 1143 | ||
| 1130 | int nfs_revalidate_mapping_rcu(struct inode *inode) | 1144 | int nfs_revalidate_mapping_rcu(struct inode *inode) |
| @@ -1536,13 +1550,6 @@ static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr · 405 unmodified lines | |||
| 1536 | { | 1550 | { |
| 1537 | unsigned long invalid = NFS_INO_INVALID_ATTR; | 1551 | unsigned long invalid = NFS_INO_INVALID_ATTR; |
| 1538 | 1552 | ||
| 1539 | /* | ||
| 1540 | * Don't revalidate the pagecache if we hold a delegation, but do | ||
| 1541 | * force an attribute update | ||
| 1542 | */ | ||
| 1543 | if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ)) | ||
| 1544 | invalid = NFS_INO_INVALID_ATTR|NFS_INO_REVAL_FORCED; | ||
| 1545 | |||
| 1546 | if (S_ISDIR(inode->i_mode)) | 1553 | if (S_ISDIR(inode->i_mode)) |
| 1547 | invalid |= NFS_INO_INVALID_DATA; | 1554 | invalid |= NFS_INO_INVALID_DATA; |
| 1548 | nfs_set_cache_invalid(inode, invalid); | 1555 | nfs_set_cache_invalid(inode, invalid); |
| @@ -381,6 +381,7 @@ extern int nfs_drop_inode(struct inode *); · 380 unmodified lines | |||
| 381 | extern void nfs_clear_inode(struct inode *); | 381 | extern void nfs_clear_inode(struct inode *); |
| 382 | extern void nfs_evict_inode(struct inode *); | 382 | extern void nfs_evict_inode(struct inode *); |
| 383 | void nfs_zap_acl_cache(struct inode *inode); | 383 | void nfs_zap_acl_cache(struct inode *inode); |
| 384 | extern bool nfs_check_cache_invalid(struct inode *, unsigned long); | ||
| 384 | extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode); | 385 | extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode); |
| 385 | extern int nfs_wait_atomic_killable(atomic_t *p); | 386 | extern int nfs_wait_atomic_killable(atomic_t *p); |
| 386 | 387 | ||
| @@ -1089,8 +1089,15 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) · 1088 unmodified lines | |||
| 1089 | 1089 | ||
| 1090 | spin_lock(&dir->i_lock); | 1090 | spin_lock(&dir->i_lock); |
| 1091 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1091 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
| 1092 | if (!cinfo->atomic || cinfo->before != dir->i_version) | 1092 | if (cinfo->atomic && cinfo->before == dir->i_version) { |
| 1093 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | ||
| 1094 | nfsi->attrtimeo_timestamp = jiffies; | ||
| 1095 | } else { | ||
| 1093 | nfs_force_lookup_revalidate(dir); | 1096 | nfs_force_lookup_revalidate(dir); |
| 1097 | if (cinfo->before != dir->i_version) | ||
| 1098 | nfsi->cache_validity |= NFS_INO_INVALID_ACCESS | | ||
| 1099 | NFS_INO_INVALID_ACL; | ||
| 1100 | } | ||
| 1094 | dir->i_version = cinfo->after; | 1101 | dir->i_version = cinfo->after; |
| 1095 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); | 1102 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); |
| 1096 | nfs_fscache_invalidate(dir); | 1103 | nfs_fscache_invalidate(dir); |
| @@ -3115,6 +3122,16 @@ static void nfs4_close_done(struct rpc_task *task, void *data) · 2018 unmodified lines | |||
| 3115 | res_stateid = &calldata->res.stateid; | 3122 | res_stateid = &calldata->res.stateid; |
| 3116 | renew_lease(server, calldata->timestamp); | 3123 | renew_lease(server, calldata->timestamp); |
| 3117 | break; | 3124 | break; |
| 3125 | case -NFS4ERR_ACCESS: | ||
| 3126 | if (calldata->arg.bitmask != NULL) { | ||
| 3127 | calldata->arg.bitmask = NULL; | ||
| 3128 | calldata->res.fattr = NULL; | ||
| 3129 | task->tk_status = 0; | ||
| 3130 | rpc_restart_call_prepare(task); | ||
| 3131 | goto out_release; | ||
| 3132 | |||
| 3133 | } | ||
| 3134 | break; | ||
| 3118 | case -NFS4ERR_ADMIN_REVOKED: | 3135 | case -NFS4ERR_ADMIN_REVOKED: |
| 3119 | case -NFS4ERR_STALE_STATEID: | 3136 | case -NFS4ERR_STALE_STATEID: |
| 3120 | case -NFS4ERR_EXPIRED: | 3137 | case -NFS4ERR_EXPIRED: |
| @@ -3140,7 +3157,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) · 19 unmodified lines | |||
| 3140 | res_stateid, calldata->arg.fmode); | 3157 | res_stateid, calldata->arg.fmode); |
| 3141 | out_release: | 3158 | out_release: |
| 3142 | nfs_release_seqid(calldata->arg.seqid); | 3159 | nfs_release_seqid(calldata->arg.seqid); |
| 3143 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); | 3160 | nfs_refresh_inode(calldata->inode, &calldata->fattr); |
| 3144 | dprintk("%s: done, ret = %d!\n", __func__, task->tk_status); | 3161 | dprintk("%s: done, ret = %d!\n", __func__, task->tk_status); |
| 3145 | } | 3162 | } |
| 3146 | 3163 | ||
| @@ -3193,9 +3210,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) · 46 unmodified lines | |||
| 3193 | goto out_wait; | 3210 | goto out_wait; |
| 3194 | } | 3211 | } |
| 3195 | 3212 | ||
| 3196 | if (calldata->arg.fmode == 0) { | 3213 | if (calldata->arg.fmode == 0) |
| 3197 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE]; | 3214 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE]; |
| 3198 | 3215 | ||
| 3216 | if (calldata->arg.fmode == 0 || calldata->arg.fmode == FMODE_READ) { | ||
| 3199 | /* Close-to-open cache consistency revalidation */ | 3217 | /* Close-to-open cache consistency revalidation */ |
| 3200 | if (!nfs4_have_delegation(inode, FMODE_READ)) | 3218 | if (!nfs4_have_delegation(inode, FMODE_READ)) |
| 3201 | calldata->arg.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; | 3219 | calldata->arg.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; |
| @@ -3207,7 +3225,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) · 5 unmodified lines | |||
| 3207 | nfs4_map_atomic_open_share(NFS_SERVER(inode), | 3225 | nfs4_map_atomic_open_share(NFS_SERVER(inode), |
| 3208 | calldata->arg.fmode, 0); | 3226 | calldata->arg.fmode, 0); |
| 3209 | 3227 | ||
| 3210 | nfs_fattr_init(calldata->res.fattr); | 3228 | if (calldata->res.fattr == NULL) |
| 3229 | calldata->arg.bitmask = NULL; | ||
| 3230 | else if (calldata->arg.bitmask == NULL) | ||
| 3231 | calldata->res.fattr = NULL; | ||
| 3211 | calldata->timestamp = jiffies; | 3232 | calldata->timestamp = jiffies; |
| 3212 | if (nfs4_setup_sequence(NFS_SERVER(inode), | 3233 | if (nfs4_setup_sequence(NFS_SERVER(inode), |
| 3213 | &calldata->arg.seq_args, | 3234 | &calldata->arg.seq_args, |
| @@ -3274,6 +3295,7 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait) · 60 unmodified lines | |||
| 3274 | calldata->arg.seqid = alloc_seqid(&state->owner->so_seqid, gfp_mask); | 3295 | calldata->arg.seqid = alloc_seqid(&state->owner->so_seqid, gfp_mask); |
| 3275 | if (IS_ERR(calldata->arg.seqid)) | 3296 | if (IS_ERR(calldata->arg.seqid)) |
| 3276 | goto out_free_calldata; | 3297 | goto out_free_calldata; |
| 3298 | nfs_fattr_init(&calldata->fattr); | ||
| 3277 | calldata->arg.fmode = 0; | 3299 | calldata->arg.fmode = 0; |
| 3278 | calldata->lr.arg.ld_private = &calldata->lr.ld_private; | 3300 | calldata->lr.arg.ld_private = &calldata->lr.ld_private; |
| 3279 | calldata->res.fattr = &calldata->fattr; | 3301 | calldata->res.fattr = &calldata->fattr; |
| @@ -5673,6 +5695,14 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) · 2393 unmodified lines | |||
| 5673 | case -NFS4ERR_STALE_STATEID: | 5695 | case -NFS4ERR_STALE_STATEID: |
| 5674 | task->tk_status = 0; | 5696 | task->tk_status = 0; |
| 5675 | break; | 5697 | break; |
| 5698 | case -NFS4ERR_ACCESS: | ||
| 5699 | if (data->args.bitmask) { | ||
| 5700 | data->args.bitmask = NULL; | ||
| 5701 | data->res.fattr = NULL; | ||
| 5702 | task->tk_status = 0; | ||
| 5703 | rpc_restart_call_prepare(task); | ||
| 5704 | return; | ||
| 5705 | } | ||
| 5676 | default: | 5706 | default: |
| 5677 | if (nfs4_async_handle_error(task, data->res.server, | 5707 | if (nfs4_async_handle_error(task, data->res.server, |
| 5678 | NULL, NULL) == -EAGAIN) { | 5708 | NULL, NULL) == -EAGAIN) { |
| @@ -5692,6 +5722,7 @@ static void nfs4_delegreturn_release(void *calldata) · 13 unmodified lines | |||
| 5692 | if (data->lr.roc) | 5722 | if (data->lr.roc) |
| 5693 | pnfs_roc_release(&data->lr.arg, &data->lr.res, | 5723 | pnfs_roc_release(&data->lr.arg, &data->lr.res, |
| 5694 | data->res.lr_ret); | 5724 | data->res.lr_ret); |
| 5725 | nfs_post_op_update_inode_force_wcc(inode, &data->fattr); | ||
| 5695 | nfs_iput_and_deactive(inode); | 5726 | nfs_iput_and_deactive(inode); |
| 5696 | } | 5727 | } |
| 5697 | kfree(calldata); | 5728 | kfree(calldata); |
| @@ -5780,10 +5811,6 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co · 82 unmodified lines | |||
| 5780 | if (status != 0) | 5811 | if (status != 0) |
| 5781 | goto out; | 5812 | goto out; |
| 5782 | status = data->rpc_status; | 5813 | status = data->rpc_status; |
| 5783 | if (status == 0) | ||
| 5784 | nfs_post_op_update_inode_force_wcc(inode, &data->fattr); | ||
| 5785 | else | ||
| 5786 | nfs_refresh_inode(inode, &data->fattr); | ||
| 5787 | out: | 5814 | out: |
| 5788 | rpc_put_task(task); | 5815 | rpc_put_task(task); |
| 5789 | return status; | 5816 | return status; |
| @@ -494,21 +494,18 @@ nfs4_alloc_state_owner(struct nfs_server *server, · 493 unmodified lines | |||
| 494 | } | 494 | } |
| 495 | 495 | ||
| 496 | static void | 496 | static void |
| 497 | nfs4_drop_state_owner(struct nfs4_state_owner *sp) | 497 | nfs4_reset_state_owner(struct nfs4_state_owner *sp) |
| 498 | { | 498 | { |
| 499 | struct rb_node *rb_node = &sp->so_server_node; | 499 | /* This state_owner is no longer usable, but must |
| 500 | 500 | * remain in place so that state recovery can find it | |
| 501 | if (!RB_EMPTY_NODE(rb_node)) { | 501 | * and the opens associated with it. |
| 502 | struct nfs_server *server = sp->so_server; | 502 | * It may also be used for new 'open' request to |
| 503 | struct nfs_client *clp = server->nfs_client; | 503 | * return a delegation to the server. |
| 504 | 504 | * So update the 'create_time' so that it looks like | |
| 505 | spin_lock(&clp->cl_lock); | 505 | * a new state_owner. This will cause the server to |
| 506 | if (!RB_EMPTY_NODE(rb_node)) { | 506 | * request an OPEN_CONFIRM to start a new sequence. |
| 507 | rb_erase(rb_node, &server->state_owners); | 507 | */ |
| 508 | RB_CLEAR_NODE(rb_node); | 508 | sp->so_seqid.create_time = ktime_get(); |
| 509 | } | ||
| 510 | spin_unlock(&clp->cl_lock); | ||
| 511 | } | ||
| 512 | } | 509 | } |
| 513 | 510 | ||
| 514 | static void nfs4_free_state_owner(struct nfs4_state_owner *sp) | 511 | static void nfs4_free_state_owner(struct nfs4_state_owner *sp) |
| @@ -797,21 +794,33 @@ void nfs4_close_sync(struct nfs4_state *state, fmode_t fmode) · 282 unmodified lines | |||
| 797 | 794 | ||
| 798 | /* | 795 | /* |
| 799 | * Search the state->lock_states for an existing lock_owner | 796 | * Search the state->lock_states for an existing lock_owner |
| 800 | * that is compatible with current->files | 797 | * that is compatible with either of the given owners. |
| 798 | * If the second is non-zero, then the first refers to a Posix-lock | ||
| 799 | * owner (current->files) and the second refers to a flock/OFD | ||
| 800 | * owner (struct file*). In that case, prefer a match for the first | ||
| 801 | * owner. | ||
| 802 | * If both sorts of locks are held on the one file we cannot know | ||
| 803 | * which stateid was intended to be used, so a "correct" choice cannot | ||
| 804 | * be made. Failing that, a "consistent" choice is preferable. The | ||
| 805 | * consistent choice we make is to prefer the first owner, that of a | ||
| 806 | * Posix lock. | ||
| 801 | */ | 807 | */ |
| 802 | static struct nfs4_lock_state * | 808 | static struct nfs4_lock_state * |
| 803 | __nfs4_find_lock_state(struct nfs4_state *state, | 809 | __nfs4_find_lock_state(struct nfs4_state *state, |
| 804 | fl_owner_t fl_owner, fl_owner_t fl_owner2) | 810 | fl_owner_t fl_owner, fl_owner_t fl_owner2) |
| 805 | { | 811 | { |
| 806 | struct nfs4_lock_state *pos; | 812 | struct nfs4_lock_state *pos, *ret = NULL; |
| 807 | list_for_each_entry(pos, &state->lock_states, ls_locks) { | 813 | list_for_each_entry(pos, &state->lock_states, ls_locks) { |
| 808 | if (pos->ls_owner != fl_owner && | 814 | if (pos->ls_owner == fl_owner) { |
| 809 | pos->ls_owner != fl_owner2) | 815 | ret = pos; |
| 810 | continue; | 816 | break; |
| 811 | atomic_inc(&pos->ls_count); | 817 | } |
| 812 | return pos; | 818 | if (pos->ls_owner == fl_owner2) |
| 819 | ret = pos; | ||
| 813 | } | 820 | } |
| 814 | return NULL; | 821 | if (ret) |
| 822 | atomic_inc(&ret->ls_count); | ||
| 823 | return ret; | ||
| 815 | } | 824 | } |
| 816 | 825 | ||
| 817 | /* | 826 | /* |
| @@ -1101,7 +1110,7 @@ void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid) · 283 unmodified lines | |||
| 1101 | 1110 | ||
| 1102 | sp = container_of(seqid->sequence, struct nfs4_state_owner, so_seqid); | 1111 | sp = container_of(seqid->sequence, struct nfs4_state_owner, so_seqid); |
| 1103 | if (status == -NFS4ERR_BAD_SEQID) | 1112 | if (status == -NFS4ERR_BAD_SEQID) |
| 1104 | nfs4_drop_state_owner(sp); | 1113 | nfs4_reset_state_owner(sp); |
| 1105 | if (!nfs4_has_session(sp->so_server->nfs_client)) | 1114 | if (!nfs4_has_session(sp->so_server->nfs_client)) |
| 1106 | nfs_increment_seqid(status, seqid); | 1115 | nfs_increment_seqid(status, seqid); |
| 1107 | } | 1116 | } |
| @@ -502,11 +502,13 @@ static int nfs4_stat_to_errno(int); · 501 unmodified lines | |||
| 502 | (compound_encode_hdr_maxsz + \ | 502 | (compound_encode_hdr_maxsz + \ |
| 503 | encode_sequence_maxsz + \ | 503 | encode_sequence_maxsz + \ |
| 504 | encode_putfh_maxsz + \ | 504 | encode_putfh_maxsz + \ |
| 505 | encode_layoutreturn_maxsz + \ | ||
| 505 | encode_open_downgrade_maxsz) | 506 | encode_open_downgrade_maxsz) |
| 506 | #define NFS4_dec_open_downgrade_sz \ | 507 | #define NFS4_dec_open_downgrade_sz \ |
| 507 | (compound_decode_hdr_maxsz + \ | 508 | (compound_decode_hdr_maxsz + \ |
| 508 | decode_sequence_maxsz + \ | 509 | decode_sequence_maxsz + \ |
| 509 | decode_putfh_maxsz + \ | 510 | decode_putfh_maxsz + \ |
| 511 | decode_layoutreturn_maxsz + \ | ||
| 510 | decode_open_downgrade_maxsz) | 512 | decode_open_downgrade_maxsz) |
| 511 | #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ | 513 | #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ |
| 512 | encode_sequence_maxsz + \ | 514 | encode_sequence_maxsz + \ |
| @@ -2277,9 +2279,9 @@ static void nfs4_xdr_enc_close(struct rpc_rqst *req, struct xdr_stream *xdr, · 1764 unmodified lines | |||
| 2277 | encode_putfh(xdr, args->fh, &hdr); | 2279 | encode_putfh(xdr, args->fh, &hdr); |
| 2278 | if (args->lr_args) | 2280 | if (args->lr_args) |
| 2279 | encode_layoutreturn(xdr, args->lr_args, &hdr); | 2281 | encode_layoutreturn(xdr, args->lr_args, &hdr); |
| 2280 | encode_close(xdr, args, &hdr); | ||
| 2281 | if (args->bitmask != NULL) | 2282 | if (args->bitmask != NULL) |
| 2282 | encode_getfattr(xdr, args->bitmask, &hdr); | 2283 | encode_getfattr(xdr, args->bitmask, &hdr); |
| 2284 | encode_close(xdr, args, &hdr); | ||
| 2283 | encode_nops(&hdr); | 2285 | encode_nops(&hdr); |
| 2284 | } | 2286 | } |
| 2285 | 2287 | ||
| @@ -2356,6 +2358,8 @@ static void nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, · 70 unmodified lines | |||
| 2356 | encode_compound_hdr(xdr, req, &hdr); | 2358 | encode_compound_hdr(xdr, req, &hdr); |
| 2357 | encode_sequence(xdr, &args->seq_args, &hdr); | 2359 | encode_sequence(xdr, &args->seq_args, &hdr); |
| 2358 | encode_putfh(xdr, args->fh, &hdr); | 2360 | encode_putfh(xdr, args->fh, &hdr); |
| 2361 | if (args->lr_args) | ||
| 2362 | encode_layoutreturn(xdr, args->lr_args, &hdr); | ||
| 2359 | encode_open_downgrade(xdr, args, &hdr); | 2363 | encode_open_downgrade(xdr, args, &hdr); |
| 2360 | encode_nops(&hdr); | 2364 | encode_nops(&hdr); |
| 2361 | } | 2365 | } |
| @@ -2701,7 +2705,8 @@ static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, · 339 unmodified lines | |||
| 2701 | encode_putfh(xdr, args->fhandle, &hdr); | 2705 | encode_putfh(xdr, args->fhandle, &hdr); |
| 2702 | if (args->lr_args) | 2706 | if (args->lr_args) |
| 2703 | encode_layoutreturn(xdr, args->lr_args, &hdr); | 2707 | encode_layoutreturn(xdr, args->lr_args, &hdr); |
| 2704 | encode_getfattr(xdr, args->bitmask, &hdr); | 2708 | if (args->bitmask) |
| 2709 | encode_getfattr(xdr, args->bitmask, &hdr); | ||
| 2705 | encode_delegreturn(xdr, args->stateid, &hdr); | 2710 | encode_delegreturn(xdr, args->stateid, &hdr); |
| 2706 | encode_nops(&hdr); | 2711 | encode_nops(&hdr); |
| 2707 | } | 2712 | } |
| @@ -6151,6 +6156,12 @@ static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, · 3443 unmodified lines | |||
| 6151 | status = decode_putfh(xdr); | 6156 | status = decode_putfh(xdr); |
| 6152 | if (status) | 6157 | if (status) |
| 6153 | goto out; | 6158 | goto out; |
| 6159 | if (res->lr_res) { | ||
| 6160 | status = decode_layoutreturn(xdr, res->lr_res); | ||
| 6161 | res->lr_ret = status; | ||
| 6162 | if (status) | ||
| 6163 | goto out; | ||
| 6164 | } | ||
| 6154 | status = decode_open_downgrade(xdr, res); | 6165 | status = decode_open_downgrade(xdr, res); |
| 6155 | out: | 6166 | out: |
| 6156 | return status; | 6167 | return status; |
| @@ -6484,16 +6495,12 @@ static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, struct xdr_stream *xdr, · 327 unmodified lines | |||
| 6484 | if (status) | 6495 | if (status) |
| 6485 | goto out; | 6496 | goto out; |
| 6486 | } | 6497 | } |
| 6498 | if (res->fattr != NULL) { | ||
| 6499 | status = decode_getfattr(xdr, res->fattr, res->server); | ||
| 6500 | if (status != 0) | ||
| 6501 | goto out; | ||
| 6502 | } | ||
| 6487 | status = decode_close(xdr, res); | 6503 | status = decode_close(xdr, res); |
| 6488 | if (status != 0) | ||
| 6489 | goto out; | ||
| 6490 | /* | ||
| 6491 | * Note: Server may do delete on close for this file | ||
| 6492 | * in which case the getattr call will fail with | ||
| 6493 | * an ESTALE error. Shouldn't be a problem, | ||
| 6494 | * though, since fattr->valid will remain unset. | ||
| 6495 | */ | ||
| 6496 | decode_getfattr(xdr, res->fattr, res->server); | ||
| 6497 | out: | 6504 | out: |
| 6498 | return status; | 6505 | return status; |
| 6499 | } | 6506 | } |
| @@ -6966,9 +6973,11 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, · 466 unmodified lines | |||
| 6966 | if (status) | 6973 | if (status) |
| 6967 | goto out; | 6974 | goto out; |
| 6968 | } | 6975 | } |
| 6969 | status = decode_getfattr(xdr, res->fattr, res->server); | 6976 | if (res->fattr) { |
| 6970 | if (status != 0) | 6977 | status = decode_getfattr(xdr, res->fattr, res->server); |
| 6971 | goto out; | 6978 | if (status != 0) |
| 6979 | goto out; | ||
| 6980 | } | ||
| 6972 | status = decode_delegreturn(xdr); | 6981 | status = decode_delegreturn(xdr); |
| 6973 | out: | 6982 | out: |
| 6974 | return status; | 6983 | return status; |
| @@ -1251,6 +1251,7 @@ bool pnfs_roc(struct inode *ino, · 1250 unmodified lines | |||
| 1251 | nfs4_stateid stateid; | 1251 | nfs4_stateid stateid; |
| 1252 | enum pnfs_iomode iomode = 0; | 1252 | enum pnfs_iomode iomode = 0; |
| 1253 | bool layoutreturn = false, roc = false; | 1253 | bool layoutreturn = false, roc = false; |
| 1254 | bool skip_read = false; | ||
| 1254 | 1255 | ||
| 1255 | if (!nfs_have_layout(ino)) | 1256 | if (!nfs_have_layout(ino)) |
| 1256 | return false; | 1257 | return false; |
| @@ -1270,18 +1271,27 @@ retry: · 13 unmodified lines | |||
| 1270 | } | 1271 | } |
| 1271 | 1272 | ||
| 1272 | /* no roc if we hold a delegation */ | 1273 | /* no roc if we hold a delegation */ |
| 1273 | if (nfs4_check_delegation(ino, FMODE_READ)) | 1274 | if (nfs4_check_delegation(ino, FMODE_READ)) { |
| 1274 | goto out_noroc; | 1275 | if (nfs4_check_delegation(ino, FMODE_WRITE)) |
| 1276 | goto out_noroc; | ||
| 1277 | skip_read = true; | ||
| 1278 | } | ||
| 1275 | 1279 | ||
| 1276 | list_for_each_entry(ctx, &nfsi->open_files, list) { | 1280 | list_for_each_entry(ctx, &nfsi->open_files, list) { |
| 1277 | state = ctx->state; | 1281 | state = ctx->state; |
| 1282 | if (state == NULL) | ||
| 1283 | continue; | ||
| 1278 | /* Don't return layout if there is open file state */ | 1284 | /* Don't return layout if there is open file state */ |
| 1279 | if (state != NULL && state->state != 0) | 1285 | if (state->state & FMODE_WRITE) |
| 1280 | goto out_noroc; | 1286 | goto out_noroc; |
| 1287 | if (state->state & FMODE_READ) | ||
| 1288 | skip_read = true; | ||
| 1281 | } | 1289 | } |
| 1282 | 1290 | ||
| 1283 | 1291 | ||
| 1284 | list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) { | 1292 | list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) { |
| 1293 | if (skip_read && lseg->pls_range.iomode == IOMODE_READ) | ||
| 1294 | continue; | ||
| 1285 | /* If we are sending layoutreturn, invalidate all valid lsegs */ | 1295 | /* If we are sending layoutreturn, invalidate all valid lsegs */ |
| 1286 | if (!test_and_clear_bit(NFS_LSEG_ROC, &lseg->pls_flags)) | 1296 | if (!test_and_clear_bit(NFS_LSEG_ROC, &lseg->pls_flags)) |
| 1287 | continue; | 1297 | continue; |
| @@ -340,10 +340,8 @@ extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); · 339 unmodified lines | |||
| 340 | extern void nfs_access_set_mask(struct nfs_access_entry *, u32); | 340 | extern void nfs_access_set_mask(struct nfs_access_entry *, u32); |
| 341 | extern int nfs_permission(struct inode *, int); | 341 | extern int nfs_permission(struct inode *, int); |
| 342 | extern int nfs_open(struct inode *, struct file *); | 342 | extern int nfs_open(struct inode *, struct file *); |
| 343 | extern int nfs_attribute_timeout(struct inode *inode); | ||
| 344 | extern int nfs_attribute_cache_expired(struct inode *inode); | 343 | extern int nfs_attribute_cache_expired(struct inode *inode); |
| 345 | extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); | 344 | extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); |
| 346 | extern int nfs_revalidate_inode_rcu(struct nfs_server *server, struct inode *inode); | ||
| 347 | extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); | 345 | extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); |
| 348 | extern bool nfs_mapping_need_revalidate_inode(struct inode *inode); | 346 | extern bool nfs_mapping_need_revalidate_inode(struct inode *inode); |
| 349 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); | 347 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); |