aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-02-22 17:46:34 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2016-02-22 17:46:34 -0500
commit9fd4b9fc7695a4da1363a0b439853f88fb6a034f (patch)
tree6b6fb3dc2560522f952c1e35fd0c727973cc593a
parent2454dfea0aef8a883d4302c38124edb373d47a25 (diff)
NFSv4.x/pnfs: Fix a race between layoutget and bulk recalls
Replace another case where the layout 'plh_block_lgets' can trigger infinite loops in send_layoutget(). Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r--fs/nfs/pnfs.c17
1 files changed, 6 insertions, 11 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 8a41538f1155..2fa483e6dbe2 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -259,7 +259,7 @@ pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
259 * is required. 259 * is required.
260 * Note that caller must hold inode->i_lock. 260 * Note that caller must hold inode->i_lock.
261 */ 261 */
262static void 262static int
263pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo, 263pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo,
264 struct list_head *lseg_list) 264 struct list_head *lseg_list)
265{ 265{
@@ -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 pnfs_mark_matching_lsegs_invalid(lo, lseg_list, &range); 273 return pnfs_mark_matching_lsegs_invalid(lo, lseg_list, &range);
274} 274}
275 275
276static int 276static int
@@ -637,11 +637,6 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list,
637{ 637{
638 struct pnfs_layout_hdr *lo; 638 struct pnfs_layout_hdr *lo;
639 struct inode *inode; 639 struct inode *inode;
640 struct pnfs_layout_range range = {
641 .iomode = IOMODE_ANY,
642 .offset = 0,
643 .length = NFS4_MAX_UINT64,
644 };
645 LIST_HEAD(lseg_list); 640 LIST_HEAD(lseg_list);
646 int ret = 0; 641 int ret = 0;
647 642
@@ -656,11 +651,11 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list,
656 651
657 spin_lock(&inode->i_lock); 652 spin_lock(&inode->i_lock);
658 list_del_init(&lo->plh_bulk_destroy); 653 list_del_init(&lo->plh_bulk_destroy);
659 lo->plh_block_lgets++; /* permanently block new LAYOUTGETs */ 654 if (pnfs_mark_layout_stateid_invalid(lo, &lseg_list)) {
660 if (is_bulk_recall) 655 if (is_bulk_recall)
661 set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); 656 set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
662 if (pnfs_mark_matching_lsegs_invalid(lo, &lseg_list, &range))
663 ret = -EAGAIN; 657 ret = -EAGAIN;
658 }
664 spin_unlock(&inode->i_lock); 659 spin_unlock(&inode->i_lock);
665 pnfs_free_lseg_list(&lseg_list); 660 pnfs_free_lseg_list(&lseg_list);
666 /* Free all lsegs that are attached to commit buckets */ 661 /* Free all lsegs that are attached to commit buckets */