[PATCH RFC 2/2] nvmet-rdma: use a separate lockdep class for the listening cm_id
Shin'ichiro Kawasaki
shinichiro.kawasaki at wdc.com
Sun Nov 8 04:01:54 PST 2026
Since the commit 2a8513091d2f ("nvme-rdma: parallelize I/O queue
allocation and startup"), the host sends commands on an I/O queue before
the target has seen RDMA_CM_EVENT_ESTABLISHED for that queue. nvmet-rdma
keeps such commands on queue->rsp_wait_list and executes them from
nvmet_rdma_cm_handler() when the ESTABLISHED event arrives, that is,
with the handler_mutex of the queue's cm_id held. Executing a connect
command takes nvmet_config_sem, which creates a handler_mutex ->
nvmet_config_sem dependency. This is the reverse of the order in
nvmet_port_subsys_drop_link(), which holds nvmet_config_sem and calls
rdma_destroy_id() on the port's listening cm_id via nvmet_disable_port().
Lockdep then reports a possible circular locking dependency:
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(nvmet_config_sem);
lock(&id_priv->handler_mutex);
lock(nvmet_config_sem);
lock(&id_priv->handler_mutex);
The warning is a false positive. The handler_mutex on CPU1 belongs to a
connected queue's cm_id, while the one on CPU0 belongs to the listening
cm_id, and nvmet-rdma does not take nvmet_config_sem while handling
events of the listening cm_id.
To silence the warning, call rdma_reclassify_id_for_listen() on the
listening cm_id right after it is created in nvmet_rdma_enable_port(),
so that its handler_mutex gets a lockdep class of its own.
This depends on the previous patch, which adds
rdma_reclassify_id_for_listen() to the RDMA CM.
Fixes: 2a8513091d2f ("nvme-rdma: parallelize I/O queue allocation and startup")
Link: https://lore.kernel.org/linux-nvme/at36um4zrsfOr3kh@shinmob/
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki at wdc.com>
---
drivers/nvme/target/rdma.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
index b9e39d1657d2..94f6d8edb517 100644
--- a/drivers/nvme/target/rdma.c
+++ b/drivers/nvme/target/rdma.c
@@ -1914,6 +1914,8 @@ static int nvmet_rdma_enable_port(struct nvmet_rdma_port *port)
return PTR_ERR(cm_id);
}
+ rdma_reclassify_id_for_listen(cm_id);
+
/*
* Allow both IPv4 and IPv6 sockets to bind a single port
* at the same time.
--
2.56.0
More information about the Linux-nvme
mailing list