summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2026-05-27 11:00:13 -0400
committerChuck Lever <cel@kernel.org>2026-07-05 21:07:22 -0400
commit0cec74f759cc2a17e1e74673ec262f75299f6256 (patch)
treedcdd0d1902142f41570a9f6fb37d6892700b9821
parent452f3092013e533b70725058cf7c365bce9f5ea1 (diff)
downloadlinux-next-0cec74f759cc2a17e1e74673ec262f75299f6256.tar.gz
linux-next-0cec74f759cc2a17e1e74673ec262f75299f6256.zip
svcrdma: Use svc_xprt_put to free listener on create failure
svc_rdma_create() calls kfree(cma_xprt) when svc_rdma_create_listen_id() fails. svc_xprt_init() has already acquired a net namespace reference via get_net_track(); kfree bypasses svc_xprt_free() which releases it. Replace the kfree() with svc_xprt_put() so the kref_init birth reference drops to zero and svc_xprt_free() dispatches svc_rdma_free() to clean up properly. sc_cm_id is still NULL at that point; the preceding patch added the necessary NULL guard in svc_rdma_free(). svc_xprt_free() also drops the module reference via module_put(), but the caller _svc_xprt_create() does the same on xpo_create failure, double-putting the single try_module_get() it acquired. Take a compensating __module_get() before the svc_xprt_put() to keep the count balanced, matching the convention in svc_rdma_accept()'s error path. Fixes: 4fb8518bdac8 ("sunrpc: Tag svc_xprt with net") Acked-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260527-rdma-follow-on-v1-3-1b09bd87b6cd@oracle.com Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_transport.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index 55e2ca036584..63dbf16dbe7f 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -388,7 +388,13 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
listen_id = svc_rdma_create_listen_id(net, sa, cma_xprt);
if (IS_ERR(listen_id)) {
- kfree(cma_xprt);
+ /* _svc_xprt_create() acquired one module reference and
+ * puts it on xpo_create failure. svc_xprt_free() puts
+ * a second one when the kref drops to zero. Take a
+ * compensating reference so both puts are balanced.
+ */
+ __module_get(cma_xprt->sc_xprt.xpt_class->xcl_owner);
+ svc_xprt_put(&cma_xprt->sc_xprt);
return ERR_CAST(listen_id);
}
cma_xprt->sc_cm_id = listen_id;