diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-07-22 11:13:22 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-07-24 16:16:40 -0400 |
commit | e036f46453f252539cb62bf91d82c3d08e37e73c (patch) | |
tree | 0c44303a8033868001a83ba488a0c3c7571e8b06 | |
parent | 2d6cf5ab0b5d13d06c4b7920d6a12dbedf003190 (diff) |
NFS: pnfs_mark_matching_lsegs_return() should match the layout sequence id
When determining which layout segments to return, we do want
pnfs_mark_matching_lsegs_return to check that they match the layout
sequence id. This ensures that we don't waste time if the server
is replaying a layout recall that has already been satisfied.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r-- | fs/nfs/pnfs.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index c57cbddca760..52b2a4dfdcb0 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -486,15 +486,6 @@ pnfs_lseg_range_intersecting(const struct pnfs_layout_range *l1, | |||
486 | (end2 == NFS4_MAX_UINT64 || end2 > start1); | 486 | (end2 == NFS4_MAX_UINT64 || end2 > start1); |
487 | } | 487 | } |
488 | 488 | ||
489 | static bool | ||
490 | should_free_lseg(const struct pnfs_layout_range *lseg_range, | ||
491 | const struct pnfs_layout_range *recall_range) | ||
492 | { | ||
493 | return (recall_range->iomode == IOMODE_ANY || | ||
494 | lseg_range->iomode == recall_range->iomode) && | ||
495 | pnfs_lseg_range_intersecting(lseg_range, recall_range); | ||
496 | } | ||
497 | |||
498 | static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg, | 489 | static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg, |
499 | struct list_head *tmp_list) | 490 | struct list_head *tmp_list) |
500 | { | 491 | { |
@@ -533,6 +524,27 @@ static bool pnfs_seqid_is_newer(u32 s1, u32 s2) | |||
533 | return (s32)(s1 - s2) > 0; | 524 | return (s32)(s1 - s2) > 0; |
534 | } | 525 | } |
535 | 526 | ||
527 | static bool | ||
528 | pnfs_should_free_range(const struct pnfs_layout_range *lseg_range, | ||
529 | const struct pnfs_layout_range *recall_range) | ||
530 | { | ||
531 | return (recall_range->iomode == IOMODE_ANY || | ||
532 | lseg_range->iomode == recall_range->iomode) && | ||
533 | pnfs_lseg_range_intersecting(lseg_range, recall_range); | ||
534 | } | ||
535 | |||
536 | static bool | ||
537 | pnfs_match_lseg_recall(const struct pnfs_layout_segment *lseg, | ||
538 | const struct pnfs_layout_range *recall_range, | ||
539 | u32 seq) | ||
540 | { | ||
541 | if (seq != 0 && pnfs_seqid_is_newer(lseg->pls_seq, seq)) | ||
542 | return false; | ||
543 | if (recall_range == NULL) | ||
544 | return true; | ||
545 | return pnfs_should_free_range(&lseg->pls_range, recall_range); | ||
546 | } | ||
547 | |||
536 | /** | 548 | /** |
537 | * pnfs_mark_matching_lsegs_invalid - tear down lsegs or mark them for later | 549 | * pnfs_mark_matching_lsegs_invalid - tear down lsegs or mark them for later |
538 | * @lo: layout header containing the lsegs | 550 | * @lo: layout header containing the lsegs |
@@ -562,10 +574,7 @@ pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, | |||
562 | if (list_empty(&lo->plh_segs)) | 574 | if (list_empty(&lo->plh_segs)) |
563 | return 0; | 575 | return 0; |
564 | list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) | 576 | list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) |
565 | if (!recall_range || | 577 | if (pnfs_match_lseg_recall(lseg, recall_range, seq)) { |
566 | should_free_lseg(&lseg->pls_range, recall_range)) { | ||
567 | if (seq && pnfs_seqid_is_newer(lseg->pls_seq, seq)) | ||
568 | continue; | ||
569 | dprintk("%s: freeing lseg %p iomode %d seq %u" | 578 | dprintk("%s: freeing lseg %p iomode %d seq %u" |
570 | "offset %llu length %llu\n", __func__, | 579 | "offset %llu length %llu\n", __func__, |
571 | lseg, lseg->pls_range.iomode, lseg->pls_seq, | 580 | lseg, lseg->pls_range.iomode, lseg->pls_seq, |
@@ -1845,7 +1854,7 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, | |||
1845 | assert_spin_locked(&lo->plh_inode->i_lock); | 1854 | assert_spin_locked(&lo->plh_inode->i_lock); |
1846 | 1855 | ||
1847 | list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) | 1856 | list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) |
1848 | if (should_free_lseg(&lseg->pls_range, return_range)) { | 1857 | if (pnfs_match_lseg_recall(lseg, return_range, seq)) { |
1849 | dprintk("%s: marking lseg %p iomode %d " | 1858 | dprintk("%s: marking lseg %p iomode %d " |
1850 | "offset %llu length %llu\n", __func__, | 1859 | "offset %llu length %llu\n", __func__, |
1851 | lseg, lseg->pls_range.iomode, | 1860 | lseg, lseg->pls_range.iomode, |