外付けUSBハードディスクドライブでRAIDを組む

Fedora 7が出たのを契機に自宅サーバのOSをFedora Core 5からDebian Etchに乗り換えたので、そのついでに色々と構成を変更することにした。


メインサーバは問題ないのだけど、サブサーバとして使っているマシン(NECのデスクトップ)の冷却性能が酷くて、内蔵ベイに二台以上HDDを突っ込むと温度が平気で60℃を超えてしまう。水冷なんてキワモノに手を出したのがいけなかったなあ。で、仕方ないので内蔵ベイに入れるHDDは一台にして、ちょうど余っていたUSB-IDE変換機を使ってもう一台のHDDを外付けにすることにした。


いつぞやの同時多発クラッシュを経験して以来RAIDでミラーを構成しないと精神的に落ち着かなくなってきたので、HDDを二台とも内蔵ベイに入れておいてRAIDを構成してからその上にOSをインストールしておいた。ちゃんとRAIDが動いているのを確認して電源を一旦落とし、一台を取り出して外付けに接続してから電源オン。

起動して

$ cat /proc/mdstat

してみたところ、外付けにしたHDDがRAIDに参加していないことが判明。なんでだー、と思いつつ、手動でre-addしてみる:

# mdadm --re-add /dev/md0 /dev/sda1

と、普通に参加してくれた。


いちおう、起動のたびに手動でre-addしてやればなんとかなるのだけど、いちいちやるのは面倒だということと、re-addのたびにresyncが始まってHDD全体のコピーが行われるのが良くないように思う。


いろいろ調べてみたところ(Linuxには不慣れなので、まずブートの仕組みから勉強しなおすことになった)、原因はブート時にmdadmが走るとき、USB storageがまだ認識されていないからみたいだ。mdadmによるRAIDの認識は当然ながらルートファイルシステムのマウントの前に行われるので、initramfsの中をいじらなければならない。


まず、USB HDDを認識するために必要なカーネルモジュールがinitramfs内でロードされているかチェック。

$ mkdir initramfs
$ cd initramfs
$ zcat /boot/initrd.img-2.6.18-4-686 | cpio -i
22930 blocks
$ find lib/modules | grep usb
lib/modules/2.6.18-4-686/kernel/drivers/usb
lib/modules/2.6.18-4-686/kernel/drivers/usb/core
lib/modules/2.6.18-4-686/kernel/drivers/usb/core/usbcore.ko
lib/modules/2.6.18-4-686/kernel/drivers/usb/storage
lib/modules/2.6.18-4-686/kernel/drivers/usb/storage/usb-storage.ko
lib/modules/2.6.18-4-686/kernel/drivers/usb/input
lib/modules/2.6.18-4-686/kernel/drivers/usb/input/usbhid.ko
lib/modules/2.6.18-4-686/kernel/drivers/usb/host
lib/modules/2.6.18-4-686/kernel/drivers/usb/host/ehci-hcd.ko
lib/modules/2.6.18-4-686/kernel/drivers/usb/host/uhci-hcd.ko
lib/modules/2.6.18-4-686/kernel/drivers/usb/host/ohci-hcd.ko

あるっぽい。うーん、なんでだめなんだ。

と思ったら、実はusb_storageは接続からマウントまで5秒ほど間をおくらしい。

毎日が撤退戦 - usb_storageマウント失敗
http://llama.logos.k.u-tokyo.ac.jp/~yokoyama/diary/archives/001966.php

これだー。というわけで、/etc/initramfs-tools/scripts/init-premountにsleep 10するスクリプトを置くことにしてみる。

# cd /etc/initramfs-tools/scripts/init-premount
# vi usbstorage
# chmod +x usbstorage
# cat usbstorage
#!/bin/sh

PREREQS=""

prereqs() { echo "$PREREQS"; }

case "$1" in
    prereqs)
    prereqs
    exit 0
    ;;
esac

. /scripts/functions

log_begin_msg "Probing USB storage modules"
sleep 10
log_end_msg

書き込んだら、

# update-initramfs -u

でinitramfsを再作成して再起動。これでめでたく起動時からRAIDが走ってくれた。