summaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r--fs/nfs/pnfs.c55
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 */
262static int
263pnfs_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
255static int 276static int
256pnfs_iomode_to_fail_bit(u32 iomode) 277pnfs_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 */
1743int 1769int
1744pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, 1770pnfs_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}