| From db601c1fa1e4fdb1f0071c291fd97c7583dc67a0 Mon Sep 17 00:00:00 2001 |
| From: Trond Myklebust <trond.myklebust@hammerspace.com> |
| Date: Wed, 13 Nov 2019 08:34:00 +0100 |
| Subject: [PATCH] NFSv4.x: Handle bad/dead sessions correctly in |
| nfs41_sequence_process() |
| |
| commit 5c441544f045e679afd6c3c6d9f7aaf5fa5f37b0 upstream. |
| |
| 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> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c |
| index 91cd512af4a2..eee199008bb8 100644 |
| --- a/fs/nfs/nfs4proc.c |
| +++ b/fs/nfs/nfs4proc.c |
| @@ -504,9 +504,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: |
| @@ -765,6 +763,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) |
| @@ -776,8 +775,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); |
| @@ -849,6 +853,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; |
| @@ -859,8 +867,10 @@ static int nfs41_sequence_process(struct rpc_task *task, |
| 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: |
| @@ -2154,7 +2164,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: |
| @@ -7710,6 +7719,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 = { |
| @@ -8756,8 +8774,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); |
| -- |
| 2.7.4 |
| |