.. | .. |
---|
26 | 26 | struct cb_getattrargs *args = argp; |
---|
27 | 27 | struct cb_getattrres *res = resp; |
---|
28 | 28 | struct nfs_delegation *delegation; |
---|
29 | | - struct nfs_inode *nfsi; |
---|
30 | 29 | struct inode *inode; |
---|
31 | 30 | |
---|
32 | 31 | res->status = htonl(NFS4ERR_OP_NOT_IN_SESSION); |
---|
.. | .. |
---|
47 | 46 | -ntohl(res->status)); |
---|
48 | 47 | goto out; |
---|
49 | 48 | } |
---|
50 | | - nfsi = NFS_I(inode); |
---|
51 | 49 | rcu_read_lock(); |
---|
52 | | - delegation = rcu_dereference(nfsi->delegation); |
---|
| 50 | + delegation = nfs4_get_valid_delegation(inode); |
---|
53 | 51 | if (delegation == NULL || (delegation->type & FMODE_WRITE) == 0) |
---|
54 | 52 | goto out_iput; |
---|
55 | 53 | res->size = i_size_read(inode); |
---|
56 | 54 | res->change_attr = delegation->change_attr; |
---|
57 | 55 | if (nfs_have_writebacks(inode)) |
---|
58 | 56 | res->change_attr++; |
---|
59 | | - res->ctime = timespec64_to_timespec(inode->i_ctime); |
---|
60 | | - res->mtime = timespec64_to_timespec(inode->i_mtime); |
---|
| 57 | + res->ctime = inode->i_ctime; |
---|
| 58 | + res->mtime = inode->i_mtime; |
---|
61 | 59 | res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) & |
---|
62 | 60 | args->bitmap[0]; |
---|
63 | 61 | res->bitmap[1] = (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) & |
---|
.. | .. |
---|
123 | 121 | */ |
---|
124 | 122 | static struct inode *nfs_layout_find_inode_by_stateid(struct nfs_client *clp, |
---|
125 | 123 | const nfs4_stateid *stateid) |
---|
| 124 | + __must_hold(RCU) |
---|
126 | 125 | { |
---|
127 | 126 | struct nfs_server *server; |
---|
128 | 127 | struct inode *inode; |
---|
129 | 128 | struct pnfs_layout_hdr *lo; |
---|
130 | 129 | |
---|
| 130 | + rcu_read_lock(); |
---|
131 | 131 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { |
---|
132 | | - list_for_each_entry(lo, &server->layouts, plh_layouts) { |
---|
| 132 | + list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) { |
---|
133 | 133 | if (!pnfs_layout_is_valid(lo)) |
---|
134 | 134 | continue; |
---|
135 | | - if (stateid != NULL && |
---|
136 | | - !nfs4_stateid_match_other(stateid, &lo->plh_stateid)) |
---|
| 135 | + if (!nfs4_stateid_match_other(stateid, &lo->plh_stateid)) |
---|
137 | 136 | continue; |
---|
138 | | - inode = igrab(lo->plh_inode); |
---|
139 | | - if (!inode) |
---|
140 | | - return ERR_PTR(-EAGAIN); |
---|
141 | | - if (!nfs_sb_active(inode->i_sb)) { |
---|
142 | | - rcu_read_unlock(); |
---|
143 | | - spin_unlock(&clp->cl_lock); |
---|
144 | | - iput(inode); |
---|
145 | | - spin_lock(&clp->cl_lock); |
---|
146 | | - rcu_read_lock(); |
---|
147 | | - return ERR_PTR(-EAGAIN); |
---|
148 | | - } |
---|
149 | | - return inode; |
---|
| 137 | + if (nfs_sb_active(server->super)) |
---|
| 138 | + inode = igrab(lo->plh_inode); |
---|
| 139 | + else |
---|
| 140 | + inode = ERR_PTR(-EAGAIN); |
---|
| 141 | + rcu_read_unlock(); |
---|
| 142 | + if (inode) |
---|
| 143 | + return inode; |
---|
| 144 | + nfs_sb_deactive(server->super); |
---|
| 145 | + return ERR_PTR(-EAGAIN); |
---|
150 | 146 | } |
---|
151 | 147 | } |
---|
152 | | - |
---|
| 148 | + rcu_read_unlock(); |
---|
153 | 149 | return ERR_PTR(-ENOENT); |
---|
154 | 150 | } |
---|
155 | 151 | |
---|
.. | .. |
---|
167 | 163 | struct inode *inode; |
---|
168 | 164 | struct pnfs_layout_hdr *lo; |
---|
169 | 165 | |
---|
| 166 | + rcu_read_lock(); |
---|
170 | 167 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { |
---|
171 | | - list_for_each_entry(lo, &server->layouts, plh_layouts) { |
---|
| 168 | + list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) { |
---|
172 | 169 | nfsi = NFS_I(lo->plh_inode); |
---|
173 | 170 | if (nfs_compare_fh(fh, &nfsi->fh)) |
---|
174 | 171 | continue; |
---|
175 | 172 | if (nfsi->layout != lo) |
---|
176 | 173 | continue; |
---|
177 | | - inode = igrab(lo->plh_inode); |
---|
178 | | - if (!inode) |
---|
179 | | - return ERR_PTR(-EAGAIN); |
---|
180 | | - if (!nfs_sb_active(inode->i_sb)) { |
---|
181 | | - rcu_read_unlock(); |
---|
182 | | - spin_unlock(&clp->cl_lock); |
---|
183 | | - iput(inode); |
---|
184 | | - spin_lock(&clp->cl_lock); |
---|
185 | | - rcu_read_lock(); |
---|
186 | | - return ERR_PTR(-EAGAIN); |
---|
187 | | - } |
---|
188 | | - return inode; |
---|
| 174 | + if (nfs_sb_active(server->super)) |
---|
| 175 | + inode = igrab(lo->plh_inode); |
---|
| 176 | + else |
---|
| 177 | + inode = ERR_PTR(-EAGAIN); |
---|
| 178 | + rcu_read_unlock(); |
---|
| 179 | + if (inode) |
---|
| 180 | + return inode; |
---|
| 181 | + nfs_sb_deactive(server->super); |
---|
| 182 | + return ERR_PTR(-EAGAIN); |
---|
189 | 183 | } |
---|
190 | 184 | } |
---|
191 | | - |
---|
| 185 | + rcu_read_unlock(); |
---|
192 | 186 | return ERR_PTR(-ENOENT); |
---|
193 | 187 | } |
---|
194 | 188 | |
---|
.. | .. |
---|
198 | 192 | { |
---|
199 | 193 | struct inode *inode; |
---|
200 | 194 | |
---|
201 | | - spin_lock(&clp->cl_lock); |
---|
202 | | - rcu_read_lock(); |
---|
203 | 195 | inode = nfs_layout_find_inode_by_stateid(clp, stateid); |
---|
204 | 196 | if (inode == ERR_PTR(-ENOENT)) |
---|
205 | 197 | inode = nfs_layout_find_inode_by_fh(clp, fh); |
---|
206 | | - rcu_read_unlock(); |
---|
207 | | - spin_unlock(&clp->cl_lock); |
---|
208 | | - |
---|
209 | 198 | return inode; |
---|
210 | 199 | } |
---|
211 | 200 | |
---|
.. | .. |
---|
284 | 273 | goto unlock; |
---|
285 | 274 | } |
---|
286 | 275 | |
---|
287 | | - pnfs_set_layout_stateid(lo, &args->cbl_stateid, true); |
---|
| 276 | + pnfs_set_layout_stateid(lo, &args->cbl_stateid, NULL, true); |
---|
288 | 277 | switch (pnfs_mark_matching_lsegs_return(lo, &free_me_list, |
---|
289 | 278 | &args->cbl_range, |
---|
290 | 279 | be32_to_cpu(args->cbl_stateid.seqid))) { |
---|
.. | .. |
---|
294 | 283 | rv = NFS4_OK; |
---|
295 | 284 | break; |
---|
296 | 285 | case -ENOENT: |
---|
| 286 | + set_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags); |
---|
297 | 287 | /* Embrace your forgetfulness! */ |
---|
298 | 288 | rv = NFS4ERR_NOMATCHING_LAYOUT; |
---|
299 | 289 | |
---|
.. | .. |
---|
364 | 354 | struct cb_process_state *cps) |
---|
365 | 355 | { |
---|
366 | 356 | struct cb_devicenotifyargs *args = argp; |
---|
| 357 | + const struct pnfs_layoutdriver_type *ld = NULL; |
---|
367 | 358 | uint32_t i; |
---|
368 | 359 | __be32 res = 0; |
---|
369 | | - struct nfs_client *clp = cps->clp; |
---|
370 | | - struct nfs_server *server = NULL; |
---|
371 | 360 | |
---|
372 | | - if (!clp) { |
---|
| 361 | + if (!cps->clp) { |
---|
373 | 362 | res = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION); |
---|
374 | 363 | goto out; |
---|
375 | 364 | } |
---|
.. | .. |
---|
377 | 366 | for (i = 0; i < args->ndevs; i++) { |
---|
378 | 367 | struct cb_devicenotifyitem *dev = &args->devs[i]; |
---|
379 | 368 | |
---|
380 | | - if (!server || |
---|
381 | | - server->pnfs_curr_ld->id != dev->cbd_layout_type) { |
---|
382 | | - rcu_read_lock(); |
---|
383 | | - list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) |
---|
384 | | - if (server->pnfs_curr_ld && |
---|
385 | | - server->pnfs_curr_ld->id == dev->cbd_layout_type) { |
---|
386 | | - rcu_read_unlock(); |
---|
387 | | - goto found; |
---|
388 | | - } |
---|
389 | | - rcu_read_unlock(); |
---|
390 | | - continue; |
---|
| 369 | + if (!ld || ld->id != dev->cbd_layout_type) { |
---|
| 370 | + pnfs_put_layoutdriver(ld); |
---|
| 371 | + ld = pnfs_find_layoutdriver(dev->cbd_layout_type); |
---|
| 372 | + if (!ld) |
---|
| 373 | + continue; |
---|
391 | 374 | } |
---|
392 | | - |
---|
393 | | - found: |
---|
394 | | - nfs4_delete_deviceid(server->pnfs_curr_ld, clp, &dev->cbd_dev_id); |
---|
| 375 | + nfs4_delete_deviceid(ld, cps->clp, &dev->cbd_dev_id); |
---|
395 | 376 | } |
---|
396 | | - |
---|
| 377 | + pnfs_put_layoutdriver(ld); |
---|
397 | 378 | out: |
---|
398 | 379 | kfree(args->devs); |
---|
399 | 380 | return res; |
---|
.. | .. |
---|
416 | 397 | validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot, |
---|
417 | 398 | const struct cb_sequenceargs * args) |
---|
418 | 399 | { |
---|
| 400 | + __be32 ret; |
---|
| 401 | + |
---|
| 402 | + ret = cpu_to_be32(NFS4ERR_BADSLOT); |
---|
419 | 403 | if (args->csa_slotid > tbl->server_highest_slotid) |
---|
420 | | - return htonl(NFS4ERR_BADSLOT); |
---|
| 404 | + goto out_err; |
---|
421 | 405 | |
---|
422 | 406 | /* Replay */ |
---|
423 | 407 | if (args->csa_sequenceid == slot->seq_nr) { |
---|
| 408 | + ret = cpu_to_be32(NFS4ERR_DELAY); |
---|
424 | 409 | if (nfs4_test_locked_slot(tbl, slot->slot_nr)) |
---|
425 | | - return htonl(NFS4ERR_DELAY); |
---|
| 410 | + goto out_err; |
---|
| 411 | + |
---|
426 | 412 | /* Signal process_op to set this error on next op */ |
---|
| 413 | + ret = cpu_to_be32(NFS4ERR_RETRY_UNCACHED_REP); |
---|
427 | 414 | if (args->csa_cachethis == 0) |
---|
428 | | - return htonl(NFS4ERR_RETRY_UNCACHED_REP); |
---|
| 415 | + goto out_err; |
---|
429 | 416 | |
---|
430 | 417 | /* Liar! We never allowed you to set csa_cachethis != 0 */ |
---|
431 | | - return htonl(NFS4ERR_SEQ_FALSE_RETRY); |
---|
| 418 | + ret = cpu_to_be32(NFS4ERR_SEQ_FALSE_RETRY); |
---|
| 419 | + goto out_err; |
---|
432 | 420 | } |
---|
433 | 421 | |
---|
434 | 422 | /* Note: wraparound relies on seq_nr being of type u32 */ |
---|
435 | | - if (likely(args->csa_sequenceid == slot->seq_nr + 1)) |
---|
436 | | - return htonl(NFS4_OK); |
---|
437 | | - |
---|
438 | 423 | /* Misordered request */ |
---|
439 | | - return htonl(NFS4ERR_SEQ_MISORDERED); |
---|
| 424 | + ret = cpu_to_be32(NFS4ERR_SEQ_MISORDERED); |
---|
| 425 | + if (args->csa_sequenceid != slot->seq_nr + 1) |
---|
| 426 | + goto out_err; |
---|
| 427 | + |
---|
| 428 | + return cpu_to_be32(NFS4_OK); |
---|
| 429 | + |
---|
| 430 | +out_err: |
---|
| 431 | + trace_nfs4_cb_seqid_err(args, ret); |
---|
| 432 | + return ret; |
---|
440 | 433 | } |
---|
441 | 434 | |
---|
442 | 435 | /* |
---|
.. | .. |
---|
597 | 590 | struct cb_recallanyargs *args = argp; |
---|
598 | 591 | __be32 status; |
---|
599 | 592 | fmode_t flags = 0; |
---|
| 593 | + bool schedule_manager = false; |
---|
600 | 594 | |
---|
601 | 595 | status = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION); |
---|
602 | 596 | if (!cps->clp) /* set in cb_sequence */ |
---|
.. | .. |
---|
619 | 613 | |
---|
620 | 614 | if (args->craa_type_mask & BIT(RCA4_TYPE_MASK_FILE_LAYOUT)) |
---|
621 | 615 | pnfs_recall_all_layouts(cps->clp); |
---|
| 616 | + |
---|
| 617 | + if (args->craa_type_mask & BIT(PNFS_FF_RCA4_TYPE_MASK_READ)) { |
---|
| 618 | + set_bit(NFS4CLNT_RECALL_ANY_LAYOUT_READ, &cps->clp->cl_state); |
---|
| 619 | + schedule_manager = true; |
---|
| 620 | + } |
---|
| 621 | + if (args->craa_type_mask & BIT(PNFS_FF_RCA4_TYPE_MASK_RW)) { |
---|
| 622 | + set_bit(NFS4CLNT_RECALL_ANY_LAYOUT_RW, &cps->clp->cl_state); |
---|
| 623 | + schedule_manager = true; |
---|
| 624 | + } |
---|
| 625 | + if (schedule_manager) |
---|
| 626 | + nfs4_schedule_state_manager(cps->clp); |
---|
| 627 | + |
---|
622 | 628 | out: |
---|
623 | 629 | dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); |
---|
624 | 630 | return status; |
---|