NFSv4.x: Handle bad/dead sessions correctly in nfs41_sequence_process()
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Wed, 13 Nov 2019 07:34:00 +0000 (08:34 +0100)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Wed, 13 Nov 2019 15:37:17 +0000 (16:37 +0100)
If the server returns a bad or dead session error, the we don't want
to update the session slot number, but just immediately schedule
recovery and allow it to proceed.

We can/should then remove handling in other places

Fixes: 3453d5708b33 ("NFSv4.1: Avoid false retries when RPC calls are interrupted")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/nfs4proc.c

index 970172d..d1a7fac 100644 (file)
@@ -521,9 +521,7 @@ static int nfs4_do_handle_exception(struct nfs_server *server,
                case -NFS4ERR_DEADSESSION:
                case -NFS4ERR_SEQ_FALSE_RETRY:
                case -NFS4ERR_SEQ_MISORDERED:
-                       dprintk("%s ERROR: %d Reset session\n", __func__,
-                               errorcode);
-                       nfs4_schedule_session_recovery(clp->cl_session, errorcode);
+                       /* Handled in nfs41_sequence_process() */
                        goto wait_on_recovery;
 #endif /* defined(CONFIG_NFS_V4_1) */
                case -NFS4ERR_FILE_OPEN:
@@ -782,6 +780,7 @@ static int nfs41_sequence_process(struct rpc_task *task,
        struct nfs4_session *session;
        struct nfs4_slot *slot = res->sr_slot;
        struct nfs_client *clp;
+       int status;
        int ret = 1;
 
        if (slot == NULL)
@@ -793,8 +792,13 @@ static int nfs41_sequence_process(struct rpc_task *task,
        session = slot->table->session;
 
        trace_nfs4_sequence_done(session, res);
+
+       status = res->sr_status;
+       if (task->tk_status == -NFS4ERR_DEADSESSION)
+               status = -NFS4ERR_DEADSESSION;
+
        /* Check the SEQUENCE operation status */
-       switch (res->sr_status) {
+       switch (status) {
        case 0:
                /* Mark this sequence number as having been acked */
                nfs4_slot_sequence_acked(slot, slot->seq_nr);
@@ -866,6 +870,10 @@ static int nfs41_sequence_process(struct rpc_task *task,
                 */
                slot->seq_nr = slot->seq_nr_highest_sent;
                goto out_retry;
+       case -NFS4ERR_BADSESSION:
+       case -NFS4ERR_DEADSESSION:
+       case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+               goto session_recover;
        default:
                /* Just update the slot sequence no. */
                slot->seq_done = 1;
@@ -876,8 +884,10 @@ out:
 out_noaction:
        return ret;
 session_recover:
-       nfs4_schedule_session_recovery(session, res->sr_status);
-       goto retry_nowait;
+       nfs4_schedule_session_recovery(session, status);
+       dprintk("%s ERROR: %d Reset session\n", __func__, status);
+       nfs41_sequence_free_slot(res);
+       goto out;
 retry_new_seq:
        ++slot->seq_nr;
 retry_nowait:
@@ -2188,7 +2198,6 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
                case -NFS4ERR_BAD_HIGH_SLOT:
                case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
                case -NFS4ERR_DEADSESSION:
-                       nfs4_schedule_session_recovery(server->nfs_client->cl_session, err);
                        return -EAGAIN;
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_STALE_STATEID:
@@ -7824,6 +7833,15 @@ nfs41_same_server_scope(struct nfs41_server_scope *a,
 static void
 nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata)
 {
+       struct nfs41_bind_conn_to_session_args *args = task->tk_msg.rpc_argp;
+       struct nfs_client *clp = args->client;
+
+       switch (task->tk_status) {
+       case -NFS4ERR_BADSESSION:
+       case -NFS4ERR_DEADSESSION:
+               nfs4_schedule_session_recovery(clp->cl_session,
+                               task->tk_status);
+       }
 }
 
 static const struct rpc_call_ops nfs4_bind_one_conn_to_session_ops = {
@@ -8871,8 +8889,6 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf
        case -NFS4ERR_BADSESSION:
        case -NFS4ERR_DEADSESSION:
        case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
-               nfs4_schedule_session_recovery(clp->cl_session,
-                               task->tk_status);
                break;
        default:
                nfs4_schedule_lease_recovery(clp);