BigAdmin の日本語訳が、Sunと共に消滅してしまったので、サルベージしたもをちょっとアレンジして再現してみました。そのうちまじめにソースを追ってみたいと思います。
Source Tour (Community Group zfs.source)
Oracle Solaris の管理: ZFS ファイルシステム
ZFS は、ZPL (ZFS POSIX Layer)、DMU (Data Management Unit)、および SPA (Storage Pool Allocator) の 3 つのコンポーネントから構成されている。
ファイルシステムコンシューマ
POSIX ファイルシステム API を介して ZFS と対話する基本アプリケーション。要するに、ZFS を使うすべてのアプリケーションがこのカテゴリに分類されるということになる。システムコールが、汎用的な OpenSolaris VFS レイヤーを経由して ZPL に渡される。
デバイスコンシューマ
ZFS は、「エミュレートされるボリューム」を作成できる。このボリュームはストレージプール内のストレージに基づいているが、通常のデバイスとして
/dev
の下にある。これらのデバイスと直接対話するアプリケーションはいくつかあるが、もっとも頻繁に使用するコンシューマは、デバイスの上位層のターゲットドライバとカーネルファイルシステムである。
管理コンシューマ
管理コンシューマになるアプリケーションとは、ZFS のファイルシステムやストレージプールを操作するアプリケーションで、この操作にはプロパティーやデータセット階層の調査が含まれる。主なアプリケーションは
zpool(1M) と
zfs(1M) の 2 つ。
このコマンドは ZFS ストレージプールを作成および管理するのに使用される。このコマンドはコマンドの構文の解析し libzfs 呼び出しに渡す。また途中で発生するすべてのエラー処理を行う。このコマンドのソースは
usr/src/cmd/zpool にある。
このコマンドは ZFS ファイルシステムの作成および管理に使用される。zpool(1M) と同様に、コマンド行の引数を解析して処理結果を libzfs に渡す。このコマンドのソースは
usr/src/cmd/ZFS にある。
libzfs
管理アプリケーションが ZFS カーネルモジュールと対話するための主要インタフェース。このライブラリは、ストレージプールおよびファイルシステムへのアクセスおよび操作のための、統合されたオブジェクトベースの機構を提供する。カーネルとの通信を行う背後の機構として、ioctl(2) による /dev/zfs の呼び出しが使用される。このライブラリのソースは
usr/src/lib/libzfs にある。
ZFS ファイルシステムと対話するための主要インタフェース。DMU の上位に位置する比較的薄い層で、ファイルおよびディレクトリからなる抽象化したファイルシステムを提供する。ZPL は OpenSolaris VFS インタフェースと背後の DMU インタフェースの間のギャップを埋める。また、アクセス制御リスト (Access Control List、ACL) 規則や同期 (O_DSYNC) セマンティクスを適用する。
ZFS には、ストレージプール空間を背後に持つ raw デバイスを提供する機能が含まれている。これらのデバイスはソースコード内では 'zvols' と呼ばれる。
/dev/zfs
このデバイスは libzfs のメイン制御ポイントである。コンシューマは ioctl(2) インタフェースを直接利用できるが、libzfs と密接に絡み合っているため、公開インタフェースではない(libzfs も)。ioctl() のパラメータの妥当性検査を行い、要求を ZFS 内の該当する場所に転送している。
DMU は SPA によって提供されるフラットアドレス空間に構築されたトランザクションオブジェクトモデルを提供する。コンシューマは DMU と対話するためにオブジェクトセット、オブジェクト、およびトランザクションを使用する。オブジェクトセットはオブジェクトの集合で、各オブジェクトは SPA からのストレージの任意の部分である。各トランザクションは、グループとしてディスクにコミットしなければならない一連の操作であり、ZFSのディスク上の一貫性の中心となる。
DSL は、継承したプロパティーおよび割り当て制限と予約の適用と共に、DMU オブジェクトセットを階層的名前空間の中に統合する。また、オブジェクトセットのスナップショットおよびクローンの管理も行う。
スナップショットの実装方法については、
Matt のブログエントリを参照。
ZAP は DMU の上位に構築され、スケーラブルなハッシュアルゴリズムを使用してオブジェクトセット内にさまざまな名前とオブジェクトの関連付けを作成する。ZAP は ZPL 内にディレクトリを実装するのにもっともよく使用されるが、拡張して DSL 全体で使用されたり、プール全体にわたるプロパティーを格納する方法としても使用される。ZAP には、非常に異なった 2 つのアルゴリズムがあり、それぞれ異なる種類のディレクトリ用にデザインされている。「マイクロ ZAP」は、エントリ数が比較的少なく各エントリがかなり短い場合に使用される。「ファット ZAP」はそれより大きめのディレクトリや非常に長い名前のディレクトリに使用される。
ZFS は常に一貫性のあるデータを提供するが、データの大半がディスクに即座に書き込まれないという、従来からのセマンティクスを採用している。このセマン ティクスを採用しないと、パフォーマンスがひどく低下するためである。しかし、アプリケーションによっては、より厳格なセマンティクス、すなわち read(2) や write(2) 呼び出しが戻った時点でデータがディスク上にあることが保証されるセマンティクスが要求されることがある。このような動作 (O_DSYNC で指定されるもの) を要求するアプリケーションのために、ZIL ではクラッシュの場合に再実行できる効率的なデータセット単位のランザクションログを使用して、必要とされるセマンティクスを提供する。
ZIL 実装については、Neil の
ブログエントリを参照。
トラバース
トラバースは、ライブプール内の全てのデータを調べるための、安全かつ効率的で再スタート可能な方法を提供する。これは再同期化および消し込みの基盤になっている。トラバースは、すべてのメタデータを調べて、一定の期間内に変更されたブロックを検索する。その際、ZFS には書き込み時コピー特性があるため、機能停止時間に変更されなかった大規模なサブツリーが検索されないで済むという利点がある。トラバースは基本的に SPA の機能だが、スナップショット、クローン、およびディスク上のフォーマットの特定の特性を扱うために、いくつかの DMU 構造と親密な関係を持っている。
ZFS は 1 次キャッシュのために ARC の修正バージョンを使用している。このキャッシュは DMU と SPA の間の層にあり、仮想ブロックレベルで動作している。これにより、ファイルシステムがキャッシュしたデータを、そのスナップショットやクローンと共有できる。
arc.c |
Adaptive Replacement Cache の実装 |
プール構成 (SPA)
プールレイヤー全体が SPA (Storage Pool Allocator) としばしば呼ばれるが、構成部分が本当の公開インタフェースである。SPA が、ZIO と vdev のレイヤーを張り合わせて、一貫性のあるプールオブジェクトにしている。SPA には、プールの作成や構成情報の破棄を行うルーチンと、データを vdev に定期的に同期化するルーチンが含まれている。
ZIO パイプラインは、ディスクに送受信されるすべてのデータが通過する。これは DVA (Device Virtual Address) を vdev 上の論理的位置に変換するだけでなく、必要に応じてデータのチェックサムの計算や、データの圧縮を行う。ZIO は複数ステージのパイプラインとして実装され、各 I/O に対して、どのステージを実行するかを制御するビットマスクを持っている。パイプラインはきわめて複雑なため一言では説明できないが、次の図で全体像を示す。
I/O タイプ |
ZIO 状態 |
圧縮 |
チェックサム |
ギャングブロック |
DVA 管理 |
Vdev I/O |
RWFCI |
オープン |
|
|
|
|
|
RWFCI |
子の準備完を待機 |
|
|
|
|
|
-W--- |
|
圧縮書き込み |
|
|
|
|
-W--- |
|
|
チェックサムの生成 |
|
|
|
-WFC- |
|
|
|
ギャングのパイプライン設定 |
|
|
-WFC- |
|
|
|
ギャングヘッダーの取得 |
|
|
-W--- |
|
|
|
ギャングヘッダーの書き換え |
|
|
--F-- |
|
|
|
ギャングメンバーの解放 |
|
|
---C- |
|
|
|
ギャングメンバーの取り込み |
|
|
-W--- |
|
|
|
|
DVA の割り当て |
|
--F-- |
|
|
|
|
DVA の解放 |
|
---C- |
|
|
|
|
DVA の取り込み |
|
-W--- |
|
|
ギャングのチェックサムの生成 |
|
|
|
RWFCI |
準備完了 |
|
|
|
|
|
RW--I |
|
|
|
|
|
I/O 開始 |
RW--I |
|
|
|
|
|
I/O 完了 |
RW--I |
|
|
|
|
|
I/O 測定 |
RWFCI |
子の準備完を待機 |
|
|
|
|
|
R---- |
|
|
チェックサム確認 |
|
|
|
R---- |
|
|
|
ギャングメンバーの読み取り |
|
|
R---- |
|
非圧縮読み取り |
|
|
|
|
RWFCI |
完了 |
|
|
|
|
|
-
I/O タイプ
- I/O パイプラインの各フェーズは特定タイプの I/O に適用される。各文字は読み取り (Read、R)、書き込み (Write、W)、解放 (Free、F)、取り込み (Claim、C)、および入出力制御 (Ioctl、I) を意味する。
-
ZIO 状態
- これらは I/O の同期をとるための内部状態である。たとえば、子 I/O を持つ I/O は、全ての子 I/O のブロックポインタの割り当て準備完了を待つ必要があり、すべての子 I/O の完了まで終了できない。
-
圧縮
- このフェーズは、適用可能な場合に任意の圧縮アルゴリズムを適用する。
-
チェックサム
- このフェーズは、適用可能な場合に任意のチェックサムアルゴリズムを適用する。
-
ギャングブロック
- ブロック全体を書き込めるだけの連続した十分な領域がない場合に、ZIO パイプラインは I/O を小さな「ギャングブロック」に分割し、あとで透過的にアセンブルして完全なブロックにする。
-
DVA 管理
- 各 I/O には、プール内の vdev の特定部分に対応する DVA (Device Virtual Address) を割り当てる必要がある。このフェーズは、metaslab および領域マップを使用して、必要とされるアドレスの割り当てを行う。
-
Vdev I/O
- プール内に含まれる vdev への I/O を実際に実行するフェーズ。
仮想デバイス·サブシステムはデバイスを配置し、アクセスするための統一された手段を提供する。仮想デバイスは、単一のルート vdev と、複数の内部 vdev(ミラーおよびRAID-Z)およびリーフ(ディスクおよびファイル)vdevsでツリーを形成する。各 vdev は利用可能な領域を表すとともに、物理ディスク上のブロックをレイアウトする。
LDI (Layered Driver Interface)
ZFS はスタックの最下部で、LDI および VFS インタフェース (ファイルの処理時) を使用して、背後の物理デバイスと対話している。
0 件のコメント:
コメントを投稿