Calling things by the same name
In response to my blog post “Whatever you do, don’t fix the kernel!“, David Zeuthen (prominent plumber, the maintainer of HAL and author of DeviceKit) wrote:
Scott, here’s why you’re wrong. It’s very simple and comes down to two points
- you obviously agree we can’t break huge amounts of userspace by changing DEVPATH
- having two names emitted from the kernel (_just_ because lots of user space is
broken) is just wrong and confusing
=> much better to fix up things in user spaceBesides, what’s in a freaking name _anyway_? Apps should be using stable symlinks or, gosh, a device enumeration framework like HAL or the upcoming DeviceKit.
He makes, I think, an interesting point.
Why do we have two names for devices?
The kernel maintains its own namespace for devices which is based on its tree of internal objects and exported via the sysfs virtual filesystem. My mouse’s object path is /devices/pci0000:00/0000:00:02.0/usb2/2-4/2-4:1.0/input/input2/mouse1 (convention is to omit the /sys prefix), and a class device link also exists as /class/input/mouse1 for easy access.
Properties of the device object are exported into user space via the sysfs filesystem, at that path under its mount point, and announcements of new objects, and significant changes to or removal of existing objects are made through the uevent system. One of those properties is details about the device node that needs to be created; the dev file contains the major and minor number, and these are also present in the MAJOR and MINOR keys of the uevent.
The udev daemon listens out for these uevents and creates device nodes under the /dev path for userspace to use. These device nodes have a naming scheme that is mostly flat, with some sub-directories used for grouping. It records both the kernel object name and device path in its database so that lookups can be performed on device removal, and queries by applications using DeviceKit.
It also passes on the uevent to HAL, which stores the mapping in its own database and performs its own actions.
Applications can then use DeviceKit or HAL to enumerate devices by type, or walk the tree of devices, and lookup the actual device node path from that. They may also use them to lookup the object information for a given device node path.
That’s quite a lot of work going on behind the scenes already to map between two different names for a single device, all my proposal tried to do was reduce a little bit of the user-space side of that work by harmonising the names.
But maybe David has a point, the real problem is that we have two names in the first place!
Obviously the /dev paths are necessary for the vast number of userspace applications that still require them. But why do applications that use DeviceKit or HAL need them?
If the kernel placed a device node inside the sysfs filesystem, we wouldn’t need to do any path lookup, we’d just append the fixed name of the node to the object name.
udev would only need to make symlinks to those devices in /dev for legacy applications.






oliver:
Hm, so what’s the advantage of your idea? Udev will still be running, there will still be two names, and also there will be two device files then, no?
28 August 2008, 2:23 pmregala:
And it would just mean put “devfs feature set” into sysfs, wouldn’t it ? I think kernel hackers already redeemed themselves from using devfs, and they stated quite strongly devfs feature set in kernel space (actually creating device nodes in kernel space for example) is racy, messy and hacky.
28 August 2008, 3:56 pmRui:
@oliver
28 August 2008, 4:17 pmAFAIU no, there wouldn’t be 2 device files since the ones in /dev are *symlinks* created by udev for the benefit of legacy apps.
Havoc:
As I put it on http://ometer.com/hardware.html 5 years ago,
2. Creating and maintaining /dev files - As long as this is suitably buried beneath the hardware abstraction library, it’s fairly irrelevant to desktop application developers how it works. Anything that works is great.
28 August 2008, 5:22 pmJames:
Oliver: one device file, and a symlink to a device file. It seems a lot like the way Solaris devices work, although device names are a lot more persistent under Solaris. Don’t make /dev/null a symlink to /devices/pseudo/mm@0:null though.
28 August 2008, 5:47 pmZack:
Doesn’t this bring back the permissions problems that were (AFAIR) one of the biggest nails in devfs’ coffin? The kernel doesn’t (and can’t) know the correct permissions to apply to a new device node, and allowing them to exist for any time with the wrong permissions is a security hole?
28 August 2008, 6:17 pmdavidz:
A couple of points
- what apps really really *want* are stable device names,
like /dev/disk/by-label/David-Zeuthens-iPod. They want
to e.g. save this name in their config files etc. Or you
want stable names in /etc/fstab or whatever.
- stable names are somewhat expensive to compute (probing
an fs for the fstype and fslabel; sending commands to a
serial device to figure out what kind of modem it is etc.)
and rely on both per-os, per-site and and per-machine policy.
Also, user space driver frameworks wants to participate here,
for example if I’m libgphoto2 or libmtp I want to somehow
create /dev/mtp/Sansa_e200 -> /dev/bus/usb/002/003
Hence why it’s good to put it in user space like we do now.
- Permissions. Figuring out the permission of a device node
may require pretty sophisticated user space components (like
PolicyKit) and you really want to ensure the permissions are
set before the device is announced to user space.
- The raw device file name (e.g. /dev/sda) are simply not
interesting; in fact it’s a bug that so many people store
it in config files etc. And that’s all you’d get from having device
nodes in sysfs.
While devfs-ish schemes can be cute and all, there’s just no
reason to do it in kernel space. And, FWIW, remember the last
time someone tried this in Linux? It was pretty much FAIL FAIL
FAIL all over the map.
[my personal opinion is that a minimal devfs would probably
work and even make things a bit simpler. But you'd need
stable names even in the initramfs anyway.]
- also, sysfs expresses the physical by-connection hierarchy,
it’s most often don’t what you want
- note that some devices don’t have file files; apps poke
them via sysfs files already so at least parts of what
you’re proposing is working like this (e.g. PCI devices,
I think libpciaccess mmaps files from sysfs)
- also, for some devices you may need to send commands / firmware
to them (for initialization) before you announce the device to
the rest of the OS. Some usb devices (I think ezusb but maybe
I got the name wrong) actually requires this; initially such
devices pop up as a vendor-specific usb devices; then you load
firmware onto them and then the device reboots (e.g. the usb
device disappears from the host’s POV) and then come back as a
different usb device. So e.g. you need some way of expressing
this and with udev it works just fine.
I hope this clarifies why udev is very useful as it does all this
28 August 2008, 6:56 pmtoday; I’m not exactly sure what part of the current udev you’re
unhappy with and how you propose to solve all the problems above
by switching to a pure devfs (as you are suggesting) solution?
Alexander E. Patrakov:
The “device in sysfs” thingy has been already considered before and rejected on the following basis. What should be the permissions and ownership of the device node?
I.e., udev combines major+minor+name information from the kernel with the permissions policy (i.e., the thing that should not be in the kernel) expressed in its rules. In yet other words, the kernel doesn’t have enough information to create a device node in sysfs.
29 August 2008, 2:48 am