FAILED: patch "[PATCH] svcrdma: Clear sc_cm_id when ADDR_CHANGE replacement fails" failed to apply to 6.18-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 6.18-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-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 01500306e1d50de7ca7a2cdcdfa28ac0523eb747
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090325-lushness-making-8377@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 01500306e1d50de7ca7a2cdcdfa28ac0523eb747 Mon Sep 17 00:00:00 2001
From: Chuck Lever <[email protected]>
Date: Wed, 27 May 2026 11:00:15 -0400
Subject: [PATCH] svcrdma: Clear sc_cm_id when ADDR_CHANGE replacement fails
When svc_rdma_listen_handler() handles RDMA_CM_EVENT_ADDR_CHANGE, it creates a replacement listener cm_id and returns 1, telling the CM core to destroy the old one. If the replacement allocation fails, sc_cm_id still points at the old cm_id that the CM core is about to destroy. Any subsequent dereference of sc_cm_id -- such as svc_rdma_detach()'s rdma_disconnect() call -- is a use-after-free.
NULL sc_cm_id on the failure path and guard svc_rdma_detach()'s rdma_disconnect() call against NULL so that the listener can be torn down safely when the server shuts down.
net/sunrpc/xprtrdma/svc_rdma_transport.c +3 -1
@@ -330,6 +330,7 @@ static int svc_rdma_listen_handler(struct rdma_cm_id *cma_id,if (IS_ERR (listen_id)) {pr_err ("Listener dead, address change failed for device %s\n" , cma_id->device->name); + cma_xprt->sc_cm_id =NULL ; }else cma_xprt->sc_cm_id = listen_id;return 1 ;
@@ -638,7 +639,8 @@ static void svc_rdma_detach(struct svc_xprt *xprt)struct svcxprt_rdma *rdma = container_of(xprt, struct svcxprt_rdma, sc_xprt); -rdma_disconnect (rdma->sc_cm_id); +if (rdma->sc_cm_id) +rdma_disconnect (rdma->sc_cm_id);/* * Most close paths go through svc_rdma_xprt_deferred_close(),
Sasha Levin
maintainerPATCH 1/2 svcrdma: Add Write chunk WRs to the RPC's Send WR chain
From: Chuck Lever <[email protected]>
[ Upstream commit d16f060f3ee297424c0aba047b1d49208adb9318 ]
Previously, Write chunk RDMA Writes were posted via a separate ib_post_send() call with their own completion handler. Each Write chunk incurred a doorbell and generated a completion event.
Link Write chunk WRs onto the RPC Reply's Send WR chain so that a single ib_post_send() call posts both the RDMA Writes and the Send WR. A single completion event signals that all operations have finished. This reduces both doorbell rate and completion rate, as well as eliminating the latency of a round-trip between the Write chunk completion and the subsequent Send WR posting.
The lifecycle of Write chunk resources changes: previously, the svc_rdma_write_done() completion handler released Write chunk resources when RDMA Writes completed. With WR chaining, resources remain live until the Send completion. A new sc_write_info_list tracks Write chunk metadata attached to each Send context, and svc_rdma_write_chunk_release() frees these resources when the Send context is released.
The svc_rdma_write_done() handler now handles only error cases. On success it returns immediately since the Send completion handles resource release. On failure (WR flush), it closes the connection to signal to the client that the RPC Reply is incomplete.
Stable-dep-of: 01500306e1d5 ("svcrdma: Clear sc_cm_id when ADDR_CHANGE replacement fails")
--- include/linux/sunrpc/svc_rdma.h | 13 +++- net/sunrpc/xprtrdma/svc_rdma_rw.c | 94 ++++++++++++++++++++------- net/sunrpc/xprtrdma/svc_rdma_sendto.c | 10 ++- 3 files changed, 91 insertions(+), 26 deletions(-)
include/linux/sunrpc/svc_rdma.h +10 -3
@@ -213,6 +213,7 @@ struct svc_rdma_recv_ctxt {*/ struct svc_rdma_write_info {struct svcxprt_rdma *wi_rdma; +struct list_head wi_list;const struct svc_rdma_chunk *wi_chunk;
@@ -241,7 +242,10 @@ struct svc_rdma_send_ctxt {struct ib_cqe sc_cqe;struct xdr_buf sc_hdrbuf;struct xdr_stream sc_stream; + +struct list_head sc_write_info_list;struct svc_rdma_write_info sc_reply_info; +void *sc_xprt_buf;int sc_page_count;int sc_cur_sge_no;
@@ -274,11 +278,14 @@ extern void svc_rdma_cc_init(struct svcxprt_rdma *rdma,extern void svc_rdma_cc_release (struct svcxprt_rdma *rdma,struct svc_rdma_chunk_ctxt *cc,enum dma_data_direction dir); +extern void svc_rdma_write_chunk_release (struct svcxprt_rdma *rdma, +struct svc_rdma_send_ctxt *ctxt);extern void svc_rdma_reply_chunk_release (struct svcxprt_rdma *rdma,struct svc_rdma_send_ctxt *ctxt); -extern int svc_rdma_send_write_list (struct svcxprt_rdma *rdma, -const struct svc_rdma_recv_ctxt *rctxt, -const struct xdr_buf *xdr); +extern int svc_rdma_prepare_write_list (struct svcxprt_rdma *rdma, +const struct svc_rdma_recv_ctxt *rctxt, +struct svc_rdma_send_ctxt *sctxt, +const struct xdr_buf *xdr); extern int svc_rdma_prepare_reply_chunk(struct svcxprt_rdma *rdma, const struct svc_rdma_pcl *write_pcl, const struct svc_rdma_pcl *reply_pcl,
net/sunrpc/xprtrdma/svc_rdma_rw.c +72 -22
150 lines not on this page · raw message
net/sunrpc/xprtrdma/svc_rdma_sendto.c +9 -1
@@ -149,6 +149,7 @@ svc_rdma_send_ctxt_alloc(struct svcxprt_rdma *rdma) ctxt->sc_send_wr.sg_list = ctxt->sc_sges; ctxt->sc_send_wr.send_flags =IB_SEND_SIGNALED ; ctxt->sc_cqe.done = svc_rdma_wc_send; +INIT_LIST_HEAD (&ctxt->sc_write_info_list); ctxt->sc_xprt_buf = buffer;xdr_buf_init (&ctxt->sc_hdrbuf, ctxt->sc_xprt_buf, rdma->sc_max_req_size);
@@ -237,6 +238,7 @@ static void svc_rdma_send_ctxt_release(struct svcxprt_rdma *rdma,struct ib_device *device = rdma->sc_cm_id->device;unsigned int i; +svc_rdma_write_chunk_release (rdma, ctxt);svc_rdma_reply_chunk_release (rdma, ctxt);if (ctxt->sc_page_count)
@@ -993,6 +995,12 @@ void svc_rdma_send_error_msg(struct svcxprt_rdma *rdma, sctxt->sc_send_wr.num_sge =1 ; sctxt->sc_send_wr.opcode =IB_WR_SEND ; sctxt->sc_sges[0 ].length = sctxt->sc_hdrbuf.len; + +/* Ensure only the error message is posted, not any previously +* prepared Write chunk WRs. +*/ + sctxt->sc_wr_chain = &sctxt->sc_send_wr; + sctxt->sc_sqecount =1 ;if (svc_rdma_post_send (rdma, sctxt)) goto put_ctxt;return ;
@@ -1040,7 +1048,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)if (!p) goto put_ctxt; - ret =svc_rdma_send_write_list (rdma, rctxt, &rqstp->rq_res); + ret =svc_rdma_prepare_write_list (rdma, rctxt, sctxt, &rqstp->rq_res);if (ret <0 ) goto put_ctxt;
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 svcrdma: Clear sc_cm_id when ADDR_CHANGE replacement fails
From: Chuck Lever <[email protected]>
[ Upstream commit 01500306e1d50de7ca7a2cdcdfa28ac0523eb747 ]
When svc_rdma_listen_handler() handles RDMA_CM_EVENT_ADDR_CHANGE, it creates a replacement listener cm_id and returns 1, telling the CM core to destroy the old one. If the replacement allocation fails, sc_cm_id still points at the old cm_id that the CM core is about to destroy. Any subsequent dereference of sc_cm_id -- such as svc_rdma_detach()'s rdma_disconnect() call -- is a use-after-free.
NULL sc_cm_id on the failure path and guard svc_rdma_detach()'s rdma_disconnect() call against NULL so that the listener can be torn down safely when the server shuts down.
--- net/sunrpc/xprtrdma/svc_rdma_transport.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_transport.c +10 -2
@@ -311,6 +311,7 @@ static int svc_rdma_listen_handler(struct rdma_cm_id *cma_id,if (IS_ERR (listen_id)) {pr_err ("Listener dead, address change failed for device %s\n" , cma_id->device->name); + cma_xprt->sc_cm_id =NULL ; }else cma_xprt->sc_cm_id = listen_id;return 1 ;
@@ -610,14 +611,20 @@ static void svc_rdma_detach(struct svc_xprt *xprt)struct svcxprt_rdma *rdma = container_of(xprt, struct svcxprt_rdma, sc_xprt); -rdma_disconnect (rdma->sc_cm_id); +if (rdma->sc_cm_id) +rdma_disconnect (rdma->sc_cm_id); }static void __svc_rdma_free (struct work_struct *work) {struct svcxprt_rdma *rdma = container_of(work, struct svcxprt_rdma, sc_work); -struct ib_device *device = rdma->sc_cm_id->device; +struct ib_device *device; + +if (!rdma->sc_cm_id) + goto out_free; + + device = rdma->sc_cm_id->device;/* This blocks until the Completion Queues are empty */ if (rdma->sc_qp && !IS_ERR (rdma->sc_qp))
@@ -648,6 +655,7 @@ static void __svc_rdma_free(struct work_struct *work)if (!test_bit (XPT_LISTENER , &rdma->sc_xprt.xpt_flags))rpcrdma_rn_unregister (device, &rdma->sc_rn); +out_free:kfree (rdma); }
Signature · 1 line
2.53.0
Re: [PATCH 6.18.y 2/2] svcrdma: Clear sc_cm_id when ADDR_CHANGE replacement fails
Quoted 23 lines · Sasha Levin
From: Chuck Lever <[email protected]>
[ Upstream commit
01500306e1d50de7ca7a2cdcdfa28ac0523eb747]When
svc_rdma_listen_handler()handlesRDMA_CM_EVENT_ADDR_CHANGE, it creates a replacement listenercm_idand returns 1, telling the CM core to destroy the old one. If the replacement allocation fails,sc_cm_idstill points at the oldcm_idthat the CM core is about to destroy. Any subsequent dereference ofsc_cm_id-- such as svc_rdma_detach()'srdma_disconnect()call -- is a use-after-free.NULL
sc_cm_idon the failure path and guard svc_rdma_detach()'srdma_disconnect()call against NULL so that the listener can be torn down safely when the server shuts down.Fixes d1b586e75ec6 ("svcrdma: Handle ADDR_CHANGE CM event properly")Acked-by Jeff Layton <[email protected]>Signed-off-by Chuck Lever <[email protected]>[ added the missing sc_cm_id NULL guard to the existing __svc_rdma_free() cleanup worker. ]Signed-off-by Sasha Levin <[email protected]>
Quoted 4 lines
--- net/sunrpc/xprtrdma/svc_rdma_transport.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
Does not apply :(