[RFC-PATCH 2/2] nvme: use the namespace id for block device names
Hannes Reinecke
hare at suse.de
Mon Mar 2 23:34:38 PST 2026
On 3/2/26 23:25, Keith Busch wrote:
> From: Keith Busch <kbusch at kernel.org>
>
> We can now assume the ns_id provides a unique number within a subsystem
> when creating a namespace kobject. Use that rather than pulling an
> available bit from an ida, which becomes unnecessary once we use the
> controller's reported identifier.
>
> The user observable change is that the suffix of the nvme namespace
> device handle name will always be consistent regardless of which
> controller is scanned first or what the namespace attachment state is
> for a given controller being scanned. The prefix will still be dependent
> on the order the controllers were connected/probed.
>
> Signed-off-by: Keith Busch <kbusch at kernel.org>
> ---
> drivers/nvme/host/core.c | 19 +++++--------------
> drivers/nvme/host/multipath.c | 4 ++--
> drivers/nvme/host/nvme.h | 2 --
> 3 files changed, 7 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
> index 7a558d5103a21..3f2f9b2be87c2 100644
> --- a/drivers/nvme/host/core.c
> +++ b/drivers/nvme/host/core.c
> @@ -667,7 +667,6 @@ static void nvme_free_ns_head(struct kref *ref)
> container_of(ref, struct nvme_ns_head, ref);
>
> nvme_mpath_put_disk(head);
> - ida_free(&head->subsys->ns_ida, head->instance);
> cleanup_srcu_struct(&head->srcu);
> nvme_put_subsystem(head->subsys);
> kfree(head->plids);
> @@ -3113,7 +3112,6 @@ static void nvme_destroy_subsystem(struct kref *ref)
> list_del(&subsys->entry);
> mutex_unlock(&nvme_subsystems_lock);
>
> - ida_destroy(&subsys->ns_ida);
> device_del(&subsys->dev);
> put_device(&subsys->dev);
> }
> @@ -3257,7 +3255,6 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
> put_device(&subsys->dev);
> goto out_unlock;
> }
> - ida_init(&subsys->ns_ida);
> list_add_tail(&subsys->entry, &nvme_subsystems);
> }
>
> @@ -3868,7 +3865,7 @@ static int nvme_add_ns_cdev(struct nvme_ns *ns)
>
> ns->cdev_device.parent = ns->ctrl->device;
> ret = dev_set_name(&ns->cdev_device, "ng%dn%d",
> - ns->ctrl->instance, ns->head->instance);
> + ns->ctrl->instance, ns->head->ns_id);
> if (ret)
> return ret;
>
> @@ -3890,14 +3887,10 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
> head = kzalloc(size, GFP_KERNEL);
> if (!head)
> goto out;
> - ret = ida_alloc_min(&ctrl->subsys->ns_ida, 1, GFP_KERNEL);
> - if (ret < 0)
> - goto out_free_head;
> - head->instance = ret;
> INIT_LIST_HEAD(&head->list);
> ret = init_srcu_struct(&head->srcu);
> if (ret)
> - goto out_ida_remove;
> + goto out_free_head;
> head->subsys = ctrl->subsys;
> head->ns_id = info->nsid;
> head->ids = info->ids;
> @@ -3925,8 +3918,6 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
> return head;
> out_cleanup_srcu:
> cleanup_srcu_struct(&head->srcu);
> -out_ida_remove:
> - ida_free(&ctrl->subsys->ns_ida, head->instance);
> out_free_head:
> kfree(head);
> out:
> @@ -4162,14 +4153,14 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
> */
> if (nvme_ns_head_multipath(ns->head)) {
> sprintf(disk->disk_name, "nvme%dc%dn%d", ctrl->subsys->instance,
> - ctrl->instance, ns->head->instance);
> + ctrl->instance, ns->head->ns_id);
> disk->flags |= GENHD_FL_HIDDEN;
> } else if (multipath) {
> sprintf(disk->disk_name, "nvme%dn%d", ctrl->subsys->instance,
> - ns->head->instance);
> + ns->head->ns_id);
> } else {
> sprintf(disk->disk_name, "nvme%dn%d", ctrl->instance,
> - ns->head->instance);
> + ns->head->ns_id);
> }
>
> if (nvme_update_ns_info(ns, info))
> diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
> index 02a50181d1dd6..8715b04ff92a8 100644
> --- a/drivers/nvme/host/multipath.c
> +++ b/drivers/nvme/host/multipath.c
> @@ -640,7 +640,7 @@ static int nvme_add_ns_head_cdev(struct nvme_ns_head *head)
>
> head->cdev_device.parent = &head->subsys->dev;
> ret = dev_set_name(&head->cdev_device, "ng%dn%d",
> - head->subsys->instance, head->instance);
> + head->subsys->instance, head->ns_id);
> if (ret)
> return ret;
> ret = nvme_cdev_add(&head->cdev, &head->cdev_device,
> @@ -767,7 +767,7 @@ int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head)
> */
> set_bit(GD_SUPPRESS_PART_SCAN, &head->disk->state);
> sprintf(head->disk->disk_name, "nvme%dn%d",
> - ctrl->subsys->instance, head->instance);
> + ctrl->subsys->instance, head->ns_id);
> nvme_tryget_ns_head(head);
> return 0;
> }
> diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
> index ed8ce356c363e..142a5684205a8 100644
> --- a/drivers/nvme/host/nvme.h
> +++ b/drivers/nvme/host/nvme.h
> @@ -499,7 +499,6 @@ struct nvme_subsystem {
> u8 cmic;
> enum nvme_subsys_type subtype;
> u16 vendor_id;
> - struct ida ns_ida;
> #ifdef CONFIG_NVME_MULTIPATH
> enum nvme_iopolicy iopolicy;
> #endif
> @@ -540,7 +539,6 @@ struct nvme_ns_head {
> struct nvme_effects_log *effects;
> u64 nuse;
> unsigned ns_id;
> - int instance;
> #ifdef CONFIG_BLK_DEV_ZONED
> u64 zsze;
> #endif
The idea is nice, and I would love to go into that
direction.
But have you checked how this holds up under
rescan/remapping (eg things like blktest/nvme/058)?
Removal of the sysfs nodes might be delayed, and we cannot
create new entries with the same name until then.
So if that is taken care of, fine, but I don't see that in
the patch ...
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare at suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
More information about the Linux-nvme
mailing list