Linux 起動時に RAID パーティションを認識させる
SOFTWARE REPORT
Slackware 10.2 で起動時に RAID パーティションを認識させたい
EZ-NET レポート: Microsoft Virtual Server 2005 R2 の Linux 用アドインソフトに関する試行錯誤 にて解消に至らなかった Slackware 10.2 で RAID パーティションを起動時に認識させようというお話しです。環境としては Microsoft Virtual Server 2005 R2 (Beta 1) にて SCSI 構成の仮想 PC を用意して、そこに Slackware 10.2 をインストールしてある環境です。
その状況でハードディスクを RAID 構成にして使用しようと思ったのですけど、カーネルに組み込まれた aic7xxx では問題なく動作するものの、Microsoft 社から提供されている Linux 用の仮想マシンアドインソフトを組み込んで vmadd-scsi モジュールを利用してみたところ、ドライバの組み込みには成功したものの、途端に RAID を思い通りに利用できなくなってしまったのでした。
あれからいろいろと調べてみて、さまざまな見通しが立ってきたので、今回はそれを記録に残しておくことにします。
起動時に RAID パーティションを有効にするための調査
RAID 開始のタイミングを計ってみる
とにかく RAID の準備が間に合わない感じがします。
というのも、起動時の /etc/fstab に設定された RAID パーティションがマウントされようとする時には失敗となるのですけど、 起動してログインしてからもまだ RAID デバイスが準備できては居ないものの、"raidstart --all" を実行すればすぐに利用できるようになるので…。
なので、どの辺りから RAID が利用できるようになるかを調べるために、Slackware 10.2 は /etc/rc.d/rc.M がマルチユーザーモードに突入した際に実行されるスクリプトですので、とりあえずここの最初の辺りに "raidstart --all" を書き加えてみることにしました。そうしてみたところ、マルチユーザー環境に突入してこの行を通過した時には、正常に RAID デバイスが機能することがわかりました。
ただし既に /etc/fstab によるマウント手続きも終了してしまっているので、さらに意図したところへマウントさせるには、また手間が必要になります。
モジュールにしたことが影響しているのかを判断してみる
新たに組み込んだ "vmadd-scsi" デバイスドライバの問題なのかもしれないので、とりあえずその辺りの判断をするために "mkinitrd" および "/etc/modules.conf" にて "vmadd-scsi" ではなく "aic7xxx" を読み込むようにしてみました。
そうしてみても、起動時にはまだ RAID パーティションを利用することが出来ないことがわかりました。カーネルに "aic7xxx" が組み込まれていたときには正常に利用できていたことから、とりあえずモジュールにしたということが、RAID パーティションを利用できないということと起因しているようです。
ただ "vmadd-scsi" モジュールによる構成にしたときに、既存の "aic7xxx" がカーネルに組み込まれてしまっていることがネックになっていたのもあって、カーネルを "bareacpi.i" に更新していたんですよね…。
そんなことから、もしかすると RAID 周りのドライバが不足していたりするのかなとも思って、いったんカーネルを "ideraid.i" にしてみました。これによって少なくとも RAID に必要なドライバは備わるだろうという推測ですけど、とりあえずこうしてみても、起動時に RAID デバイスをマウントすることは出来ませんでした。それなので、カーネルは改めて "bareacpi.i" に戻しておきました。
改めて RAID 開始のタイミングを計ってみる
"dmesg" を実行してそのログ内容とにらめっこしてみると、次の辺りがとても気になるところでした。
kmod: failed to exec /sbin/modprobe -s -k scsi_hostadapter, errno = 2
kmod: failed to exec /sbin/modprobe -s -k scsi_hostadapter, errno = 2
kmod: failed to exec /sbin/modprobe -s -k scsi_hostadapter, errno = 2
md: linear personality registered as nr 1
md: raid0 personality registered as nr 2
md: raid1 personality registered as nr 3
md: raid5 personality registered as nr 4
raid5: measuring checksumming speed
8regs : 2413.200 MB/sec
32regs : 1784.800 MB/sec
pIII_sse : 1002.800 MB/sec
pII_mmx : 950.000 MB/sec
p5_mmx : 1255.200 MB/sec
raid5: using function: pIII_sse (1002.800 MB/sec)
md: md driver 0.90.0 MAX_MD_DEVS=256, MD_SB_DISKS=27
md: Autodetecting RAID arrays.
md: autorun ...
md: ... autorun DONE.
LVM version 1.0.8(17/11/2003)
内容としては、まず kmod が "scsi_hostadapter" の認識に失敗していて、その直後に RAID (md) システムが有効になります。そして RAID デバイスの自動認識が行われるといった感じです。そして上記には含めませんでしたけど、さらにその後で vmadd-scsi が認識された様子を示すメッセージ が現れて、そこに接続されているハードディスクが検出される感じでした。
ここに現れる errno = 2 というのは、どうやら適切なモジュールが見つからないとのことのようです。なので "/etc/modules.conf" をいろいろと調整してみたり、起動 RAM ディスクに含めるモジュールを "vmadd-scsi" から "aic7xxx" にしてみても駄目だったので、 もしかすると mkinitrd の作成自体が失敗しているか、またはモジュールにしてしまっている時点で駄目になっているのかもしれないです。
mkinitrd によって作成した起動 RAM ディスクイメージを確認する
そのような理由から "mkinitrd" によって RAM ディスクイメージが予期されたように出来ているか確認してみることにします。
たとえば "initrd-vmadd-2.4.31.gz" という RAM ディスクイメージを作成してあった場合には、次のように "zcat" で圧縮を解いた上で、ファイルをそのまま "/mnt" ディレクトリにマウントしてあげることで、その内容を確認したり調整したりすることが出来ます。
zcat initrd-vmadd-2.4.31.gz > initrd-vmadd-2.4.31.custom
mount -o loop initrd-vmadd-2.4.31.custom /mnt
こうしたら "/mnt" ディレクトリへ移動してその中身を覗いてみると、とりあえず "dev/" ディレクトリには "md0", "md1", "md3" や "sda1", "sdb1" などといった、起動する上で必要そうなデバイスが取り揃えられていました。
また "lib/modules/2.4.31/" ディレクトリには "aic7xxx.o" と "vmadd-scsi.o" が 入っていましたので、少なくとも RAM ディスクイメージの中にモジュールが含まれていないというような心配はなさそうです。
起動時に読み込まれると思われる "linuxrc" スクリプトを追ってみます。
"/proc" ディレクトリをマウントしたら、続いて "./load_kernel_modules" を読み込んでいました。そして "/sbin/vgscan" および "/sbin/vgscan --mknodes" と "/sbin/vgchange -ay" を実行して LVM システムを初期化したら、あとは root パーティションをマウントして処理を終えるといった流れになっているようです。
そしてその途中で読み込まれた "load_kernel_modules" には、"mkinitrd" の "-m" オプションで指定したモジュールを "insmod" で読み込ませるスクリプトが記載されていました。
insmod /lib/modules/$(uname -r)/vmadd-scsi.o
パス的には合っているはずなのですけど、errno=2 が "モジュールが見つからない" ことを示すものというのなら、もしかすると "$(uname -r)" のところで正常にバージョン番号を入手できていないのかなとも思って、せっかくなので随所に "echo" コマンドをちりばめて、どういった感じで "linuxrc" が実行されて行くかを探ってみることにしました。
"echo" の記載場所はいろいろあって書ききれないですけど、ともあれ編集が終わったら、次のようにして変更内容を保存します。
cd /boot
umount /mnt
gzip -c initrd-vmadd-2.4.31.custom > initrd-vmadd-2.4.31.custom.gz
こうしたら、"/etc/lilo.conf" の "initrd=initrd-vmadd-2.4.31.custom.gz" というように変更済みの RAM ディスクイメージが採用されるように設定を調整したうえで、"lilo" を実行して LILO を更新します。そして Linux を再起動してみると、システムの準備が整っていないのか最初の方の "echo" メッセージには表示されないものもありましたけど、とりあえず "vmadd-scsi" モジュールの読み込みは正常に行われているようです。
ただそのタイミングは RAID デバイスの自動認識よりも後の、まさに "vmadd-scsi" 関連が画面に表示された頃合からだったので、やはりモジュールの読み込みが間に合っていない感じです。
ちなみに echo が表示されたのがちょうど "load_kernel_modules" スクリプトを抜けようとする瞬間でしたので確かなことはいえませんけど、"linuxrc" 内に記載されていた "# Initialize LVM:" の項目は "vmadd-scsi" を認識した次となるようで、起動メッセージ中でそれより手前に表示されていた "LVM version 1.0.8(17/11/2003) には関与していないようです。
ともあれ dmesg で表示された modprobe のエラーが気になったのもあって、起動 RAM ディスクイメージの中の "etc/" ディレクトリを調べてみましたけど、その中には何もファイルはありませんでした。そこで的確に "scsi_hostadapter" として "vmadd-scsi" の認識を試みてもらえるようにと、"modules.conf" や "modprobe.conf" を作成して "alias scsi_hostadapter vmadd-scsi" といった記載を追加してみたりはしましたけど、それでエラーがなくなるようなことはありませんでした。
他にも初期化が終わるまでに時間がかかるのかとも思って、"load_kernel_modules" を抜けたすぐに "sleep 15" として 15 秒間の猶予を持たせてみたりもしましたけど、これも特に意味はありませんでした。
また、どこかしらのタイミングで強制的に "raidstart --all" を実行してしまおうかと思ってみれば、そもそもまだ "raidstart" という命令は見つからない状態みたいな感じでした。
RAID 機能もモジュールにしてみる
考えあぐねて少し休憩していたら、もしかすると RAID もモジュールにしてしまえば "vmadd-scsi" よりも後に読み込めるかもしれないなと思って、早速やってみることにしました。
"/usr/src/linux" へ移動したら "make menuconfig" を実行して、次のように RAID 関連の項目を <M> に設定します。
Multi-device support (RAID and LVM) --->
<M> RAID support
<M> Linear (append) mode
<M> RAID-0 (striping) mode
<M> RAID-1 (mirroring) mode
<M> RAID-4/RAID-5 mode
<M> Multipath I/O support
<*> Logical volume manager (LVM) support
そうしたら "make bzImage modules modules_install install" としてカーネルの再構築を行います。
再構築後にとりあえず "/lib/modules/2.4.31/kernel/drivers/md/" を眺めてみると、"md.o", "linear.o", "raid0.o", "raid1.o", "raid5.o", "xor.o" というモジュールがが新たに出来ていました。"multipath.o" はもともと モジュール指定だったので最初からありましたけど、このモジュールは使っていない感じでした。
あとはとりあえずシステムを再起動して "raidstart --all" を実行すれば、必要なモジュールが組み込まれますので、そこで "lsmod" を実行すれば RAID 構成に必要なモジュールが判断できます。そしてそれによって、"raid1.o" が必要で、さらにはそれが "md.o" を必要としていることが判りました。
必要なモジュールが判ったところで、"mkinitrd" に "-m vmadd-scsi:md:raid1" を引数に与えてそれ らを組み込む形にしたら、LILO を更新した上で再起動です。
そうしてみたところ、モジュールの読み込み順番が良くなって、先に "vmadd-scsi" 関連の認識が行われ、続いて RAID 関連のモジュールがしっかりと読み込まれました。
md: md driver 0.90.0 MAX_MD_DEVS=256, MD_SB_DISKS=27
ただ…、上記は表示されるのですけど、下記は表示されなくなってしまいました。
md: Autodetecting RAID arrays.
md: autorun ...
md: ... autorun DONE.
これではやはり、この後のタイミングで "raidstart --all" としない限りは RAID パーティションを正常にマウントすることは出来ません。
raidstart のタイミングを計る
そんな観点から調べていると、なにやら "raidstart --all" の実行タイミングと、"/etc/fstab" の最後の 数値が重要らしいお話しが目に留まりました。
"/etc/fstab" に関しては、そこでは "ext2" ファイルシステムの場合とされていたけど、最後の数値がディフォルトだと raidstart 実行前に fsck を実行しようとしてしま うためにエラーになってしまうのだそうでした。これを回避するためには、その値を 0 にしてチェックをさせないようにする必要があるとのことです。なのでさっそく "/etc/fstab" ファイル内の "/dev/md?" 関連の最後を 2 から 0 にして みました。
また "raidstart" のタイミングは、Slackware の場合は "/etc/rc.d/rc.S" の中の "/sbin/mount -a -v -t nonfs,nosmbfs,noproc" という行の直前に、次のような感じで追記してあげると良いそうです。
/sbin/raidstart /dev/md0
/sbin/e2fsck /dev/md0 -a -C
上記は /dev/md0 に特化した内容ですけど、全てのデバイスを有効にしたいのならば "raidstart --all" など、必要に応じて調整してあげる感じになります。
これらを整えて Linux を再起動してみたところ、たしかに fsck のあとの手続きではあるものの、"/etc/fstab" によるマウント処理よりも前に"raidstart" が実行されて、無事に RAID パーティションが自動マウントされました。
ただ、これはあくまでも "非ルートパーティション" に関するお話しだけであって、ルートパーティションはさらに前にマウントを試みてしまうため、この方法では起動ディスクまでを RAID パーティションにすることは無理なようでした。さらに前に "raidstart" を実行できないかとも思ったのですけど、ルートパーティションを認識しない限りは "raidstart" が無いようです。
まだ他に手はあるのかもしれないですけど、とりあえず、起動パーティションを RAID にしたい場合には、SCSI ドライバおよび RAID ドライバをカーネルに含められる環境が欲しいところでした。
起動時に RAID パーティションを有効にする
上記を踏まえて、起動時に RAID パーティションを認識させる上での要点をまとめてみようと思います。
SCSI ドライバをカーネルに組み込める場合
SCSI ドライバをカーネルに組み込むことが出来る場合は、RAID 関連のドライバも含めて含めてしまった方が良さそうです。
そうすることで起動 RAM ディスクの手続きよりも先に RAID パーティションが認識された状態になりますので、あとは EZ-NET レポート: Slackware 10.2 のシステムパーティションを RAID 1 にしてみる に示したような感じで、起動パーティションもそれ以外も、利用することができるようになると思います。
SCSI ドライバをカーネルに組み込めない場合
SCSI ドライバをカーネルに組み込むことが出来ない場合は、上記で示したような感じで、非ルートパーティションを起動時に認識させることは出来そうです。具体的な手順としては、次のような感じでしょうか。
まずは SCSI ドライバおよび RAID ドライバをモジュールとしてカーネルを構築します。
cd /usr/src/linux
make menuconfig
make bzImage modules modules_install install
また mkinitrd を使用して SCSI モジュールおよび RAID モジュールを起動 RAM ディスクに含めます。この辺りのお話しについては EZ-NET レポート: Microsoft Virtual Server 2005 R2 の Linux 用アドインソフトに関する試行錯誤 も参考になると思います。
mkinitrd -c -f reiserfs -k 2.4.31 -m vmadd-scsi -o initrd-vmadd−2.4.31.gz -r /dev/md0 -s initrd-vmadd-2.4.31-tree
さらには "/etc/rc.d/rc.S" を編集して、"/sbin/mount -a -v -t nonfs,nosmbfs,noproc" という行の直前あたりに次の行を追加してあげることで、意図的に RAID パーティションの認識およびディスクチェックを促進します。
/sbin/raidstart /dev/md0
/sbin/e2fsck /dev/md0 -a -C
こうすることで、ルートパーティションのマウントにこそ間に合わないものの、非ルートパーティションのマウントまでには RAID パーティションの準備を整えることが出来ました。
ソフトウェア RAID パーティションを起動ディスクにするにはどうしたらよいのでしょうね…。
SCSI ドライバ自体はルートパーティションをマウントしようとする前に認識できてはいるので、あとは raidstart が実行できれば良いのですけど、そのタイミングをどこにしたら良いのかが難しいところです。無理やり RAM ディスクイメージ内に "raidstart" をコピーして "linuxrc" 内で実行させてみようとしましたけど、"/bin/raidstart: not found" というエラーが出てしまってそれは駄目でした。
またはやったことはないですけど /boot パーティションだけは非 RAID デバイスに作成するとか、そんな何らかの配慮は必要そうな感じでした。