On 2/23/26 11:19 PM, Allison Henderson wrote:
From: Gerd Rausch <[email protected]>

Delegate fan-out to a background worker in order to allow
kernel_getpeername() to acquire a lock on the socket.

This has become necessary since the introduction of
commit "9dfc685e0262d ("inet: remove races in inet{6}_getname()")

The socket is already locked in the context that
"kernel_getpeername" used to get called by either
rds_tcp_recv_path" or "tcp_v{4,6}_rcv",
and therefore causing a deadlock.

Luckily, the fan-out need not happen in-context nor fast,
so we can easily just do the same in a background worker.

Also, while we're doing this, we get rid of the unused
struct members "t_conn_w", "t_send_w", "t_down_w" & "t_recv_w".

The fan-out work and the shutdown worker (cp_down_w) are both
queued on the same ordered workqueue (cp0->cp_wq), so they
cannot execute concurrently.  We only need cancel_work_sync()
in rds_tcp_conn_free() and rds_tcp_conn_path_connect() because
those run from outside the ordered workqueue.

Signed-off-by: Gerd Rausch <[email protected]>
Signed-off-by: Allison Henderson <[email protected]>
---
  net/rds/tcp.c         |  3 +++
  net/rds/tcp.h         |  7 ++----
  net/rds/tcp_connect.c |  2 ++
  net/rds/tcp_listen.c  | 54 +++++++++++++++++++++++++++++++------------
  4 files changed, 46 insertions(+), 20 deletions(-)


Isn't this change kind of dangerous since 021fd0f87004 ("net/rds: fix recursive lock in rds_tcp_conn_slots_available") [1]?. Why is kernel_getpeername() needed as only the peer source port is required for the operation?

Thanks,
Fernando.

Reply via email to