]> git.hungrycats.org Git - linux/commitdiff
pNFS: Fix LAYOUTGET handling of NFS4ERR_BAD_STATEID and NFS4ERR_EXPIRED
authorTrond Myklebust <trond.myklebust@primarydata.com>
Thu, 14 Jul 2016 19:14:02 +0000 (15:14 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 20 Aug 2016 16:10:57 +0000 (18:10 +0200)
commit f7db0b283868411dc6bc8a223fd032b211d2d91f upstream.

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")
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Reviewed-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/nfs/nfs4proc.c

index a0c9ace821d58fca201943a51e6f34d062416543..7796beacdefb74097477204d9a39c8dc9d091c92 100644 (file)
@@ -7872,6 +7872,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);
 
@@ -7916,30 +7917,25 @@ 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);
-                       spin_unlock(&inode->i_lock);
-                       pnfs_free_lseg_list(&head);
-                       status = -EAGAIN;
-                       goto out;
-               } else
-                       spin_unlock(&inode->i_lock);
+
+               /*
+                * Mark the bad layout state as invalid, then retry
+                */
+               set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
+               pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0);
+               spin_unlock(&inode->i_lock);
+               pnfs_free_lseg_list(&head);
+               status = -EAGAIN;
+               goto out;
        }
 
        err = nfs4_handle_exception(server, nfs4err, exception);