]> git.ipfire.org Git - thirdparty/kernel/linux.git/blobdiff - net/sunrpc/clnt.c
SUNRPC: Ignore queue transmission errors on successful transmission
[thirdparty/kernel/linux.git] / net / sunrpc / clnt.c
index 228970e6e52ba8b407be724d055976dd67530f81..8ff11dc98d7f93fefeff6ecc53ff6d7815da47f8 100644 (file)
@@ -1540,7 +1540,6 @@ call_start(struct rpc_task *task)
        clnt->cl_stats->rpccnt++;
        task->tk_action = call_reserve;
        rpc_task_set_transport(task, clnt);
-       call_reserve(task);
 }
 
 /*
@@ -1554,9 +1553,6 @@ call_reserve(struct rpc_task *task)
        task->tk_status  = 0;
        task->tk_action  = call_reserveresult;
        xprt_reserve(task);
-       if (rpc_task_need_resched(task))
-               return;
-        call_reserveresult(task);
 }
 
 static void call_retry_reserve(struct rpc_task *task);
@@ -1579,7 +1575,6 @@ call_reserveresult(struct rpc_task *task)
        if (status >= 0) {
                if (task->tk_rqstp) {
                        task->tk_action = call_refresh;
-                       call_refresh(task);
                        return;
                }
 
@@ -1605,7 +1600,6 @@ call_reserveresult(struct rpc_task *task)
                /* fall through */
        case -EAGAIN:   /* woken up; retry */
                task->tk_action = call_retry_reserve;
-               call_retry_reserve(task);
                return;
        case -EIO:      /* probably a shutdown */
                break;
@@ -1628,9 +1622,6 @@ call_retry_reserve(struct rpc_task *task)
        task->tk_status  = 0;
        task->tk_action  = call_reserveresult;
        xprt_retry_reserve(task);
-       if (rpc_task_need_resched(task))
-               return;
-       call_reserveresult(task);
 }
 
 /*
@@ -1645,9 +1636,6 @@ call_refresh(struct rpc_task *task)
        task->tk_status = 0;
        task->tk_client->cl_stats->rpcauthrefresh++;
        rpcauth_refreshcred(task);
-       if (rpc_task_need_resched(task))
-               return;
-       call_refreshresult(task);
 }
 
 /*
@@ -1666,7 +1654,6 @@ call_refreshresult(struct rpc_task *task)
        case 0:
                if (rpcauth_uptodatecred(task)) {
                        task->tk_action = call_allocate;
-                       call_allocate(task);
                        return;
                }
                /* Use rate-limiting and a max number of retries if refresh
@@ -1685,7 +1672,6 @@ call_refreshresult(struct rpc_task *task)
                task->tk_cred_retry--;
                dprintk("RPC: %5u %s: retry refresh creds\n",
                                task->tk_pid, __func__);
-               call_refresh(task);
                return;
        }
        dprintk("RPC: %5u %s: refresh creds failed with error %d\n",
@@ -1711,10 +1697,8 @@ call_allocate(struct rpc_task *task)
        task->tk_status = 0;
        task->tk_action = call_encode;
 
-       if (req->rq_buffer) {
-               call_encode(task);
+       if (req->rq_buffer)
                return;
-       }
 
        if (proc->p_proc != 0) {
                BUG_ON(proc->p_arglen == 0);
@@ -1740,12 +1724,8 @@ call_allocate(struct rpc_task *task)
 
        status = xprt->ops->buf_alloc(task);
        xprt_inject_disconnect(xprt);
-       if (status == 0) {
-               if (rpc_task_need_resched(task))
-                       return;
-               call_encode(task);
+       if (status == 0)
                return;
-       }
        if (status != -ENOMEM) {
                rpc_exit(task, status);
                return;
@@ -1828,8 +1808,12 @@ call_encode(struct rpc_task *task)
                xprt_request_enqueue_receive(task);
        xprt_request_enqueue_transmit(task);
 out:
-       task->tk_action = call_bind;
-       call_bind(task);
+       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;
 }
 
 /*
@@ -1847,7 +1831,6 @@ rpc_task_handle_transmitted(struct rpc_task *task)
 {
        xprt_end_transmit(task);
        task->tk_action = call_transmit_status;
-       call_transmit_status(task);
 }
 
 /*
@@ -1865,7 +1848,6 @@ call_bind(struct rpc_task *task)
 
        if (xprt_bound(xprt)) {
                task->tk_action = call_connect;
-               call_connect(task);
                return;
        }
 
@@ -1896,7 +1878,6 @@ call_bind_status(struct rpc_task *task)
                dprint_status(task);
                task->tk_status = 0;
                task->tk_action = call_connect;
-               call_connect(task);
                return;
        }
 
@@ -1981,7 +1962,6 @@ call_connect(struct rpc_task *task)
 
        if (xprt_connected(xprt)) {
                task->tk_action = call_transmit;
-               call_transmit(task);
                return;
        }
 
@@ -2051,7 +2031,6 @@ call_connect_status(struct rpc_task *task)
        case 0:
                clnt->cl_stats->netreconn++;
                task->tk_action = call_transmit;
-               call_transmit(task);
                return;
        }
        rpc_exit(task, status);
@@ -2087,9 +2066,6 @@ call_transmit(struct rpc_task *task)
                xprt_transmit(task);
        }
        xprt_end_transmit(task);
-       if (rpc_task_need_resched(task))
-               return;
-       call_transmit_status(task);
 }
 
 /*
@@ -2105,11 +2081,8 @@ call_transmit_status(struct rpc_task *task)
         * test first.
         */
        if (rpc_task_transmitted(task)) {
-               if (task->tk_status == 0)
-                       xprt_request_wait_receive(task);
-               if (rpc_task_need_resched(task))
-                       return;
-               call_status(task);
+               task->tk_status = 0;
+               xprt_request_wait_receive(task);
                return;
        }
 
@@ -2170,7 +2143,6 @@ call_bc_encode(struct rpc_task *task)
 {
        xprt_request_enqueue_transmit(task);
        task->tk_action = call_bc_transmit;
-       call_bc_transmit(task);
 }
 
 /*
@@ -2195,6 +2167,9 @@ call_bc_transmit_status(struct rpc_task *task)
 {
        struct rpc_rqst *req = task->tk_rqstp;
 
+       if (rpc_task_transmitted(task))
+               task->tk_status = 0;
+
        dprint_status(task);
 
        switch (task->tk_status) {
@@ -2261,7 +2236,6 @@ call_status(struct rpc_task *task)
        status = task->tk_status;
        if (status >= 0) {
                task->tk_action = call_decode;
-               call_decode(task);
                return;
        }
 
@@ -2311,6 +2285,15 @@ out_exit:
        rpc_exit(task, status);
 }
 
+static bool
+rpc_check_connected(const struct rpc_rqst *req)
+{
+       /* No allocated request or transport? return true */
+       if (!req || !req->rq_xprt)
+               return true;
+       return xprt_connected(req->rq_xprt);
+}
+
 static void
 rpc_check_timeout(struct rpc_task *task)
 {
@@ -2322,10 +2305,11 @@ rpc_check_timeout(struct rpc_task *task)
        dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid);
        task->tk_timeouts++;
 
-       if (RPC_IS_SOFTCONN(task)) {
+       if (RPC_IS_SOFTCONN(task) && !rpc_check_connected(task->tk_rqstp)) {
                rpc_exit(task, -ETIMEDOUT);
                return;
        }
+
        if (RPC_IS_SOFT(task)) {
                if (clnt->cl_chatty) {
                        printk(KERN_NOTICE "%s: server %s not responding, timed out\n",