[PATCH 5/6] nvmet: fix controller reference leak in nvmet_install_queue() error paths

Guixin Liu kanie at linux.alibaba.com
Thu Nov 5 17:58:41 PST 2026


nvmet_install_queue() takes a controller reference for req->cq->ctrl
and installs the controller in both req->sq->ctrl and req->cq->ctrl,
but neither error path undoes its work: the busy return after the
failed cq->ctrl cmpxchg leaves sq->ctrl set and the reference taken,
and the err path for a failed transport ->install_queue() clears
sq->ctrl but leaves cq->ctrl set with the reference still held.

The queue is then permanently wedged: a connect retry finds the stale
cq->ctrl, takes another reference and fails again, and the leaked
references keep the controller alive forever. Clearing cq->ctrl also
matters because the caller drops its own reference, which can be the
last one on the admin connect path, leaving cq->ctrl dangling.

Roll back the sq->ctrl assignment and drop the reference on both
error paths, and also clear ctrl->cqs[qid] on the err path to mirror
what nvmet_cq_destroy() would do.

Fixes: bb78836b3a7ca ("nvmet: fabrics: add CQ init and destroy")
Cc: stable at vger.kernel.org
Signed-off-by: Guixin Liu <kanie at linux.alibaba.com>
---
 drivers/nvme/target/fabrics-cmd.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/nvme/target/fabrics-cmd.c b/drivers/nvme/target/fabrics-cmd.c
index fc626c2fd2c9..773dad857a35 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;
 	}
 
@@ -234,6 +236,7 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
 			pr_err("failed to install queue %d cntlid %d ret %x\n",
 				qid, ctrl->cntlid, ret);
 			ctrl->sqs[qid] = NULL;
+			ctrl->cqs[qid] = NULL;
 			goto err;
 		}
 	}
@@ -242,6 +245,8 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
 
 err:
 	req->sq->ctrl = NULL;
+	req->cq->ctrl = NULL;
+	nvmet_ctrl_put(ctrl);
 	return ret;
 }
 
-- 
2.43.7




More information about the Linux-nvme mailing list