[PATCH v2] nvmet: Handle a NULL admin queue in nvmet_queue_tls_keyid()

Guixin Liu kanie at linux.alibaba.com
Thu Oct 29 19:36:39 PDT 2026



在 2026/10/29 20:15, Christoph Hellwig 写道:
> On Thu, Oct 29, 2026 at 11:43:06AM +0800, Guixin Liu wrote:
>> The admin queue is not necessarily installed when the tls_key debugfs
>> entry is read: it may not have been created yet, or it may have been
>> destroyed already.  nvmet_queue_tls_keyid() then dereferences a NULL
>> sq.
>>
>> Guard the helper and return 0 instead, which also covers the read
>> racing with admin queue teardown.
> The patch itself looks obviously fine, but do we have any synchronization
> that ensure it does not go away while we're looking at the submission
> queue?
The nvmet_sq has percpu_ref, but it can keep nvmet_sq_destroy() from
freeing sq only, it can't keep nvmet_tcp_release_queue_work() from
setting tls_key to NULL, so we need serialize with nvmet_sq_put_tls_key():

"""""
diff --git a/drivers/nvme/target/debugfs.c b/drivers/nvme/target/debugfs.c
index e85fe1d4c9f8..cc451e25ea1d 100644
--- a/drivers/nvme/target/debugfs.c
+++ b/drivers/nvme/target/debugfs.c
@@ -136,8 +136,19 @@ NVMET_DEBUGFS_ATTR(nvmet_ctrl_host_traddr);
 static int nvmet_ctrl_tls_key_show(struct seq_file *m, void *p)
 {
        struct nvmet_ctrl *ctrl = m->private;
-       key_serial_t keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);
-
+       struct nvmet_sq *sq = ctrl->sqs[0];
+       key_serial_t keyid = 0;
+
+       /*
+        * Pin the admin queue against teardown, and serialize with
+        * nvmet_sq_put_tls_key() so the key cannot be dropped mid-read.
+        */
+       if (sq && percpu_ref_tryget_live(&sq->ref)) {
+               mutex_lock(&ctrl->lock);
+               keyid = nvmet_queue_tls_keyid(sq);
+               mutex_unlock(&ctrl->lock);
+               percpu_ref_put(&sq->ref);
+       }
        seq_printf(m, "%08x\n", keyid);
        return 0;
 }
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index e315f1c24e73..24df9e4a1e1c 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -957,13 +957,17 @@ static inline void nvmet_req_bio_put(struct nvmet_req *req, struct bio *bio)
 #ifdef CONFIG_NVME_TARGET_TCP_TLS
 static inline key_serial_t nvmet_queue_tls_keyid(struct nvmet_sq *sq)
 {
+       if (!sq)
+               return 0;
        return sq->tls_key ? key_serial(sq->tls_key) : 0;
 }
 static inline void nvmet_sq_put_tls_key(struct nvmet_sq *sq)
 {
        if (sq->tls_key) {
+               mutex_lock(&sq->ctrl->lock);
                key_put(sq->tls_key);
                sq->tls_key = NULL;
+               mutex_unlock(&sq->ctrl->lock);
        }
 }
""""

Best Regards,
Guixin Liu






More information about the Linux-nvme mailing list