You may have noticed some udev log messages about deprecated rule syntax with recent kernels, or even older custom udev rules not working anymore. And yes, the documentation is still somewhat scattered, as well as the older (and slightly incorrect) instructions for querying the device tree, etc. I try to keep certain systems as current as possible, at least in terms of the latest stable kernel release and the latest Gentoo ~arch toolchain (and probably too many ~arch packages). That way I get to see most of the change-related breakage of certain APIs, which forces me to update my custom configs on a regular basis (sometimes just to get a basic working setup). Such is life on the bleeding edge of free software development...
Fortunately, normal users should be shielded from much of this "churn" by their upstream distribution maintainers. There are generally several choices of package feeds (stable vs. testing) as well as additional package repositories with more bleeding edge packages (e.g., Planet CCRMA). The bottom line is that you must understand the choices available and the consequences of those choices. After years of using many different operating systems, and a couple dozen Linux distributions, I choose mostly Gentoo Linux for myself (and my household), along with some Debian or Ubuntu for special applications (such as a netbook for my mother-in-law).
But this is supposed to be about udev and hal with recent kernels (2.6.31 and onward), and since I recently had to create some new udev rules, as well as update some older ones, I figured it would be worth documenting. The motivation was the purchase of a 500 GB Seagate FreeAgent Go USB 2.0 hard drive on sale (it even came with a free docking cradle; not sure why it needs two USB plugs for one device). The first issue was a couple of drive settings that weren't being set correctly (although one of them was correct with the latest 2.6.32 kernel) when the drive is hot-plugged. The second issue was my choice of partition scheme and the default auto-mount behavior (which wants to mount every mountable partition). Actually, the drive comes formatted with one large NTFS partition, which most default linux setups can't seem to auto-mount anyway.
So the default behavoir out of the box, at least with recent kernels and a fairly standard desktop, is to generate
a mount failure and fail to set the max_sectors correctly; on slightly older systems, this also
includes an incorrect allow_restart setting which makes the drive sleep and not wake up:
...
sd 6:0:0:0: Device not ready: <6>: Current: sense key: Not Ready
Additional sense: Logical unit not ready, initializing command required
end_request: I/O error, dev sde, sector 976767935
Buffer I/O error on device sde1, logical block 488383936
...
Googling results in plenty of problem hits, along with many fixes that don't seem to work anymore, depending on your current versions of the kernel and udev (hal comes in later). The cause seems to be changes in the layout and naming conventions of device info under /sys (the kernel side) and changes in the way udev parses rules (plus changes in the udev, sysfs, and hal tools). It took me a bit of trial-and-error to get my udev rules to work correctly; crafting a custom hal .fdi file was pretty straight-forward. Based on the current udev documentation (such as it is) I tried getting one or more udev rules to set these parameters directly, but it seems like each setting needs a different match and I got tired of testing after a while, so I fell back to having the rule call a shell script to set the parameters directly via sysfs.
Note the argument to the shell script is the kernel device name. We want the rules to be independent of any kernel-assigned device names or USB device numbers, so we look for SCSI devices that match the Vendor and model info. Once the device is handled by udev, we also want hal to mount only the specified partition.
The udev rule:
$ cat /etc/udev/rules.d/93-usbhdfix.rules
# This is pretty much only for Seagate FreeAgent Go USB drives
# If not adding the device, go away
ACTION!="add", GOTO="usbhdfix_rules_end"
#ATTRS{model}=="FreeAgent Go*", ATTR{max_sectors}="1024", ATTR{allow_restart}="1"
SUBSYSTEMS=="scsi", KERNEL=="sd*[!0-9]", ATTRS{vendor}=="Seagate*", ATTRS{model}=="FreeAgent*", RUN+="/usr/bin/usbhdfix %k"
# All done
LABEL="usbhdfix_rules_end"
The shell script:
$ cat /usr/bin/usbhdfix
#!/bin/bash
# USB fix for Seagate FreeAgent Go drives:
echo 1024 > /sys/block/$1/device/max_sectors
echo 1 > /sys/block/$1/device/scsi_disk/*/allow_restart
The above works correctly on a current Gnome desktop (mostly 2.28) with hal-0.5.14, udev-151, and kernel 2.6.32.2.
Because I chose to partition my drive into 4 partitions (a mixture of swap, ext3, and vfat) the default auto-mount behavior is to mount everything it can mount, meaning all but swap, which was not exactly optimal. Since I only wanted one of the partitions to automount, ie, the main backup partition, it requires a custom hal .fdi file to make it stop mounting the other two. Hal is quite flexible in what it can match on, but it requires the use of volume labels or UUIDs to get the kind of fine-grained control I was looking for. There are other alternatives (using something like pmount) but I wanted to stick with the standard desktop as much as possible.
I decided to use volume labels, since they're much more human-readable than volume UUIDs, and the resulting .fdi file is linked here (but not shown inline). Note the hal .fdi file should go under /etc/hal/fdi/policy/.
It would be nice to have an admin GUI of some kind to create things like this, however, we *are* talking about free software... I'm just happy to have the source code and tools to make my desktop act the way I want it to. The only real annoying part is figuring out what the current tools and syntax are to get things working, along with the multiple interfaces. Trial-and-error seems to be the only way to determine what does or doesn't work; just tail the system log and watch what happens when you plug stuff in. As far as basic hints, there are a few:
Feb 28 11:02:20 shiva kernel: usb 6-2: new high speed USB device using ehci_hcd and address 5
Feb 28 11:02:20 shiva kernel: usb 6-2: New USB device found, idVendor=0bc2, idProduct=2100
Feb 28 11:02:20 shiva kernel: usb 6-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Feb 28 11:02:20 shiva kernel: usb 6-2: Product: FreeAgent Go
Feb 28 11:02:20 shiva kernel: usb 6-2: Manufacturer: Seagate
Feb 28 11:02:20 shiva kernel: usb 6-2: SerialNumber: 2GE2G0HK
Feb 28 11:02:20 shiva kernel: usb 6-2: configuration #1 chosen from 1 choice
Feb 28 11:02:20 shiva kernel: scsi7 : SCSI emulation for USB Mass Storage devices
Feb 28 11:02:20 shiva kernel: usb-storage: device found at 5
Feb 28 11:02:20 shiva kernel: usb-storage: waiting for device to settle before scanning
Feb 28 11:02:25 shiva kernel: usb-storage: device scan complete
Feb 28 11:02:25 shiva kernel: scsi 7:0:0:0: Direct-Access Seagate FreeAgent Go 102D PQ: 0 ANSI: 4
Feb 28 11:02:25 shiva kernel: sd 7:0:0:0: Attached scsi generic sg4 type 0
Feb 28 11:02:25 shiva kernel: sd 7:0:0:0: [sdc] 976773168 512-byte logical blocks: (500 GB/465 GiB)
Feb 28 11:02:25 shiva kernel: sd 7:0:0:0: [sdc] Write Protect is off
Feb 28 11:02:25 shiva kernel: sd 7:0:0:0: [sdc] Mode Sense: 1c 00 00 00
Feb 28 11:02:25 shiva kernel: sd 7:0:0:0: [sdc] Assuming drive cache: write through
Feb 28 11:02:25 shiva kernel: sd 7:0:0:0: [sdc] Assuming drive cache: write through
Feb 28 11:02:25 shiva kernel: sdc: sdc1 sdc2 sdc3 sdc4
Feb 28 11:02:25 shiva kernel: sd 7:0:0:0: [sdc] Assuming drive cache: write through
Feb 28 11:02:25 shiva kernel: sd 7:0:0:0: [sdc] Attached SCSI disk
Feb 28 11:02:26 shiva kernel: kjournald starting. Commit interval 5 seconds
Feb 28 11:02:26 shiva kernel: EXT3-fs warning: maximal mount count reached, running e2fsck is recommended
Feb 28 11:02:26 shiva kernel: EXT3 FS on sdc4, internal journal
Feb 28 11:02:26 shiva kernel: EXT3-fs: mounted filesystem with writeback data mode.
Feb 28 11:02:26 shiva hald: mounted /dev/sdc4 on behalf of uid XXX
$ cat /sys/block/sdc/device/max_sectors
1024
$ cat /sys/block/sdc/device/scsi_disk/7\:0\:0\:0/allow_restart
1
Since many of the better documents on writing udev rules are somewhat out of date, in that the examples given use deprecated and/or missing commands, here are some working examples (assuming you use a valid device name).
udevadm info --attribute-walk --name=sdc
udevadm info -a -p /sys/class/scsi_disk/7\:0\:0\:0/
Note in this example, for a USB device the device ID will increment each time the device is plugged in.
udevadm info --query=all --path=/sys/block/sdb
udevadm trigger
systool -v -b scsi
systool -v -c scsi_disk
lshal -s
lshal -u volume_uuid_6a0f0e32_ab37_085d_c64e_af34681027cb_0
See this forum thread for some additional discussion: Trouble with external USB harddrive (Seagate FreeAgent) [SOLVED]