diff options
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index bf4186b8f2fc..bc4089769735 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -256,6 +256,7 @@ put_lseg_locked(struct pnfs_layout_segment *lseg, | |||
256 | spin_unlock(&clp->cl_lock); | 256 | spin_unlock(&clp->cl_lock); |
257 | clear_bit(NFS_LAYOUT_BULK_RECALL, &lseg->pls_layout->plh_flags); | 257 | clear_bit(NFS_LAYOUT_BULK_RECALL, &lseg->pls_layout->plh_flags); |
258 | } | 258 | } |
259 | rpc_wake_up(&NFS_SERVER(ino)->roc_rpcwaitq); | ||
259 | list_add(&lseg->pls_list, tmp_list); | 260 | list_add(&lseg->pls_list, tmp_list); |
260 | return 1; | 261 | return 1; |
261 | } | 262 | } |
@@ -401,7 +402,8 @@ pnfs_layoutgets_blocked(struct pnfs_layout_hdr *lo, nfs4_stateid *stateid, | |||
401 | if ((stateid) && | 402 | if ((stateid) && |
402 | (int)(lo->plh_barrier - be32_to_cpu(stateid->stateid.seqid)) >= 0) | 403 | (int)(lo->plh_barrier - be32_to_cpu(stateid->stateid.seqid)) >= 0) |
403 | return true; | 404 | return true; |
404 | return test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) || | 405 | return lo->plh_block_lgets || |
406 | test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) || | ||
405 | (list_empty(&lo->plh_segs) && | 407 | (list_empty(&lo->plh_segs) && |
406 | (atomic_read(&lo->plh_outstanding) > lget)); | 408 | (atomic_read(&lo->plh_outstanding) > lget)); |
407 | } | 409 | } |
@@ -474,6 +476,83 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
474 | return lseg; | 476 | return lseg; |
475 | } | 477 | } |
476 | 478 | ||
479 | bool pnfs_roc(struct inode *ino) | ||
480 | { | ||
481 | struct pnfs_layout_hdr *lo; | ||
482 | struct pnfs_layout_segment *lseg, *tmp; | ||
483 | LIST_HEAD(tmp_list); | ||
484 | bool found = false; | ||
485 | |||
486 | spin_lock(&ino->i_lock); | ||
487 | lo = NFS_I(ino)->layout; | ||
488 | if (!lo || !test_and_clear_bit(NFS_LAYOUT_ROC, &lo->plh_flags) || | ||
489 | test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) | ||
490 | goto out_nolayout; | ||
491 | list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list) | ||
492 | if (test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) { | ||
493 | mark_lseg_invalid(lseg, &tmp_list); | ||
494 | found = true; | ||
495 | } | ||
496 | if (!found) | ||
497 | goto out_nolayout; | ||
498 | lo->plh_block_lgets++; | ||
499 | get_layout_hdr(lo); /* matched in pnfs_roc_release */ | ||
500 | spin_unlock(&ino->i_lock); | ||
501 | pnfs_free_lseg_list(&tmp_list); | ||
502 | return true; | ||
503 | |||
504 | out_nolayout: | ||
505 | spin_unlock(&ino->i_lock); | ||
506 | return false; | ||
507 | } | ||
508 | |||
509 | void pnfs_roc_release(struct inode *ino) | ||
510 | { | ||
511 | struct pnfs_layout_hdr *lo; | ||
512 | |||
513 | spin_lock(&ino->i_lock); | ||
514 | lo = NFS_I(ino)->layout; | ||
515 | lo->plh_block_lgets--; | ||
516 | put_layout_hdr_locked(lo); | ||
517 | spin_unlock(&ino->i_lock); | ||
518 | } | ||
519 | |||
520 | void pnfs_roc_set_barrier(struct inode *ino, u32 barrier) | ||
521 | { | ||
522 | struct pnfs_layout_hdr *lo; | ||
523 | |||
524 | spin_lock(&ino->i_lock); | ||
525 | lo = NFS_I(ino)->layout; | ||
526 | if ((int)(barrier - lo->plh_barrier) > 0) | ||
527 | lo->plh_barrier = barrier; | ||
528 | spin_unlock(&ino->i_lock); | ||
529 | } | ||
530 | |||
531 | bool pnfs_roc_drain(struct inode *ino, u32 *barrier) | ||
532 | { | ||
533 | struct nfs_inode *nfsi = NFS_I(ino); | ||
534 | struct pnfs_layout_segment *lseg; | ||
535 | bool found = false; | ||
536 | |||
537 | spin_lock(&ino->i_lock); | ||
538 | list_for_each_entry(lseg, &nfsi->layout->plh_segs, pls_list) | ||
539 | if (test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) { | ||
540 | found = true; | ||
541 | break; | ||
542 | } | ||
543 | if (!found) { | ||
544 | struct pnfs_layout_hdr *lo = nfsi->layout; | ||
545 | u32 current_seqid = be32_to_cpu(lo->plh_stateid.stateid.seqid); | ||
546 | |||
547 | /* Since close does not return a layout stateid for use as | ||
548 | * a barrier, we choose the worst-case barrier. | ||
549 | */ | ||
550 | *barrier = current_seqid + atomic_read(&lo->plh_outstanding); | ||
551 | } | ||
552 | spin_unlock(&ino->i_lock); | ||
553 | return found; | ||
554 | } | ||
555 | |||
477 | /* | 556 | /* |
478 | * Compare two layout segments for sorting into layout cache. | 557 | * Compare two layout segments for sorting into layout cache. |
479 | * We want to preferentially return RW over RO layouts, so ensure those | 558 | * We want to preferentially return RW over RO layouts, so ensure those |
@@ -732,6 +811,11 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) | |||
732 | *lgp->lsegpp = lseg; | 811 | *lgp->lsegpp = lseg; |
733 | pnfs_insert_layout(lo, lseg); | 812 | pnfs_insert_layout(lo, lseg); |
734 | 813 | ||
814 | if (res->return_on_close) { | ||
815 | set_bit(NFS_LSEG_ROC, &lseg->pls_flags); | ||
816 | set_bit(NFS_LAYOUT_ROC, &lo->plh_flags); | ||
817 | } | ||
818 | |||
735 | /* Done processing layoutget. Set the layout stateid */ | 819 | /* Done processing layoutget. Set the layout stateid */ |
736 | pnfs_set_layout_stateid(lo, &res->stateid, false); | 820 | pnfs_set_layout_stateid(lo, &res->stateid, false); |
737 | spin_unlock(&ino->i_lock); | 821 | spin_unlock(&ino->i_lock); |