aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/callback_proc.c3
-rw-r--r--fs/nfs/nfs42proc.c2
-rw-r--r--fs/nfs/nfs4proc.c5
-rw-r--r--fs/nfs/pnfs.c64
-rw-r--r--fs/nfs/pnfs.h6
5 files changed, 52 insertions, 28 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 7c9fbf504f07..aaa2e8d3df6f 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -217,7 +217,8 @@ static u32 initiate_file_draining(struct nfs_client *clp,
217 } 217 }
218 218
219 if (pnfs_mark_matching_lsegs_return(lo, &free_me_list, 219 if (pnfs_mark_matching_lsegs_return(lo, &free_me_list,
220 &args->cbl_range)) { 220 &args->cbl_range,
221 be32_to_cpu(args->cbl_stateid.seqid))) {
221 rv = NFS4_OK; 222 rv = NFS4_OK;
222 goto unlock; 223 goto unlock;
223 } 224 }
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
index 579ee20e4120..20c44d1209dc 100644
--- a/fs/nfs/nfs42proc.c
+++ b/fs/nfs/nfs42proc.c
@@ -337,7 +337,7 @@ nfs42_layoutstat_done(struct rpc_task *task, void *calldata)
337 * with the current stateid. 337 * with the current stateid.
338 */ 338 */
339 set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); 339 set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
340 pnfs_mark_matching_lsegs_invalid(lo, &head, NULL); 340 pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0);
341 spin_unlock(&inode->i_lock); 341 spin_unlock(&inode->i_lock);
342 pnfs_free_lseg_list(&head); 342 pnfs_free_lseg_list(&head);
343 } else 343 } else
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index c9b66085d392..2a29f5d12aeb 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -7953,7 +7953,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
7953 * with the current stateid. 7953 * with the current stateid.
7954 */ 7954 */
7955 set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); 7955 set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
7956 pnfs_mark_matching_lsegs_invalid(lo, &head, NULL); 7956 pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0);
7957 spin_unlock(&inode->i_lock); 7957 spin_unlock(&inode->i_lock);
7958 pnfs_free_lseg_list(&head); 7958 pnfs_free_lseg_list(&head);
7959 } else 7959 } else
@@ -8145,7 +8145,8 @@ static void nfs4_layoutreturn_release(void *calldata)
8145 8145
8146 dprintk("--> %s\n", __func__); 8146 dprintk("--> %s\n", __func__);
8147 spin_lock(&lo->plh_inode->i_lock); 8147 spin_lock(&lo->plh_inode->i_lock);
8148 pnfs_mark_matching_lsegs_invalid(lo, &freeme, &lrp->args.range); 8148 pnfs_mark_matching_lsegs_invalid(lo, &freeme, &lrp->args.range,
8149 be32_to_cpu(lrp->args.stateid.seqid));
8149 pnfs_mark_layout_returned_if_empty(lo); 8150 pnfs_mark_layout_returned_if_empty(lo);
8150 if (lrp->res.lrs_present) 8151 if (lrp->res.lrs_present)
8151 pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); 8152 pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 3ad6bd377d35..21ff53fe7a9e 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -270,7 +270,7 @@ pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo,
270 }; 270 };
271 271
272 set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); 272 set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
273 return pnfs_mark_matching_lsegs_invalid(lo, lseg_list, &range); 273 return pnfs_mark_matching_lsegs_invalid(lo, lseg_list, &range, 0);
274} 274}
275 275
276static int 276static int
@@ -308,7 +308,7 @@ pnfs_layout_io_set_failed(struct pnfs_layout_hdr *lo, u32 iomode)
308 308
309 spin_lock(&inode->i_lock); 309 spin_lock(&inode->i_lock);
310 pnfs_layout_set_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode)); 310 pnfs_layout_set_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode));
311 pnfs_mark_matching_lsegs_invalid(lo, &head, &range); 311 pnfs_mark_matching_lsegs_invalid(lo, &head, &range, 0);
312 spin_unlock(&inode->i_lock); 312 spin_unlock(&inode->i_lock);
313 pnfs_free_lseg_list(&head); 313 pnfs_free_lseg_list(&head);
314 dprintk("%s Setting layout IOMODE_%s fail bit\n", __func__, 314 dprintk("%s Setting layout IOMODE_%s fail bit\n", __func__,
@@ -522,13 +522,35 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
522 return rv; 522 return rv;
523} 523}
524 524
525/* Returns count of number of matching invalid lsegs remaining in list 525/*
526 * after call. 526 * Compare 2 layout stateid sequence ids, to see which is newer,
527 * taking into account wraparound issues.
528 */
529static bool pnfs_seqid_is_newer(u32 s1, u32 s2)
530{
531 return (s32)(s1 - s2) > 0;
532}
533
534/**
535 * pnfs_mark_matching_lsegs_invalid - tear down lsegs or mark them for later
536 * @lo: layout header containing the lsegs
537 * @tmp_list: list head where doomed lsegs should go
538 * @recall_range: optional recall range argument to match (may be NULL)
539 * @seq: only invalidate lsegs obtained prior to this sequence (may be 0)
540 *
541 * Walk the list of lsegs in the layout header, and tear down any that should
542 * be destroyed. If "recall_range" is specified then the segment must match
543 * that range. If "seq" is non-zero, then only match segments that were handed
544 * out at or before that sequence.
545 *
546 * Returns number of matching invalid lsegs remaining in list after scanning
547 * it and purging them.
527 */ 548 */
528int 549int
529pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, 550pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
530 struct list_head *tmp_list, 551 struct list_head *tmp_list,
531 const struct pnfs_layout_range *recall_range) 552 const struct pnfs_layout_range *recall_range,
553 u32 seq)
532{ 554{
533 struct pnfs_layout_segment *lseg, *next; 555 struct pnfs_layout_segment *lseg, *next;
534 int remaining = 0; 556 int remaining = 0;
@@ -540,10 +562,12 @@ pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
540 list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) 562 list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list)
541 if (!recall_range || 563 if (!recall_range ||
542 should_free_lseg(&lseg->pls_range, recall_range)) { 564 should_free_lseg(&lseg->pls_range, recall_range)) {
543 dprintk("%s: freeing lseg %p iomode %d " 565 if (seq && pnfs_seqid_is_newer(lseg->pls_seq, seq))
566 continue;
567 dprintk("%s: freeing lseg %p iomode %d seq %u"
544 "offset %llu length %llu\n", __func__, 568 "offset %llu length %llu\n", __func__,
545 lseg, lseg->pls_range.iomode, lseg->pls_range.offset, 569 lseg, lseg->pls_range.iomode, lseg->pls_seq,
546 lseg->pls_range.length); 570 lseg->pls_range.offset, lseg->pls_range.length);
547 if (!mark_lseg_invalid(lseg, tmp_list)) 571 if (!mark_lseg_invalid(lseg, tmp_list))
548 remaining++; 572 remaining++;
549 } 573 }
@@ -730,15 +754,6 @@ pnfs_destroy_all_layouts(struct nfs_client *clp)
730 pnfs_destroy_layouts_byclid(clp, false); 754 pnfs_destroy_layouts_byclid(clp, false);
731} 755}
732 756
733/*
734 * Compare 2 layout stateid sequence ids, to see which is newer,
735 * taking into account wraparound issues.
736 */
737static bool pnfs_seqid_is_newer(u32 s1, u32 s2)
738{
739 return (s32)(s1 - s2) > 0;
740}
741
742/* update lo->plh_stateid with new if is more recent */ 757/* update lo->plh_stateid with new if is more recent */
743void 758void
744pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new, 759pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new,
@@ -1014,7 +1029,7 @@ _pnfs_return_layout(struct inode *ino)
1014 pnfs_get_layout_hdr(lo); 1029 pnfs_get_layout_hdr(lo);
1015 empty = list_empty(&lo->plh_segs); 1030 empty = list_empty(&lo->plh_segs);
1016 pnfs_clear_layoutcommit(ino, &tmp_list); 1031 pnfs_clear_layoutcommit(ino, &tmp_list);
1017 pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL); 1032 pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL, 0);
1018 1033
1019 if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) { 1034 if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) {
1020 struct pnfs_layout_range range = { 1035 struct pnfs_layout_range range = {
@@ -1721,7 +1736,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
1721 * inode invalid, and don't bother validating the stateid 1736 * inode invalid, and don't bother validating the stateid
1722 * sequence number. 1737 * sequence number.
1723 */ 1738 */
1724 pnfs_mark_matching_lsegs_invalid(lo, &free_me, NULL); 1739 pnfs_mark_matching_lsegs_invalid(lo, &free_me, NULL, 0);
1725 1740
1726 nfs4_stateid_copy(&lo->plh_stateid, &res->stateid); 1741 nfs4_stateid_copy(&lo->plh_stateid, &res->stateid);
1727 lo->plh_barrier = be32_to_cpu(res->stateid.seqid); 1742 lo->plh_barrier = be32_to_cpu(res->stateid.seqid);
@@ -1775,7 +1790,8 @@ pnfs_set_plh_return_info(struct pnfs_layout_hdr *lo, enum pnfs_iomode iomode,
1775int 1790int
1776pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, 1791pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
1777 struct list_head *tmp_list, 1792 struct list_head *tmp_list,
1778 const struct pnfs_layout_range *return_range) 1793 const struct pnfs_layout_range *return_range,
1794 u32 seq)
1779{ 1795{
1780 struct pnfs_layout_segment *lseg, *next; 1796 struct pnfs_layout_segment *lseg, *next;
1781 int remaining = 0; 1797 int remaining = 0;
@@ -1798,8 +1814,11 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
1798 continue; 1814 continue;
1799 remaining++; 1815 remaining++;
1800 set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags); 1816 set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags);
1801 pnfs_set_plh_return_info(lo, return_range->iomode, lseg->pls_seq);
1802 } 1817 }
1818
1819 if (remaining)
1820 pnfs_set_plh_return_info(lo, return_range->iomode, seq);
1821
1803 return remaining; 1822 return remaining;
1804} 1823}
1805 1824
@@ -1822,7 +1841,8 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,
1822 * segments at hand when sending layoutreturn. See pnfs_put_lseg() 1841 * segments at hand when sending layoutreturn. See pnfs_put_lseg()
1823 * for how it works. 1842 * for how it works.
1824 */ 1843 */
1825 if (!pnfs_mark_matching_lsegs_return(lo, &free_me, &range)) { 1844 if (!pnfs_mark_matching_lsegs_return(lo, &free_me,
1845 &range, lseg->pls_seq)) {
1826 nfs4_stateid stateid; 1846 nfs4_stateid stateid;
1827 enum pnfs_iomode iomode = lo->plh_return_iomode; 1847 enum pnfs_iomode iomode = lo->plh_return_iomode;
1828 1848
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 3476c9850678..971068b58647 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -266,10 +266,12 @@ int pnfs_choose_layoutget_stateid(nfs4_stateid *dst,
266 struct nfs4_state *open_state); 266 struct nfs4_state *open_state);
267int pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, 267int pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
268 struct list_head *tmp_list, 268 struct list_head *tmp_list,
269 const struct pnfs_layout_range *recall_range); 269 const struct pnfs_layout_range *recall_range,
270 u32 seq);
270int pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, 271int pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
271 struct list_head *tmp_list, 272 struct list_head *tmp_list,
272 const struct pnfs_layout_range *recall_range); 273 const struct pnfs_layout_range *recall_range,
274 u32 seq);
273bool pnfs_roc(struct inode *ino); 275bool pnfs_roc(struct inode *ino);
274void pnfs_roc_release(struct inode *ino); 276void pnfs_roc_release(struct inode *ino);
275void pnfs_roc_set_barrier(struct inode *ino, u32 barrier); 277void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);