Commit f7db0b28 authored by Trond Myklebust's avatar Trond Myklebust

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
...@@ -7886,6 +7886,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task, ...@@ -7886,6 +7886,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
struct pnfs_layout_hdr *lo; struct pnfs_layout_hdr *lo;
int nfs4err = task->tk_status; int nfs4err = task->tk_status;
int err, status = 0; int err, status = 0;
LIST_HEAD(head);
dprintk("--> %s tk_status => %d\n", __func__, -task->tk_status); dprintk("--> %s tk_status => %d\n", __func__, -task->tk_status);
...@@ -7930,30 +7931,25 @@ nfs4_layoutget_handle_exception(struct rpc_task *task, ...@@ -7930,30 +7931,25 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
case -NFS4ERR_BAD_STATEID: case -NFS4ERR_BAD_STATEID:
exception->timeout = 0; exception->timeout = 0;
spin_lock(&inode->i_lock); 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)) { &lgp->args.ctx->state->stateid)) {
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
/* If the open stateid was bad, then recover it. */
exception->state = lgp->args.ctx->state; exception->state = lgp->args.ctx->state;
break; 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)) { * Mark the bad layout state as invalid, then retry
LIST_HEAD(head); */
set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
/* pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0);
* Mark the bad layout state as invalid, then retry spin_unlock(&inode->i_lock);
* with the current stateid. pnfs_free_lseg_list(&head);
*/ status = -EAGAIN;
set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); goto out;
pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0);
spin_unlock(&inode->i_lock);
pnfs_free_lseg_list(&head);
status = -EAGAIN;
goto out;
} else
spin_unlock(&inode->i_lock);
} }
err = nfs4_handle_exception(server, nfs4err, exception); err = nfs4_handle_exception(server, nfs4err, exception);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment