diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-02-22 17:46:34 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-02-22 17:46:34 -0500 |
commit | 9fd4b9fc7695a4da1363a0b439853f88fb6a034f (patch) | |
tree | 6b6fb3dc2560522f952c1e35fd0c727973cc593a | |
parent | 2454dfea0aef8a883d4302c38124edb373d47a25 (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.c | 17 |
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 | */ |
262 | static void | 262 | static int |
263 | pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo, | 263 | pnfs_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 | ||
276 | static int | 276 | static 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 */ |