FUSE経由でZFSを使う

 ZFSはSun Microsystemsによって作成された先進的なファイルシステムだが、Linuxカーネルではサポートされていない。しかしZFS_on_FUSEを利用すれば、Linuxカーネル上でもZFSをFUSEファイルシステムとして使用することができる。つまりLinuxカーネル上で利用可能な他のファイルシステムとまったく同様にZFSファイルシステムにアクセスできるようになる。

 LinuxカーネルにZFSのサポートが統合されていない主な理由には、技術的/資金的な問題以外にも、SunがZFSをリリースしているCommon Development and Distribution LicenseがLinuxカーネルのGPLとは非互換だということがある。また特許の問題もある。とは言えZFSのソースコードは公開されており、またCDDLコードとGPLコードとをリンクするわけではないので、FUSE経由でZFSを実行することはどのライセンスにも違反しない。ただし特許に関しては自己責任として利用することになる。

 カーネル内ファイルシステムの開発者の中には、通常であればカーネル内に含まれているファイルシステムをFUSE経由で実行するということについて効率的な観点から不満を感じる人もいる。アプリケーションがカーネルを呼び出す際にはコンテキストスイッチを行なう必要があるが、x86アーキテクチャでのコンテキストスイッチはとりわけ高速だというわけではない。そしてFUSEファイルシステムはカーネル外で実行されるため、カーネルはFUSEファイルシステムのために折りに触れてコンテキストスイッチを行なう必要がある。したがってFUSE経由でのファイルシステムの利用に必要なコンテキストスイッチの総回数は、カーネル内ファイルシステムを利用する場合よりも多くなってしまう。とは言っても1度のコンテキストスイッチの代わりに2度のコンテキストスイッチを行なうために必要となる時間よりも、ディスク上に保存されている情報にアクセスする時間の方が大幅に長いため、ベンチマークの結果を見ても分かるように、影響があったとしても大したことはないと考えて良いだろう。FUSE経由で実行したNTFSは、ネイティブのLinuxファイルシステムと互角だという結果もある。

インストール

 Ubuntu、openSUSE、Fedoraの各ディストリビューション用のzfs-fuseのパッケージは存在しない。執筆時点でのzfs-fuseの最新版は2007年3月にリリースされた0.4.0 betaだ。zfs-fuseの0.4.xバージョンのソースリポジトリを見る限り、最新版のリリース以来数多くの改善が施されているようだ――例えば2007年3月の時点以降、gccの新しいバージョンを使ってコンパイルすることができるようになった点などがある。そこで最新版としてリリースされているtarファイルではなく、ソースリポジトリからの0.4.xバージョンを使用して、Fedora 8をインストールしてある64ビットマシン上でベンチマークを行ってみた。

 ソースコードリポジトリはリビジョン管理システムにMercurialを利用しているが、Mercurial自体はHardyやFedora 9のメインのリポジトリから入手可能だ。またzfs-fuseをコンパイルするにはSConsとlibaioの開発用パッケージが必要となるが、どちらのパッケージもUbuntu Hardy(libaio-devscons)、openSUSE 10.3 1-Clickインストール(libaio-develとscons)、Fedora 9のリポジトリから入手することができる。インストール作業を行なうと、/usr/local/sbin内に5つの実行ファイルが作成される。

$ hg clone http://www.wizy.org/mercurial/zfs-fuse/0.4.x
$ cd 0.4.x/src
$ scons
$ sudo scons install
$ sudo zfs-fuse

 zfs-fuseデーモンの起動後は、zpoolコマンドとzfsコマンドを使ってzfsファイルシステムをセットアップする。ZFSを使うのが初めての場合にはOpenSolarisの入門ページや、より本格的な文書を読むと良いかもしれない。

性能

 性能はVMWareサーバの仮想マシン内で試してみた。新規の仮想ディスクを作成して、ディスク内の8GBの領域をあらかじめ割り当てた。仮想化を使用することがベンチマーク全体に対して影響を与えると考えられるが、FUSE経由でZFSを実行した場合に期待できる性能は、仮想マシン内でのZFSと仮想マシン内でのカーネル内ファイルシステムとの性能比からある程度の予測ができるはずだ。カーネル内のLinuxファイルシステムとしては、今回使用したBonnie++ ベンチマークのような大規模ファイルについての性能が高いXFSを使用した。

 ZFSの設計は、ほとんどのLinuxファイルシステムとやや異なっている。ZFSでは、一つ以上のパーティションがある状態でまずはZFSの「プール」を作成し、その後プールの中に必要な数のファイルシステムを作成する。今回はベンチマーク用として、8GBの仮想ディスク上の単一のパーティション内に単一のプールを作成して、そのプールの中に2つのZFSファイルシステムを作成した。一方XFSのベンチマークのためには、ZFSが使用していたパーティションのZFSのデータをすべて消去した後、そのパーティション上に直接XFSファイルシステムを作成した。

 以下にZFSファイルシステムの作成とベンチマークの様子を示す。まず始めにfdiskを使ってディスク全体を占めるパーティション1つを新規に作成した。その後「zpool create」コマンドを使って新規のプールを作成して、上記で作成したパーティションにそのプールを割り当てた。-nオプションを付ければ、実際にはプールを作成せずにコマンドの結果をシミュレーションする。分かりやすくするためにその結果も以下に示した。その後zfsコマンドを使ってtank/testfsというZFSファイルシステムを作成すると、以下のように普通のdfコマンドを使って/tank/testfsとしてLinuxカーネルからアクセス可能な新しいファイルシステムができる。それからBonnieベンチマークを実行した。なおベンチマークは、初回の実行ゆえの何らかの悪影響を受けていない数値を得るために何度か実行した。

