FreeBSDでZFSを使ったときの素朴な疑問について、調べたり試したりしたことのメモです。

■100MBのファイルをコピーしたら、中身は同じでもそれぞれ100MBの容量を食うの?

  • それぞれ100MBの容量を食います。
  • ZFS poolのバージョン21でサポートされたDeduplicationをオンにするとコピーしても容量を食わなくなりますが、非常に大量のメモリを消費するので、よく考えてから使うべきでしょう。圧縮をonにする方が実用的という場面も多いようです。

■大きなファイルを作ってスナップショット取ったあとに、ファイル名やパスを変えても、スナップショットは膨らまないの?

  • ほとんど膨らみません。
  • ディレクトリエントリの変更分だけが増えていくので、ファイルのサイズ分増えていくわけではない、という感じでしょうか。

■大きなファイルを作ってスナップショット取ったあとに、ファイルの一部だけを書き換えると、スナップショットが膨らむのは書き換えたブロックの分だけ?

  • はい、プールのディスク消費量は、書き換えたブロックの分しか増えません。

■大きなファイルを作ってスナップショットを取ったあとに、そのファイルを同じプールの別のファイルシステムに移動した場合、スナップショットは膨らまない?

  • ファイルサイズの分だけ膨らみます。

■スナップショットの中身のファイルって、個別に参照できるの?

  • できます。
  • zfs snapshotで作ったスナップショットは、そのファイルシステムの最上位階層にある.zfs/snapshotの中に作られますが、それ自体がディレクトリのようになっているので、中のディレクトリツリーやファイルを覗いたり、別の場所(もちろんそのスナップショットの外)にコピーしたりできます。なお、.zfsはlsでは見えないディレクトリです。
    zfs set snapdir=visible pool/fs
    とすると、.zfsを見えるようにすることもできます。

■スナップショットって、ある階層以下のファイルシステムを全部まとめて取ったりできるの?

  • できます。
  • -rオプションをつけて
    zfs snapshot -r tank/a@now
    とすると、「tank/a」だけでなく「tank/a/b」や「tank/a/b/c」にもまとめて「now」という名前のスナップショットが作られます。
    zfs destroy -r tank/a@now
    でまとめて消すこともできます。
    zfs rollback -r tank/a@now
    でまとめてロールバックもできます。

■プールって、ひとつのシステムに2つ以上作れるの?

  • 作れます。
  • プールは、zpool createで何個でも作れるし、zpool importで何個でも取り込めます。
  • ちなみに、2個のプールをまとめてexportはできますが、importは1つずつしかできません。
    zpool export pool1 pool2
    は、pool1とpool2をシステムから切り離す処理ですが、同じノリで
    zpool import pool1 pool2
    とやってしまうと、これは「pool1をpool2という名前に変えてimportする」という意味になりますので、注意が必要です。両方インポートするつもりでこれをやってしまった場合、一旦zpool export pool2してから、名前ではなくid指定で、1つずつzpool importしていくしかないでしょう。

■zpool exportしたプールはOS再起動しても見えないままなの?

  • 見えないままです。
  • zpool exportしたプールは/boot/zfs/zpool.cacheから消えるので、次回起動時に自動でimportされることはありません。

■プールの中にルート(になりうる)ファイルシステムを2つ作っておいて、マシン起動時にgptzfsbootのboot:プロンプトでファイルシステムを指定して、どちらから起動するか選べるようにできるの?

  • できません。明示的に「zpool set bootfs=pool/fs pool」にて、/boot/zfsloaderを探しに行くファイルシステムを指定する必要があります。
  • 9.0-RELEASEのgptzfsbootは、boot:の書式が「pool:/path/to/zfsloader」だったので、そもそもファイルシステムは指定できませんでした。9.1-RELEASE-RC3のgptzfsbootは、boot:の書式が「pool:fs:/path/to/zfsloader」になって、一見ファイルシステムも指定できるようにみせかけて、実はpoolしかみておらず、結局プールのbootfsに設定されたファイルシステムから/boot/zfsloaderが読み込まれるようになっているようです。

■zpoolが2つあるとき、gptzfsbootはどっちをつかうの?

  • パーティション番号が若い方のfreebsd-zfsパーティションを使っていると思われます。
  • 試しに、1つのディスクにfreebsd-zfsパーティションを2つ作り、それぞれにZFSのプールを作って見ましたが、1番目のパーティションから起動しました。電源投入後に / | \ -がクルクル回る表示のときにキーを押して、boot:で2番目のパーティションにあるプール名を指定したら、レジスタの内容をダンプして「BTX halted」で止まってしまいました。gpart deleteで1番目のパーティションを削除すると、こんどは2番目のパーティションから起動しました。1番目のパーティションの跡地にfreebsd-ufsパーティションを作ってみたら、それは無視されて、やはり2番目のパーティションから起動しました。

■ZFSのファイルシステムを暗号化するには?

  • パーティションをGEOM ELIなどで暗号化し、その上にプールを作ってください。
  • Solaris本家では、zpoolのバージョン30で暗号化が追加されていますが、いろいろ壁があってFreeBSDにはなかなか来ないみたいです。

■暗号化するけど起動時にはパスフレーズ入れなくて済むようにするには?

  • ルートファイルシステムは暗号化しないパーティションに作ってそこから起動し、そのあと手動でgeli attachとzpool importをすれば、起動時にはパスフレーズを入れなくできます。ただし、シャットダウンする前に暗号化パーティション上のプールをzpool exportで外しておかないと、次回起動時に実データにアクセスできない状態でimportされてるので、プールがUNAVAIL状態になります(まあ、そのあとgeli attachしてエラーを解消してやればいいだけですが)。

■スワップ領域ををZFS内に作れるの?

  • 作れます。
    zfs create -V 16G tank/swap
    zfs set org.freebsd:swap=on tank/swap
    zfs set checksum=off tank/swap
    などとしてやるといいようです。org.freebsd:swapのように、名前に「:」が入っているのはユーザプロパティです。

■プールを作ったあとに物理ディスクをつなぎ変えてデバイス名が変わったらどうなるの?

  • デバイス名が変わっても、zpool importするときに/devの下(あるいは-dで指定した場所)を見に行って、その中に指定した名前のプールが見つかれば、見つかったデバイス名でプールが使えるようになります。なお、GPTを使うなら、gpart addするときに-lオプションでパーティションにラベルを付けておき、zpool createするときに/dev/gptの下のラベルを指定するようにすれば、機器の接続構成に依存せずに固定名でパーティションを指定できます。

※バージョンメモ

  • FreeBSD-9.1-RC3-i386