Recent Changes - Search:


Code:


Social:


My journals will take the place of a blog. If you go to the Journal page there is an RSS feed to subscribe with.

« July 2017 
SunMonTueWedThuFriSat
      1
2345678
9101112131415
16171819202122
23242526272829
3031     

Sites I take responsibility for

West Volusia, Florida

Documents

Technical

General

Me

Living

Places I frequent

Hobbies

Humor

Items for sale:


Clipboard

edit SideBar

Auto-detection and auto-mounting of devices in Linux

Include our styles below Infobox - invoke as >>infobox<< ... >><<

Codebox: - invoke as >>codebox<< ... >><<

warnbox: - invoke as >>codebox<< ... >><<

editingbox: - invoke as >>codebox<< ... >><<

noticebox: - invoke as >>codebox<< ... >><<

Page bread crumbs: Welcome to ke3vin.org! - My Public Technical Notes - Software And Operating Systems - Linux - Howtos - Disks And Volumes - Device Management Under Linux - Autodetection And Automounting

Pages by tags: (:listtags:)
Subscribe to this wiki: RSS Feed RSS or subscribe to this page for changes: RSS Feed RSS
496 articles have been published so far. Recent changes
Share

2016-03-22: This site is being moved to my main site at https://kevininscoe.com/wiki as part of a consolidation to one domain.


References:

http://www.reactivated.net/writing_udev_rules.html

http://www.debianhelp.org/node/9937

http://www.gentoo.org/doc/en/udev-guide.xml

http://webpages.charter.net/decibelshelp/LinuxHelp_UDEVPrimer.html

There are essentially two ways to auto-detect and then auto-mount portable, card or "hot plug" devices in Linux.

All USB and PCI devices contain an identifier that describes either what kind of functions they support (like a USB audio or USB mass storage device), or if they do not support a class specification, they contain a unique vendor and product identifier. PCMCIA devices also contain these same kind of identifiers.

These identifiers are known by the PCI and USB kernel drivers, as they need to know which kind of devices they work properly for. The USB and PCI kernel drivers register with the kernel a list of the different types of devices that they support. This list is used to determine which driver will control which devices.

The kernel knows when and what kind of devices are inserted or removed from the system through the device bus core code (USB, FireWire, PCI, etc.). It can send this information to the user.

Taking these three pieces together (devices tell the computer what they are, drivers know what devices they support and the kernel knows what is going on) provides us with a solution to let the computer automatically load the proper driver whenever a new device is inserted.

First a little history:

Starting with kernel 2.4.14 (in January 2001), hotplugging became a standard feature of Linux. It's been backported to kernel 2.2 (for USB), and kernel 2.6 makes it available to all sysfs-adapted busses and driver classes. In the Linux 2.6 kernel, hotplugging has been integrated with the driver model core so that any bus or class can report hotplug events when devices are added or removed. There has been much improvement in the support of for hotplugging for many kinds of devices, including things like disks, power supplies (many newer UPSes are usb-programmable), input devices, and even more. In particular, udev builds on hotplug, to help make sure your /dev/... directory matches the devices actually present on your system. Some where around the year 2005 and kernel 2.6.10 or so devfs gave way to udev as a device structure. There were a number of reasons for this decision and udev is now the standard for the 2.6 kernel and beyond (so far as of this writing).

udev and desktops.

OK fine now we know Linux can dynamically locate and mount devices at boot time but how about if they are plugged in later? Well as I mentioned earlier there are two ways this is achieved by the non-root user (typically a desktop). You can write a rule in udev to perform this for a given USB for Firewire device or you can have the window manager (if it is indeed a desktop and you are running a window manager) itself (KDE or Gnome typically) do it for you via either HAL (depreciated) or DeviceKit. Personally since I run a server/desktop combo and prefer command line I typically let udev do it for me.

udev rules:

