NFSv4.x/pnfs: Don't try to recover stateids twice in layoutget
authorTrond Myklebust <trond.myklebust@primarydata.com>
Sun, 20 Sep 2015 17:30:30 +0000 (13:30 -0400)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 21 Sep 2015 02:34:35 +0000 (22:34 -0400)
If the current open or layout stateid doesn't match the stateid used
in the layoutget RPC call, then don't try to recover it.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/nfs4proc.c

index e129347b656fe29f3d0b4e0e5ee1ec1d423d61ef..ef6b46e08ac67bac41e63e652c5d964b259b0a57 100644 (file)
@@ -7813,20 +7813,23 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
                        dprintk("%s: NFS4ERR_RECALLCONFLICT waiting %lu\n",
                                __func__, delay);
                        rpc_delay(task, delay);
-                       task->tk_status = 0;
-                       rpc_restart_call_prepare(task);
-                       goto out; /* Do not call nfs4_async_handle_error() */
+                       /* Do not call nfs4_async_handle_error() */
+                       goto out_restart;
                }
                break;
        case -NFS4ERR_EXPIRED:
        case -NFS4ERR_BAD_STATEID:
                spin_lock(&inode->i_lock);
-               lo = NFS_I(inode)->layout;
-               if (!lo || list_empty(&lo->plh_segs)) {
+               if (nfs4_stateid_match(&lgp->args.stateid,
+                                       &lgp->args.ctx->state->stateid)) {
                        spin_unlock(&inode->i_lock);
                        /* If the open stateid was bad, then recover it. */
                        state = lgp->args.ctx->state;
-               } else {
+                       break;
+               }
+               lo = NFS_I(inode)->layout;
+               if (lo && nfs4_stateid_match(&lgp->args.stateid,
+                                       &lo->plh_stateid)) {
                        LIST_HEAD(head);
 
                        /*
@@ -7837,16 +7840,19 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
                        pnfs_mark_matching_lsegs_invalid(lo, &head, NULL);
                        spin_unlock(&inode->i_lock);
                        pnfs_free_lseg_list(&head);
-       
-                       task->tk_status = 0;
-                       rpc_restart_call_prepare(task);
-               }
+               } else
+                       spin_unlock(&inode->i_lock);
+               goto out_restart;
        }
        if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN)
-               rpc_restart_call_prepare(task);
+               goto out_restart;
 out:
        dprintk("<-- %s\n", __func__);
        return;
+out_restart:
+       task->tk_status = 0;
+       rpc_restart_call_prepare(task);
+       return;
 out_overflow:
        task->tk_status = -EOVERFLOW;
        goto out;