| From ea7a1019d8baf8503ecd6e3ec8436dec283569e6 Mon Sep 17 00:00:00 2001 |
| From: Trond Myklebust <trond.myklebust@hammerspace.com> |
| Date: Mon, 12 Jul 2021 09:52:59 -0400 |
| Subject: SUNRPC: Partial revert of commit 6f9f17287e78 |
| |
| From: Trond Myklebust <trond.myklebust@hammerspace.com> |
| |
| commit ea7a1019d8baf8503ecd6e3ec8436dec283569e6 upstream. |
| |
| 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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/sunrpc/xprt.c | 28 +++++++++++++++------------- |
| 1 file changed, 15 insertions(+), 13 deletions(-) |
| |
| --- a/net/sunrpc/xprt.c |
| +++ b/net/sunrpc/xprt.c |
| @@ -1538,15 +1538,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); |
| @@ -1554,13 +1553,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); |
| } |