[PATCH RFC V2 RESEND] nvme: make providing NGUID as UUID usage less scary

AlanCui4080 me at alancui.cc
Mon May 11 04:26:52 PDT 2026


[see https://lists.infradead.org/pipermail/linux-nvme/2026-May/062762.html for full thread]

Hi everyone,

About this patch and the discussion above, I just did a survey on
kernel commit history:

Long ago, the kernel sees NGUID as UUID.

2b9b6e86bca7209de02754fc84acf7ab3e78734e (NVMe: Export namespace attributes to sysfs)
> 	if (ns->ctrl->vs >= NVME_VS(1, 2))
>		memcpy(ns->uuid, id->nguid, sizeof(ns->uuid));

Then, the kernel begins by retrieving the UUID from the driver and,
in a backward compatible manner, reports the NGUID as the UUID when
the UUID is unavailable, and throws a warning.

d934f9848a77be4afe0ca336ea419dd066c934f3 (nvme: provide UUID value to userspace
Now that we have a way for getting the UUID from a target, provide it
to userspace as well.
Unfortunately there is already a sysfs attribute called UUID which is
a misnomer as it holds the NGUID value. So instead of creating yet
another wrong name, create a new 'nguid' sysfs attribute for the
NGUID. For the UUID attribute add a check wheter the namespace has a
UUID assigned to it and return this or return the NGUID to maintain
backwards compatibility. This should give userspace a chance to catch
up.)
>    static ssize_t uuid_show(...)
>	/* For backward compatibility expose the NGUID to userspace if
>	 * we have no UUID set
>	 */
>	if (uuid_is_null(&ns->uuid)) {
>		printk_ratelimited(KERN_WARNING
>				   "No UUID available providing old NGUID\n");
>		return sprintf(buf, "%pU\n", ns->nguid);
>	}
>	return sprintf(buf, "%pU\n", &ns->uuid);

And at d934f984:

> static umode_t nvme_ns_attrs_are_visible(struct kobject *kobj,
>		struct attribute *a, int n)
>{
>	struct device *dev = container_of(kobj, struct device, kobj);
>	struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
>
>	if (a == &dev_attr_uuid.attr) {
>		if (uuid_is_null(&ns->uuid) ||
>		    !memchr_inv(ns->nguid, 0, sizeof(ns->nguid))) // ??????? Why
>			return 0;
>	}
>	if (a == &dev_attr_nguid.attr) {
>		if (!memchr_inv(ns->nguid, 0, sizeof(ns->nguid)))
>			return 0;
>	}
>	if (a == &dev_attr_eui.attr) {
>		if (!memchr_inv(ns->eui, 0, sizeof(ns->eui)))
>			return 0;
>	}Therefore, my suggestion is to directly remove the UUID that is copied from NGUID.
>	return a->mode;
>}

The visibility of the uuid attr is depends on if NGUID exists, I'dont know why.
I believe that in this scenario, if NGUID doesn't exist, then UUID won't exist either.
Therefore, the user-space assumption that UUID exists has always been a bug.
Consequently, we don't need to assume any responsibility for backward compatibility.

I have hard drives that can demonstrate this behavior.

```
sudo nvme id-ctrl /dev/nvme1n1
vid       : 0x144d
mn        : Samsung SSD 970 EVO Plus 500GB          
fr        : 2B2QEXM7
ieee      : 002538
ver       : 0x10300

cat /sys/block/nvme1n1/eui
00 25 ** ** ** ** ** 2a

cat /sys/block/nvme1n1/nguid
cat: /sys/block/nvme1n1/nguid: No such file or directory

cat /sys/block/nvme1n1/uuid
cat: /sys/block/nvme1n1/uuid: No such file or directory

cat /sys/block/nvme1n1/wwid
eui.0025**********a2
```
As you can see, this NVMe 1.3 compatible device have no nguid,
so it has no both nguid and uuid node.

```
sudo nvme id-ctrl /dev/nvme0n1
NVME Identify Controller:
vid       : 0x1e49
mn        : ZHITAI TiPlus7100 2TB                   
fr        : ZTA22002
ieee      : 000000
ver       : 0x10400

cat /sys/block/nvme0n1/eui
a4 ** ** ** ** ** ** c3

cat /sys/block/nvme0n1/nguid
00000000-0000-0000-a428-**********c3

cat /sys/block/nvme0n1/uuid
00000000-0000-0000-a428-**********c3

cat /sys/block/nvme0n1/wwid
eui.0000000000000000a428**********c3
```
As you can see, this NVMe 1.4 compatible device have a nguid, its nguid
is derived from eui64, then because it has an nguid, its uuid is visible
and is copied from nguid.

According to the spec., both devices are compliant.

Therefore, I believe the core issue is no longer just the level or location
of the warning. As you can see, in the current version of the kernel,
the visibility of each attr is highly device-dependent. I think we shouldn't
retain a backward-compatible UUID attr since no userspace software should
assume the existence of any attr and The current kernel code is not backward
compatible in essence! (How can userspace determine whether a device has an
NGUID through means other than the kernel sysfs? If a program in a previous
version assumed the existence of /sys/block/nvmexx/uuid, then that assumption
is incorrect, because NGUID itself may not exist. Only any one of EUI, NGUID,
and UUID needs to exist.)

Another issue is Why WWIDs generated from NGUIDs have prefix "eui."?
Seems come from:
118472ab8532e55f48395ef5764b354fe48b1d73 (NVMe: Expose ns wwid through single sysfs entry)
> if (memchr_inv(ns->uuid, 0, sizeof(ns->uuid)))
>		return sprintf(buf, "eui.%16phN\n", ns->uuid);
This should be a naming error.

Then, when the kernel changed the UUID to a more appropriate name,
the eui. prefix was also carried over. And the commit said "This
patch has the driver figure this out and exports the unique string
through a single 'wwid' attribute so the user doesn't have this burden.”

Since /dev/disk/by-id/ already uses wwid, I don't think there's much we can do,
otherwise this would destroy compatibility. This seems to indirectly confirm
that the kernel is requiring users to check the existence of
/sys/block/nvmexx/[eui,nguid,uuid] before using it.

Therefore, my suggestion is to directly remove the UUID that is copied from
NGUID. Make the visibility of UUID depend on whether the device has a UUID,
rather than an NGUID to completely eliminates this strange warning and
backward compatibility path.

Thank you for your attention to this matter, I'm look forward to your thoughts.

Alan.








More information about the Linux-nvme mailing list