Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f7db0b28 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

pNFS: Fix LAYOUTGET handling of NFS4ERR_BAD_STATEID and NFS4ERR_EXPIRED



We want to recover the open stateid if there is no layout stateid
and/or the stateid argument matches an open stateid.
Otherwise throw out the existing layout and recover from scratch, as
the layout stateid is bad.

Fixes: 183d9e7b ("pnfs: rework LAYOUTGET retry handling")
Cc: stable@vger.kernel.org # 4.7
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Reviewed-by: default avatarJeff Layton <jlayton@redhat.com>
parent 66b53f32
Loading
Loading
Loading
Loading
+15 −19
Original line number Diff line number Diff line
@@ -7886,6 +7886,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
	struct pnfs_layout_hdr *lo;
	int nfs4err = task->tk_status;
	int err, status = 0;
	LIST_HEAD(head);

	dprintk("--> %s tk_status => %d\n", __func__, -task->tk_status);

@@ -7930,21 +7931,18 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
	case -NFS4ERR_BAD_STATEID:
		exception->timeout = 0;
		spin_lock(&inode->i_lock);
		if (nfs4_stateid_match(&lgp->args.stateid,
		lo = NFS_I(inode)->layout;
		/* If the open stateid was bad, then recover it. */
		if (!lo || test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags) ||
		    nfs4_stateid_match_other(&lgp->args.stateid,
					&lgp->args.ctx->state->stateid)) {
			spin_unlock(&inode->i_lock);
			/* If the open stateid was bad, then recover it. */
			exception->state = lgp->args.ctx->state;
			break;
		}
		lo = NFS_I(inode)->layout;
		if (lo && !test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags) &&
		    nfs4_stateid_match_other(&lgp->args.stateid, &lo->plh_stateid)) {
			LIST_HEAD(head);

		/*
		 * Mark the bad layout state as invalid, then retry
			 * with the current stateid.
		 */
		set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
		pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0);
@@ -7952,8 +7950,6 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
		pnfs_free_lseg_list(&head);
		status = -EAGAIN;
		goto out;
		} else
			spin_unlock(&inode->i_lock);
	}

	err = nfs4_handle_exception(server, nfs4err, exception);