Commit 5c441544 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFSv4.x: Handle bad/dead sessions correctly in nfs41_sequence_process()



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: 3453d570 ("NFSv4.1: Avoid false retries when RPC calls are interrupted")
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 634d811c
Loading
Loading
Loading
Loading
+25 −9
Original line number Diff line number Diff line
@@ -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 @@ 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:
@@ -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);