Hack a Day has a good article on this. Before we write a rule for auto-mounting we first need to get some information about the device. Plug the device in and let the kernel auto-detect it. Now let's find out what the kernel knows about the device. Be sure to execute this command quickly after insert the device:

 # dmesg | tail -n 20 
 [110523.590582] drivers/usb/core/inode.c: creating file '006'
 [110523.590643] usb 1-6: New USB device found, idVendor=05ac, idProduct=120a
 [110523.590646] usb 1-6: New USB device strings: Mfr=1, Product=2, SerialNumber=3
 [110523.590648] usb 1-6: Product: iPod
 [110523.590650] usb 1-6: Manufacturer: Apple
 [110523.590651] usb 1-6: SerialNumber: 000A27001855C2D7
 [110523.590655] usb-storage: device found at 6
 [110523.590657] usb-storage: waiting for device to settle before scanning
 [110523.627682] usb 1-6: uevent
 [110528.590340] usb-storage: device scan complete
 [110528.592579] scsi 8:0:0:0: Direct-Access     Apple    iPod             1.62 PQ: 0 ANSI: 0
 [110528.595940] sd 8:0:0:0: [sdd] 1999871 512-byte hardware sectors: (1.02 GB/976 MiB)
 [110528.599309] sd 8:0:0:0: [sdd] Write Protect is off
 [110528.599312] sd 8:0:0:0: [sdd] Mode Sense: 68 00 00 08
 [110528.599314] sd 8:0:0:0: [sdd] Assuming drive cache: write through
 [110528.601188] sd 8:0:0:0: [sdd] 1999871 512-byte hardware sectors: (1.02 GB/976 MiB)
 [110528.605316] sd 8:0:0:0: [sdd] Write Protect is off
 [110528.605320] sd 8:0:0:0: [sdd] Mode Sense: 68 00 00 08
 [110528.605322] sd 8:0:0:0: [sdd] Assuming drive cache: write through
 [110528.605326]  sdd: sdd1 sdd2
 [110528.609259] sd 8:0:0:0: [sdd] Attached SCSI removable disk
 [110528.609330] sd 8:0:0:0: Attached scsi generic sg8 type 0

