| From d041e0304a2444c963a826aacbf8e198ee2d8d4d Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sat, 13 Nov 2021 15:33:35 +0800 |
| Subject: net/smc: Transfer remaining wait queue entries during fallback |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Wen Gu <guwen@linux.alibaba.com> |
| |
| [ Upstream commit 2153bd1e3d3dbf6a3403572084ef6ed31c53c5f0 ] |
| |
| The SMC fallback is incomplete currently. There may be some |
| wait queue entries remaining in smc socket->wq, which should |
| be removed to clcsocket->wq during the fallback. |
| |
| For example, in nginx/wrk benchmark, this issue causes an |
| all-zeros test result: |
| |
| server: nginx -g 'daemon off;' |
| client: smc_run wrk -c 1 -t 1 -d 5 http://11.200.15.93/index.html |
| |
| Running 5s test @ http://11.200.15.93/index.html |
| 1 threads and 1 connections |
| Thread Stats Avg Stdev Max ± Stdev |
| Latency 0.00us 0.00us 0.00us -nan% |
| Req/Sec 0.00 0.00 0.00 -nan% |
| 0 requests in 5.00s, 0.00B read |
| Requests/sec: 0.00 |
| Transfer/sec: 0.00B |
| |
| The reason for this all-zeros result is that when wrk used SMC |
| to replace TCP, it added an eppoll_entry into smc socket->wq |
| and expected to be notified if epoll events like EPOLL_IN/ |
| EPOLL_OUT occurred on the smc socket. |
| |
| However, once a fallback occurred, wrk switches to use clcsocket. |
| Now it is clcsocket->wq instead of smc socket->wq which will |
| be woken up. The eppoll_entry remaining in smc socket->wq does |
| not work anymore and wrk stops the test. |
| |
| This patch fixes this issue by removing remaining wait queue |
| entries from smc socket->wq to clcsocket->wq during the fallback. |
| |
| Link: https://www.spinics.net/lists/netdev/msg779769.html |
| Signed-off-by: Wen Gu <guwen@linux.alibaba.com> |
| Reviewed-by: Tony Lu <tonylu@linux.alibaba.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/smc/af_smc.c | 14 ++++++++++++++ |
| 1 file changed, 14 insertions(+) |
| |
| diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c |
| index ac8265e35b2d2..04bf8088872a9 100644 |
| --- a/net/smc/af_smc.c |
| +++ b/net/smc/af_smc.c |
| @@ -513,12 +513,26 @@ static void smc_link_save_peer_info(struct smc_link *link, |
| |
| static void smc_switch_to_fallback(struct smc_sock *smc) |
| { |
| + wait_queue_head_t *smc_wait = sk_sleep(&smc->sk); |
| + wait_queue_head_t *clc_wait = sk_sleep(smc->clcsock->sk); |
| + unsigned long flags; |
| + |
| smc->use_fallback = true; |
| if (smc->sk.sk_socket && smc->sk.sk_socket->file) { |
| smc->clcsock->file = smc->sk.sk_socket->file; |
| smc->clcsock->file->private_data = smc->clcsock; |
| smc->clcsock->wq.fasync_list = |
| smc->sk.sk_socket->wq.fasync_list; |
| + |
| + /* There may be some entries remaining in |
| + * smc socket->wq, which should be removed |
| + * to clcsocket->wq during the fallback. |
| + */ |
| + spin_lock_irqsave(&smc_wait->lock, flags); |
| + spin_lock(&clc_wait->lock); |
| + list_splice_init(&smc_wait->head, &clc_wait->head); |
| + spin_unlock(&clc_wait->lock); |
| + spin_unlock_irqrestore(&smc_wait->lock, flags); |
| } |
| } |
| |
| -- |
| 2.33.0 |
| |