From: Allison Henderson <achender@kernel.org>
To: netdev@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org, pabeni@redhat.com,
edumazet@google.com, rds-devel@oss.oracle.com, kuba@kernel.org,
horms@kernel.org, linux-rdma@vger.kernel.org,
allison.henderson@oracle.com
Subject: [PATCH net-next v2 1/4] net/rds: Refactor __rds_conn_create for blocking transport cleanup
Date: Sat, 7 Feb 2026 22:37:13 -0700 [thread overview]
Message-ID: <20260208053716.1617809-2-achender@kernel.org> (raw)
In-Reply-To: <20260208053716.1617809-1-achender@kernel.org>
The next patch will delegate fanout operations to a background worker,
which requires cancel_work_sync() during connection cleanup. However,
the error path of __rds_conn_create() currently calls
trans->conn_free() while holding rds_conn_lock (spinlock) and
rcu_read_lock, which creates an atomic context where cancel_work_sync()
cannot sleep.
To avoid this, refactor the error/race paths to defer
trans->conn_free() calls until after locks are released. This allows
transport cleanup functions to perform blocking operations safely.
This patch moves the cp_transport_data cleanup to the 'out:' label
where it runs outside the critical section, after the connection has
been freed from the slab and cannot be accessed by racing threads.
Signed-off-by: Allison Henderson <achender@kernel.org>
---
net/rds/connection.c | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/net/rds/connection.c b/net/rds/connection.c
index 185f73b01694..695ab7446178 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -170,6 +170,7 @@ static struct rds_connection *__rds_conn_create(struct net *net,
struct hlist_head *head = rds_conn_bucket(laddr, faddr);
struct rds_transport *loop_trans;
struct rds_conn_path *free_cp = NULL;
+ struct rds_transport *free_trans = NULL;
unsigned long flags;
int ret, i;
int npaths = (trans->t_mp_capable ? RDS_MPATH_WORKERS : 1);
@@ -305,7 +306,7 @@ static struct rds_connection *__rds_conn_create(struct net *net,
if (parent) {
/* Creating passive conn */
if (parent->c_passive) {
- trans->conn_free(conn->c_path[0].cp_transport_data);
+ free_trans = trans;
free_cp = conn->c_path;
kmem_cache_free(rds_conn_slab, conn);
conn = parent->c_passive;
@@ -321,18 +322,7 @@ static struct rds_connection *__rds_conn_create(struct net *net,
found = rds_conn_lookup(net, head, laddr, faddr, trans,
tos, dev_if);
if (found) {
- struct rds_conn_path *cp;
- int i;
-
- for (i = 0; i < npaths; i++) {
- cp = &conn->c_path[i];
- /* The ->conn_alloc invocation may have
- * allocated resource for all paths, so all
- * of them may have to be freed here.
- */
- if (cp->cp_transport_data)
- trans->conn_free(cp->cp_transport_data);
- }
+ free_trans = trans;
free_cp = conn->c_path;
kmem_cache_free(rds_conn_slab, conn);
conn = found;
@@ -349,9 +339,23 @@ static struct rds_connection *__rds_conn_create(struct net *net,
out:
if (free_cp) {
- for (i = 0; i < npaths; i++)
+ for (i = 0; i < npaths; i++) {
+ /*
+ * The trans->conn_alloc call may have allocated
+ * resources for the cp paths, which will need to
+ * be freed before freeing cp itself. We do this here
+ * so it runs outside the rds_conn_lock spinlock
+ * and rcu_read_lock section, because conn_free()
+ * may call cancel_work_sync() which
+ * can sleep. free_trans is only set in the
+ * race-loss paths where conn_alloc() succeeded.
+ */
+ if (free_trans && free_cp[i].cp_transport_data)
+ free_trans->conn_free
+ (free_cp[i].cp_transport_data);
if (free_cp[i].cp_wq != rds_wq)
destroy_workqueue(free_cp[i].cp_wq);
+ }
kfree(free_cp);
}
--
2.43.0
next prev parent reply other threads:[~2026-02-08 5:37 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-08 5:37 [PATCH net-next v2 0/4] net/rds: RDS-TCP reconnect and fanout improvements Allison Henderson
2026-02-08 5:37 ` Allison Henderson [this message]
2026-02-08 5:37 ` [PATCH net-next v2 2/4] net/rds: Delegate fan-out to a background worker Allison Henderson
2026-02-08 5:37 ` [PATCH net-next v2 3/4] net/rds: Use proper peer port number even when not connected Allison Henderson
2026-02-08 5:37 ` [PATCH net-next v2 4/4] net/rds: rds_sendmsg should not discard payload_len Allison Henderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260208053716.1617809-2-achender@kernel.org \
--to=achender@kernel.org \
--cc=allison.henderson@oracle.com \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=rds-devel@oss.oracle.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.