by Chris Lumens
September 8, 2004
hotplug is a system for managing devices that can be dynamically attached to and removed from the system while it's running. The most obvious use for this system is handling USB and firewire devices, though it also handles PCI (32-bit PCMCIA - or CardBus - devices are really PCI in disguise), tape drives, SCSI devices, devices requiring firmware to be loaded into them, input devices, and more. It consists of a kernel part and a userland part. I'll only cover the userland part in any depth, as users should not ever have to dive into the kernel half.
The problem hotplug tries to solve is a very difficult one, especially for the land of Unix where hardware is accessed through device nodes and includes real permission checking. Device nodes themselves are special little files in /dev that are referenced through static major and minor numbers which must be registered somewhere. They must also be given owners and groups, as well as permissions for access. For static devices like an internal hard disk or a sound card, this system works fairly well.
However once dynamic devices are added to the system, the traditional Unix approach falls apart. When a USB drive is plugged into the system, what is it even called? A device node needs to be automatically created before ownerships and permissions can be assigned to it. Once this device file is created, the system will also need to know who to assign ownership to and what permissions everyone else should have. Unfortunately, the kernel can't really keep track of this information without some sort of outside help. This is where hotplug comes in, but it tried to be much more generic. Instead of just handling device node creation and permissions, hotplug allows arbitrary scripts to be run. hotplug was introduced in the 2.4 kernel series and has become much more important in the 2.6 series.
hotplug refers to anything that happens as an action or event. The two main kinds are add and remove, though they may also be referred to as register and unregister depending on which subsystem files you're looking at. Get used to this sort of consistency.
In this presentation, I will first cover how hotplug is put together and a trace of an event going through the system. I'll also cover some examples of what you can use hotplug to do, before finally discussing some of the problems with the hotplug system and outlining an alternate implementation.
The default hotplug implementation comes from the Linux Hotplugging Project and is maintained by Greg Kroah-Hartman. It is written entirely in shell and little specially formatted config files, though there's no reason it couldn't be written in Perl, C, or any other language you want. The default implementation has a whole lot of files that call each other with some magic parameters and environment settings. Here's what you have to deal with:
As you can see, there's a lot of parts. This is good in that you can pretty thoroughly extend the system - you can hook in via a subsystem-specific script in /etc/hotplug.d, modifying the agent and rc files, or by modifying a map file and adding in your own script to be run when that device is detected. All this makes it easy on the package maintainer to add their own thing, but difficult on people who want to understand how it all fits together. Debugging is not hotplug's strongest point.
Just staring at a big list of files isn't very helpful. To really understand how it all fits together, we should take a look at how the entire system works together to handle an event. We'll examine plugging in a USB keychain drive, though the process will be similar for any hotplug-enabled driver. I won't cover any special add-on functionality like automounting until the next section.
gphoto is a program for manipulating digital cameras. For USB cameras, you can plug the camera into a USB port and have gphoto copy the pictures off the camera and onto your hard drive. This is a good place for using hotplug to automate the task.
The first step is to generate a map file that contains your camera's entry. The print-usb-usermap program that ships with libgphoto2 can output a map file describing all the cameras it supports:
This map file will run a usbcam script every time a camera is attached to the system. You can then make a /etc/hotplug/usb/usbcam script to do whatever you wanted. The simplest script making use of gphoto would just copy the pictures off. Your script can make use of all those environment variables that hotplug keeps passing around, as well.
hotplug can be used to do automatic backups when a disk is attached. This quick little example isn't very automatic, though, because figuring out the device name assigned to a hotplugged disk is very difficult. You'll need things like udev and sysfs to help with that. As before, you'll need to make a map file entry to match your particular disk, but for this match you should point it at a script named syncup. Then, your script could look something like this:
In this example, I have assumed the name of the device as well as skipped the whole problem of unmounting the disk when the device is detached. A sophisticated backup script would be much longer and have lots of error checking, but this gives you the basic idea of what's possible. I originally intended this example to use firewire, but the current agent script doesn't support map file hooks like the USB agent does. You could, of course, change this on your own system.
The problem hotplug tries to solve is a very difficult one, and it provides an extremely flexible and extensible set of scripts. However, its current implementation is not without some significant problems. Unfortunately it's also the most popular implementation right now so these are problems we are going to have to face for some time, unless significant patches are made. As the 2.6 kernel gets more widely used, hotplug is also only going to get more important.
Anyone who's motivated enough can write their own hotplug replacement. All that's required is to write a program that accepts the arguments and environment variables the kernel passes and loads the appropriate modules. If you're really motivated, you can also provide hooks for running arbitrary scripts. However, much of what hotplug does or tries to do is completely optional.
One such alternate implementation is the probulator, part of the Genthree distribution. The probulator handles the USB, firewire, PCI, and firmware agents and the add and remove events. It can load and unload modules and firmware blobs. It does not currently allow for arbitrary scripts being run or add-on map files but these would be trivial to implement. It currently does everything the developers require in a single 255 line shell script.
The current CVS version of the probulator can be downloaded from http://www.bangmoney.org/presentations/hotplug/probulator.
hotplug is a complex subsystem that first appeared in 2.4 to handle USB and firewire devices, but has grown well beyond that original purpose. Under 2.6, it handles all sorts of hardware events now including firmware loading, PCI devices, network cards, and so forth. It provides an extensible system for writing your own scripts that hook in to the events. However, it is also a complex tangle of shell scripts that move kernel functionality out into user land. As 2.6 becomes more and more popular, this subsystem will become even more important to regular users who will have to deal with it every day.
This presentation is available at http://www.bangmoney.org/presentations/hotplug/ and is © 2004 Chris Lumens.