Ok we know several things about the device we just plugged: the device path it has been assigned (/dev/sdd) and what readable partitions the device has (sdd: sdd1 sdd2). Since this is an Apple iPod I want the second partition (sdd2). As the article points out we then pass the device path (/dev/sdd2) to two commands that we run at the same time. Some distributions use the "udevinfo" command but with Ubuntu 9.04 the command has changed to "udevadm info". I am using Gentoo and the command udevadm applies here:

 # udevadm info -a -p $(udevadm info -q path -n /dev/sdd2)

 Udevadm info starts with the device specified by the devpath and then
 walks up the chain of parent devices. It prints for every device
 found, all possible attributes in the udev rules key format.
 A rule to match, can be composed by the attributes of the device
 and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:0b.1/usb1/1-6/1-6:1.0/host8/target8:0:0/8:0:0:0/block/sdd/sdd2':
    KERNEL=="sdd2"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{partition}=="2"
    ATTR{start}=="63"
    ATTR{size}=="160587"
    ATTR{stat}=="      15      452      467      186        0        0        0        0        0      160      186"

  looking at parent device '/devices/pci0000:00/0000:00:0b.1/usb1/1-6/1-6:1.0/host8/target8:0:0/8:0:0:0/block/sdd':
    KERNELS=="sdd"
    SUBSYSTEMS=="block"
    DRIVERS==""
    ATTRS{range}=="16"
    ATTRS{ext_range}=="256"
    ATTRS{removable}=="1"
    ATTRS{ro}=="0"
    ATTRS{size}=="1999871"
    ATTRS{capability}=="53"
    ATTRS{stat}=="      39     1024     1063      415        0        0        0        0        0      218      415"

  looking at parent device '/devices/pci0000:00/0000:00:0b.1/usb1/1-6/1-6:1.0/host8/target8:0:0/8:0:0:0':
    KERNELS=="8:0:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS=="sd"
    ATTRS{device_blocked}=="0"
    ATTRS{type}=="0"
    ATTRS{scsi_level}=="0"
    ATTRS{vendor}=="Apple   "
    ATTRS{model}=="iPod            "
    ATTRS{rev}=="1.62"
    ATTRS{state}=="running"
    ATTRS{timeout}=="30"
    ATTRS{iocounterbits}=="32"
    ATTRS{iorequest_cnt}=="0x3f7"
    ATTRS{iodone_cnt}=="0x3f7"
    ATTRS{ioerr_cnt}=="0x0"
    ATTRS{modalias}=="scsi:t-0x00"
    ATTRS{evt_media_change}=="0"
    ATTRS{queue_depth}=="1"
    ATTRS{queue_type}=="none"
    ATTRS{max_sectors}=="240"

  looking at parent device '/devices/pci0000:00/0000:00:0b.1/usb1/1-6/1-6:1.0/host8/target8:0:0':
    KERNELS=="target8:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS==""

  looking at parent device '/devices/pci0000:00/0000:00:0b.1/usb1/1-6/1-6:1.0/host8':
    KERNELS=="host8"
    SUBSYSTEMS=="scsi"
    DRIVERS==""

  looking at parent device '/devices/pci0000:00/0000:00:0b.1/usb1/1-6/1-6:1.0':
    KERNELS=="1-6:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb-storage"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bNumEndpoints}=="02"
    ATTRS{bInterfaceClass}=="08"
    ATTRS{bInterfaceSubClass}=="06"
    ATTRS{bInterfaceProtocol}=="50"
    ATTRS{modalias}=="usb:v05ACp120Ad0002dc00dsc00dp00ic08isc06ip50"
    ATTRS{supports_autosuspend}=="0"

  looking at parent device '/devices/pci0000:00/0000:00:0b.1/usb1/1-6':
    KERNELS=="1-6"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="c0"
    ATTRS{bMaxPower}=="500mA"
    ATTRS{urbnum}=="2201"
    ATTRS{idVendor}=="05ac"
    ATTRS{idProduct}=="120a"
    ATTRS{bcdDevice}=="0002"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="2"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="6"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Apple"
    ATTRS{product}=="iPod"
    ATTRS{serial}=="000A27001855C2D7"

  looking at parent device '/devices/pci0000:00/0000:00:0b.1/usb1':
    KERNELS=="usb1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}=="  0mA"
    ATTRS{urbnum}=="144"
    ATTRS{idVendor}=="1d6b"
    ATTRS{idProduct}=="0002"
    ATTRS{bcdDevice}=="0206"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="1"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="8"
    ATTRS{quirks}=="0x0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Linux 2.6.28-gentoo-r5 ehci_hcd"
    ATTRS{product}=="EHCI Host Controller"
    ATTRS{serial}=="0000:00:0b.1"
    ATTRS{authorized_default}=="1"

  looking at parent device '/devices/pci0000:00/0000:00:0b.1':
    KERNELS=="0000:00:0b.1"
    SUBSYSTEMS=="pci"
    DRIVERS=="ehci_hcd"
    ATTRS{vendor}=="0x10de"
    ATTRS{device}=="0x026e"
    ATTRS{subsystem_vendor}=="0x105b"
    ATTRS{subsystem_device}=="0x0caf"
    ATTRS{class}=="0x0c0320"
    ATTRS{irq}=="20"
    ATTRS{local_cpus}=="f"
    ATTRS{local_cpulist}=="0-3"
    ATTRS{modalias}=="pci:v000010DEd0000026Esv0000105Bsd00000CAFbc0Csc03i20"
    ATTRS{enable}=="1"
    ATTRS{broken_parity_status}=="0"
    ATTRS{msi_bus}==""

  looking at parent device '/devices/pci0000:00':
    KERNELS=="pci0000:00"
    SUBSYSTEMS==""
    DRIVERS==""

We must now locate several device identifiers for this device to allow udev to recognize this device uniquely without confusion over other similar devices. It is important to note that you can only reference one parent from the above udevadm command output so pick one that has the MOST unique strings. In my case I will use SUBSYSTEMS of "usb" as the parent block since it has a device serial number. Other times you will have devices that have no serial number and it will become tougher to uniquely match them particularly if you have more than one of them. In that case try to either partition the device or make something about it as unique as you can that the device file system will see. Perhaps some attribute code from the manufacturer. Again referring to the article linked above "In writing a udev rule, any of these characteristics can be used as conditions for the rule’s execution. That being said, only properties from one parent of the device and from the device itself can be match. Trying to match values from more than one parent in the chain will be invalid and will not work."

The rule:

Notes:

http://www.reactivated.net/writing_udev_rules.html

