[PATCH 6/6] nvmet: roll back queue bindings on connection failure

From: shao.mingyin

Date: Tue Nov 10 2026 - 10:17:43 EST


From: Shao Mingyin <shao.mingyin@xxxxxxxxxx>

nvmet_install_queue() publishes the SQ controller pointer before
claiming the CQ. If the CQ is already connected, it leaves the SQ
pointer and the controller reference taken for it behind on failure.

An install_queue() callback failure also leaves the CQ bound after
clearing the SQ pointer. The reference taken in nvmet_install_queue()
is in addition to the one the caller already holds: the caller's put
releases the reference acquired before the call, while this one belongs
to the CQ binding. It is not released on this path, so the controller
stays alive and a Connect retry on the same queue keeps finding the
stale binding.

Clear the tentative SQ binding and release the extra reference on a CQ
conflict. On a transport installation failure, destroy the CQ binding
as well, so its controller table entry and reference are released.

Link: https://lore.kernel.org/all/20261106015842.3534898-6-kanie@xxxxxxxxxxxxxxxxx/
Fixes: bb78836b3a7c ("nvmet: fabrics: add CQ init and destroy")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
---
drivers/nvme/target/fabrics-cmd.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/nvme/target/fabrics-cmd.c b/drivers/nvme/target/fabrics-cmd.c
index fc626c2fd2c9..6f0fc695e649 100644
--- a/drivers/nvme/target/fabrics-cmd.c
+++ b/drivers/nvme/target/fabrics-cmd.c
@@ -216,6 +216,8 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
if (old) {
pr_warn("queue already connected!\n");
req->error_loc = offsetof(struct nvmf_connect_command, opcode);
+ req->sq->ctrl = NULL;
+ nvmet_ctrl_put(ctrl);
return NVME_SC_CONNECT_CTRL_BUSY | NVME_STATUS_DNR;
}

@@ -242,6 +244,7 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req)

err:
req->sq->ctrl = NULL;
+ nvmet_cq_destroy(req->cq);
return ret;
}

--
2.27.0