mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
svcrdma: Reorder rpcrdma_rn_unregister before rdma_destroy_id
svc_rdma_free() caches rdma->sc_cm_id->device before teardown,
then calls rdma_destroy_id(sc_cm_id) which frees the cm_id.
rpcrdma_rn_unregister() follows, but between those two calls
the transport's sc_rn entry is still installed in the device's
rd_xa. A concurrent ib_unregister_device walk can dispatch
svc_rdma_xprt_done() against the now-freed sc_cm_id.
Move rpcrdma_rn_unregister() before rdma_destroy_id() so the
transport's notification entry is removed from the xarray before
the cm_id it references is destroyed.
Also guard the sc_cm_id dereference with a NULL check: the
following patches introduce paths that reach svc_rdma_free()
with sc_cm_id == NULL (listener create failure, ADDR_CHANGE
replacement failure).
Fixes: c4de97f7c4 ("svcrdma: Handle device removal outside of the CM event handler")
Cc: stable@vger.kernel.org
Acked-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260527-rdma-follow-on-v1-2-1b09bd87b6cd@oracle.com
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
26190394c6
commit
4488e91297
|
|
@ -648,10 +648,15 @@ static void svc_rdma_free(struct svc_xprt *xprt)
|
|||
{
|
||||
struct svcxprt_rdma *rdma =
|
||||
container_of(xprt, struct svcxprt_rdma, sc_xprt);
|
||||
struct ib_device *device = rdma->sc_cm_id->device;
|
||||
struct ib_device *device;
|
||||
|
||||
might_sleep();
|
||||
|
||||
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))
|
||||
ib_drain_qp(rdma->sc_qp);
|
||||
|
|
@ -676,11 +681,13 @@ static void svc_rdma_free(struct svc_xprt *xprt)
|
|||
if (rdma->sc_pd && !IS_ERR(rdma->sc_pd))
|
||||
ib_dealloc_pd(rdma->sc_pd);
|
||||
|
||||
if (!test_bit(XPT_LISTENER, &rdma->sc_xprt.xpt_flags))
|
||||
rpcrdma_rn_unregister(device, &rdma->sc_rn);
|
||||
|
||||
/* Destroy the CM ID */
|
||||
rdma_destroy_id(rdma->sc_cm_id);
|
||||
|
||||
if (!test_bit(XPT_LISTENER, &rdma->sc_xprt.xpt_flags))
|
||||
rpcrdma_rn_unregister(device, &rdma->sc_rn);
|
||||
out_free:
|
||||
kfree(rdma);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user