http://www.linuxquestions.org/questions/slackware-14/ipod-udev-rules-for-2-different-ipods-444425/

At this point I am going to quote heavily from the article as it states what we need to do verb succinctly.

Rule files are stored in the /etc/udev/rules.d/ directory (in my case Gentoo sys-apps/baselayout 1.12.13 and sys-fs/udev 146-r1) the rules directory is in /etc/udev/rules.d). We got some advice from the README in that directory on how to name rule files:

Files should be named xx-descriptive-name.rules, the xx should be chosen first according to the following sequence points:

< 60 most user rules; if you want to prevent an assignment being overriden by default rules, use the := operator.these cannot access persistent information such as that from vol_id

< 70 rules that run helpers such as vol_id to populate the udev db

< 90 rules that run other programs (often using information in the

    udev db)

>=90 rules that should run last

I plan to run a script with this rule so we gave it a name that started with a higher number than our other rules but lower than 90. We used the filename:

 81-ipod.rules 

I created /etc/udev/rules.d/81-ipod.rules with the following lines:

 SUBSYSTEMS=="usb", \
 KERNEL=="sd[defghijkl]2", \
 ATTRS{serial}=="000A27001855C2D7", \
 SYMLINK="ipod", \
 OWNER="kinscoe", \
 RUN+="/bin/mount -t vfat -o user,auto,owner,uid=kinscoe,gid=kinscoe /dev/ipod /media/ipod"

I chose "sd[defghijkl]2" for the device string because I already have disk drives in the system for sda, sdb and sdc so I figured I would just skip those but as long as you have unique strings "sd?2" would probably work just as well. I used a symlink because I want to mount based on the original block device assigned by the system when I plugged it in however I also want a unique persistent device name for scripting if I need that later. Depending on what distro you are using you may need to create the mountpoint (/media/ipod) if it's not dynamic in sysfs. Note that I used the OWNER field and mounted as my uid/gid non-root pair so I could manage the device without becoming root and could also eject it later from my account. This is an important step if you wish the use the device as a non-root user. I also set owner so I could remount the device later from my non-root account if I want to change something.

  # mkdir -p /media/ipod

*** WARNING *** WARNING ***

DO NOT RUN THIS IF YOU ARE USING A DESKTOP WHICH HAS RUNNING APPLICATIONS OR
ESPECIALLY ON A SERVER WITH OTHERS DEPENDING ON IT. IF THE RULES HAVE ERRORS IN
THEM UDEV WILL GET CONFUSED AND YOUR SERVER WILL BECOME USELESS! THIS HAS HAPPENED
TO ME MORE THAN ONCE. IN OTHER WORDS BE PREPARED TO REBOOT INTO RECOVERY IF THIS
DOES NOT WORK. MAKE SURE YOU HAVE A SINGLE USER MODE PROFILE IN GRUB AND YOU KNOW
HOW TO MAKE A RECOVERY EDIT IN SINGLE USER MODE. YOU HAVE BEEN WARNED!!!!

*** WARNING *** WARNING ***

New to trigger the new rule don't restart the udev daemon instead use the command

 # udevadm trigger

Check to make sure our device alias is correct

 $ ls -l /dev/ipod*
 lrwxrwxrwx 1 kinscoe kinscoe 4 2009-11-22 10:10 /dev/ipod -> sdd2

You can now reference your device (ipod) as /dev/ipod via the symlink.

The mount command should have taken effect so let's check that we have mounted
the device:

 $ df -h /media/ipod
 Filesystem            Size  Used Avail Use% Mounted on
 /dev/sdd2             897M  128M  770M  15% /media/ipod

Viola your done. Now you can access your iPod or USB stick like any other file system.

Don't forget to eject your device when your done with it (AND BEFORE YOU DISCONNECT IT) so it can be auto-mounted (hence the mount -o auto option).

 $ eject /media/ipod

(:tags Linux, HOWTO:)


Kevin's Public Wiki maintained and created by Kevin P. Inscoe is licensed under a
Creative Commons Attribution 3.0 United States License.

Back to my web site - http://kevininscoe.com

Edit - History - Print - Recent Changes - Search
Page last modified on January 15, 2010, at 11:28 AM EST