# fdisk /dev/sdd
...
Disk /dev/sdd: 8589 MB, 8589934592 bytes
255 heads, 63 sectors/track, 1044 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
...
/dev/sdd1               1        1044     8385898+  83  Linux
...
# zfs-fuse
# zpool create -n tank /dev/sdd1
would create 'tank' with the following layout:

        tank
          sdd1
# zpool create    tank /dev/sdd1
# zpool list
NAME   SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
tank  7.94G  92.5K  7.94G     0%  ONLINE  -
# zfs create tank/testfs
# df -h /tank/testfs/
Filesystem            Size  Used Avail Use% Mounted on
tank/testfs           7.9G   18K  7.9G   1% /tank/testfs

$ cd /tank/testfs
$ /usr/sbin/bonnie++ -d `pwd`
...
$ /usr/sbin/bonnie++ -d `pwd`
Version  1.03       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
linuxcomf8       4G 12373  24 14707  11 10604   8 33935  50 36985   3 109.0   0
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16  2272  17  3657  20  2754  18  2534  15  3736  20  3061  20
linuxcomf8,4G,12373,24,14707,11,10604,8,33935,50,36985,3,109.0,0,16,2272,17,3657,20,2754,18,2534,15,3736,20,3061,20

 以下に、XFSファイルシステム上でBonnieベンチマークを実行した様子を示す。やはりベンチマークは複数回実行した。

# mkfs.xfs /dev/sdd1
meta-data=/dev/sdd1              isize=256    agcount=8, agsize=262059 blks
         =                       sectsz=512   attr=0
data     =                       bsize=4096   blocks=2096472, imaxpct=25
         =                       sunit=0      swidth=0 blks, unwritten=1
naming   =version 2              bsize=4096
log      =internal log           bsize=4096   blocks=2560, version=1
         =                       sectsz=512   sunit=0 blks, lazy-count=0
realtime =none                   extsz=4096   blocks=0, rtextents=0
# mkdir /raw
# mount /dev/sdd1 /raw

$ cd /raw
$ /usr/sbin/bonnie++ -d `pwd`
...
$ /usr/sbin/bonnie++ -d `pwd`
Version  1.03       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
linuxcomf8       4G 38681  65 34840   6 16528   6 18312  40 18585   5 365.8   2
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16  1250  26 +++++ +++  3032  39  2883  69 +++++ +++  3143  59
linuxcomf8,4G,38681,65,34840,6,16528,6,18312,40,18585,5,365.8,2,16,1250,26,+++++,+++,3032,39,2883,69,+++++,+++,3143,59

 ベンチマーク結果から分かるように、FUSE経由でZFSを使った場合、出力操作についてはXFSの30~60%の性能しか得られないようだ。一方、キャラクタ入力とブロック入力についてのテストでは、FUSEが行なうキャッシュの効果によってzfs-fuseの性能の方がXFSよりも顕著に優れていた。つまり実用上の観点から言えば、書き込みよりも読み取りを多く行なうファイルシステムの場合には、FUSE経由でZFSを使用することによる速度的なマイナスはないということだ。またzfs-fuseでの書き込み操作の性能がカーネル内ファイルシステムと比べたときに劣るとは言っても、システムが使用に耐えないというほどではない。ただし例のごとく、期待通りの性能を得られるかどうかについては、各自の使用目的についてのベンチマークを行って確かめるべきだろう。

 ZFSをLinux上で使用することには、多くの問題点がある。例えばzfs-fuseのFUSEプロセスはルートユーザとして実行されるので潜在的なセキュリティホールになっていて、そのため何らかのバグが存在した場合にはzfs-fuseがシステムを自由に支配可能になってしまう。またZFSのsharenfsプロパティが現時点ではzfs-fuseでは有効にならないため、ZFSファイルシステムのエクスポートは手動で行なう必要がある。またその場合には多くのシステムの場合FUSEカーネルモジュールをコンパイルし直す必要もある。

 とは言えzfs-fuseを使えば、ファイルシステム自身のクォータや領域確保などLinuxのシステム管理では新しい考え方を使って、いくつものファイルシステムを柔軟に作成できるようになる。ZFSでは、プールを使って好きなだけ多くのファイルシステムを素早く作成可能なので、新たなプロジェクトに取り掛かる際に新たなZFSファイルシステムをプール内に作成するというようなこともごく普通の利用方法となっている。新しいファイルシステムを手早く簡単に作成可能であることはZFS管理のその他の特徴との相性も良い。ZFSではファイルシステムの現在の状態のスナップショットを作成したり、現在の状態や過去のスナップショットを他のマシンにエクスポートしたりすることができる。ただし前述したように今のところはzfs-fuseではsharenfsプロパティはサポートされていない。

 またZFSでは、ソフトウェアRAIDとLVM(論理ボリュームマネージャ)の組み合わせなど、Linuxカーネルの機能の多くが重複して実装されている。このことのマイナスの影響として、2008年3月のZFS管理文書の60ページにも記されているように、既存のRAID-Z構成にディスクを新たに追加することができない(Linuxでは既存のRAID-5アレイに新たなディスクを好きなだけ追加することができる)。

Ben Martinは10年以上もファイルシステムに携わっている。博士号を取得し、libferris、ファイルシステム、検索ソリューションを中心としたコンサルティングサービスを提供している。

Linux.com 原文