Hotplugging

When a new device is connected (or removed) at a hotpluggable bus, the kernel, again with the help of a userspace application, ensures that the correct driver is loaded. In contrast to normal module insertion, it is necessary to perform several additional tasks (e.g., the right driver must be found by reference to a device identification string, or configuration work must be carried out). For this reason, another tool (usually /sbin/udevd21) is used in place of modprobe.

Note that the kernel provides messages to userspace not only when devices are inserted and removed, but also for a much more generic set of events. When, for instance, a new hard disk is connected to the system, the kernel does not just provide information about this event, but also sends notifications about partitions that have been found on the device. Every component of the device model can send registration and unregistration events to the userland. Since this results in a rather large and comprehensive set of messages that can be potentially passed on from the kernel, I do not want to describe them all in detail.

20In other words, modprobe is dependent on a service in a module; accordingly, the kernel issues an instruction to modprobe to load the module — and this, in turn, causes modprobe to instruct the kernel to start modprobe to load the module.

21For former versions of the kernel, /sbin/hotplug was used as the only hotplug agent. With the introduction of the device model and its maturation during the development of 2.6, udevd is now the method of choice for most distributions. Nevertheless, the kernel does provide generic messages and is not tied to a particular mechanism in userspace. In some places, the kernel still calls the program registered in uevent_helper, which can be set to /sbin/hotplug — the setting is accessible via /proc/sys/kernel/hotplug. Setting the value to an empty string disables the mechanism. Since it is only needed during early boot or for some very specific configurations (mostly systems where networking is completely disabled), I will not consider it any further.

Instead, we focus on a specific example illustrating the basic mechanism. Consider that a USB memory stick is attached to the system, but the module that provides USB mass storage support has not yet been loaded into the kernel. Additionally, the distribution wants to automatically mount the device so that the user can immediately access it without further ado. The following steps are necessary to achieve this:

□ The USB host controller detects a new device on the bus and reports this to the device driver. The host controller allocates a new device and calls usb_new_device to register it.

□ usb_new_device triggers kobject_uevent to be called.22This function calls the subsystem-specific event notification procedure registered in the kobject instance for the object in question.

□ For USB device objects, usb_uevent is used as the notification function. The function prepares a message that contains all necessary information for udevd to react properly to the insertion of the new USB mass storage device.

The udevd daemon allows inspection of all messages received from the kernel. Observe the following log of the communication that takes place when a new USB stick is plugged into the system.

[email protected] # udevmonitor --environment

UEVENT[120112980 6.3 68892] add /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0

ACTION=add

DEVPATH=/devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0

SUBSYSTEM=usb

DEVTYPE=usb_interface

DEVICE=/proc/bus/usb/007/005

PRODUCT=951/1600/100

TYPE=0/0/0

INTERFACE=8/6/80

MODALIAS=usb:v0951p1600d0100dc00dsc00dp00ic08isc0 6ip50 SEQNUM=183 0

The first message is generated by the abovementioned function usb_uevent. Every message consists of identifier/value pairs that determine what is going on inside the kernel. Since a new device is added to the system, the value for action is add. device denotes where the information about the device can be found in the USB filesystem, and PRODUCT offers some information about vendor and device. The most important field in this case is interface because this determines the interface class to which the new device belongs. The USB standard reserves 8 for mass storage devices:

#define USB_CLASS_MASS_STORAGE 8

The field modalias contains all generic pieces of information that are available about the device. It is encoded in a string that is obviously not designed for the human eye, but can easily be parsed by a computer. It is generated as follows (add_uevent_var is a helper function that adds a new identifier/value pair to a hotplug message).

drivers/usb/core/usb.c add_uevent_var(env,

"M0DALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",

22The precise call path is usb_new_device ^ device_add ^ kobject_uevent.

le16_to_cpu(usb_dev->descriptor.idVendor), le16_to_cpu(usb_dev->descriptor.idProduct), le16_to_cpu(usb_dev->descriptor.bcdDevice), usb_dev->descriptor.bDeviceClass, usb_dev->descriptor.bDeviceSubClass, usb_dev->descriptor.bDeviceProtocol, alt->desc.bInterfaceClass, alt->desc.bInterfaceSubClass, alt->desc.bInterfaceProtocol));

By comparing the value of modalias against the aliases provided by the modules, udevd can find the proper module that needs to be inserted. In this case, usb-storage is the right choice because the following alias matches the requirements:

[email protected]> /sbin/modinfo usb-storage alias: usb:v*p*d*dc*dsc*dp*ic08isc0 6ip50*

The asterisks are placeholders for arbitrary values as in normal regular expressions, and the last part of the alias (ic08isc06ip50*) is identical with the modalias value. Thus the alias matches, and udevd can insert the usb-storage module into the kernel. How does udevd know which aliases a given module has? It relies on the program depmod, which scans all available modules, extracts the alias information, and stores them in the text file /lib/modules/2.6.x/modules.alias.

The story, however, has not come to an end here. After the USB mass storage module has been inserted into the kernel, the block layer recognizes the device and the partitions contained on it. This leads to another notification.

[email protected] # udevmonitor

UDEV [1201129811.890376] add /block/sdc/sdcl (block)

UDEV_LOG=3

ACTI0N=add

DEVPATH=/block/sdc/sdc1

SUBSYSTEM=block

MINOR=33

MAJOR=8

PHYSDEVPATH=/devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host7/target7:0:0/7:0:0:0

PHYSDEVBUS=scsi

SEQNUM=1837

UDEVD_EVENT=1

DEVTYPE=partition

ID_VENDOR=Kingston

ID_MODEL=DataTraveler_II

ID_REVISION=PMAP

ID_SERIAL=Kingston_DataTraveler_II_5B67040095EB-0:0

ID_SERIAL_SH0RT=5B67040095EB

ID_TYPE=disk

ID_INSTANCE=0:0

ID_BUs=usb

ID_FS_USAGE=filesystem

ID_FS_TYPE=vfat

ID_FS_VERSION=FAT16

ID_FS_UUID=0920-E14D

ID_FS_UUID_ENC=0920-E14D

ID_FS_LABEL=KINGSTON

ID_FS_LABEL_ENC=KINGSTON

ID_FS_LABEL_SAFE=KINGSTON

DEVNAME=/dev/sdc1

DEVLINKS=/dev/disk/by-id/usb-Kingston_DataTraveler_II_5B67040095EB-0:0-part1 /dev/disk/by-path/pci-0000:00:1a.7-usb-0:4:1.0-scsi-0:0:0:0-part1 /dev/disk/by-uuid/0920-E14D /dev/disk/by-label/KINGSTON

The message provides information about the name of the newly detected partition (/dev/sdc1) and the filesystem that is found on the partition (vfat). This is enough for udevd to automatically mount the filesystem and make the USB stick accessible.

Continue reading here: Version Control

Was this article helpful?

0 0