無理やりのRAID復旧

毎週恒例という感じで、ファイルサーバがクラッシュ

「毎週恒例」と言うよりは、リブートする度にと言っても過言じゃない。ログを見る限りDEの異常ではなく、「突然ディスクが応答しなくなった」という感じの現象が起きている。 どうやらPMP(ポートマルチプレクサ)が犯人らしい。

先日から、どうもPMPが怪しいんじゃないかと思って、カーネルを最新 + lib-sataにしたのだが、これが却ってアダになる。RAID5の空間は2つあるのだが、仲良く両方とも2DE異常。

RAID5で2DE異常になると、にっちもさっちも行かなくなるのは御存知の通り。普通ならここで諦めるものだ。

ところがよく考えてみれば、「2DE異常」とか言っても、実はDEがおかしくなったわけじゃない。単にDEの応答がなくなったので異常と判断されただけで、カーネルのログ(/var/log/kern.log)にもディスク異常にありがちのI/Oエラーはない。つまり、

DEがPMPによって濡れ衣を着せられた

だけなのだ。だったら、この異常な状態だけを復旧してやれば良いのではないかと考えた。つまり、DEにつけられた「DE異常」というフラグを解除して再構成してやれば、うまく動くのではないかと。

手順としては、まずは無理やりの再構成をやってみる。

# mdadm -A /dev/md0 -u 3fee8ddc:fc710c65:daa5f7c5:4109bf44 --run --force

これでもダメなら、

# mdadm -A /dev/md0 /dev/sd[abcde]1

とかやってみる。これでactiveになれば、後は普通の復旧でいい。外れているDEをhot addしてやれば、再構成が始まる。

# mdadm /dev/md0 -a /dev/sdd1

でも、運が悪いとこれでは復旧しない。ここでまずやることは、

先に外れたDEの発見

だ。DEは完全に同時に死ぬことはまずないので、1つ目が外れただけでは、まだ残りのDEに書き込みがされる。2つ目が外れた瞬間に閉塞する。だから、まずは「1DE死んだ時の状態(縮退モード)」まで復元することを考えるのだ。これは前回説明した通り

通常のやり方で復旧しなかった場合、/proc/mdstatを見ると、DEに(F)がついている。これが2つあるはずだ。2つつけば閉塞するから、3つついていることはない。dmesgや/var/log/kern.logあたりを見て、2つのうちどちらが先に落ちたか調べる。そして、とりあえずそいつのことは忘れる。

今回はさらに、このフラグを

無理やり正常に戻す

ことをやった。

RAIDのDEには「raid superblock」というのがあり、ここにRAIDの諸々の情報が入っている。詳しいことはカーネルソースでも見てもらうといいが、ごく大雑把に言えば、

  • MDの情報
  • DE固有の情報
  • 他のDEの情報

が入っている。「DE固有の情報」以外は、どのDEにも同じ情報が入っている。DE固有の情報の中にDEの状態があるので、それを直してやるのだ。

どう直すかは、プログラムを用意したので、それを見てもらいたい。

このプログラムは、raid superblockにパッチを当てる。「このDEは正常です」というフラグを入れてしまうのだ。

このプログラムは非常に危険だ。なぜなら、どんな異常なDEでも正常であるかのように「偽装」してしまうからだ。カーネルはまんまとそれに騙されて、正常なDEであるかのように動かしてしまう(カーネルはraid superblockが正常に読めれば、それ以上のチェックは起動時には行わない)。それがハード的に壊れていようと、先に外されたDEであろうとお構いなしだ。その結果、場合によってはもうどうやっても復旧出来ない状態にしてしまうかも知れない。

という危険なプログラムでもあるので、「そのままコンパイルすれば動く」という状態にはなっていない。コンパイルしただけだと、情報を調べることしか出来ないようになっているので、少なくともソースを見なければ機能しない。また、正しく機能させるには、何をやっているかを理解してソースに手を入れなければならない。まぁどのフラグをどんな値にするかをいいじるだけなんで、カーネルソースまで追わなくても、検査モードで内容を出力させたりすれば、何となくわかるだろう。

といっぱい脅しておいたところで、まずraidをinactiveにする。

# mdadm --stop /dev/md0

その後、件のプログラムをコンパイルして、

# gcc raidzap.c -o raidzap

実行する。

# raidzap -r

そして、あらためて構成させる。

# mdadm -A /dev/md0 /dev/sd[abcde]1

これで縮退モードのRAIDが作られるはずだ。もしかしたらI/Oエラー等が出るかも知れないが、その時はraidzap.cをいろいろいじる。

# raidzap -s /dev/sdd1

のようにすると、sdd1.bakというファイルにraid superblockを保存するので、これを元に復元してやれば、パッチを当てる前に戻せる。

I/Oエラーが出ないで、縮退モードで動かすことに成功したら、後は縮退モードからの復旧そのものなので、

# mdadm /dev/md0 -a /dev/sdc1

とかやってやればいい。raidの再構成が開始される。

再構成を待つのが嫌だとか、何となく気持ち悪いと思う人は、縮退モードのうちにバックアップでも取ってしまうといい。

このhack(本当にhackだ)で、「最悪の事態」を回避することが出来るかも知れない。まぁいつもこれが成功するというわけではないが。

無理やりのRAID復旧” への2件のコメント

  1. raidなlinuxは年末にOpenBSDにリプレースしてしまったので手元に無いのに

    > 少なくともソースを見なければ機能しない。

    とか言われたので思わずコード読んじゃいました.で,「えー,コード追わんでも動かせるやん」と思いきや.

    > 正しく機能させるには、何をやっているかを理解してソースに手を入れなければならない。

    なるほど.危うくひっかかる所だった.さすがに芸(芸?)が細かいですな :-)

  2. ピンバック: Tweets that mention 無理やりのRAID復旧 | おごちゃんの雑文 -- Topsy.com

コメントは受け付けていません。