Another thing I noticed is that the udev rule for NVMe namespaces is not based on a wwid of a namespace - it is tied to a serial of a controller. For NVMe devices with a single namespace this is ok but NVMe controllers can create multiple namespaces each with its own unique identifier (e.g. in the NVMeOF use-case).
https://paste.ubuntu.com/p/WJYpnWmnxp/
for i in `ls -1 /dev/vd* /dev/sd* /dev/nvme*n*` ; do echo "Info for device $i" ; cat /etc/udev/rules.d/`basename $i`.rules ; echo "Unique attribute: " ; udevadm info -a --path $(udevadm info -q path -n $i) | grep -P 'serial|wwid' ; done
Info for device /dev/nvme0n1
# Written by curtin
SUBSYSTEM=="block", ACTION=="add|change", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}=="QEMU NVMe Ctrl_nvmec0", SYMLINK+="disk/by-dname/nvme0n1"
[1] "5.15.2 Identify Namespace data structure
Namespace Globally Unique Identifier (NGUID): This field contains a 128-bit value that is globally unique and assigned to the namespace when the namespace is created. This field remains fixed throughout the life of the namespace and is preserved across namespace and controller operations (e.g., controller reset, namespace format, etc.)."
[2] Namespaces also have non-unique (across controllers or NVMe subsystems) numeric namespace identifiers (NSID) that are similar to SCSI LUNs (nvme<controller-num>n<namespace-identifier>), see “Section 6.1.2 Valid and Invalid NSIDs” in the NVMe specification:
“Associated with each controller namespace is a namespace ID, labeled as NSID 1 and NSID 2, that is used by the controller to reference a specific namespace.
Another thing I noticed is that the udev rule for NVMe namespaces is not based on a wwid of a namespace - it is tied to a serial of a controller. For NVMe devices with a single namespace this is ok but NVMe controllers can create multiple namespaces each with its own unique identifier (e.g. in the NVMeOF use-case).
https:/ /paste. ubuntu. com/p/WJYpnWmnx p/ rules.d/ `basename $i`.rules ; echo "Unique attribute: " ; udevadm info -a --path $(udevadm info -q path -n $i) | grep -P 'serial|wwid' ; done
for i in `ls -1 /dev/vd* /dev/sd* /dev/nvme*n*` ; do echo "Info for device $i" ; cat /etc/udev/
Info for device /dev/nvme0n1 ="add|change" , ENV{DEVTYPE} =="disk" , ENV{ID_ SERIAL} =="QEMU NVMe Ctrl_nvmec0", SYMLINK+ ="disk/ by-dname/ nvme0n1"
# Written by curtin
SUBSYSTEM=="block", ACTION=
SUBSYSTEM=="block", ACTION= ="add|change" , ENV{DEVTYPE} =="partition" , ENV{ID_ SERIAL} =="QEMU NVMe Ctrl_nvmec0", SYMLINK+ ="disk/ by-dname/ nvme0n1- part%n" wwid}== "nvme.8086- 6e766d656330- 51454d55204e564 d65204374726c- 00000001" serial} =="nvmec0 "
Unique attribute:
ATTR{
ATTRS{
nvme.8086- 6e766d656330- 51454d55204e564 d65204374726c- 00000001 is a wwid of a namespace.
So, I think we should prefer ID_WWN over ID_SERIAL in general and use ID_SERIAL as a fallback:
udevadm info --query=property --name /dev/nvme0n1 /dev/disk/ by-id/nvme- QEMU_NVMe_ Ctrl_nvmec0 /dev/disk/ by-path/ pci-0000: 00:03.0- nvme-1 /dev/disk/ by-id/nvme- nvme.8086- 6e766d656330- 51454d55204e564 d65204374726c- 00000001 /dev/disk/ by-dname/ nvme0n1 /dev/nvme0n1 /devices/ pci0000: 00/0000: 00:03.0/ nvme/nvme0/ nvme0n1 pci-0000: 00:03.0- nvme-1 TAG=pci- 0000_00_ 03_0-nvme- 1 SHORT=nvmec0 nvme.8086- 6e766d656330- 51454d55204e564 d65204374726c- 00000001 D=1792441
DEVLINKS=
DEVNAME=
DEVPATH=
DEVTYPE=disk
ID_MODEL=QEMU NVMe Ctrl
ID_PATH=
ID_PATH_
ID_SERIAL=QEMU NVMe Ctrl_nvmec0
ID_SERIAL_
ID_WWN=
MAJOR=259
MINOR=0
SUBSYSTEM=block
TAGS=:systemd:
USEC_INITIALIZE
NVMe spec references:
[1] "5.15.2 Identify Namespace data structure
Namespace Globally Unique Identifier (NGUID): This field contains a 128-bit value that is globally unique and assigned to the namespace when the namespace is created. This field remains fixed throughout the life of the namespace and is preserved across namespace and controller operations (e.g., controller reset, namespace format, etc.)."
A namespace ID is extracted from a controller and exported via sysfs via a wwid node: /github. com/torvalds/ linux/blob/ v4.14/drivers/ nvme/host/ core.c# L802-L818 /github. com/torvalds/ linux/blob/ v4.14/drivers/ nvme/host/ core.c# L2054-L2081
https:/
https:/
[2] Namespaces also have non-unique (across controllers or NVMe subsystems) numeric namespace identifiers (NSID) that are similar to SCSI LUNs (nvme<controlle r-num>n< namespace- identifier> ), see “Section 6.1.2 Valid and Invalid NSIDs” in the NVMe specification:
“Associated with each controller namespace is a namespace ID, labeled as NSID 1 and NSID 2, that is used by the controller to reference a specific namespace.