FAILED: patch "[PATCH] svcrdma: Use svc_xprt_put to free listener on create failure" failed to apply to 5.15-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x e346ef7bcb137f50c49f969330ab7dcf64ea1654
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090356-skimpily-grape-6667@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From e346ef7bcb137f50c49f969330ab7dcf64ea1654 Mon Sep 17 00:00:00 2001
From: Chuck Lever <[email protected]>
Date: Wed, 27 May 2026 11:00:13 -0400
Subject: [PATCH] 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.
net/sunrpc/xprtrdma/svc_rdma_transport.c +7 -1
@@ -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;
Sasha Levin
maintainerPATCH 1/4 svcrdma: Allocate new transports on device's NUMA node
From: Chuck Lever <[email protected]>
[ Upstream commit fe2b401e55482cf90a0056209c8a232b2d39056c ]
The physical device's NUMA node ID is available when allocating an svc_xprt for an incoming connection. Use that value to ensure the svc_xprt structure is allocated on the NUMA node closest to the device.
Stable-dep-of: e346ef7bcb13 ("svcrdma: Use svc_xprt_put to free listener on create failure")
--- net/sunrpc/xprtrdma/svc_rdma_transport.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_transport.c +9 -9
@@ -64,7 +64,7 @@#define RPCDBG_FACILITY RPCDBG_SVCXPRTstatic struct svcxprt_rdma *svc_rdma_create_xprt (struct svc_serv *serv, -struct net *net); +struct net *net,int node); static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, struct net *net, struct sockaddr *sa, int salen,
@@ -125,14 +125,14 @@ static void qp_event_handler(struct ib_event *event, void *context) }static struct svcxprt_rdma *svc_rdma_create_xprt (struct svc_serv *serv, -struct net *net) +struct net *net,int node) { -struct svcxprt_rdma *cma_xprt =kzalloc (sizeof *cma_xprt,GFP_KERNEL ); +struct svcxprt_rdma *cma_xprt; -if (!cma_xprt) { -dprintk ("svcrdma: failed to create new transport\n" ); + cma_xprt =kzalloc_node (sizeof (*cma_xprt),GFP_KERNEL , node); +if (!cma_xprt)return NULL ; - } +svc_xprt_init (net, &svc_rdma_class, &cma_xprt->sc_xprt, serv);INIT_LIST_HEAD (&cma_xprt->sc_accept_q);INIT_LIST_HEAD (&cma_xprt->sc_rq_dto_q);
@@ -195,9 +195,9 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id,struct svcxprt_rdma *newxprt;struct sockaddr *sa; -/* Create a new transport */ newxprt =svc_rdma_create_xprt (listen_xprt->sc_xprt.xpt_server, - listen_xprt->sc_xprt.xpt_net); + listen_xprt->sc_xprt.xpt_net, +ibdev_to_node (new_cma_id->device));if (!newxprt)return ; newxprt->sc_cm_id = new_cma_id;
@@ -306,7 +306,7 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,if (sa->sa_family !=AF_INET && sa->sa_family !=AF_INET6 )return ERR_PTR (-EAFNOSUPPORT ); - cma_xprt =svc_rdma_create_xprt (serv, net); + cma_xprt =svc_rdma_create_xprt (serv, net,NUMA_NO_NODE );if (!cma_xprt)return ERR_PTR (-ENOMEM );set_bit (XPT_LISTENER , &cma_xprt->sc_xprt.xpt_flags);
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/4 svcrdma: Refactor the creation of listener CMA ID
From: Chuck Lever <[email protected]>
[ Upstream commit 283d28546234b1764a0a37cb3df30cc3321c75b4 ]
In a moment, I will add a second consumer of CMA ID creation in svcrdma. Refactor so this code can be reused.
Stable-dep-of: e346ef7bcb13 ("svcrdma: Use svc_xprt_put to free listener on create failure")
--- net/sunrpc/xprtrdma/svc_rdma_transport.c | 67 ++++++++++++++---------- 1 file changed, 40 insertions(+), 27 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_transport.c +40 -27
@@ -65,6 +65,8 @@static struct svcxprt_rdma *svc_rdma_create_xprt (struct svc_serv *serv,struct net *net,int node); +static int svc_rdma_listen_handler (struct rdma_cm_id *cma_id, +struct rdma_cm_event *event); static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, struct net *net, struct sockaddr *sa, int salen,
@@ -124,6 +126,41 @@ static void qp_event_handler(struct ib_event *event, void *context) } } +static struct rdma_cm_id * +svc_rdma_create_listen_id (struct net *net,struct sockaddr *sap, +void *context) +{ +struct rdma_cm_id *listen_id; +int ret; + + listen_id =rdma_create_id (net, svc_rdma_listen_handler, context, +RDMA_PS_TCP ,IB_QPT_RC ); +if (IS_ERR (listen_id)) +return listen_id; + +/* Allow both IPv4 and IPv6 sockets to bind a single port +* at the same time. +*/ +#if IS_ENABLED (CONFIG_IPV6 ) + ret =rdma_set_afonly (listen_id,1 ); +if (ret) + goto out_destroy; +#endif + ret =rdma_bind_addr (listen_id, sap); +if (ret) + goto out_destroy; + + ret =rdma_listen (listen_id,RPCRDMA_LISTEN_BACKLOG ); +if (ret) + goto out_destroy; + +return listen_id; + +out_destroy: +rdma_destroy_id (listen_id); +return ERR_PTR (ret); +} +static struct svcxprt_rdma *svc_rdma_create_xprt (struct svc_serv *serv,struct net *net,int node) {
@@ -302,7 +339,6 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, {struct rdma_cm_id *listen_id;struct svcxprt_rdma *cma_xprt; -int ret;if (sa->sa_family !=AF_INET && sa->sa_family !=AF_INET6 )return ERR_PTR (-EAFNOSUPPORT );
@@ -312,30 +348,13 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,set_bit (XPT_LISTENER , &cma_xprt->sc_xprt.xpt_flags);strcpy (cma_xprt->sc_xprt.xpt_remotebuf,"listener" ); - listen_id =rdma_create_id (net, svc_rdma_listen_handler, cma_xprt, -RDMA_PS_TCP ,IB_QPT_RC ); + listen_id =svc_rdma_create_listen_id (net, sa, cma_xprt);if (IS_ERR (listen_id)) { - ret =PTR_ERR (listen_id); - goto err0; +kfree (cma_xprt); +return (struct svc_xprt *)listen_id; } - -/* Allow both IPv4 and IPv6 sockets to bind a single port -* at the same time. -*/ -#if IS_ENABLED (CONFIG_IPV6 ) - ret =rdma_set_afonly (listen_id,1 ); -if (ret) - goto err1; -#endif - ret =rdma_bind_addr (listen_id, sa); -if (ret) - goto err1; cma_xprt->sc_cm_id = listen_id; - ret =rdma_listen (listen_id,RPCRDMA_LISTEN_BACKLOG ); -if (ret) - goto err1; -/* * We need to use the address from the cm_id in case the * caller specified 0 for the port number.
@@ -344,12 +363,6 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,svc_xprt_set_local (&cma_xprt->sc_xprt, sa, salen);return &cma_xprt->sc_xprt; - - err1: -rdma_destroy_id (listen_id); - err0: -kfree (cma_xprt); -return ERR_PTR (ret); }/*
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/4 sunrpc: xprtrdma: Use ERR_CAST() to return
In reply to Sasha LevinFrom: Yan Zhen <[email protected]>
[ Upstream commit aeddf8e6c5662d60d434ce59f7e08ea020162323 ]
Using ERR_CAST() is more reasonable and safer, When it is necessary to convert the type of an error pointer and return it.
Stable-dep-of: e346ef7bcb13 ("svcrdma: Use svc_xprt_put to free listener on create failure")
--- net/sunrpc/xprtrdma/svc_rdma_transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sunrpc/xprtrdma/svc_rdma_transport.c +1 -1
@@ -351,7 +351,7 @@ 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); -return (struct svc_xprt *)listen_id; +return ERR_CAST (listen_id); } cma_xprt->sc_cm_id = listen_id;
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 4/4 svcrdma: Use svc_xprt_put to free listener on create failure
In reply to Sasha LevinFrom: Chuck Lever <[email protected]>
[ Upstream commit e346ef7bcb137f50c49f969330ab7dcf64ea1654 ]
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.
--- net/sunrpc/xprtrdma/svc_rdma_transport.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
net/sunrpc/xprtrdma/svc_rdma_transport.c +7 -1
@@ -350,7 +350,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;
Signature · 1 line
2.53.0