Commit ed7dc973 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

SUNRPC: Prevent thundering herd when the socket is not connected



If the socket is not connected, then we want to initiate a reconnect
rather that trying to transmit requests. If there is a large number
of requests queued and waiting for the lock in call_transmit(),
then it can take a while for one of the to loop back and retake
the lock in call_connect.

Fixes: 89f90fe1 ("SUNRPC: Allow calls to xprt_transmit() to drain...")
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 0d1bf340
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -1807,7 +1807,12 @@ call_encode(struct rpc_task *task)
		xprt_request_enqueue_receive(task);
	xprt_request_enqueue_transmit(task);
out:
	task->tk_action = call_transmit;
	/* Check that the connection is OK */
	if (!xprt_bound(task->tk_xprt))
		task->tk_action = call_bind;
	else if (!xprt_connected(task->tk_xprt))
		task->tk_action = call_connect;
}

/*
@@ -1999,13 +2004,19 @@ call_transmit(struct rpc_task *task)
{
	dprint_status(task);

	task->tk_status = 0;
	task->tk_action = call_transmit_status;
	if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) {
		if (!xprt_prepare_transmit(task))
			return;
		task->tk_status = 0;
		if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) {
			if (!xprt_connected(task->tk_xprt)) {
				task->tk_status = -ENOTCONN;
				return;
			}
			xprt_transmit(task);
		}
	task->tk_action = call_transmit_status;
	}
	xprt_end_transmit(task);
}

@@ -2067,6 +2078,8 @@ call_transmit_status(struct rpc_task *task)
	case -EADDRINUSE:
	case -ENOTCONN:
	case -EPIPE:
		task->tk_action = call_bind;
		task->tk_status = 0;
		break;
	}
}