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 | 1274 | static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags) |
| 1275 | 1275 | { |
| 1276 | − int error; | |
| 1277 | 1276 | struct inode *inode = d_inode(dentry); |
| 1277 | + int error = 0; | |
| 1278 | 1278 | |
| 1279 | 1279 | /* |
| 1280 | 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 | 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 | 1298 | dfprintk(LOOKUPCACHE, "NFS: %s: inode %lu is %s\n", |
| 1298 | 1299 | __func__, inode->i_ino, error ? "invalid" : "valid"); |
| 1299 | 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 | 2286 | if (cache == NULL) |
| 2286 | 2287 | goto out; |
| 2287 | 2288 | /* Found an entry, is our attribute cache valid? */ |
| 2288 | − if (!nfs_attribute_cache_expired(inode) && | |
| 2289 | − !(nfsi->cache_validity & NFS_INO_INVALID_ATTR)) | |
| 2289 | + if (!nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS)) | |
| 2290 | 2290 | break; |
| 2291 | 2291 | err = -ECHILD; |
| 2292 | 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 | 2334 | cache = NULL; |
| 2335 | 2335 | if (cache == NULL) |
| 2336 | 2336 | goto out; |
| 2337 | − err = nfs_revalidate_inode_rcu(NFS_SERVER(inode), inode); | |
| 2338 | − if (err) | |
| 2337 | + if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS)) | |
| 2339 | 2338 | goto out; |
| 2340 | 2339 | res->jiffies = cache->jiffies; |
| 2341 | 2340 | res->cred = cache->cred; |
| 2342 | 2341 | res->mask = cache->mask; |
| 2342 | + err = 0; | |
| 2343 | 2343 | out: |
| 2344 | 2344 | rcu_read_unlock(); |
| 2345 | 2345 | return err; |
| @@ -2491,12 +2491,13 @@ EXPORT_SYMBOL_GPL(nfs_may_open); · 145 unmodified lines | ||
| 2491 | 2491 | static int nfs_execute_ok(struct inode *inode, int mask) |
| 2492 | 2492 | { |
| 2493 | 2493 | struct nfs_server *server = NFS_SERVER(inode); |
| 2494 | − int ret; | |
| 2494 | + int ret = 0; | |
| 2495 | 2495 | |
| 2496 | − if (mask & MAY_NOT_BLOCK) | |
| 2497 | − ret = nfs_revalidate_inode_rcu(server, inode); | |
| 2498 | − else | |
| 2499 | − ret = nfs_revalidate_inode(server, inode); | |
| 2496 | + if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS)) { | |
| 2497 | + if (mask & MAY_NOT_BLOCK) | |
| 2498 | + return -ECHILD; | |
| 2499 | + ret = __nfs_revalidate_inode(server, inode); | |
| 2500 | + } | |
| 2500 | 2501 | if (ret == 0 && !execute_ok(inode)) |
| 2501 | 2502 | ret = -EACCES; |
| 2502 | 2503 | return ret; |
| @@ -101,21 +101,11 @@ EXPORT_SYMBOL_GPL(nfs_file_release); · 100 unmodified lines | ||
| 101 | 101 | static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) |
| 102 | 102 | { |
| 103 | 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 | 105 | if (filp->f_flags & O_DIRECT) |
| 113 | 106 | goto force_reval; |
| 114 | − if (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) | |
| 115 | − goto force_reval; | |
| 116 | − if (nfs_attribute_timeout(inode)) | |
| 107 | + if (nfs_check_cache_invalid(inode, NFS_INO_REVAL_PAGECACHE)) | |
| 117 | 108 | goto force_reval; |
| 118 | −out_noreval: | |
| 119 | 109 | return 0; |
| 120 | 110 | force_reval: |
| 121 | 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 | 282 | s->nfs_client->cl_minorversion); |
| 283 | 283 | |
| 284 | 284 | out_test_devid: |
| 285 | − if (filelayout_test_devid_unavailable(devid)) | |
| 285 | + if (ret->ds_clp == NULL || | |
| 286 | + filelayout_test_devid_unavailable(devid)) | |
| 286 | 287 | ret = NULL; |
| 287 | 288 | out: |
| 288 | 289 | return ret; |
| @@ -1126,7 +1126,8 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task, · 1125 unmodified lines | ||
| 1126 | 1126 | case -EPIPE: |
| 1127 | 1127 | dprintk("%s DS connection error %d\n", __func__, |
| 1128 | 1128 | task->tk_status); |
| 1129 | − nfs4_mark_deviceid_unavailable(devid); | |
| 1129 | + nfs4_delete_deviceid(devid->ld, devid->nfs_client, | |
| 1130 | + &devid->deviceid); | |
| 1130 | 1131 | rpc_wake_up(&tbl->slot_tbl_waitq); |
| 1131 | 1132 | /* fall through */ |
| 1132 | 1133 | default: |
| @@ -1175,7 +1176,8 @@ static int ff_layout_async_handle_error_v3(struct rpc_task *task, · 42 unmodified lines | ||
| 1175 | 1176 | default: |
| 1176 | 1177 | dprintk("%s DS connection error %d\n", __func__, |
| 1177 | 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 | 1182 | /* FIXME: Need to prevent infinite looping here. */ |
| 1181 | 1183 | return -NFS4ERR_RESET_TO_PNFS; |
| @@ -177,7 +177,7 @@ out_err: · 176 unmodified lines | ||
| 177 | 177 | static void ff_layout_mark_devid_invalid(struct pnfs_layout_segment *lseg, |
| 178 | 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 | 181 | if (!ff_layout_has_available_ds(lseg)) |
| 182 | 182 | pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode, |
| 183 | 183 | lseg); |
| @@ -160,6 +160,43 @@ int nfs_sync_mapping(struct address_space *mapping) · 159 unmodified lines | ||
| 160 | 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 | 200 | static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags) |
| 164 | 201 | { |
| 165 | 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 | 832 | if (!is_sync) |
| 796 | 833 | return; |
| 797 | 834 | inode = d_inode(ctx->dentry); |
| 835 | + if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ)) | |
| 836 | + return; | |
| 798 | 837 | nfsi = NFS_I(inode); |
| 799 | 838 | if (inode->i_mapping->nrpages == 0) |
| 800 | 839 | return; |
| @@ -1044,13 +1083,6 @@ out: · 243 unmodified lines | ||
| 1044 | 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 | 1086 | int nfs_attribute_cache_expired(struct inode *inode) |
| 1055 | 1087 | { |
| 1056 | 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 | 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 | 1108 | static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping) |
| 1086 | 1109 | { |
| 1087 | 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 | 1138 | bool nfs_mapping_need_revalidate_inode(struct inode *inode) |
| 1116 | 1139 | { |
| 1117 | − unsigned long cache_validity = NFS_I(inode)->cache_validity; | |
| 1118 | − | |
| 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); | |
| 1140 | + return nfs_check_cache_invalid(inode, NFS_INO_REVAL_PAGECACHE) || | |
| 1141 | + NFS_STALE(inode); | |
| 1128 | 1142 | } |
| 1129 | 1143 | |
| 1130 | 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 | 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 | 1553 | if (S_ISDIR(inode->i_mode)) |
| 1547 | 1554 | invalid |= NFS_INO_INVALID_DATA; |
| 1548 | 1555 | nfs_set_cache_invalid(inode, invalid); |
| @@ -381,6 +381,7 @@ extern int nfs_drop_inode(struct inode *); · 380 unmodified lines | ||
| 381 | 381 | extern void nfs_clear_inode(struct inode *); |
| 382 | 382 | extern void nfs_evict_inode(struct inode *); |
| 383 | 383 | void nfs_zap_acl_cache(struct inode *inode); |
| 384 | +extern bool nfs_check_cache_invalid(struct inode *, unsigned long); | |
| 384 | 385 | extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode); |
| 385 | 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 | 1090 | spin_lock(&dir->i_lock); |
| 1091 | 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 | 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 | 1101 | dir->i_version = cinfo->after; |
| 1095 | 1102 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); |
| 1096 | 1103 | nfs_fscache_invalidate(dir); |
| @@ -3115,6 +3122,16 @@ static void nfs4_close_done(struct rpc_task *task, void *data) · 2018 unmodified lines | ||
| 3115 | 3122 | res_stateid = &calldata->res.stateid; |
| 3116 | 3123 | renew_lease(server, calldata->timestamp); |
| 3117 | 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 | 3135 | case -NFS4ERR_ADMIN_REVOKED: |
| 3119 | 3136 | case -NFS4ERR_STALE_STATEID: |
| 3120 | 3137 | case -NFS4ERR_EXPIRED: |
| @@ -3140,7 +3157,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) · 19 unmodified lines | ||
| 3140 | 3157 | res_stateid, calldata->arg.fmode); |
| 3141 | 3158 | out_release: |
| 3142 | 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 | 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 | 3210 | goto out_wait; |
| 3194 | 3211 | } |
| 3195 | 3212 | |
| 3196 | − if (calldata->arg.fmode == 0) { | |
| 3213 | + if (calldata->arg.fmode == 0) | |
| 3197 | 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 | 3217 | /* Close-to-open cache consistency revalidation */ |
| 3200 | 3218 | if (!nfs4_have_delegation(inode, FMODE_READ)) |
| 3201 | 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 | 3225 | nfs4_map_atomic_open_share(NFS_SERVER(inode), |
| 3208 | 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 | 3232 | calldata->timestamp = jiffies; |
| 3212 | 3233 | if (nfs4_setup_sequence(NFS_SERVER(inode), |
| 3213 | 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 | 3295 | calldata->arg.seqid = alloc_seqid(&state->owner->so_seqid, gfp_mask); |
| 3275 | 3296 | if (IS_ERR(calldata->arg.seqid)) |
| 3276 | 3297 | goto out_free_calldata; |
| 3298 | + nfs_fattr_init(&calldata->fattr); | |
| 3277 | 3299 | calldata->arg.fmode = 0; |
| 3278 | 3300 | calldata->lr.arg.ld_private = &calldata->lr.ld_private; |
| 3279 | 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 | 5695 | case -NFS4ERR_STALE_STATEID: |
| 5674 | 5696 | task->tk_status = 0; |
| 5675 | 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 | 5706 | default: |
| 5677 | 5707 | if (nfs4_async_handle_error(task, data->res.server, |
| 5678 | 5708 | NULL, NULL) == -EAGAIN) { |
| @@ -5692,6 +5722,7 @@ static void nfs4_delegreturn_release(void *calldata) · 13 unmodified lines | ||
| 5692 | 5722 | if (data->lr.roc) |
| 5693 | 5723 | pnfs_roc_release(&data->lr.arg, &data->lr.res, |
| 5694 | 5724 | data->res.lr_ret); |
| 5725 | + nfs_post_op_update_inode_force_wcc(inode, &data->fattr); | |
| 5695 | 5726 | nfs_iput_and_deactive(inode); |
| 5696 | 5727 | } |
| 5697 | 5728 | kfree(calldata); |
| @@ -5780,10 +5811,6 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co · 82 unmodified lines | ||
| 5780 | 5811 | if (status != 0) |
| 5781 | 5812 | goto out; |
| 5782 | 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 | 5814 | out: |
| 5788 | 5815 | rpc_put_task(task); |
| 5789 | 5816 | return status; |
| @@ -494,21 +494,18 @@ nfs4_alloc_state_owner(struct nfs_server *server, · 493 unmodified lines | ||
| 494 | 494 | } |
| 495 | 495 | |
| 496 | 496 | static void |
| 497 | −nfs4_drop_state_owner(struct nfs4_state_owner *sp) | |
| 498 | −{ | |
| 499 | − struct rb_node *rb_node = &sp->so_server_node; | |
| 500 | − | |
| 501 | − if (!RB_EMPTY_NODE(rb_node)) { | |
| 502 | − struct nfs_server *server = sp->so_server; | |
| 503 | − struct nfs_client *clp = server->nfs_client; | |
| 504 | − | |
| 505 | − spin_lock(&clp->cl_lock); | |
| 506 | − if (!RB_EMPTY_NODE(rb_node)) { | |
| 507 | − rb_erase(rb_node, &server->state_owners); | |
| 508 | − RB_CLEAR_NODE(rb_node); | |
| 509 | − } | |
| 510 | − spin_unlock(&clp->cl_lock); | |
| 511 | − } | |
| 497 | +nfs4_reset_state_owner(struct nfs4_state_owner *sp) | |
| 498 | +{ | |
| 499 | + /* This state_owner is no longer usable, but must | |
| 500 | + * remain in place so that state recovery can find it | |
| 501 | + * and the opens associated with it. | |
| 502 | + * It may also be used for new 'open' request to | |
| 503 | + * return a delegation to the server. | |
| 504 | + * So update the 'create_time' so that it looks like | |
| 505 | + * a new state_owner. This will cause the server to | |
| 506 | + * request an OPEN_CONFIRM to start a new sequence. | |
| 507 | + */ | |
| 508 | + sp->so_seqid.create_time = ktime_get(); | |
| 512 | 509 | } |
| 513 | 510 | |
| 514 | 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 | 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 | 808 | static struct nfs4_lock_state * |
| 803 | 809 | __nfs4_find_lock_state(struct nfs4_state *state, |
| 804 | 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 | 813 | list_for_each_entry(pos, &state->lock_states, ls_locks) { |
| 808 | − if (pos->ls_owner != fl_owner && | |
| 809 | − pos->ls_owner != fl_owner2) | |
| 810 | − continue; | |
| 811 | − atomic_inc(&pos->ls_count); | |
| 812 | − return pos; | |
| 814 | + if (pos->ls_owner == fl_owner) { | |
| 815 | + ret = pos; | |
| 816 | + break; | |
| 817 | + } | |
| 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 | 1111 | sp = container_of(seqid->sequence, struct nfs4_state_owner, so_seqid); |
| 1103 | 1112 | if (status == -NFS4ERR_BAD_SEQID) |
| 1104 | − nfs4_drop_state_owner(sp); | |
| 1113 | + nfs4_reset_state_owner(sp); | |
| 1105 | 1114 | if (!nfs4_has_session(sp->so_server->nfs_client)) |
| 1106 | 1115 | nfs_increment_seqid(status, seqid); |
| 1107 | 1116 | } |
| @@ -502,11 +502,13 @@ static int nfs4_stat_to_errno(int); · 501 unmodified lines | ||
| 502 | 502 | (compound_encode_hdr_maxsz + \ |
| 503 | 503 | encode_sequence_maxsz + \ |
| 504 | 504 | encode_putfh_maxsz + \ |
| 505 | + encode_layoutreturn_maxsz + \ | |
| 505 | 506 | encode_open_downgrade_maxsz) |
| 506 | 507 | #define NFS4_dec_open_downgrade_sz \ |
| 507 | 508 | (compound_decode_hdr_maxsz + \ |
| 508 | 509 | decode_sequence_maxsz + \ |
| 509 | 510 | decode_putfh_maxsz + \ |
| 511 | + decode_layoutreturn_maxsz + \ | |
| 510 | 512 | decode_open_downgrade_maxsz) |
| 511 | 513 | #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ |
| 512 | 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 | 2279 | encode_putfh(xdr, args->fh, &hdr); |
| 2278 | 2280 | if (args->lr_args) |
| 2279 | 2281 | encode_layoutreturn(xdr, args->lr_args, &hdr); |
| 2280 | − encode_close(xdr, args, &hdr); | |
| 2281 | 2282 | if (args->bitmask != NULL) |
| 2282 | 2283 | encode_getfattr(xdr, args->bitmask, &hdr); |
| 2284 | + encode_close(xdr, args, &hdr); | |
| 2283 | 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 | 2358 | encode_compound_hdr(xdr, req, &hdr); |
| 2357 | 2359 | encode_sequence(xdr, &args->seq_args, &hdr); |
| 2358 | 2360 | encode_putfh(xdr, args->fh, &hdr); |
| 2361 | + if (args->lr_args) | |
| 2362 | + encode_layoutreturn(xdr, args->lr_args, &hdr); | |
| 2359 | 2363 | encode_open_downgrade(xdr, args, &hdr); |
| 2360 | 2364 | encode_nops(&hdr); |
| 2361 | 2365 | } |
| @@ -2701,7 +2705,8 @@ static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, · 339 unmodified lines | ||
| 2701 | 2705 | encode_putfh(xdr, args->fhandle, &hdr); |
| 2702 | 2706 | if (args->lr_args) |
| 2703 | 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 | 2710 | encode_delegreturn(xdr, args->stateid, &hdr); |
| 2706 | 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 | 6156 | status = decode_putfh(xdr); |
| 6152 | 6157 | if (status) |
| 6153 | 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 | 6165 | status = decode_open_downgrade(xdr, res); |
| 6155 | 6166 | out: |
| 6156 | 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 | 6495 | if (status) |
| 6485 | 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 | 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 | 6504 | out: |
| 6498 | 6505 | return status; |
| 6499 | 6506 | } |
| @@ -6966,9 +6973,11 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, · 466 unmodified lines | ||
| 6966 | 6973 | if (status) |
| 6967 | 6974 | goto out; |
| 6968 | 6975 | } |
| 6969 | − status = decode_getfattr(xdr, res->fattr, res->server); | |
| 6970 | − if (status != 0) | |
| 6971 | − goto out; | |
| 6976 | + if (res->fattr) { | |
| 6977 | + status = decode_getfattr(xdr, res->fattr, res->server); | |
| 6978 | + if (status != 0) | |
| 6979 | + goto out; | |
| 6980 | + } | |
| 6972 | 6981 | status = decode_delegreturn(xdr); |
| 6973 | 6982 | out: |
| 6974 | 6983 | return status; |
| @@ -1251,6 +1251,7 @@ bool pnfs_roc(struct inode *ino, · 1250 unmodified lines | ||
| 1251 | 1251 | nfs4_stateid stateid; |
| 1252 | 1252 | enum pnfs_iomode iomode = 0; |
| 1253 | 1253 | bool layoutreturn = false, roc = false; |
| 1254 | + bool skip_read = false; | |
| 1254 | 1255 | |
| 1255 | 1256 | if (!nfs_have_layout(ino)) |
| 1256 | 1257 | return false; |
| @@ -1270,18 +1271,27 @@ retry: · 13 unmodified lines | ||
| 1270 | 1271 | } |
| 1271 | 1272 | |
| 1272 | 1273 | /* no roc if we hold a delegation */ |
| 1273 | − if (nfs4_check_delegation(ino, FMODE_READ)) | |
| 1274 | − goto out_noroc; | |
| 1274 | + if (nfs4_check_delegation(ino, FMODE_READ)) { | |
| 1275 | + if (nfs4_check_delegation(ino, FMODE_WRITE)) | |
| 1276 | + goto out_noroc; | |
| 1277 | + skip_read = true; | |
| 1278 | + } | |
| 1275 | 1279 | |
| 1276 | 1280 | list_for_each_entry(ctx, &nfsi->open_files, list) { |
| 1277 | 1281 | state = ctx->state; |
| 1282 | + if (state == NULL) | |
| 1283 | + continue; | |
| 1278 | 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 | 1286 | goto out_noroc; |
| 1287 | + if (state->state & FMODE_READ) | |
| 1288 | + skip_read = true; | |
| 1281 | 1289 | } |
| 1282 | 1290 | |
| 1283 | 1291 | |
| 1284 | 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 | 1295 | /* If we are sending layoutreturn, invalidate all valid lsegs */ |
| 1286 | 1296 | if (!test_and_clear_bit(NFS_LSEG_ROC, &lseg->pls_flags)) |
| 1287 | 1297 | continue; |
| @@ -340,10 +340,8 @@ extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); · 339 unmodified lines | ||
| 340 | 340 | extern void nfs_access_set_mask(struct nfs_access_entry *, u32); |
| 341 | 341 | extern int nfs_permission(struct inode *, int); |
| 342 | 342 | extern int nfs_open(struct inode *, struct file *); |
| 343 | −extern int nfs_attribute_timeout(struct inode *inode); | |
| 344 | 343 | extern int nfs_attribute_cache_expired(struct inode *inode); |
| 345 | 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 | 345 | extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); |
| 348 | 346 | extern bool nfs_mapping_need_revalidate_inode(struct inode *inode); |
| 349 | 347 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); |