Commit 2c8d5fc3 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

pNFS: Stricter ordering of layoutget and layoutreturn



If a layout return is in progress, we should wait for it to complete,
in case the layout segment we are picking up gets returned too.

Fixes: 30cb3ee2 ("pNFS: Handle NFS4ERR_OLD_STATEID on layoutreturn by bumping the state seqid")
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent c18d1e17
Loading
Loading
Loading
Loading
+21 −22
Original line number Diff line number Diff line
@@ -2018,6 +2018,27 @@ pnfs_update_layout(struct inode *ino,
		goto lookup_again;
	}

	/*
	 * Because we free lsegs when sending LAYOUTRETURN, we need to wait
	 * for LAYOUTRETURN.
	 */
	if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) {
		spin_unlock(&ino->i_lock);
		dprintk("%s wait for layoutreturn\n", __func__);
		lseg = ERR_PTR(pnfs_prepare_to_retry_layoutget(lo));
		if (!IS_ERR(lseg)) {
			pnfs_put_layout_hdr(lo);
			dprintk("%s retrying\n", __func__);
			trace_pnfs_update_layout(ino, pos, count, iomode, lo,
						 lseg,
						 PNFS_UPDATE_LAYOUT_RETRY);
			goto lookup_again;
		}
		trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
					 PNFS_UPDATE_LAYOUT_RETURN);
		goto out_put_layout_hdr;
	}

	lseg = pnfs_find_lseg(lo, &arg, strict_iomode);
	if (lseg) {
		trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
@@ -2070,28 +2091,6 @@ pnfs_update_layout(struct inode *ino,
		nfs4_stateid_copy(&stateid, &lo->plh_stateid);
	}

	/*
	 * Because we free lsegs before sending LAYOUTRETURN, we need to wait
	 * for LAYOUTRETURN even if first is true.
	 */
	if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) {
		spin_unlock(&ino->i_lock);
		dprintk("%s wait for layoutreturn\n", __func__);
		lseg = ERR_PTR(pnfs_prepare_to_retry_layoutget(lo));
		if (!IS_ERR(lseg)) {
			if (first)
				pnfs_clear_first_layoutget(lo);
			pnfs_put_layout_hdr(lo);
			dprintk("%s retrying\n", __func__);
			trace_pnfs_update_layout(ino, pos, count, iomode, lo,
					lseg, PNFS_UPDATE_LAYOUT_RETRY);
			goto lookup_again;
		}
		trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
				PNFS_UPDATE_LAYOUT_RETURN);
		goto out_put_layout_hdr;
	}

	if (pnfs_layoutgets_blocked(lo)) {
		trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
				PNFS_UPDATE_LAYOUT_BLOCKED);