web-dev-qa-db-ja.com

ファイルシステムはどのようにしてブロックをディスクにアトミックに書き込みますか?

ブロックはファイルシステムによって提供される抽象概念であり、ブロックサイズはディスクセクターサイズの整数倍です。ファイルシステムがブロックサイズとして4Kを使用し、ディスクセクターサイズが512Bであるとすると、ファイルシステムがディスクドライバーに書き込み要求を発行すると、4Kブロック全体をディスクにアトミックに書き込む方法(部分的な書き込みを避ける)?最新のカーネルがこの問題にどのように対処するのか知りたいが、答えを見つけるためにLinuxコードベースに飛び込みたくはない。どんな助けでもありがたいです。

6
StrikeW

ディスクは、セクターがアトミックに書き込まれることを許可する必要があります。セクターサイズは512バイトでしたが、現在、より大きなディスクの場合は通常4096バイトです。

部分的に書かれた「ブロック」から問題を起こさないためには、すべてを特別な順序で書くことが重要です。

ファイルシステムに部分的に書き込まれたの部分が存在する可能性がある唯一の理由は、停電または同様の何かであることに注意してください。

方法は次のとおりです。

  • 最初にすべてのファイルコンテンツを書き込み、これが機能することを確認します

  • 次に、メタデータを書き込み、メタデータ内のすべてのデータ構造が単一のディスクセクターに収まり、セクターの境界にまたがらないことを確認します。これは例えばディレクトリコンテンツとしての可変長ファイル名にとって重要です。

4
schily

それは、基盤となるストレージテクノロジーによって異なります。

一部のストレージでは、特定のブロックサイズをアトミックに保存できます。通常は2の累乗で、少なくとも256で、通常は1kB〜4kBの範囲です。その場合、ブロックの置換によって有効なシステム状態が得られる限り、ファイルシステム層はその場でブロックを置換できます。これは、ファイルのコンテンツを書き込む場合は問題ありませんが(Unixはそのための原子性を保証しません)、ファイルシステムメタデータを書き込む場合は常にそうとは限りません。

ディスク層からの協力を必要としない別のアプローチ(ブロックへの書き込みが他のブロックのコンテンツを損傷しないことを知っていることを除く)は、既存のブロックを決して消去せず、常に現在使用されていないストレージブロックに書き込むことです。書き込みが成功した場合、そのブロックへの参照を別のブロックに追加して、このブロックの以前のバージョンへの参照を置き換えることができます。以前のバージョンを含むブロックは無料としてマークされます。ブロックを更新するには別のブロックを更新する必要があるため、これはさらに遅くなります。その結果、別のブロックを更新する必要があります。再帰は、システムが複数のコピーを保持するブロックで停止します。コピーの1つを書き込んでいるときにクラッシュが発生した場合は、代わりに他のコピーが使用されます。正しいコピーの選択は、3つ以上ある場合は過半数の比較に基づいて、2つのコピーがある場合はチェックサムに基づいて行うことができます。

次に、log-structuredファイルシステムがあり、ブロックリストの最後にブロックが追加され続けます。ファイルシステムの基本的なメタデータは、最後の有効なブロックで見つかったものです。最後のブロックは、ブロックのタイムスタンプとチェックサムをチェックすることによって決定されます。

(注:この回答は、一般的なファイルシステムの実装の問題に関するものです。さまざまなUnixバリアントのさまざまなストレージメディア上のさまざまなファイルシステムが実際に何をしているのかを確認していません。)