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

Guixin Liu kanie at linux.alibaba.com
Sun Nov 8 18:35:35 PST 2026


Hi Christoph,
  Any feedback?

Best Regards,
Guixin Liu

在 2026/10/30 10:36, Guixin Liu 写道:
>
> 在 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