diff options
-rw-r--r-- | fs/nfs/callback_proc.c | 3 | ||||
-rw-r--r-- | fs/nfs/nfs42proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 5 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 64 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 6 |
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 | ||
276 | static int | 276 | static 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 | */ | ||
529 | static 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 | */ |
528 | int | 549 | int |
529 | pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, | 550 | pnfs_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 | */ | ||
737 | static 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 */ |
743 | void | 758 | void |
744 | pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new, | 759 | pnfs_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, | |||
1775 | int | 1790 | int |
1776 | pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, | 1791 | pnfs_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); |
267 | int pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, | 267 | int 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); | ||
270 | int pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, | 271 | int 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); | ||
273 | bool pnfs_roc(struct inode *ino); | 275 | bool pnfs_roc(struct inode *ino); |
274 | void pnfs_roc_release(struct inode *ino); | 276 | void pnfs_roc_release(struct inode *ino); |
275 | void pnfs_roc_set_barrier(struct inode *ino, u32 barrier); | 277 | void pnfs_roc_set_barrier(struct inode *ino, u32 barrier); |