* [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
* [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
* 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
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