2005年9月28日

壊れたファイルシステムは元に戻らない

1:1 Hot Standby型のシステムがある。サービスを提供するマシンAと、その双子マシンBで出来ていて、Aが何らかの理由で倒れたらBが take over する、というものだ。

AとBはSAN経由でディスクを共有している。とはいえ、A が動いている最中にBが同じディスクをマウントしてしまうとディスク上のイメージに矛盾が発生する。そこで、A が動いている最中はAだけがこのディスクをマウントし、AがこけたらBがマウントするようにしたい。

問題はこうだ。Aがこけた。当然、Aがマウントしていたディスクは適切な umount 処理を経ずに倒れている。Bが mount しようとすれば、当然「適切に umount していない」ことは検出される。Bはこのディスクを mount する前に何をすればよいだろうか?

この問題、意外と面倒くさい。まず、Journal FS 以外の場合、無条件に fsck が動く。がfsckが動いて ファイルシステムが正常になるかというと、そんな保証はない。fsckは矛盾を検出して矛盾を解消するだけであって、その解消方法が2通り以上合った場合、正しい解消方法を選ぶ保証はない。つまり、fsckは破壊を確定的にする危険性があるのだ。

Journal FS であれば、Journal を apply すれば大丈夫だろうって? そんなことはない。
そもそも Journal に記録されているメタデータ更新が「必要十分」とは限らない。indirect block更新をユーザーデータ更新だと言い張るファイルシステムは存在するし、この場合、fsckを動かさないと indirect block上にある矛盾は検出しない。

Journalに書かれている通りにメタデータを更新したらメタデータが壊れた、何てこともざらにある。ext3なんかこのバグの温床だ。理由は3つ。
1) Journalのフォーマットがあまりにも高密度すぎて、Journal なのか「前回 journal を書いた際の忘れ形見」なのか区別がつかないJournalが発生してしまうこと。
2) Metadataの更新順序がそもそも間違って Journal に記録されている場合があること
3) Journal block の更新順序が正しくない場合がある(Journalはlogなので、先頭から順に書き込まれる必要がある。これが守られていない場合がある。シークに対するaccess最適化がかかってしまっている場合にこれが生じる)

最後に、Journal をいくら apply しても bad sector 検出にはならない。理由は簡単で、bad sector は head 退避中に生じるかもしれないからだ。本来書き込むはずのない sector が bad sector を起こしている場合、これの検出は全sectorチェックしかない。fsckでフルセットのチェックをかけるしかないのだ。


A->Bの一回目の切り替えの際に障害が起こっている可能性は低いと思う。でも、だからと言って、チェックを怠れば、A->B->A->B->A->B ぐらいの切り替えで、赤字のタイミングで生じた障害が、顔を出す危険性がある。あまりにも遠い過去に生じた破壊によって生まれた障害は、もうバックアップ をどこまで戻せばよいのかも、そこからどうやって復旧すればよいのかも、判らない状態に陥るだろう。もう、ホットスタンバイどころの話ではない。

fsckで障害が検出された場合、修復できる保障ができるチャンスは低い。しかし、fsckで障害が検出されない、というのはサービスを継続するべきかどうかの判断には重要なのだ。

fsckは、非正常切り替え時には毎回行うべきである。自分が致命傷を負ったのか、まだ大丈夫だったのか、判定できるのは fsck だけなのだから。

その意味で言うと、Journal FS にしたからといって、何かを速くしてよいわけではないのだ。