]> git.baikalelectronics.ru Git - kernel.git/commitdiff
SUNRPC: Prevent thundering herd when the socket is not connected
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 4 Mar 2019 19:19:31 +0000 (14:19 -0500)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Thu, 7 Mar 2019 21:45:19 +0000 (16:45 -0500)
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: 402368d6c65b ("SUNRPC: Allow calls to xprt_transmit() to drain...")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
net/sunrpc/clnt.c

index 241e8423fd0c949bd575c9dab8d76bd36e350faf..7ab4da342ab52c791cd03e1a118c16af96c717cc 100644 (file)
@@ -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_bind;
+       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;
-               xprt_transmit(task);
+               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;
        }
 }