5.0-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Trond Myklebust <trond.mykleb...@hammerspace.com>

commit ed7dc973bd91da234d93aff6d033a5206a6c9885 upstream.

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: 89f90fe1ad8b ("SUNRPC: Allow calls to xprt_transmit() to drain...")
Signed-off-by: Trond Myklebust <trond.mykleb...@hammerspace.com>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 net/sunrpc/clnt.c |   21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1786,7 +1786,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;
 }
 
 /*
@@ -1978,13 +1983,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);
 }
 
@@ -2046,6 +2057,8 @@ call_transmit_status(struct rpc_task *ta
        case -EADDRINUSE:
        case -ENOTCONN:
        case -EPIPE:
+               task->tk_action = call_bind;
+               task->tk_status = 0;
                break;
        }
 }


Reply via email to