デバイス名を固定するのにudevのルールを書いてみた

fstabでUUIDで指定する - Bouldering & Com.で書いた、起動のたびにデバイスIDが変わってしまうという話、実は全然解決していないのでした。mdadmでraidを組んでいるので、 /etc/mdadm/mdadm.conf に

DEVICE /dev/sd[ab]1

みたいにデバイスの指定を書くんですが、ここではUUIDが使えない(マニュアル見たけどそういうのは書いてない)のでデバイス名を書かざるをえず、デバイスIDが変わるとraidの構築に失敗するという悲しい事態になっていました。
今から思うと、USBメモリの認識順が固定じゃないから、こいつがsdaになったり、sdcになったりして、その余波でHDDのほうのデバイスIDが不安定になってるんですね。

で、最近仕事でudevの役割について学んで、どうやらこいつで解決させることができそうだと思ったのでいろいろ調べて試してみたことの記録。

追記: /dev/diskにある固定のデバイス名を使ってmdadmを使う - Bouldering & Com.に書いたけど、udevルールなんて必要なかったんや...。デフォルトで固有のデバイス名を用意してくれてるから、それを使えばよろしい

結論

/etc/udev/rules.d/ に 10-local.rules のようなファイル名のファイルを作り、

SUBSYSTEMS=="usb", ATTRS{serial}=="07780C6312A7", NAME="usbhda%n"
SUBSYSTEMS=="scsi", DRIVERS=="sd", ATTRS{vendor}=="HAGIWARA" SYMLINK+="hagiwarausb%n"
SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{serial}=="07780C6312A7" SYMLINK+="happyusb%n"

みたいに記述。数字は読み込む順番。
SUBSYSTEMS, ATTRS, DRIVERSなどが条件で、NAME, SYMLINKがその結果どうする、と考えるいいみたい。
詳細は http://opensuse-man-ja.berlios.de/opensuse-html/cha.udev.html をみるのがいいと思う。

しばらくハマっていたのは、演算子の書き方。普通のプログラミング言語みたいに、==なら比較で、=なら代入になっているんだけど、NAMEまで==で書いていて全然動かずにウンウン唸ってた。
ATTRSはネットでみるとSYSFSになってるのが多いけど、後述するudevadm infoの結果の通り、ATTRSをそのまま使えばいい。

デバイス指定方法の探し方

IDを固定したいデバイスを接続して普通に認識させて、infoをみて、ユニークになる情報を探す。serialとかがよいんじゃなかろうか。

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

基本的に、ここにでてくるのをそのまま素直に書けばいい。

  looking at parent device '/devices/pci0000:00/0000:00:0b.0/usb1/1-1':
    KERNELS=="1-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="80"
    ATTRS{bMaxPower}=="200mA"
    ATTRS{urbnum}=="872"
    ATTRS{idVendor}=="0693"
    ATTRS{idProduct}=="0018"
    ATTRS{bcdDevice}=="0100"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="2"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="HAGIWARA"
    ATTRS{product}=="USB Flash Memory"
    ATTRS{serial}=="07780C6312A7"

デバッグ

udevadm monitor --env

でudevdのモニタリングができるけど、あんまり役に立たなかったような…

UDEV  [1329558999.845850] add      /devices/pci0000:00/0000:00:0b.0/usb1/1-1 (usb)
UDEV_LOG=3
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:0b.0/usb1/1-1
SUBSYSTEM=usb
DEVNAME=/dev/bus/usb/001/005
DEVTYPE=usb_device
DEVICE=/proc/bus/usb/001/005
PRODUCT=693/18/100
TYPE=0/0/0
BUSNUM=001
DEVNUM=005
SEQNUM=1354
ID_VENDOR=HAGIWARA
ID_VENDOR_ENC=HAGIWARA
ID_VENDOR_ID=0693
ID_MODEL=USB_Flash_Memory
ID_MODEL_ENC=USB\x20Flash\x20Memory
ID_MODEL_ID=0018
ID_REVISION=0100
ID_SERIAL=HAGIWARA_USB_Flash_Memory_07780C6312A7
ID_SERIAL_SHORT=07780C6312A7
ID_BUS=usb
ID_USB_INTERFACES=:080650:
MAJOR=189
MINOR=4
DEVLINKS=/dev/char/189:4