aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-02-22 17:34:59 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2016-02-22 17:34:59 -0500
commit2454dfea0aef8a883d4302c38124edb373d47a25 (patch)
treee6ffc2bd5a1bc51a60bd22c5d7d59aa0f72d9935
parentd07fbb8fdf57c4af28679ad7c4b2542e78ca7218 (diff)
NFSv4.x/pnfs: Fix a race between layoutget and pnfs_destroy_layout
If the server reboots while there is a layoutget outstanding, then the call to pnfs_choose_layoutget_stateid() will fail with an EAGAIN error, which causes an infinite loop in send_layoutget(). The reason why we never break out of the loop is that the layout 'plh_block_lgets' field is never cleared. Fix is to replace plh_block_lgets with NFS_LAYOUT_INVALID_STID, which can be reset after a new layoutget. Fixes: ab7d763e477c5 ("pNFS: Ensure nfs4_layoutget_prepare returns...") Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r--fs/nfs/pnfs.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 5064f23ca8cc..8a41538f1155 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 void
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 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);