コピーオンライト型ファイルシステム(ZFS/Btrfs)
上書きしないファイルシステムなら、スナップショットが一瞬で取れ、サイレントなデータ破損まで検知できます。ZFSとBtrfsがどうやってそれを実現するかを内部構造から解き明かします。
- 1.CoWファイルシステムは既存ブロックを上書きせず別の場所に書き、ルートからの参照をまとめて差し替えるため、常に整合した状態しか永続化しません。
- 2.全ブロックのチェックサムを親ブロックに持たせることで、ディスクが嘘をついても(サイレント破損)検知でき、冗長があれば自動修復します。
- 3.スナップショットは古いルートを保持するだけ、トランザクショングループは多数の変更を一括コミットして書き込みを償却します。
CoWファイルシステムが解く問題
従来のファイルシステム(ext4 など)は、データブロックを その場で上書き します。書き込みの途中で電源が落ちると、新旧が混ざった半端な状態が残り、これを防ぐために ジャーナリング でメタデータの整合性を別途守る必要がありました。
ZFS と Btrfs は発想を変え、コピーオンライト(CoW) を木構造そのものに適用します。既存ブロックは決して上書きせず、変更分を空き領域に新しく書き、最後にルートだけを差し替える。これにより「常に整合した断面しかディスクに存在しない」状態を、ジャーナルなしで作り出します。
CoWファイルシステムでは、参照中(live)のブロックは一切書き換えません。更新は必ず未使用領域への新規書き込みで、参照の付け替えが完了した瞬間に旧ブロックが論理的に不要になります。これが整合性・スナップショット・チェックサム全機能の共通基盤です。
CoW B-tree:更新がルートまで伝播する
ファイルシステムは内部的に木構造です。ZFS は uberblock を頂点とするブロックポインタの木、Btrfs は複数の B-tree(B+木の変種)で構成されます。CoW B-tree では、あるリーフ(葉)の1ブロックを変えると、それを指す親も新しい場所に書き直す必要があり、その変更が ルートまで連鎖 します。
更新前(実線=参照): leaf X を変更:
Root Root'(新)
/ \ / \
A B A B'(新)
/ \ / \ / \ / \
. leafX . . leafX' . .(旧Bの子を共有)
(上書きしない) ↑新規 ↑旧ブロックは共有のまま
変わらなかった枝(上図の A や B' 配下の片側)は 旧ブロックを共有 し続けます。書き直されるのはルートからリーフへ至る1本の経路(パス)だけなので、コストは木の高さ、すなわちブロック数 N に対して O(log N) に収まります。
- ZFS: ブロックポインタが子のアドレス・チェックサム・圧縮情報をまとめて持ち、uberblock を根とする1本の大きな木を成す
- Btrfs: ファイルツリー・エクステントツリー・チェックサムツリーなど役割別の B-tree 群を、上位のルートツリーが束ねる
チェックサムによる整合性検証
CoW構造の副産物として強力なのが チェックサムの親子分離 です。あるブロックのチェックサムを、そのブロック自身ではなく 親(ブロックポインタ)側 に格納します。
ブロックポインタ { // 親が持つ
アドレス: 物理位置
checksum: 子ブロックのハッシュ(例 fletcher4 / SHA-256)
}
│ 読み込み時に再計算して照合
▼
[ 子ブロック(実データ) ]
読み込み時に子を再ハッシュして親の値と照合するため、次のような故障を 検知 できます。
| 故障パターン | 従来FSの挙動 | CoW+チェックサムの挙動 |
|---|---|---|
| ビット反転(bit rot) | 気づかず誤データを返す | 照合不一致で検知し、冗長から修復 |
| 誤った場所への書き込み | 別ファイルを破壊 | 親が指す内容と不一致で検知 |
| 古い内容の読み出し(phantom write) | 検知不能 | チェックサム不一致で検知 |
自分自身のチェックサムを自分で持つと、ブロック全体が古いまま入れ替わる事故を検知できません。親に持たせることで「正しいルートから正しくたどってきたか」まで保証され、ルートの uberblock 自身は固定位置に複数コピーを置いて守ります。
ディスクやケーブルは、エラーを返さずに 誤ったデータを正常として返す ことがあります(silent data corruption)。チェックサムの真価は、この「黙って嘘をつく」故障を捕まえる点にあります。冗長構成(ミラー/RAID-Z)があれば、検知に留まらず正しいコピーから自動修復します。
トランザクショングループ:変更を束ねてコミット
CoWは更新ごとにルートまで書き直すため、1操作ずつ即コミットすると書き込みが増えます。ZFS はこれを トランザクショングループ(txg) で償却します。
- 一定期間(既定で数秒)または閾値まで、複数の変更をメモリ上に溜める
- 溜めた変更を一括で空き領域に書き出す(データ→間接ブロック→…の順に下から上へ)
- すべての書き込みが永続化されたら、最後に uberblock を1回だけ アトミックに更新
uberblock の差し替えが成功するまで、ディスク上は完全に旧状態のまま。差し替えた瞬間に新状態へ切り替わるため、クラッシュしても「txg 単位で前か後か」のどちらかにしかならず、半端な状態が原理的に生じません。
txg のコミット間隔(数秒)を待てない fsync 等の同期要求のために、ZFS は ZIL(ZFS Intent Log)を併用します。同期書き込みは先に ZIL へ記録して即座に応答を返し、本体は次の txg でまとめて反映します。ZIL は通常時は読まれず、クラッシュ復旧時のみ再生されます。Btrfs も同様にログツリーで fsync を高速化します。
スナップショットとサブボリューム
CoWでは、スナップショットは 古いルートを参照したまま保持するだけ で完成します。新しい書き込みは別ブロックへ向かうので、スナップショットが指す旧ブロックは上書きされず温存されます。作成は定数時間、消費領域は当初ゼロ、以後は差分だけ増えていきます。
snap@月 → Root(月) ─┐
├─ 変更されていないブロックは共有
現在 → Root(今) ─┘ + 変更分だけ新規ブロック
ブロックは複数のルートから参照され得るため、解放の判断には 参照数の管理 が要ります。ZFS は txg の生成番号(birth time)で世代を比較し、Btrfs は エクステントの参照カウント(back reference)で「まだ誰かが指しているか」を判定します。最後の参照が消えて初めてブロックが空き領域に戻ります。
- ZFS のデータセット: ファイルシステム・スナップショット・ZVOL(ブロックデバイス)を、プールの空き容量を共有しつつ階層管理する単位
- Btrfs のサブボリューム: 独立したファイルツリーのルート。個別にスナップショット・マウントでき、スナップショットは書き込み可能な独立サブボリュームにもできる
書き込み可能スナップショットは、ある断面から分岐して両系統を並行更新でき、コンテナイメージの世代管理などに向きます。整合性の観点はトランザクション処理の 排他制御 とも通じる発想です。
RAID-Z:write hole を構造で消す
従来の RAID5 には write hole という弱点があります。データ更新とパリティ更新は別ブロックで、片方だけ書けた状態で電源が落ちるとストライプの整合が崩れ、しかもそれを検知できません。
RAID-Z は CoW と一体化してこれを解消します。各書き込みで ストライプ幅を可変 にし、書き込むデータ量ちょうどに合わせてパリティを計算、データとパリティを 同一 txg で一括コミット します。
| 観点 | 従来 RAID5 | RAID-Z(ZFS) |
|---|---|---|
| ストライプ幅 | 固定 | 書き込みごとに可変(full-stripe write) |
| write hole | あり(部分更新で破綻) | なし(部分上書きしない=full-stripe) |
| 破損検知 | パリティ照合(位置特定は弱い) | ブロックチェックサムで該当を特定し修復 |
| 階層 | FSとは別レイヤ | FSと統合(冗長度を木が把握) |
CoWゆえに既存ストライプを部分上書きしないので、常に full-stripe write となり write hole が原理的に発生しません。読み出し時にチェックサムで壊れたブロックを特定し、パリティから再構成して その場で修復(self-healing)します。RAID-Z1/Z2/Z3 は許容する同時故障台数(1〜3)に対応します。
まとめ
- CoWファイルシステムは 既存ブロックを上書きせず、変更をルートまで O(log N) で伝播させ、ルートのアトミック差し替えで常に整合した断面だけを永続化する。
- チェックサムを親に持たせる ことで、ディスクのサイレント破損まで検知し、冗長があれば自動修復する。
- トランザクショングループ が多数の変更を束ねて書き込みを償却し、同期要求は ZIL/ログツリーで補う。
- スナップショットは旧ルート保持で定数時間、解放は世代番号や参照カウントで判断。RAID-Z は full-stripe write で write hole を構造的に排除する。
- 基礎は ファイルシステム と コピーオンライト、整合性の発想は 排他制御 も参照。
OS Article
コピーオンライト型ファイルシステム(ZFS/Btrfs)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
ZFS
比較で見る軸
難易度: advanced / カテゴリ: OS / タグ数: 6
導入後に効く点
全ブロックのチェックサムを親ブロックに持たせることで、ディスクが嘘をついても(サイレント破損)検知でき、冗長があれば自動修復します。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- OS
- タグ数
- 6
判断チェックリスト
- 自社の用途が「ZFS / Btrfs」に近いか確認する。
- 強みである「CoWファイルシステムは既存ブロックを上書きせず別の場所に書き、ルートからの参照をまとめて差し替えるため、常に整合した状態しか永続化しません。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。