Persistent block device naming
This article describes how to use persistent names for your block devices. This has been made possible by the introduction of udev and has some advantages over bus-based naming. If your machine has more than one drive sharing a naming scheme, the order in which their corresponding device nodes are added is arbitrary. This may result in block device names (e.g. /dev/sda
and /dev/sdb
, /dev/nvme0n1
and /dev/nvme1n1
, /dev/mmcblk0
and /dev/mmcblk1
) switching around on each boot, culminating in an unbootable system, kernel panic, or a block device disappearing. Persistent naming solves these issues.
- Persistent naming has limits that are out-of-scope in this article. For example, while mkinitcpio may support a method, systemd may impose its own limits (e.g. FS#42884) on naming it can process during boot.
- This article is not relevant for LVM logical volumes as the
/dev/VolumeGroupName/LogicalVolumeName
device paths are persistent.
Persistent naming methods
There are four different schemes used for persistent naming by udev (through 60-persistent-storage.rules
): by-label, by-uuid, by-id and by-path. For those using disks with GUID Partition Table (GPT), two additional schemes can be used by-partlabel and by-partuuid.
The directories in /dev/disk/
are created and destroyed dynamically, depending on whether there are devices in them.
The following sections describe what the different persistent naming methods are and how they are used.
The lsblk command can be used for viewing graphically the first persistent schemes:
$ lsblk -f
NAME FSTYPE LABEL UUID MOUNTPOINT sda ├─sda1 vfat CBB6-24F2 /boot ├─sda2 ext4 Arch Linux 0a3407de-014b-458b-b5c1-848e92a327a3 / ├─sda3 ext4 Data b411dc99-f0a0-4c87-9e05-184977be8539 /home └─sda4 swap f9fe0b69-a280-415d-a03a-a32752370dee [SWAP] mmcblk0 └─mmcblk0p1 vfat F4CA-5D75
For those using GPT, use the blkid
command instead. The latter is more convenient for scripts, but more difficult to read.
# blkid
/dev/sda1: UUID="CBB6-24F2" TYPE="vfat" PARTLABEL="EFI system partition" PARTUUID="d0d0d110-0a71-4ed6-936a-304969ea36af" /dev/sda2: LABEL="Arch Linux" UUID="0a3407de-014b-458b-b5c1-848e92a327a3" TYPE="ext4" PARTLABEL="GNU/Linux" PARTUUID="98a81274-10f7-40db-872a-03df048df366" /dev/sda3: LABEL="Data" UUID="b411dc99-f0a0-4c87-9e05-184977be8539" TYPE="ext4" PARTLABEL="Home" PARTUUID="7280201c-fc5d-40f2-a9b2-466611d3d49e" /dev/sda4: UUID="f9fe0b69-a280-415d-a03a-a32752370dee" TYPE="swap" PARTLABEL="Swap" PARTUUID="039b6c1c-7553-4455-9537-1befbc9fbc5b" /dev/mmcblk0: PTUUID="0003e1e5" PTTYPE="dos" /dev/mmcblk0p1: UUID="F4CA-5D75" TYPE="vfat" PARTUUID="0003e1e5-01"
by-label
Almost every file system type can have a label. All your volumes that have one are listed in the /dev/disk/by-label
directory.
$ ls -l /dev/disk/by-label/
total 0 lrwxrwxrwx 1 root root 10 May 27 23:31 Data -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 Arch\x20Linux -> ../../sda2
Most file systems support setting the label upon file system creation, see the man page of the relevant mkfs.*
utility. For some file systems it is also possible to change the labels. Following are some methods for changing labels on common file systems:
- btrfs
-
btrfs filesystem label /dev/XXX "new label"
(use the mountpoint of the device if already mounted) using btrfs-progs - crypto_LUKS (LUKS2 only)
-
cryptsetup config --label="new label" /dev/XXX
using cryptsetup - exfat
-
tune.exfat -L "new label" /dev/XXX
using exfatprogs -
exfatlabel /dev/XXX "new label"
using exfatprogs or exfat-utils - ext2/3/4
-
e2label /dev/XXX "new label"
using e2fsprogs - fat/vfat
-
fatlabel /dev/XXX "new label"
using dosfstools -
mlabel -i /dev/XXX ::"new label"
using mtools - jfs
-
jfs_tune -L "new label" /dev/XXX
using jfsutils - ntfs
-
ntfslabel /dev/XXX "new label"
using ntfs-3g - reiserfs
-
reiserfstune -l "new label" /dev/XXX
using reiserfsprogs - swap
-
swaplabel -L "new label" /dev/XXX
using util-linux - udf
-
udflabel /dev/XXX "new label"
using udftools - xfs
-
xfs_admin -L "new label" /dev/XXX
(use the mountpoint of the device if already mounted) using xfsprogs
The label of a device can be obtained with lsblk:
$ lsblk -dno LABEL /dev/sda2
Arch Linux
Or with blkid:
# blkid -s LABEL -o value /dev/sda2
Arch Linux
- Labels have to be unambiguous to prevent any possible conflicts.
- Labels can be up to 16 characters long.
- Since the label is a property of the filesystem, it is not suitable for addressing a single RAID device persistently.
- When using encrypted containers with dm-crypt, the labels of filesystems inside of containers are not available while the container is locked/encrypted.
by-uuid
UUID is a mechanism to give each filesystem a unique identifier. These identifiers are generated by filesystem utilities (e.g. mkfs.*
) when the device gets formatted and are designed so that collisions are unlikely. All GNU/Linux filesystems (including swap and LUKS headers of raw encrypted devices) support UUID. FAT, exFAT and NTFS filesystems do not support UUID, but are still listed in /dev/disk/by-uuid/
with a shorter UID (unique identifier):
$ ls -l /dev/disk/by-uuid/
total 0 lrwxrwxrwx 1 root root 10 May 27 23:31 0a3407de-014b-458b-b5c1-848e92a327a3 -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 b411dc99-f0a0-4c87-9e05-184977be8539 -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 CBB6-24F2 -> ../../sda1 lrwxrwxrwx 1 root root 10 May 27 23:31 f9fe0b69-a280-415d-a03a-a32752370dee -> ../../sda4 lrwxrwxrwx 1 root root 10 May 27 23:31 F4CA-5D75 -> ../../mmcblk0p1
The UUID of a device can be obtained with lsblk:
$ lsblk -dno UUID /dev/sda1
CBB6-24F2
Or with blkid:
# blkid -s UUID -o value /dev/sda1
CBB6-24F2
The advantage of using the UUID method is that it is much less likely that name collisions occur than with labels. Further, it is generated automatically on creation of the filesystem. It will, for example, stay unique even if the device is plugged into another system (which may perhaps have a device with the same label).
The disadvantage is that UUIDs make long code lines hard to read and break formatting in many configuration files (e.g. fstab or crypttab). Also every time a volume is reformatted a new UUID is generated and configuration files have to get manually adjusted.
by-id and by-path
by-id
creates a unique name depending on the hardware serial number, by-path
depending on the shortest physical path (according to sysfs). Both contain strings to indicate which subsystem they belong to (i.e. pci-
for by-path
, and ata-
for by-id
), so they are linked to the hardware controlling the device. This implies different levels of persistence: the by-path
will already change when the device is plugged into a different port of the controller, the by-id
will change when the device is plugged into a port of a hardware controller subject to another subsystem. [1] Thus, both are not suitable to achieve persistent naming tolerant to hardware changes.
However, both provide important information to find a particular device in a large hardware infrastructure. For example, if you do not manually assign persistent labels (by-label
or by-partlabel
) and keep a directory with hardware port usage, by-id
and by-path
can be used to find a particular device.[2] [3]
-
by-id
andby-path
links can only be considered persistent for disks, not partitions. Partitions will be referenced by their number in the partition table and that can change if the partitions are reordered. - The
/dev/disk/by-path/pci-*
paths for NVMe devices may change if a PCIe device is added or removed from the system or if the system firmware does not enumerate them deterministically.
$ ls -l /dev/disk/by-id/
total 0 lrwxrwxrwx 1 root root 10 May 27 23:31 ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470 -> ../../sda lrwxrwxrwx 1 root root 10 May 27 23:31 ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470-part1 -> ../../sda1 lrwxrwxrwx 1 root root 10 May 27 23:31 ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470-part2 -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470-part3 -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470-part4 -> ../../sda4 lrwxrwxrwx 1 root root 10 May 27 23:31 mmc-SD32G_0x0040006d -> ../../mmcblk0 lrwxrwxrwx 1 root root 10 May 27 23:31 mmc-SD32G_0x0040006d-part1 -> ../../mmcblk0p1 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NJ0N704064T -> ../../nvme1n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NJ0N704064T-part1 -> ../../nvme1n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NJ0N704064T-part2 -> ../../nvme1n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NJ0N704064T_1 -> ../../nvme1n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NJ0N704064T_1-part1 -> ../../nvme1n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-Samsung_SSD_970_EVO_Plus_2TB_S4J4NJ0N704064T_1-part2 -> ../../nvme1n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-WDS100T1X0E-00AFY0_21455A801268 -> ../../nvme0n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-WDS100T1X0E-00AFY0_21455A801268-part1 -> ../../nvme0n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-WDS100T1X0E-00AFY0_21455A801268-part2 -> ../../nvme0n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-WDS100T1X0E-00AFY0_21455A801268_1 -> ../../nvme0n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-WDS100T1X0E-00AFY0_21455A801268_1-part1 -> ../../nvme0n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-WDS100T1X0E-00AFY0_21455A801268_2-part2 -> ../../nvme0n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-eui.002538570142d716 -> ../../nvme1n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.002538570142d716-part1 -> ../../nvme1n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.002538570142d716-part2 -> ../../nvme1n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-eui.e8238fa6bf530001001b448b4566aa1a -> ../../nvme0n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.e8238fa6bf530001001b448b4566aa1a-part1 -> ../../nvme0n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.e8238fa6bf530001001b448b4566aa1a-part2 -> ../../nvme0n1p2 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f -> ../../sda lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part1 -> ../../sda1 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part2 -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part3 -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part4 -> ../../sda4
$ ls -l /dev/disk/by-path/
total 0 lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:00:1f.2-ata-1 -> ../../sda lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:00:1f.2-ata-1-part1 -> ../../sda1 lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:00:1f.2-ata-1-part2 -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:00:1f.2-ata-1-part3 -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:00:1f.2-ata-1-part4 -> ../../sda4 lrwxrwxrwx 1 root root 13 May 27 23:31 pci-0000:01:00.0-nvme-1 -> ../../nvme0n1 lrwxrwxrwx 1 root root 15 May 27 23:31 pci-0000:01:00.0-nvme-1-part1 -> ../../nvme0n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 pci-0000:01:00.0-nvme-1-part2 -> ../../nvme0n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 pci-0000:04:00.0-nvme-1 -> ../../nvme1n1 lrwxrwxrwx 1 root root 15 May 27 23:31 pci-0000:04:00.0-nvme-1-part1 -> ../../nvme1n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 pci-0000:04:00.0-nvme-1-part2 -> ../../nvme1n1p2 lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:07:00.0-platform-rtsx_pci_sdmmc.0 -> ../../mmcblk0 lrwxrwxrwx 1 root root 10 May 27 23:31 pci-0000:07:00.0-platform-rtsx_pci_sdmmc.0-part1 -> ../../mmcblk0p1
World Wide Name
by-id
also creates World Wide Name (WWN) links of storage devices that support it. Unlike other by-id
links, WWNs are fully persistent and will not change depending on the used subsystem.
SATA and SAS devices have a wwn-
prefix while NVMe devices use a different WWN format and are prefixed with nvme-eui.
.[4]
$ ls -l /dev/disk/by-id/{wwn-,nvme-eui.}*
lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-eui.002538570142d716 -> ../../nvme1n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.002538570142d716-part1 -> ../../nvme1n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.002538570142d716-part2 -> ../../nvme1n1p2 lrwxrwxrwx 1 root root 13 May 27 23:31 nvme-eui.e8238fa6bf530001001b448b4566aa1a -> ../../nvme0n1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.e8238fa6bf530001001b448b4566aa1a-part1 -> ../../nvme0n1p1 lrwxrwxrwx 1 root root 15 May 27 23:31 nvme-eui.e8238fa6bf530001001b448b4566aa1a-part2 -> ../../nvme0n1p2 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f -> ../../sda lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part1 -> ../../sda1 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part2 -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part3 -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 wwn-0x60015ee0000b237f-part4 -> ../../sda4
by-partlabel
GPT partition labels can be defined in the header of the partition entry on GPT disks.
This method is very similar to the filesystem labels, except the partition labels do not get affected if the file system on the partition is changed.
All partitions that have partition labels are listed in the /dev/disk/by-partlabel
directory.
$ ls -l /dev/disk/by-partlabel/
total 0 lrwxrwxrwx 1 root root 10 May 27 23:31 EFI\x20system\x20partition -> ../../sda1 lrwxrwxrwx 1 root root 10 May 27 23:31 GNU\x2fLinux -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 Home -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 Swap -> ../../sda4
The partition label of a device can be obtained with lsblk:
$ lsblk -dno PARTLABEL /dev/sda1
EFI system partition
Or with blkid:
# blkid -s PARTLABEL -o value /dev/sda1
EFI system partition
- GPT partition labels also have to be different to avoid conflicts. To change your partition label, you can use gdisk or the ncurses-based version cgdisk. Both are available from the gptfdisk package. See Partitioning#Partitioning tools.
- According to the specification, GPT partition labels can be up to 72 characters long.
by-partuuid
Like GPT partition labels, GPT partition UUIDs are defined in the partition entry on GPT disks.
MBR does not support partition UUIDs, but Linux[5] and software using libblkid[6] (e.g. udev[7]) are capable of generating pseudo PARTUUIDs for MBR partitions. The format is SSSSSSSS-PP
, where SSSSSSSS
is a zero-filled 32-bit MBR disk signature, and PP
is a zero-filled partition number in hexadecimal form. Unlike a regular PARTUUID of a GPT partition, MBR's pseudo PARTUUID can change if the partition number changes.
The dynamic directory is similar to other methods and, like filesystem UUIDs, using UUIDs is preferred over labels.
$ ls -l /dev/disk/by-partuuid/
total 0 lrwxrwxrwx 1 root root 10 May 27 23:31 0003e1e5-01 -> ../../mmcblk0p1 lrwxrwxrwx 1 root root 10 May 27 23:31 039b6c1c-7553-4455-9537-1befbc9fbc5b -> ../../sda4 lrwxrwxrwx 1 root root 10 May 27 23:31 7280201c-fc5d-40f2-a9b2-466611d3d49e -> ../../sda3 lrwxrwxrwx 1 root root 10 May 27 23:31 98a81274-10f7-40db-872a-03df048df366 -> ../../sda2 lrwxrwxrwx 1 root root 10 May 27 23:31 d0d0d110-0a71-4ed6-936a-304969ea36af -> ../../sda1
The partition UUID of a device can be obtained with lsblk:
$ lsblk -dno PARTUUID /dev/sda1
d0d0d110-0a71-4ed6-936a-304969ea36af
Or with blkid:
# blkid -s PARTUUID -o value /dev/sda1
d0d0d110-0a71-4ed6-936a-304969ea36af
Using persistent naming
There are various applications that can be configured using persistent naming. Following are some examples of how to configure them.
fstab
See the main article: fstab#Identifying file systems.
Kernel parameters
To use persistent names in kernel parameters, the following prerequisites must be met. On a standard installation following the installation guide both prerequisites are met:
- You are using an initramfs image that has udev in it.
- For mkinitcpio, enable either the
udev
orsystemd
hook in/etc/mkinitcpio.conf
The location of the root filesystem is given by the parameter root
on the kernel command line. The kernel command line is configured from the boot loader, see Kernel parameters#Configuration. To change to persistent device naming, only change the parameters which specify block devices, e.g. root
and resume
, while leaving other parameters as is. Various naming schemes are supported:
Persistent device naming using label and the LABEL=
format, in this example Arch Linux
is the LABEL of the root file system.
root="LABEL=Arch Linux"
Persistent device naming using UUID and the UUID=
format, in this example 0a3407de-014b-458b-b5c1-848e92a327a3
is the UUID of the root file system.
root=UUID=0a3407de-014b-458b-b5c1-848e92a327a3
Persistent device naming using disk id and the /dev
path format, in this example wwn-0x60015ee0000b237f-part2
is the id of the root partition.
root=/dev/disk/by-id/wwn-0x60015ee0000b237f-part2
Persistent device naming using GPT partition UUID and the PARTUUID=
format, in this example 98a81274-10f7-40db-872a-03df048df366
is the PARTUUID of the root partition.
root=PARTUUID=98a81274-10f7-40db-872a-03df048df366
Persistent device naming using GPT partition label and the PARTLABEL=
format, in this example GNU/Linux
is the PARTLABEL of the root partition.
root="PARTLABEL=GNU/Linux"