状況確認と安全確認
まずは現状を確認。
/dev/hdb1 20GB raid(0xfd) -> /dev/md0 /dev/hdd1 5GB swap(0x83) /dev/hdd2 20GB raid(0xfd) -> /dev/md0
RAID領域にあるデータを退避させて、RAIDデバイスのマウントを解除、RAIDデバイスのストップ、スワップ領域のマウントを解除。
# mkdir -p /mnt/hdc1/RAID/; rsync -av ~/RAID/ /mnt/hdc1/RAID/ # umount /dev/md0 # mdadm --misc --stop /dev/md0 # swapoff /dev/hdd1
[badblocks][e2fsck] badblocksかe2fsckで不良ブロックを探す
データがなくなるのはやばいのでとりあえずチェック。まぁしなくてもいいかもしれない。不良ブロックがないのにこしたことはないが、結果にあまり神経質になってもいけない。なぜなら、badblocksは常に同じ結果を出さないからだ。いまの検査で不良ブロックが無いと診断されても次の瞬間にはいくつか不良ブロックが見付かるかもしれないし、不良ブロックと判断されたものが正常と判断されるかもしれない。
# badblocks /dev/hdb # badblocks /dev/hdd
badblocksのmanにはe2fsckを使えとあるので試してみた。e2fsckはブロックデバイスの番号を指定するのでbadlocksのようなデバイス全体の不良ブロック検査には使えない。
# e2fsck -c /dev/hdd2 # e2fsck -c /dev/hdb2
重要なことは、これからRAIDディスクとして使用するつもりの全てのディスクに検査をかけておき、不良ブロックの見付かったディスクを使わないことだ。
[fdisk] パーティションを切ってRAID用の領域番号に変更
RAIDディスクの容量はRAID領域の大きさが全て同じだと使えない領域が少なくて済む。大きさが同じでないとだめだという訳ではないが、RAIDディスクの容量はRAIDディスクを構成するディスクの内もっとも容量の少ないディスクの大きさになる。死ぬ領域が多くても構わないという場合はRAID領域の大きさをそろえなくてもOK。2つの異なるディスクにRAID用の領域(18GB)を作成、それぞれのあまった部分はスワップにしておく。スワップのパフォーマンスをあげるために2つのディスクの先頭にスワップパーティションを作っておく。スワップパーティションの最大サイズはアーキテクチャ依存。jman swaponで確認できる。ここではうちのコンピュータでスワップサイズとして割り当てることの出来る最大サイズでえある2Gにしておいた。スワップ関係の話は昔から議論されていたのだけれど、「スワップサイズの上限はほぼ存在しない」という話もあるらしい。
領域番号の変更は必ず必要。Tで領域種類の選択。fdでLinux RAID領域にする。
# jman swapon # fdisk /dev/hdb # fdisk /dev/hdd
領域確保の後はこんな感じ。
# fdisk -lu /dev/hdd /dev/hdb Disk /dev/hdd: 25.5 GB, 25590620160 bytes 16 heads, 63 sectors/track, 49585 cylinders, total 49981680 sectors Units = セクタ数 of 1 * 512 = 512 bytes デバイス Boot Start End Blocks Id System /dev/hdd1 63 14823647 7411792+ 5 拡張領域 /dev/hdd2 14823648 49981679 17579016 fd Linux raid 自動検出 /dev/hdd5 126 3907007 1953441 82 Linux swap / Solaris /dev/hdd6 3907071 7814015 1953472+ 82 Linux swap / Solaris /dev/hdd7 7814079 11721023 1953472+ 82 Linux swap / Solaris /dev/hdd8 11721087 14823647 1551280+ 82 Linux swap / Solaris Disk /dev/hdb: 20.4 GB, 20416757760 bytes 16 heads, 63 sectors/track, 39560 cylinders, total 39876480 sectors Units = セクタ数 of 1 * 512 = 512 bytes デバイス Boot Start End Blocks Id System /dev/hdb1 63 4718447 2359192+ 82 Linux swap / Solaris /dev/hdb2 4718448 39876479 17579016 fd Linux raid 自動検出
どっちにしてもHDDの内容はからにしておかないとだめ。あとからフォーマットするので。
[mdadm] RAIDアレイの作成とフォーマット
アレイの作成はすぐに終わる。同期を取るのに時間がかかるが、次のフォーマットに進んでもOK。最後に状況のチェック。
# mdadm -C /dev/md0 --level=1 --raid-devices=2 /dev/hdb2 /dev/hdd2 # mkfs.ext3 /dev/md0 # mdadm --detail /dev/md0
この節に含まれる内容はもう古い
mkraidとかraidtabとかはもう古いのかもしれない。
[raidtab] /etc/raidtabの作成(RAID1用)
/etc/raidtabでRAIDを制御する。
# vi /etc/raidtab > raiddev /dev/md0 > raid-level 1 > nr-raid-disks 2 > nr-spare-disks 0 > chunk-size 4 > persistent-superblock 1 > device /dev/hdb2 > raid-disk 0 > device /dev/hdd2 > raid-disk 1
[mkraid] raidtooleを導入して/dev/md0デバイスファイルを作成する
mkraidコマンドとかが無かったらraidtoolsを導入しよう。うちにはなかった。
# apt-get install raidtools
デバイスファイルを作成する。
# mkraid /dev/md0
プロンプトはすぐに戻ってくるが、バックグラウンドで仕事が行われているらしい。確認は/proc/mdstatで確認できる。
# cat /proc/mdstat
[mkfs] RAIDディスクのフォーマット
# mkfs -t etx3 /dev/md0
[fstab] /etc/fstabを編集して起動時にマウントできるようにする
マウントポイントを作成。マウントポイントのユーザ、グループ、パーミッションを設定。
# mkdir /home/hoge/RAID/ # chgrp hoge /home/hoge/RAID/ # chown hoge /home/hoge/RAID/ # chmod 0755 /home/hoge/RAID/
/etc/fstabの編集
# vi /etc/fstab %gt; /dev/md0 /home/hoge/RAID ext3 defaults 1 1
RAIDデバイスをマウント
/etc/fstabでオートマウントにしていない場合は、再起動のたびにこれをしないとだめ。
# mount /dev/md0 /home/hoge/RAID
スワップパーティションの有効化
せっかく作ったので有効にしておこう。スワップパーティションはストライピングにしたいのでfstabを編集。pri=9として2つのパーティションの優先度を同じにすればストライピング。ドライブの先頭のプライオリティは同じにして後ろに行くほどプライオリティを下げておく。プライオリティの大きい順にスワップは消費されるそうな。
# cat /etc/fstab | grep swap /dev/hdd5 swap swap defaults,pri=9 0 0 /dev/hdd6 swap swap defaults,pri=8 0 0 /dev/hdd7 swap swap defaults,pri=7 0 0 /dev/hdd8 swap swap defaults,pri=6 0 0 /dev/hdb1 swap swap defaults,pri=9 0 0 # swapon -a
ファイルの移動
大事なファイルを移動しておく。
$ cp -r -P /home/hoge/important/ /home/hoge/RAID/
rsyneを使う手もある。--dry-runで状況をチェックしてから行ったほうが安全。
$ rsync -av --dry-run ~/RAID/ /mnt/RAID/
RAIDアレイの再構築
何らかの原因でRAIDアレイに含まれるデバイスが故障した場合にはRAIDアレイの再構築を行う必要がある。まずは故障したデバイスを確認する。/proc/mdstatにはその名の通りRAIDアレイの状態が収められている。このスペシャルファイルをcatで見るとhdb2が(F)となっているのでhdd2がfail状態になっていることがわかる。
# cat /proc/mdstat Personalities : [raid1] md0 : active raid1 hdd2[0] hdb2[2](F) 17578944 blocks [2/1] [U_] unused devices: <none>
このときの/var/log/messagesは下のような感じ
Feb 1 01:06:04 localhost kernel: md: syncing RAID array md0 Feb 1 01:06:04 localhost kernel: md: minimum _guaranteed_ reconstruction speed: 1000 KB/sec/disc. Feb 1 01:06:04 localhost kernel: md: using maximum available idle IO bandwidth (but not more than 200000 KB/sec) for reconstruction. Feb 1 01:06:04 localhost kernel: md: using 128k window, over a total of 17578944 blocks. Feb 1 01:11:24 localhost kernel: hdb: dma_intr: status=0x51 { DriveReady SeekComplete Error } Feb 1 01:11:27 localhost kernel: hdb: dma_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12339956 Feb 1 01:11:27 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:27 localhost kernel: hdb: dma_intr: status=0x51 { DriveReady SeekComplete Error } Feb 1 01:11:27 localhost kernel: hdb: dma_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12339956 Feb 1 01:11:27 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:27 localhost kernel: hdb: dma_intr: status=0x51 { DriveReady SeekComplete Error } Feb 1 01:11:27 localhost kernel: hdb: dma_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12339956 Feb 1 01:11:27 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:27 localhost kernel: hdb: dma_intr: status=0x51 { DriveReady SeekComplete Error } Feb 1 01:11:27 localhost kernel: hdb: dma_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12339956 Feb 1 01:11:27 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:27 localhost kernel: hda: DMA disabled Feb 1 01:11:27 localhost kernel: hdb: DMA disabled Feb 1 01:11:27 localhost kernel: ide0: reset: success Feb 1 01:11:28 localhost kernel: hdb: task_in_intr: status=0x59 { DriveReady SeekComplete DataRequest Error } Feb 1 01:11:28 localhost kernel: hdb: task_in_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12340056 Feb 1 01:11:28 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:28 localhost kernel: hdb: task_in_intr: status=0x59 { DriveReady SeekComplete DataRequest Error } Feb 1 01:11:28 localhost kernel: hdb: task_in_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12340056 Feb 1 01:11:28 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:29 localhost kernel: hdb: task_in_intr: status=0x59 { DriveReady SeekComplete DataRequest Error } Feb 1 01:11:29 localhost kernel: hdb: task_in_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12340056 Feb 1 01:11:29 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:30 localhost kernel: hdb: task_in_intr: status=0x59 { DriveReady SeekComplete DataRequest Error } Feb 1 01:11:30 localhost kernel: hdb: task_in_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12340056 Feb 1 01:11:30 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:30 localhost kernel: ide0: reset: success Feb 1 01:11:31 localhost kernel: hdb: task_in_intr: status=0x59 { DriveReady SeekComplete DataRequest Error } Feb 1 01:11:31 localhost kernel: hdb: task_in_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12340056 Feb 1 01:11:31 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:32 localhost kernel: hdb: task_in_intr: status=0x59 { DriveReady SeekComplete DataRequest Error } Feb 1 01:11:32 localhost kernel: hdb: task_in_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12340056 Feb 1 01:11:32 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:33 localhost kernel: hdb: task_in_intr: status=0x59 { DriveReady SeekComplete DataRequest Error } Feb 1 01:11:33 localhost kernel: hdb: task_in_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12340056 Feb 1 01:11:33 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:34 localhost kernel: hdb: task_in_intr: status=0x59 { DriveReady SeekComplete DataRequest Error } Feb 1 01:11:34 localhost kernel: hdb: task_in_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12340056 Feb 1 01:11:34 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:34 localhost kernel: ide0: reset: success Feb 1 01:11:35 localhost kernel: hdb: task_in_intr: status=0x59 { DriveReady SeekComplete DataRequest Error } Feb 1 01:11:35 localhost kernel: hdb: task_in_intr: error=0x01 { AddrMarkNotFound }, LBAsect=12340056, sector=12340056 Feb 1 01:11:35 localhost kernel: ide: failed opcode was: unknown Feb 1 01:11:35 localhost kernel: end_request: I/O error, dev hdb, sector 12340056 Feb 1 01:11:35 localhost kernel: ^IOperation continuing on 1 devices Feb 1 01:11:35 localhost kernel: hdb: task_out_intr: status=0x50 { DriveReady SeekComplete } Feb 1 01:11:36 localhost kernel: md: md0: sync done. Feb 1 01:11:36 localhost kernel: RAID1 conf printout: Feb 1 01:11:36 localhost kernel: --- wd:1 rd:2 Feb 1 01:11:36 localhost kernel: disk 0, wo:0, o:1, dev:hdd2 Feb 1 01:11:36 localhost kernel: disk 1, wo:1, o:0, dev:hdb2 Feb 1 01:11:36 localhost kernel: RAID1 conf printout: Feb 1 01:11:36 localhost kernel: --- wd:1 rd:2 Feb 1 01:11:36 localhost kernel: disk 0, wo:0, o:1, dev:hdd2
ここから再構築のための作業を始める。まずは/dev/md0からfailしたデバイス/dev/hdb2をremoveする。removeの後に/proc/mdstatを見ると確かに/dev/md0からhdb2が除かれている。
# mdadm /dev/md0 -r /dev/hdb2 mdadm: hot removed /dev/hdb2 # cat /proc/mdstat Personalities : [raid1] md0 : active raid1 hdd2[0] 17578944 blocks [2/1] [U_] unused devices: <none>
本来ならここでログを見ながら故障の原因を考えて、電源を落として/dev/hdbを別のHDDに変えるとか、別のパーティションに動かすとか、そのままいくか考えるのだが、ここでは一切の構成を変えずに再度追加してみる。追加後に/proc/mdstatを見ると自動的に再構築が始まっていることがわかる。再構築の処理は透過的なので再構築の間でも/dev/md0に書き込み読み込みが出来る。
# mdadm /dev/md0 -a /dev/hdb2 mdadm: re-added /dev/hdb2 # cat /proc/mdstat Personalities : [raid1] md0 : active raid1 hdb2[2] hdd2[0] 17578944 blocks [2/1] [U_] [>....................] recovery = 0.0% (11776/17578944) finish=99.2min speed=2944K/sec unused devices: <none>
この作業の間に増えた/var/log/messagesは下のような感じ。
Feb 1 01:47:47 localhost kernel: md: unbind<hdb2> Feb 1 01:47:48 localhost kernel: md: export_rdev(hdb2) Feb 1 01:48:10 localhost kernel: md: bind<hdb2> Feb 1 01:48:10 localhost kernel: RAID1 conf printout: Feb 1 01:48:10 localhost kernel: --- wd:1 rd:2 Feb 1 01:48:10 localhost kernel: disk 0, wo:0, o:1, dev:hdd2 Feb 1 01:48:10 localhost kernel: disk 1, wo:1, o:1, dev:hdb2 Feb 1 01:48:10 localhost kernel: md: syncing RAID array md0 Feb 1 01:48:10 localhost kernel: md: minimum _guaranteed_ reconstruction speed: 1000 KB/sec/disc. Feb 1 01:48:10 localhost kernel: md: using maximum available idle IO bandwidth (but not more than 200000 KB/sec) for reconstruction. Feb 1 01:48:10 localhost kernel: md: using 128k window, over a total of 17578944 blocks. (END)
RAIDデバイスの再構築が終了すると/proc/mdstatは下のようになる。これがミラーリングが完了しているタイミングの/proc/mdstat。
# cat /proc/mdstat Personalities : [raid1] md0 : active raid1 hdb2[1] hdd2[0] 17578944 blocks [2/2] [UU] unused devices: <none>
この間に増えた/var/log/messagesは下のような感じ。
Feb 1 03:20:34 localhost kernel: md: md0: sync done. Feb 1 03:20:34 localhost kernel: RAID1 conf printout: Feb 1 03:20:34 localhost kernel: --- wd:2 rd:2 Feb 1 03:20:34 localhost kernel: disk 0, wo:0, o:1, dev:hdd2 Feb 1 03:20:34 localhost kernel: disk 1, wo:0, o:1, dev:hdb2