net/rds: use wq_has_sleeper() in rds_cong_map_updated()
authorAllison Henderson <achender@kernel.org>
Sat, 22 Aug 2026 05:26:47 +0000 (22:26 -0700)
committerJakub Kicinski <kuba@kernel.org>
Mon, 24 Aug 2026 19:03:25 +0000 (12:03 -0700)
rds_cong_map_updated() runs after a peer's congestion map has been
rewritten (by rds_tcp_cong_recv() and rds_ib_cong_recv(), or the
clear-all in the loopback and IB send-completion paths).  It bumps
rds_cong_generation and then checks waitqueue_active() on
map->m_waitq and on rds_poll_waitq to decide whether anyone needs
waking.  atomic_inc() carries no ordering and waitqueue_active() is a
plain load, so nothing orders the map and generation stores before
the wait queue reads.  The waiters do the mirror image: rds_cong_wait()
adds itself to m_waitq and then tests the port bit, and rds_poll()
registers on rds_poll_waitq and then reads the generation.  That is
the store-buffering pattern described above waitqueue_active() in
include/linux/wait.h - the updater can observe an empty wait queue
while the waiter still observes the port as congested, and no wake-up
is issued.

rds_cong_wait() is an interruptible sleep with no timeout, so a
sender blocked on a congested port stays blocked until the next
congestion update from that peer arrives or a signal is delivered.
A poll() waiter misses the map-updated notification the same way.

Use wq_has_sleeper(), which is waitqueue_active() preceded by the
required full barrier, as rds_tcp_state_change() already does for
the same pattern.

Fixes: 922cb17a5c81 ("RDS: Congestion-handling code")
Signed-off-by: Allison Henderson <achender@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260822052647.88318-1-achender@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/rds/cong.c

index 3133b91..f7634ce 100644 (file)
@@ -256,9 +256,9 @@ void rds_cong_map_updated(struct rds_cong_map *map, uint64_t portmask)
          map, &map->m_addr);
        rds_stats_inc(s_cong_update_received);
        atomic_inc(&rds_cong_generation);
-       if (waitqueue_active(&map->m_waitq))
+       if (wq_has_sleeper(&map->m_waitq))
                wake_up(&map->m_waitq);
-       if (waitqueue_active(&rds_poll_waitq))
+       if (wq_has_sleeper(&rds_poll_waitq))
                wake_up_all(&rds_poll_waitq);
 
        if (portmask && !list_empty(&rds_cong_monitor)) {