diff options
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 55 |
1 files changed, 40 insertions, 15 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 482b6e94bb37..2fa483e6dbe2 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -252,6 +252,27 @@ pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo) | |||
252 | } | 252 | } |
253 | } | 253 | } |
254 | 254 | ||
255 | /* | ||
256 | * Mark a pnfs_layout_hdr and all associated layout segments as invalid | ||
257 | * | ||
258 | * In order to continue using the pnfs_layout_hdr, a full recovery | ||
259 | * is required. | ||
260 | * Note that caller must hold inode->i_lock. | ||
261 | */ | ||
262 | static int | ||
263 | pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo, | ||
264 | struct list_head *lseg_list) | ||
265 | { | ||
266 | struct pnfs_layout_range range = { | ||
267 | .iomode = IOMODE_ANY, | ||
268 | .offset = 0, | ||
269 | .length = NFS4_MAX_UINT64, | ||
270 | }; | ||
271 | |||
272 | set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); | ||
273 | return pnfs_mark_matching_lsegs_invalid(lo, lseg_list, &range); | ||
274 | } | ||
275 | |||
255 | static int | 276 | static int |
256 | pnfs_iomode_to_fail_bit(u32 iomode) | 277 | pnfs_iomode_to_fail_bit(u32 iomode) |
257 | { | 278 | { |
@@ -554,9 +575,8 @@ pnfs_destroy_layout(struct nfs_inode *nfsi) | |||
554 | spin_lock(&nfsi->vfs_inode.i_lock); | 575 | spin_lock(&nfsi->vfs_inode.i_lock); |
555 | lo = nfsi->layout; | 576 | lo = nfsi->layout; |
556 | if (lo) { | 577 | if (lo) { |
557 | lo->plh_block_lgets++; /* permanently block new LAYOUTGETs */ | ||
558 | pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL); | ||
559 | pnfs_get_layout_hdr(lo); | 578 | pnfs_get_layout_hdr(lo); |
579 | pnfs_mark_layout_stateid_invalid(lo, &tmp_list); | ||
560 | pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RO_FAILED); | 580 | pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RO_FAILED); |
561 | pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED); | 581 | pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED); |
562 | spin_unlock(&nfsi->vfs_inode.i_lock); | 582 | spin_unlock(&nfsi->vfs_inode.i_lock); |
@@ -617,11 +637,6 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list, | |||
617 | { | 637 | { |
618 | struct pnfs_layout_hdr *lo; | 638 | struct pnfs_layout_hdr *lo; |
619 | struct inode *inode; | 639 | struct inode *inode; |
620 | struct pnfs_layout_range range = { | ||
621 | .iomode = IOMODE_ANY, | ||
622 | .offset = 0, | ||
623 | .length = NFS4_MAX_UINT64, | ||
624 | }; | ||
625 | LIST_HEAD(lseg_list); | 640 | LIST_HEAD(lseg_list); |
626 | int ret = 0; | 641 | int ret = 0; |
627 | 642 | ||
@@ -636,11 +651,11 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list, | |||
636 | 651 | ||
637 | spin_lock(&inode->i_lock); | 652 | spin_lock(&inode->i_lock); |
638 | list_del_init(&lo->plh_bulk_destroy); | 653 | list_del_init(&lo->plh_bulk_destroy); |
639 | lo->plh_block_lgets++; /* permanently block new LAYOUTGETs */ | 654 | if (pnfs_mark_layout_stateid_invalid(lo, &lseg_list)) { |
640 | if (is_bulk_recall) | 655 | if (is_bulk_recall) |
641 | set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); | 656 | set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); |
642 | if (pnfs_mark_matching_lsegs_invalid(lo, &lseg_list, &range)) | ||
643 | ret = -EAGAIN; | 657 | ret = -EAGAIN; |
658 | } | ||
644 | spin_unlock(&inode->i_lock); | 659 | spin_unlock(&inode->i_lock); |
645 | pnfs_free_lseg_list(&lseg_list); | 660 | pnfs_free_lseg_list(&lseg_list); |
646 | /* Free all lsegs that are attached to commit buckets */ | 661 | /* Free all lsegs that are attached to commit buckets */ |
@@ -1738,8 +1753,19 @@ pnfs_set_plh_return_iomode(struct pnfs_layout_hdr *lo, enum pnfs_iomode iomode) | |||
1738 | if (lo->plh_return_iomode != 0) | 1753 | if (lo->plh_return_iomode != 0) |
1739 | iomode = IOMODE_ANY; | 1754 | iomode = IOMODE_ANY; |
1740 | lo->plh_return_iomode = iomode; | 1755 | lo->plh_return_iomode = iomode; |
1756 | set_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags); | ||
1741 | } | 1757 | } |
1742 | 1758 | ||
1759 | /** | ||
1760 | * pnfs_mark_matching_lsegs_return - Free or return matching layout segments | ||
1761 | * @lo: pointer to layout header | ||
1762 | * @tmp_list: list header to be used with pnfs_free_lseg_list() | ||
1763 | * @return_range: describe layout segment ranges to be returned | ||
1764 | * | ||
1765 | * This function is mainly intended for use by layoutrecall. It attempts | ||
1766 | * to free the layout segment immediately, or else to mark it for return | ||
1767 | * as soon as its reference count drops to zero. | ||
1768 | */ | ||
1743 | int | 1769 | int |
1744 | pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, | 1770 | pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, |
1745 | struct list_head *tmp_list, | 1771 | struct list_head *tmp_list, |
@@ -1762,12 +1788,11 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, | |||
1762 | lseg, lseg->pls_range.iomode, | 1788 | lseg, lseg->pls_range.iomode, |
1763 | lseg->pls_range.offset, | 1789 | lseg->pls_range.offset, |
1764 | lseg->pls_range.length); | 1790 | lseg->pls_range.length); |
1791 | if (mark_lseg_invalid(lseg, tmp_list)) | ||
1792 | continue; | ||
1793 | remaining++; | ||
1765 | set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags); | 1794 | set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags); |
1766 | pnfs_set_plh_return_iomode(lo, return_range->iomode); | 1795 | pnfs_set_plh_return_iomode(lo, return_range->iomode); |
1767 | if (!mark_lseg_invalid(lseg, tmp_list)) | ||
1768 | remaining++; | ||
1769 | set_bit(NFS_LAYOUT_RETURN_REQUESTED, | ||
1770 | &lo->plh_flags); | ||
1771 | } | 1796 | } |
1772 | return remaining; | 1797 | return remaining; |
1773 | } | 1798 | } |