* [PATCH net-next v2 0/2] net/smc: fix v2 slot clearing and reduce TX slot contention @ 2026-08-21 9:17 D. Wythe 2026-08-21 9:17 ` [PATCH net-next v2 1/2] net/smc: clear the correct v2 slot and buffer in smc_wr_tx_put_slot() D. Wythe 2026-08-21 9:17 ` [PATCH net-next v2 2/2] net/smc: reduce TX slot contention with exclusive wait D. Wythe 0 siblings, 2 replies; 5+ messages in thread From: D. Wythe @ 2026-08-21 9:17 UTC (permalink / raw) To: mjambigi, wenjia, wintera, dust.li, tonylu, guwen Cc: kuba, davem, netdev, linux-s390, linux-rdma, leonro, pabeni, edumazet, sidraya, jaka, oliver.yang This series contains the two reviewed patches from the previously posted "net/smc: transition to RDMA core CQ pooling" series (v4), reposted as a standalone series so they can land independently. The remaining CQ pooling patch will be reposted separately after these two are merged. Patch 1 fixes smc_wr_tx_put_slot() to clear the v2 pending slot and buffer structures instead of the pointer variables, the memset targets were the 8-byte pointers themselves so the structures were never actually cleared. Patch 2 reduces TX slot contention by switching TX slot allocation from non-exclusive wait_event() to prepare_to_wait_exclusive(), avoiding thundering-herd wakes when slots are scarce. For patch 2, uperf numbers are now included in the commit message, as requested by Mahanta during v1 review. The short version is that the gain tracks how often the TX slot wait path is actually taken: with the default sysctl settings, where a link group multiplexes many connections over a small send queue, throughput improves by 134% on the 200x1000 request/response workload and by 458% on the 1-byte ping-pong workload; with a tuned configuration where slots are rarely exhausted, the change is neutral (+3.4% and +1.0%, i.e. within noise). See patch 2 for the full table. Link: https://lore.kernel.org/netdev/20260721175309.321b6503@kernel.org/ Link: https://lore.kernel.org/netdev/20260716113745.65234-1-alibuda@linux.alibaba.com/ --- v1 -> v2: - patch 2: add uperf baseline vs patched throughput figures to the commit message, as requested by Mahanta Jambigi. No functional change. Link: https://lore.kernel.org/netdev/e16d16f1-029b-4d30-b393-2e9e525a2998@linux.ibm.com/ - patch 1: unchanged. v1: https://lore.kernel.org/netdev/20260806064252.39180-1-alibuda@linux.alibaba.com/ D. Wythe (2): net/smc: clear the correct v2 slot and buffer in smc_wr_tx_put_slot() net/smc: reduce TX slot contention with exclusive wait net/smc/smc_wr.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) -- 2.45.0 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net-next v2 1/2] net/smc: clear the correct v2 slot and buffer in smc_wr_tx_put_slot() 2026-08-21 9:17 [PATCH net-next v2 0/2] net/smc: fix v2 slot clearing and reduce TX slot contention D. Wythe @ 2026-08-21 9:17 ` D. Wythe 2026-08-22 9:17 ` sashiko-bot 2026-08-21 9:17 ` [PATCH net-next v2 2/2] net/smc: reduce TX slot contention with exclusive wait D. Wythe 1 sibling, 1 reply; 5+ messages in thread From: D. Wythe @ 2026-08-21 9:17 UTC (permalink / raw) To: mjambigi, wenjia, wintera, dust.li, tonylu, guwen Cc: kuba, davem, netdev, linux-s390, linux-rdma, leonro, pabeni, edumazet, sidraya, jaka, oliver.yang smc_wr_tx_put_slot() tries to reset the v2 pending slot and buffer with memset(&link->wr_tx_v2_pend, 0, sizeof(link->wr_tx_v2_pend)) and the equivalent for wr_tx_buf_v2. Both are pointers, so this zeroes the 8-byte pointer variable instead of the structure it points to. The pending slot and buffer are therefore never actually cleared, and the pointers get overwritten with NULL. Pass the pointers directly and use sizeof(*pointer) so the intended structures are cleared. Fixes: 8799e310fb3f ("net/smc: add v2 support to the work request layer") Signed-off-by: D. Wythe <alibuda@linux.alibaba.com> Reviewed-by: Dust Li <dust.li@linux.alibaba.com> Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com> --- net/smc/smc_wr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c index 59c92b46945c..6b5add922993 100644 --- a/net/smc/smc_wr.c +++ b/net/smc/smc_wr.c @@ -288,10 +288,10 @@ int smc_wr_tx_put_slot(struct smc_link *link, } else if (link->lgr->smc_version == SMC_V2 && pend->idx == link->wr_tx_cnt) { /* Large v2 buffer */ - memset(&link->wr_tx_v2_pend, 0, - sizeof(link->wr_tx_v2_pend)); - memset(&link->lgr->wr_tx_buf_v2, 0, - sizeof(link->lgr->wr_tx_buf_v2)); + memset(link->wr_tx_v2_pend, 0, + sizeof(*link->wr_tx_v2_pend)); + memset(link->lgr->wr_tx_buf_v2, 0, + sizeof(*link->lgr->wr_tx_buf_v2)); return 1; } -- 2.45.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH net-next v2 1/2] net/smc: clear the correct v2 slot and buffer in smc_wr_tx_put_slot() 2026-08-21 9:17 ` [PATCH net-next v2 1/2] net/smc: clear the correct v2 slot and buffer in smc_wr_tx_put_slot() D. Wythe @ 2026-08-22 9:17 ` sashiko-bot 0 siblings, 0 replies; 5+ messages in thread From: sashiko-bot @ 2026-08-22 9:17 UTC (permalink / raw) To: D. Wythe Cc: Christian Borntraeger, linux-s390, Vasily Gorbik, Heiko Carstens, Alexander Gordeev Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [High] smc_wr_tx_wait_no_pending_sends() fails to wait for pending v2 WQEs, leading to premature link teardown and UAF in the CQE handler. - [High] Blind zeroing of V2 pending slot in CQE error path causes corruption of normal TX slot 0. -- --- Patch [1]: [PATCH net-next v2 1/2] net/smc: clear the correct v2 slot and buffer in smc_wr_tx_put_slot() --- commit c70c362b54a94b8914b4d46aec29581eca109cd3 Author: D. Wythe <alibuda@linux.alibaba.com> net/smc: clear the correct v2 slot and buffer in smc_wr_tx_put_slot() This patch fixes an issue where smc_wr_tx_put_slot() incorrectly zeroes the pointer variable itself rather than the intended v2 pending slot and buffer structures. It achieves this by passing the pointers directly and using sizeof(*pointer). > diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c > index 59c92b46945c5..6b5add9229937 100644 > --- a/net/smc/smc_wr.c > +++ b/net/smc/smc_wr.c > @@ -288,10 +288,10 @@ int smc_wr_tx_put_slot(struct smc_link *link, > } else if (link->lgr->smc_version == SMC_V2 && > pend->idx == link->wr_tx_cnt) { > /* Large v2 buffer */ > - memset(&link->wr_tx_v2_pend, 0, > - sizeof(link->wr_tx_v2_pend)); > - memset(&link->lgr->wr_tx_buf_v2, 0, > - sizeof(link->lgr->wr_tx_buf_v2)); > + memset(link->wr_tx_v2_pend, 0, > + sizeof(*link->wr_tx_v2_pend)); [Severity: High] This is a pre-existing issue, but does changing this memset from zeroing the pointer to zeroing the structure transform a previous NULL-pointer dereference into a silent data corruption regression? In smc_wr_tx_process_cqe(), if any CQE completes with an error, it indiscriminately zeroes the link->wr_tx_v2_pend structure. If a V2 slot operation is concurrently in progress, zeroing its structure changes its internal idx from link->wr_tx_cnt to 0. If the concurrent V2 operation then fails to post and calls smc_wr_tx_put_slot(), pend->idx < link->wr_tx_cnt evaluates to true. This targets normal slot 0, improperly clearing bit 0 in link->wr_tx_mask and freeing a slot that might be actively used by another thread. [Severity: High] This isn't a bug introduced by this patch, but does the link teardown process fail to wait for these V2 slots? smc_wr_tx_wait_no_pending_sends() waits by calling smc_wr_is_tx_pend(), which only checks if link->wr_tx_mask is empty: return !bitmap_empty(link->wr_tx_mask, link->wr_tx_cnt); However, the V2 TX slot is tracked separately and does not set a bit in wr_tx_mask. If a V2 WQE is in flight during link teardown, the wait condition will instantly return and the teardown process frees link->wr_tx_v2_pend. When the completion queue event (CQE) for the V2 WQE eventually fires, smc_wr_tx_process_cqe() dereferences the freed link->wr_tx_v2_pend to check the wr_id, resulting in a Use-After-Free regression. > + memset(link->lgr->wr_tx_buf_v2, 0, > + sizeof(*link->lgr->wr_tx_buf_v2)); > return 1; > } -- Sashiko AI review · https://sashiko.dev/#/patchset/20260821091702.21458-1-alibuda@linux.alibaba.com?part=1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net-next v2 2/2] net/smc: reduce TX slot contention with exclusive wait 2026-08-21 9:17 [PATCH net-next v2 0/2] net/smc: fix v2 slot clearing and reduce TX slot contention D. Wythe 2026-08-21 9:17 ` [PATCH net-next v2 1/2] net/smc: clear the correct v2 slot and buffer in smc_wr_tx_put_slot() D. Wythe @ 2026-08-21 9:17 ` D. Wythe 2026-08-22 9:17 ` sashiko-bot 1 sibling, 1 reply; 5+ messages in thread From: D. Wythe @ 2026-08-21 9:17 UTC (permalink / raw) To: mjambigi, wenjia, wintera, dust.li, tonylu, guwen Cc: kuba, davem, netdev, linux-s390, linux-rdma, leonro, pabeni, edumazet, sidraya, jaka, oliver.yang smc_wr_tx_get_free_slot() waits for a free TX slot with wait_event_interruptible_timeout(). Since the wait_event family enqueues waiters as non-exclusive, wake_up() may wake multiple waiters even though only one can use the slot, causing thundering-herd contention when slots are scarce. Use an exclusive wait loop with prepare_to_wait_exclusive() so wake_up() wakes only one waiter per freed slot. smc_wr_wakeup_tx_wait() still uses wake_up_all() during link teardown, so teardown behavior is unchanged. This also corrects the return value on a pending signal: the previous wait_event_interruptible_timeout() path fell through to the "no free slot" case and returned -EPIPE, masking the signal as a connection error. The open-coded loop now returns -ERESTARTSYS, matching the standard interruptible-wait semantics and letting the syscall restart machinery handle it. Performance =========== Measured with uperf between two peers over SMC-R. The benefit depends on how often the TX slot wait path is actually taken. With the default settings, where many connections share a link group and the send queue is small, slots are scarce and the wait path is hot: net.smc.smcr_max_conns_per_lgr = 255 net.smc.smcr_max_send_wr = 16 net.smc.smcr_max_recv_wr = 48 workload baseline patched delta --------------------------------------------------------- rr1c-200x1000-50.xml 655.06 Mb/s 1.53 Gb/s +134% rr1c-1x1-250.xml 371.03 Kb/s 2.07 Mb/s +458% With a tuned configuration, where slots are mostly available and the wait path is rarely entered, the change is neutral to slightly positive: net.smc.smcr_max_conns_per_lgr = 32 net.smc.smcr_max_send_wr = 64 net.smc.smcr_max_recv_wr = 64 workload baseline patched delta --------------------------------------------------------- rr1c-200x1000-50.xml 1.74 Gb/s 1.80 Gb/s +3.4% rr1c-1x1-250.xml 3.11 Mb/s 3.14 Mb/s +1.0% So the change does not regress the uncontended case, and recovers most of the throughput lost to thundering-herd wakeups once slots become scarce. Signed-off-by: D. Wythe <alibuda@linux.alibaba.com> Reviewed-by: Wen Gu <guwen@linux.alibaba.com> --- net/smc/smc_wr.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c index 6b5add922993..2cdd4063c13d 100644 --- a/net/smc/smc_wr.c +++ b/net/smc/smc_wr.c @@ -198,11 +198,13 @@ int smc_wr_tx_get_free_slot(struct smc_link *link, struct smc_rdma_wr **wr_rdma_buf, struct smc_wr_tx_pend_priv **wr_pend_priv) { + unsigned long timeout = SMC_WR_TX_WAIT_FREE_SLOT_TIME; struct smc_link_group *lgr = smc_get_lgr(link); struct smc_wr_tx_pend *wr_pend; u32 idx = link->wr_tx_cnt; struct ib_send_wr *wr_ib; u64 wr_id; + DEFINE_WAIT(wait); int rc; *wr_buf = NULL; @@ -212,17 +214,31 @@ int smc_wr_tx_get_free_slot(struct smc_link *link, if (rc) return rc; } else { - rc = wait_event_interruptible_timeout( - link->wr_tx_wait, - !smc_link_sendable(link) || - lgr->terminating || - (smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY), - SMC_WR_TX_WAIT_FREE_SLOT_TIME); - if (!rc) { - /* timeout - terminate link */ - smcr_link_down_cond_sched(link); - return -EPIPE; + rc = 0; + for (;;) { + prepare_to_wait_exclusive(&link->wr_tx_wait, &wait, + TASK_INTERRUPTIBLE); + if (!smc_link_sendable(link) || lgr->terminating || + smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY) + break; + timeout = schedule_timeout(timeout); + /* re-check */ + if (!smc_link_sendable(link) || lgr->terminating || + smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY) + break; + if (!timeout) { + /* timeout - terminate link */ + smcr_link_down_cond_sched(link); + break; + } + if (signal_pending(current)) { + rc = -ERESTARTSYS; + break; + } } + finish_wait(&link->wr_tx_wait, &wait); + if (rc) + return rc; if (idx == link->wr_tx_cnt) return -EPIPE; } -- 2.45.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH net-next v2 2/2] net/smc: reduce TX slot contention with exclusive wait 2026-08-21 9:17 ` [PATCH net-next v2 2/2] net/smc: reduce TX slot contention with exclusive wait D. Wythe @ 2026-08-22 9:17 ` sashiko-bot 0 siblings, 0 replies; 5+ messages in thread From: sashiko-bot @ 2026-08-22 9:17 UTC (permalink / raw) To: D. Wythe Cc: Alexander Gordeev, Vasily Gorbik, Christian Borntraeger, Heiko Carstens, linux-s390 > smc_wr_tx_get_free_slot() waits for a free TX slot with > wait_event_interruptible_timeout(). Since the wait_event family > enqueues waiters as non-exclusive, wake_up() may wake multiple > waiters even though only one can use the slot, causing > thundering-herd contention when slots are scarce. > > Use an exclusive wait loop with prepare_to_wait_exclusive() so > wake_up() wakes only one waiter per freed slot. > smc_wr_wakeup_tx_wait() still uses wake_up_all() during link > teardown, so teardown behavior is unchanged. > > This also corrects the return value on a pending signal: the previous > wait_event_interruptible_timeout() path fell through to the "no free > slot" case and returned -EPIPE, masking the signal as a connection > error. The open-coded loop now returns -ERESTARTSYS, matching the > [ ... ] > So the change does not regress the uncontended case, and recovers most > of the throughput lost to thundering-herd wakeups once slots become > scarce. > > Signed-off-by: D. Wythe <alibuda@linux.alibaba.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260821091702.21458-1-alibuda@linux.alibaba.com?part=2 ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-22 9:17 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-08-21 9:17 [PATCH net-next v2 0/2] net/smc: fix v2 slot clearing and reduce TX slot contention D. Wythe 2026-08-21 9:17 ` [PATCH net-next v2 1/2] net/smc: clear the correct v2 slot and buffer in smc_wr_tx_put_slot() D. Wythe 2026-08-22 9:17 ` sashiko-bot 2026-08-21 9:17 ` [PATCH net-next v2 2/2] net/smc: reduce TX slot contention with exclusive wait D. Wythe 2026-08-22 9:17 ` sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox