SUNRPC: Partial revert of commit 6f9f17287e78
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 12 Jul 2021 13:52:59 +0000 (09:52 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 4 Oct 2021 00:49:05 +0000 (20:49 -0400)
The premise of commit 6f9f17287e78 ("SUNRPC: Mitigate cond_resched() in
xprt_transmit()") was that cond_resched() is expensive and unnecessary
when there has been just a single send.
The point of cond_resched() is to ensure that tasks that should pre-empt
this one get a chance to do so when it is safe to do so. The code prior
to commit 6f9f17287e78 failed to take into account that it was keeping a
rpc_task pinned for longer than it needed to, and so rather than doing a
full revert, let's just move the cond_resched.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
net/sunrpc/xprt.c

index cfd6817..d4aeee8 100644 (file)
@@ -1603,15 +1603,14 @@ xprt_transmit(struct rpc_task *task)
 {
        struct rpc_rqst *next, *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
-       int counter, status;
+       int status;
 
        spin_lock(&xprt->queue_lock);
-       counter = 0;
-       while (!list_empty(&xprt->xmit_queue)) {
-               if (++counter == 20)
+       for (;;) {
+               next = list_first_entry_or_null(&xprt->xmit_queue,
+                                               struct rpc_rqst, rq_xmit);
+               if (!next)
                        break;
-               next = list_first_entry(&xprt->xmit_queue,
-                               struct rpc_rqst, rq_xmit);
                xprt_pin_rqst(next);
                spin_unlock(&xprt->queue_lock);
                status = xprt_request_transmit(next, task);
@@ -1619,13 +1618,16 @@ xprt_transmit(struct rpc_task *task)
                        status = 0;
                spin_lock(&xprt->queue_lock);
                xprt_unpin_rqst(next);
-               if (status == 0) {
-                       if (!xprt_request_data_received(task) ||
-                           test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate))
-                               continue;
-               } else if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate))
-                       task->tk_status = status;
-               break;
+               if (status < 0) {
+                       if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate))
+                               task->tk_status = status;
+                       break;
+               }
+               /* Was @task transmitted, and has it received a reply? */
+               if (xprt_request_data_received(task) &&
+                   !test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate))
+                       break;
+               cond_resched_lock(&xprt->queue_lock);
        }
        spin_unlock(&xprt->queue_lock);
 }