Udev

A Stable Name for a Restless USB Disk

My backup script failed because the USB disk appeared under a different device node after a reboot. The script had one job and had apparently outsourced it to probe order.

I first added a loop that searched /dev/sd* and selected the first disk of roughly the right size. That is not identification; it is speed dating with block devices. One wrong match would turn a backup problem into a restoration problem.

The better route starts with the event. When the kernel discovers hardware, hotplug information reaches user space. sysfs exposes attributes and the device hierarchy. udev applies naming policy and creates nodes or symbolic links. A rule can therefore match something intrinsic to this disk, such as a serial attribute, rather than its temporary kernel name.

Before writing the rule, I inspected the sysfs path associated with the block device and walked upward to understand where the useful attribute lived. This distinction matters: a rule may receive attributes from the device itself and from parent devices, but blindly matching an attribute seen somewhere in /sys is an excellent way to create a rule that never fires.

The result was a stable symbolic link under /dev while the ordinary sd name remained available. My script uses the stable link and checks the filesystem before mounting it. udev supplies naming policy; it does not absolve the script from verifying what it is about to write.

I tested by unplugging the disk, attaching another one first, and reconnecting in different orders. Watching the hotplug environment and udev’s diagnostics was much faster than repeatedly editing a rule and staring at /dev with wounded optimism.

Cold-plug startup deserved the same test. A useful rule must behave consistently whether the disk is present during boot or attached later.

The division of responsibility is clean. The kernel reports what appeared and where it sits in the device model. User space decides what local name is useful. My machine’s nickname for a disk does not belong in a kernel driver.

Dynamic device management still has an intimidating number of moving parts, but the principle is reliable: match stable attributes, create a stable link, and keep transient enumeration out of scripts. Hardware order is an observation, not a promise.

Following the Device Through sysfs

A USB card reader prompted today’s trip through /sys. I wanted one answer: which physical device sits behind the block-class entry /sys/block/sda?

The useful relationship is the device symlink. /sys/block/sda presents the disk as a member of the block class; its device link points into the physical device hierarchy. Those are two views of one kernel object, not two devices.

I started at the block entry and followed its device link rather than guessing from the node name:

$ readlink -f /sys/block/sda/device
/sys/devices/pci0000:00/0000:00:10.4/usb2/2-2/2-2:1.0/host1/1:0:0:0

The exact target is machine-specific. Here it says that the block disk came through a SCSI host attached to USB interface 2-2:1.0, itself below a PCI USB controller. On another machine the chain will differ, but the link still joins the class view to the device that implements it.

Walking upward from that target lets me inspect the parents that actually own bus attributes. The block entry doesn’t need to copy USB details into its own directory; the parent links already express the relationship.

I don’t parse the punctuation in the resolved path. Directory names and topology are useful while diagnosing a machine, but exported links and attributes are the interface. Hard-coding every component would just trade /dev/sda for a longer accidental name.

This also explains why /dev/sda isn’t a hardware biography. The node names a block interface; sysfs supplies the link back to the device model when I need to ask where that interface came from.

The service corridors are a little dim, but this one symlink answers the question without guesswork.

Letting udev Name the Devices

I have been trying udev on a Linux 2.6 test installation because I want removable devices to receive useful permissions without maintaining a giant static /dev. The project is still young, so this is an experiment rather than my new universal recipe.

The mechanism is pleasantly divided. The kernel discovers hardware and emits a hotplug event. Sysfs exposes the device and its attributes under /sys. A userspace helper uses that information and its rules to create or remove the appropriate node in /dev.

This means policy lives in userspace. The kernel does not need to decide which local group may open a scanner or what friendly name I prefer for a particular disk. It reports identity and major/minor numbers; udev applies the administrator’s rule.

For debugging, I start with sysfs rather than guessing a rule from the device node:

find /sys/class -name dev -print

The dev attribute contains the major and minor number for devices that have one. Following the device links reveals parent hardware and useful attributes. The exact early rule syntax and available helper programs are changing, so I keep rules small and check the documentation shipped with the installed version instead of copying an example for some other release.

My test sequence is equally small. I boot with a conventional device setup available as a fallback, start udev, attach one known USB device, and watch both the system log and /dev. I verify the node type, major/minor number, owner, group, and mode before opening it from an application.

Permissions are the easiest part to get subtly wrong. Creating the correct node with mode 0666 may make the test pass while giving every local user access to hardware that should be restricted. A group-based rule is usually a better policy. Convenience should not arrive disguised as an accidental security decision.

Persistent naming is the more interesting promise. Kernel names can depend on discovery order. Userspace can use stable attributes to select a consistent name for a known device. But choose attributes that are genuinely stable and unique; a generic product string shared by every unit is neither.

I like the architecture because it keeps detection in the kernel and local policy outside it. I remain cautious because early boot needs device nodes before much userspace is running, and distributions must integrate the pieces carefully. For now I am testing one class of device at a time. Dynamic /dev is useful, but a missing root disk remains impressively dynamic in the wrong direction.