彷徨えるフジワラ

年がら年中さまよってます

ZFSソース読み重点項目メモ

先日の OpenSolaris 勉強会参加で俄然 ZFS のソース読み意欲が高まったわけだが、高まったからと言って即着手できるほど世の中甘くはない。

本当は「思い立ったが吉日」で、即行動こそが勝利の方程式なんだろうけどね。

とりあえず、忘れないように疑問点などの重点項目をメモしておく。

排他スコープと性能の関係

ZFS は copy-on-write を採用しており、木構造の末端から徐々に改変のための複製が進んでいくイメージになっている。言うなれば、シールを貼りっぱなしにできるエルメスのキッスのようなもの(嘘)。

この実行モデル、スナップショット生成がほぼ実行コストゼロで実現できるあたりは優れものなんだけど、排他のことを考えるとちょっと面倒(な筈)。

木構造全体の排他は性能上無理なので、部分的に排他獲得・解放を繰り返しつつ、木構造をなめていくことになる筈なのだけど、参照系の「親⇒子」の排他と、更新系の「子⇒親」の排他が衝突してデッドロックとなる事態をどうやって抑止するかが問題。

UFS とかは、木構造中の要素を直接書き換えるモデルなので、書き換え対象さえ排他すれば良かったんだけどね。

「改変中」と「改変前」で排他獲得がちょうどすり抜けるようになっているのかな?

メモリ効率/冗長性

ZFS の『トランザクションは時限締め切りモデル』らしいのだが、その場合、同一オブジェクト(= ファイル)に対して:

  • ストレージに書き込むための確定イメージ
  • 現時点で参照・改変対象となる最新イメージ

の最低2つ分はメモリ上に保持していなければならない筈(そうでないと、トランザクション確定までの間、改変を許すわけにはいかなくなる)。

更に、参照・改変対象となる「最新イメージ」の方は、前述の copy-on-write モデルで改変されると、「未改変」版と「改変中」版で2倍のデータが必要になる(これで都合3倍)。

ところで、UFS とか NFS(クライアント側)の実装だと、所謂「ページキャッシュ」を効かせるために、媒体上のデータとは別に、メモリ上にデータ内容を「キャッシュ」するようにしている。

性能上、このキャッシュは非常に有効なんだけど、これまでに出てきただけで ZFS は同じファイルのためのデータ領域を既に3つ分も抱えていることになるから、さすがにこれ以上は抱え込まない気がするんだけど、どうなんだろう?

ただ、ページキャッシュ無しだと、実質 mmap() ができないわけなのだけど、最近のコマンド実装は何気に mmap() を使っていたりするから侮れない(Solaris の cp コマンドとか)。

しかし、mmap() でユーザ空間に貼り付けた領域への書き込みは、write() での書き込みと違い、アクセスの一切が FS 層に通知されないので、ZFS の「一貫性保障」とは相容れないと思うのだけど…。ページキャッシュは、FS 層の意図とは関係なしに invalidate されたりするし。