aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-07-14 15:14:02 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2016-07-19 16:23:23 -0400
commitf7db0b283868411dc6bc8a223fd032b211d2d91f (patch)
treecf7a2f7e1aee50843669d5c8548c1879b0725430
parent66b53f325876703b7ab815c482cd104609f8772c (diff)
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: 183d9e7b112aa ("pnfs: rework LAYOUTGET retry handling") Cc: stable@vger.kernel.org # 4.7 Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Reviewed-by: Jeff Layton <jlayton@redhat.com>
-rw-r--r--fs/nfs/nfs4proc.c34
1 files changed, 15 insertions, 19 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ee8efe0a5202..a1a3b4c9a563 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -7886,6 +7886,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
7886 struct pnfs_layout_hdr *lo; 7886 struct pnfs_layout_hdr *lo;
7887 int nfs4err = task->tk_status; 7887 int nfs4err = task->tk_status;
7888 int err, status = 0; 7888 int err, status = 0;
7889 LIST_HEAD(head);
7889 7890
7890 dprintk("--> %s tk_status => %d\n", __func__, -task->tk_status); 7891 dprintk("--> %s tk_status => %d\n", __func__, -task->tk_status);
7891 7892
@@ -7930,30 +7931,25 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
7930 case -NFS4ERR_BAD_STATEID: 7931 case -NFS4ERR_BAD_STATEID:
7931 exception->timeout = 0; 7932 exception->timeout = 0;
7932 spin_lock(&inode->i_lock); 7933 spin_lock(&inode->i_lock);
7933 if (nfs4_stateid_match(&lgp->args.stateid, 7934 lo = NFS_I(inode)->layout;
7935 /* If the open stateid was bad, then recover it. */
7936 if (!lo || test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags) ||
7937 nfs4_stateid_match_other(&lgp->args.stateid,
7934 &lgp->args.ctx->state->stateid)) { 7938 &lgp->args.ctx->state->stateid)) {
7935 spin_unlock(&inode->i_lock); 7939 spin_unlock(&inode->i_lock);
7936 /* If the open stateid was bad, then recover it. */
7937 exception->state = lgp->args.ctx->state; 7940 exception->state = lgp->args.ctx->state;
7938 break; 7941 break;
7939 } 7942 }
7940 lo = NFS_I(inode)->layout; 7943
7941 if (lo && !test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags) && 7944 /*
7942 nfs4_stateid_match_other(&lgp->args.stateid, &lo->plh_stateid)) { 7945 * Mark the bad layout state as invalid, then retry
7943 LIST_HEAD(head); 7946 */
7944 7947 set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
7945 /* 7948 pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0);
7946 * Mark the bad layout state as invalid, then retry 7949 spin_unlock(&inode->i_lock);
7947 * with the current stateid. 7950 pnfs_free_lseg_list(&head);
7948 */ 7951 status = -EAGAIN;
7949 set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); 7952 goto out;
7950 pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0);
7951 spin_unlock(&inode->i_lock);
7952 pnfs_free_lseg_list(&head);
7953 status = -EAGAIN;
7954 goto out;
7955 } else
7956 spin_unlock(&inode->i_lock);
7957 } 7953 }
7958 7954
7959 err = nfs4_handle_exception(server, nfs4err, exception); 7955 err = nfs4_handle_exception(server, nfs4err, exception);