JFSを30日間試してみた

 JFS(Journaled File System)は1999年にIBMがオープンソース化し2002年にLinuxカーネルに統合された、あまり知られていないファイルシステムだ。JFSはもともとはAIXを搭載したUnixサーバ上の標準ファイルシステムとしてIBMによって開発され、その後OS/2にも移植された。そのような立派な血統にも関わらずJFSはあまり知られておらず、またext2/ext3やReiserFSなどの他のLinux用のファイルシステムのように広くは使用されていない。今回JFSについてより詳しく知るために、ルートファイルシステムとしてJFSをインストールしてみた。その結果、JFSは他の有名なファイルシステムの代替物として遜色のないファイルシステムだということが分かった。

 JFSを試してみるため、ノートPC上にSlackware 12をインストールして、インストール時にファイルシステムとしてJFSを選択した。パーティション分割に関して特別なことは何もせず、すべてを含む一つのJFSファイルシステムを作成した。インストールは順調に終わり、システムはGRUBから問題なくブートした。JFSはすべてのディストリビューションでインストールオプションとして提供されているわけではなく、また、デフォルトのカーネルがJFSを含めずにコンパイルされているディストリビューションもあるだろう。FedoraとSUSEでは、JFSを使用することができるようになっているものの、どちらもデフォルトのファイルシステムはext3になっている。JFSを試してみたい人には、Slackware、Debian、Ubuntuとそれらの派生ディストリビューションが良い選択肢だろう。

 JFSを初めて使ってみて最初に気付いた点は、二流のファイルシステムには付き物のlost+foundディレクトリがないということだ。

 JFSは完全に64ビットのファイルシステムだ。デフォルトのブロックサイズは4KBで、ファイルシステムのサイズとして最大4ペタバイト(ただしブロックサイズが4KBより小さい場合は上限も小さくなる)をサポートしている。サポートしているファイルシステムの最小サイズは16MBだ。JFSのトランザクションログのサイズは、デフォルトでは集合体のサイズの0.4%(メガバイト単位に切り上げ)で、最大32MBとなっている。ディスクのレイアウトの興味深い点として、fsckの作業領域があった。これはファイルシステム内に割り当てられている小さな領域で、ブート時に大規模なファイルシステムを追跡するだけの十分なRAMがない場合に、ブロックの割り当てを記録しておくためのものだ。

 JFSはiノードに対して動的にディスク領域を割り当て、必要がなくなればその領域を解放する。そのため小さなファイルが数多くある場合にも、iノードの数が不足することはない。すでにカーネル内に統合済のファイルシステムのうち、この機能を持つファイルシステムは、私が知る限りはJFSだけだ。また性能と効率を上げるために、小さなディレクトリの内容はディレクトリのiノードの中に保存されている。自分自身(.)と親ディレクトリ(..)以外に8個までのエントリがiノード内にインラインで保存される。それよりも大きなディレクトリは、高速に検索できるようにするため、名前をキーとしたB+ツリーを使用している。内部的にはJFSは、ファイルにブロックを割り当てるのにエクステントを使用しているので、ファイルのサイズが大きくなっても領域を効率良く使用することができる。なおエクステントはXFSでも使用されており、またext4の主な新機能の一つでもある。

 JFSは、スパースファイルとデンスファイルの両方をポートしている。スパースファイルでは、途中のファイルブロックにデータを書き込むことなしに、データをファイル内の任意の位置に書き込むことができる。JFSは、使用されている可能性のある最大ブロック数をファイルのサイズとして報告するが、割り当ては実際に使用するブロックに対してのみ行う。スパースファイルは、大規模な論理領域を必要とするがその領域を部分的にしか利用しないようなアプリケーションに向いている。一方デンスファイルでは、データが書き込まれていても書き込まれていなくても、ファイルのサイズの分だけブロックが割り当てられる。

 JFSでは通常のパーミッションに加えて、不変属性(i)や追加専用属性(a)などの基本的な拡張属性をサポートしている。lsattrプログラムとchattrプログラムで試してみたところ、問題なく設定/確認することができた。なおLinuxでのJFSのACL(Access Control List)についてはあまり情報を見つけることができなかった。

ロギング

 JFSの主な設計目標は、大規模なファイルシステムのために、古いUnixのファイルシステムにあるような長時間のfsck(ファイルシステムチェック)をなくして高速なクラッシュ復旧を提供することだった。このことはext3やReiserFSなどのファイルシステムにおいても同様にメインの目標だった。しかしext3とは違ってJFSではジャーナリングは後からの付け足しではなく、設計当初から設計の中に組み込まれていた。JFSではアプリケーションの性能を高めるために、ファイルシステムの最初の作成時に指定することでトランザクションログファイルを外部ボリューム上に作成することができる。

 JFSはファイルシステム構造の一貫性を維持するためにメタデータの変更を伴う操作をログに記録するが、ファイルの中身はログに記録されないためファイルの中身の整合性は必ずしも維持されない。そのためクラッシュが起こった場合データは古い状態になる可能性があるが、ファイルシステムの一貫性は保たれていて使用可能な状態であるはずだ。

 以下に、JFSがログに記録するファイルシステム操作を示す。

  • ファイル作成(create)
  • リンク(link)
  • ディレクトリ作成(mkdir)
  • ノード作成(mknod)
  • リンク削除(unlink)
  • 名前変更(rename)
  • ディレクトリ削除(rmdir)
  • シンボリックリンク(symlink)
  • 通常ファイルのトランケート