]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
SUNRPC: Respect RPC call timeouts when retrying transmission
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Thu, 7 Mar 2019 19:10:32 +0000 (14:10 -0500)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Thu, 7 Mar 2019 21:45:51 +0000 (16:45 -0500)
Fix a regression where soft and softconn requests are not timing out
as expected.

Fixes: 89f90fe1ad8b ("SUNRPC: Allow calls to xprt_transmit() to drain...")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
net/sunrpc/clnt.c

index b9558e10c6c166ac428366f7a86e2fe2ea6a4dbe..311029b7c33ad321ea65f25f3a8072f6b3cee02a 100644 (file)
@@ -79,6 +79,7 @@ static int    rpc_encode_header(struct rpc_task *task,
 static int     rpc_decode_header(struct rpc_task *task,
                                  struct xdr_stream *xdr);
 static int     rpc_ping(struct rpc_clnt *clnt);
+static void    rpc_check_timeout(struct rpc_task *task);
 
 static void rpc_register_client(struct rpc_clnt *clnt)
 {
@@ -1962,8 +1963,7 @@ call_connect_status(struct rpc_task *task)
                        break;
                if (clnt->cl_autobind) {
                        rpc_force_rebind(clnt);
-                       task->tk_action = call_bind;
-                       return;
+                       goto out_retry;
                }
                /* fall through */
        case -ECONNRESET:
@@ -1983,16 +1983,19 @@ call_connect_status(struct rpc_task *task)
                /* fall through */
        case -ENOTCONN:
        case -EAGAIN:
-               /* Check for timeouts before looping back to call_bind */
        case -ETIMEDOUT:
-               task->tk_action = call_timeout;
-               return;
+               goto out_retry;
        case 0:
                clnt->cl_stats->netreconn++;
                task->tk_action = call_transmit;
                return;
        }
        rpc_exit(task, status);
+       return;
+out_retry:
+       /* Check for timeouts before looping back to call_bind */
+       task->tk_action = call_bind;
+       rpc_check_timeout(task);
 }
 
 /*
@@ -2069,7 +2072,7 @@ call_transmit_status(struct rpc_task *task)
                                trace_xprt_ping(task->tk_xprt,
                                                task->tk_status);
                        rpc_exit(task, task->tk_status);
-                       break;
+                       return;
                }
                /* fall through */
        case -ECONNRESET:
@@ -2081,6 +2084,7 @@ call_transmit_status(struct rpc_task *task)
                task->tk_status = 0;
                break;
        }
+       rpc_check_timeout(task);
 }
 
 #if defined(CONFIG_SUNRPC_BACKCHANNEL)
@@ -2217,7 +2221,7 @@ call_status(struct rpc_task *task)
        case -EPIPE:
        case -ENOTCONN:
        case -EAGAIN:
-               task->tk_action = call_encode;
+               task->tk_action = call_timeout;
                break;
        case -EIO:
                /* shutdown or soft timeout */
@@ -2231,20 +2235,13 @@ call_status(struct rpc_task *task)
        }
 }
 
-/*
- * 6a. Handle RPC timeout
- *     We do not release the request slot, so we keep using the
- *     same XID for all retransmits.
- */
 static void
-call_timeout(struct rpc_task *task)
+rpc_check_timeout(struct rpc_task *task)
 {
        struct rpc_clnt *clnt = task->tk_client;
 
-       if (xprt_adjust_timeout(task->tk_rqstp) == 0) {
-               dprintk("RPC: %5u call_timeout (minor)\n", task->tk_pid);
-               goto retry;
-       }
+       if (xprt_adjust_timeout(task->tk_rqstp) == 0)
+               return;
 
        dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid);
        task->tk_timeouts++;
@@ -2280,10 +2277,19 @@ call_timeout(struct rpc_task *task)
         * event? RFC2203 requires the server to drop all such requests.
         */
        rpcauth_invalcred(task);
+}
 
-retry:
+/*
+ * 6a. Handle RPC timeout
+ *     We do not release the request slot, so we keep using the
+ *     same XID for all retransmits.
+ */
+static void
+call_timeout(struct rpc_task *task)
+{
        task->tk_action = call_encode;
        task->tk_status = 0;
+       rpc_check_timeout(task);
 }
 
 /*