Persistent names for block devices
November 10, 2021
Table of contents
Block devices include hard drives, SSDs, USB sticks and disks, as well as memory cards.
In Linux, there are only block devices, that is, data in them is read and written in blocks, as opposed to character devices, in which data can be read or written in single characters. Character device files are used for unbuffered data exchange. On Linux, you must use a “raw” driver to get a character device for a disk, although you can get the same effect as opening a character device by opening a block device with the Linux-specific O_DIRECT flag.
The previous information is provided only for your understanding that “disks” and “block devices” are the same for the purposes of this article.
Internal and external disks, as well as USB flash drives have names like /dev/sdX, where the letter a, b, c and so on is substituted for X, for example: /dev/sda and /dev/sdb.
NVM Express (NVMe) device names start with nvme, for example /dev/nvme0n1.
If your computer has multiple SATA, SCSI, or IDE drive controllers, the order of adding the corresponding device nodes is arbitrary. This can cause device names such as /dev/sda and /dev/sdb to change with each other on every boot, making the system unable to boot. Also, assigning the same name to the same disk can be important for handling them in scripts or other uses when it is important that the block device has the same name.
Block device overview:
In fact, Linux “out of the box” provides the ability to customize disks – no additional configuration or installation of utilities is required. The problem is that distinguishing one disk from another (especially after formatting) is not always an easy task, therefore, on the one hand, there is no unambiguous single solution, but on the other hand, several options are offered at once, among which you can choose the most suitable one.
The bottom line is the following, in addition to the names of the form /dev/sd* which most users are used to, there are four more permanent naming schemes, all of them are presented as links in directories:
Directories and files in /dev/disk/ are created and destroyed dynamically, depending on whether they have devices or not. That is, this means that some of these directories may not exist in your system, or be present only after connecting certain devices (disks).
By the way, this article has nothing to do with LVM logical volumes, since device paths of the form /dev/VolumeGroupName/LogicalVolumeName are persistent.
Almost every type of filesystem can have a label. All your volumes that have it 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
Advantages of this method of uniqueizing a disk and obtaining a permanent name:
- you yourself choose the name by which you can access the disk
- the label is lost when formatting and creating a new filesystem
- by default, if not specified when the filesystem was created, most disks and partitions are unlabeled
- label refers to the file system, i.e. it is not possible to create a label for an entire disk if it is partitioned
- it is impossible to create a label for a disk without a file system
Most filesystems support customizing the label during filesystem creation, see the man page for the corresponding mkfs.* utilities for details. For some filesystems it is possible to change labels, below are several methods for changing labels on popular filesystems:
Package: util-linux. Command to change disk or partition label:
swaplabel -L "new label" /dev/XXX
Package: e2fsprogs. Command to change disk or partition label:
e2label /dev/XXX "new label"
Package: btrfs-progs. Command to change disk or partition label:
btrfs filesystem label /dev/XXX "new label"
Package: reiserfsprogs. Command to change disk or partition label:
reiserfstune -l "new label" /dev/XXX
Package: jfsutils. Command to change disk or partition label:
jfs_tune -L "new label" /dev/XXX
Package: xfsprogs. Command to change disk or partition label:
xfs_admin -L "new label" /dev/XXX
Package: dosfstools. Command to change disk or partition label:
fatlabel /dev/XXX "new label"
Package: mtools. Command to change disk or partition label:
mlabel -i /dev/XXX ::"new label"
Package: exfatprogs. Command to change disk or partition label:
tune.exfat -L "new label" /dev/XXX
Package: exfatprogs or exfat-utils. Command to change disk or partition label:
exfatlabel /dev/XXX "new label"
Package: ntfs-3g. Command to change disk or partition label:
ntfslabel /dev/XXX "new label"
Package: udftools. Command to change disk or partition label:
udflabel /dev/XXX "new label"
- crypto_LUKS (LUKS2 only)
Package: cryptsetup. Command to change disk or partition label:
cryptsetup config --label="new label" /dev/XXX
The device label can be viewed with lsblk:
lsblk -dno LABEL /dev/sda2
Or with blkid:
sudo blkid -s LABEL -o value /dev/sda2
- The filesystem must not be mounted to change the label. For the root file system, this can be achieved by booting from a different volume (from the Live system, for example).
- Labels should be different for all partitions to avoid possible conflicts.
- Labels can be up to 16 characters long.
- Since the label is a property of the file system, it is not suitable for permanently addressing a single device in a RAID array.
- When using encrypted containers with dm-crypt, the filesystem labels inside the containers are not available while the container is locked/encrypted.
UUID is a mechanism that allows each file system to be assigned a unique identifier. These identifiers are generated by filesystem utilities (such as mkfs.*) When the device is formatted and are designed so that collisions are unlikely. All GNU/Linux filesystems (including the swap and LUKS headers of raw encrypted devices) support UUIDs. FAT, exFAT and NTFS file systems do not support UUIDs, but are still listed in /dev/disk/by-uuid/ with a shorter UID (unique identifier):
ls -l /dev/disk/by-uuid/
The UUID of the disk (if there is only one partition) can be obtained using lsblk:
lsblk -dno UUID /dev/sda aad9d8d7-b1b9-435a-9e41-fc8159d2c484
If there are several partitions, then you need to specify the partition number:
lsblk -dno UUID /dev/nvme0n1p1 7327-B4E4
There is no UUID for the disk as a whole if the disk contains multiple partitions. Also there is no UUID for disks and partitions without file systems.
The advantage of using the UUID method is that name collisions are much less likely than with labels. It is also generated automatically when the file system is created. For example, it will remain unique even if the device is connected to another system (which could possibly have a device with the same lable).
The downside is that UUIDs are difficult for humans to read and break formatting in many configuration files (like fstab or crypttab). In addition, every time the volume is reformatted, a new UUID is created and the configuration files must be manually changed.
- if your swap does not have a UUID assigned, you will need to reset it using the mkswap utility.
by-id creates a unique name based on the serial number of the hardware. It contains a string indicating which subsystem the device belongs to (for example, ata-, nvme-, usb-, or wwn- for by-id), so it is associated with the hardware that controls the device.
An example of a by-id for a USB flash drive: /dev/disk/by-id/usb-Samsung_Flash_Drive_0325121050019952-0:0
This identifier will be constant even if the filesystem is formatted. Thus, it can be used to access RAW file devices.
by-id also creates World Wide Name links for storage devices that support it. Unlike other links by ID, WWNs are completely persistent and do not change depending on the subsystem used.
The by-id will change when the device is connected to a hardware controller port that is subordinate to another subsystem. It means that if the device is connected as USB or as SATA, then its by-id will change.
by-path creates a unique name based on the shortest physical path (according to sysfs).
The by-path value for a file device will change if you switch it from one slot to another. In the case of a single socket, the by-path value remains constant.
This method only applies to disks with a GUID Partition Table (GPT).
GPT Partition Labels can be defined in the header of a partition entry on GPT disks.
This method is very similar to file system labels, except that the partition labels do not change when the file system on the partition changes.
All partitions with 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 device partition label can be obtained using lsblk:
lsblk -dno PARTLABEL /dev/sda1 EFI system partition
Or with blkid:
sudo blkid -s PARTLABEL -o value /dev/sda1 EFI system partition
- GPT partition labels should also be different to avoid conflicts. To change the label of a partition, you can use gdisk or the ncurses version of cgdisk. Both are available in the gptfdisk package.
- According to the specification, GPT partition labels can be up to 72 characters long.
- The by-partlabel will be cleared when the GPT scheme is removed.
Like GPT partition labels, the UUIDs of GPT partitions are defined in the partition entry on GPT disks.
MBR does not support UUID partitions, but Linux and software using libblkid (like udev) are capable of generating a pseudo PARTUUID for MBR partitions. The format is SSSSSSSS-PP, where SSSSSSSS is the 32-bit zero padded MBR disk signature and PP is the zero padded partition number in hexadecimal form. Unlike the usual PARTUUID of a GPT partition, the pseudo PARTUUID of the MBR can change when the partition number changes.
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 UUID of the device partition can be obtained using lsblk:
lsblk -dno PARTUUID /dev/sda1 d0d0d110-0a71-4ed6-936a-304969ea36af
Or with blkid:
sudo blkid -s PARTUUID -o value /dev/sda1 d0d0d110-0a71-4ed6-936a-304969ea36af
You can use persistent names in the same way as /dev/sdX. That is, in programs for working with block devices, such as mount, umount, fdisk, gdisk, VBoxManage and others, you can use one of the constant names instead of the name /dev/sdX.
An example of unmounting a disk by its by-id:
sudo umount '/dev/disk/by-id/usb-Samsung_Flash_Drive_0325121050019952-0:0-part2'
An example of getting information about disk partitions by its by-id:
fdisk -l '/dev/disk/by-id/usb-Samsung_Flash_Drive_0325121050019952-0:0'
An example of creating a virtual disk file pointing to a real disk by its by-id:
VBoxManage internalcommands createrawvmdk -filename flash.vmdk -rawdisk '/dev/disk/by-id/usb-Samsung_Flash_Drive_0325121050019952-0:0'
Related: How to boot into VirtualBox from USB
Please note that it is not enough to specify only the identifier, for example usb-Samsung_Flash_Drive_0325121050019952-0:0, you must specify the full name like /dev/disk/by-*, for example '/dev/disk/by-id/usb-Samsung_Flash_Drive_0325121050019952-0:0'.
You can also use persistent disk device names in the /etc/fstab file, but you must explicitly specify which disk alias to use.
LABEL=<label> or UUID=<uuid> may be given instead of a device name. This is the recommended method, as device names are often a coincidence of hardware detection order, and can change when other disks are added or removed. For example, 'LABEL=Boot' or 'UUID=3e6be9de-8139-11d1-9106-a43f08d823a6'. (Use a filesystem-specific tool like e2label, xfs_admin, or fatlabel to set LABELs on filesystems).
It’s also possible to use PARTUUID= and PARTLABEL=. These partitions identifiers are supported for example for GUID Partition Table (GPT).
The string representation of the UUID should be based on lower case characters. But when specifying the volume ID of FAT or NTFS file systems upper case characters are used (e.g UUID="A40D-85E7" or UUID="61DB7756DB7779B3").
An example /etc/fstab file using UUIDs (common names of disk devices are indicated in the comments):
# /dev/nvme0n1p2 UUID=01e4d4f5-698f-4dc2-987b-270499457f48 / ext4 rw,relatime 0 1 # /dev/nvme0n1p1 UUID=7327-B4E4 /boot vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 2 /dev/sda /mnt/disk_d ext4 rw,relatime 0 2 # /dev/sdc1 1.5 TB external USB UUID=26FC3023FC2FEC2D /mnt/disk_e ntfs noauto,nofail,rw,utf8 0 0
Note that you do not need to specify a fully qualified name like /dev/disk/by-*.
So, for most applications that do not require formatting and creating new file systems, constant names (aliases) from the /dev/disk/by-label and /dev/disk/by-uuid directories are suitable.
If you need to use the disk as a RAW device, that is, without relying on its file systems, then aliases from the /dev/disk/by-id directory will do the job.
- An unplugged disk causes a delay in system boot (81.6%)
- How to check if a computer is using BIOS or UEFI; GRUB or systemd-boot bootloader; MBR or GPT partition table (71.2%)
- How to determine why Linux boots into Emergency mode (69.4%)
- How to repair an LVM disk using fsck (69.4%)
- The in-memory file system - how to use tmpfs (65.1%)
- How to make VirtualBox virtual machines destroy on computer restart (RANDOM - 50%)