Linuxのファイルシステムとファイルの概要

Linux上で行う作業にはすべて何らかの形でファイルが関係している。たとえば、プログラムをファイルから起動し、プログラム設定をファイルから読み込み、データをファイルに保存し、サーバを経由してファイルをクライアントに配信する、という具合だ。

したがって、Linuxのファイル操作関連のツールは、システム全体のパフォーマンスにとって非常に重要な意味を持つ。基本的には、こうしたファイル操作ツールがファイルシステム――つまりLinuxがファイルを探して操作するために使うデータ構造の集まり――を形成している。Linuxにはいくつかネイティブなファイルシステムが存在しており、最も重要なのは、ext2fs(Second Extended File System)、ext3fs(Third Extended File System)、ReiserFS(Reiser File System)、JFS(Journaled File System)、そしてXFSである。どのファイルシステムを使用するかによって、コンピュータの全体的なパフォーマンスと特定の作業への適合性が左右される。

本稿は、先日刊行された書籍『Linux Power Tools』からの抜粋である。

ファイルシステムを選ぶ前に、さまざまなファイルシステムツールについて調べておく必要がある。ファイルシステム作成オプションとパフォーマンス改善ツールがあればディスクスループットを向上させることができ、パーティションサイズ変更ツールがあればパーティションを記憶域のニーズに合わせて拡大・縮小することができる。ときにはファイルシステムが壊れることもあり、こうした問題が発生したときにはそれを修復する手段が重要になってくる。さらに、最もよくある問題の1つは、ファイルを誤って削除してしまうことである。そのようなファイルを回復する方法を知っていれば、管理者やユーザの作業時間や労力を大いに節約することができる。

適切なファイルシステムの選択

Linuxをインストールするときには、使用できるファイルシステムについてのオプションが提示される。2.4.x以降のカーネルを含んでいるディストリビューションの大部分は、ext2fs、ext3fs、およびReiserFSをサポートしている。一部のディストリビューションは、これらに加えてJFSやXFSもサポートしている。たとえJFSやXFSをサポートしていないディストリビューションでも、適切なカーネルパッチやパッチ適用済みのカーネルをJFSまたはXFSのサイトからダウンロードし、このサポートをモジュールとしてコンパイルするかカーネルプロパーに組み込むことで、JFSやXFSのサポートを追加することができる。その後は、現在のシステムをバックアップし、新しいファイルシステムを作成してから復元すれば、パーティションを別のファイルシステムに変換できる(2.4.20および2.5.6カーネルにはJFSのサポート、2.5.36カーネルにはXFSのサポートが既に追加されている。そのため、これらのファイルシステムは、ほとんどのディストリビューションのインストール時にオプションとして提示されるようになると思われる)。

残念ながら、どれが最善のファイルシステムであるかがいつも明白であるとは限らない。ある環境ではそれほど重要でない機能でも、別の環境では重要な意味を持つことがある。ファイルシステムの設計の違いにより、あるファイルシステムが特定の処理を他のファイルシステムより効率的に実行できる場合もある。また、サポートツールが異なれば、高度なファイルシステム機能にも違いが出てくる。この節では、いくつかの代表的なLinuxファイルシステムの長所と短所を、ファイルシステムの移植性、ディスクチェック時間、ディスク速度、ディスク空間の消費量、多数ファイルへの対応、高度なセキュリティ機能という側面から見ていく。

ファイルシステムの移植性を重視する

ext2fsは、最も移植性の高いLinuxネイティブファイルシステムである。ext2fs用のドライバとアクセスツールは数多くのOSに用意されているので、さまざまな非Linux OSからext2fsのデータにアクセスすることができる。しかし、ほとんどのツールにはさまざまな形の制限がある。たとえば、真のドライバではなくユーティリティにアクセスする、最新版のext2fsでは使用できない、ext2fsの読み取りだけで書き込みはできない、ext2fsに書き込むとファイルシステムが壊れるおそれがある、というものだ。したがって、ext2fsの移植性には限界がある。

ext3fsは、ext2fsにジャーナルを追加したものである(ジャーナルについては後述の「ディスクチェック時間」を参照)。そのため、ext2fsのアクセスツールの多くはext3fsにも対応可能だが、中にはext3fsへの書き込みができないものもある。

JFSは、IBMが自社のAIX OSのために開発し、のちにOS/2に移植したファイルシステムである。その後、同社はOS/2のJFS実装をオープンソース化し、それがLinuxのJFSサポートになった。この経緯により、JFSはLinuxとOS/2のマルチブートシステムに適した選択肢と言える。しかし、互換性の問題がある。最も重要なのは、LinuxとOS/2の両方が同じJFSパーティションを使用するには4,096バイトのクラスタを使用しなければならないという点だ。さらに、ファイル名の大文字/小文字の維持という問題もある(OS/2は大文字/小文字を区別しないが、Linuxは両者を区別する)。Linuxからは大文字/小文字を区別してJFSを利用できるが、この方法を使うのは専用のデータ転送パーティション上のみにすることをお勧めする。

XFSも、もともとはSilicon Graphics(SGI)のIRIXのために開発され、のちにLinuxで使われるようになったファイルシステムである。Linux/IRIXのデュアルブートシステムはめったにないが、LinuxシステムとIRIXシステムの間で抜き差しするリムーバブルディスク上では、XFSを互換ファイルシステムとして使用することがある。また、元はIRIXシステム上にあったハードディスクを読み取るときにも、LinuxのXFSサポートを使用することができる。

ReiserFSは、主要なLinuxネイティブファイルシステムの中では現在最も移植性の低いファイルシステムである。BeOSバージョンはあるが、他のプラットフォーム用のバージョンはまだ登場していない。したがって、クロスプラットフォームの互換性が必要な場合にはReiserFSを避けるべきである。

ディスクチェック時間を減らす

どのファイルシステムでも、データの書き込みは必ずある程度の「塊」を単位として行われる。停電やシステムクラッシュなどの問題が発生すると、中途半端な処理のせいでディスクが不安定な状態になることがある。その結果、データが失われたり、ディスクエラーが起きたりする可能性もある。このような問題を防ぐために、最近のファイルシステムは「ダーティビット」をサポートしている。Linuxはファイルシステムをマウントするときにダーティビットをセットし、ファイルシステムをアンマウントするときにダーティビットをクリアする。ファイルシステムのマウント時に、ダーティビットが既にセットされた状態になっている場合は、前回そのファイルシステムが正しくアンマウントされなかったということであり、エラーを含んでいる可能性がある。ダーティビットがセットされているときは、/etc/fstabまたはmountコマンドオプションに応じて、Linuxがそのファイルシステム上でfsckを実行することができる。このプログラムは、ディスクエラーをチェックし、可能であればエラーを修正する。

ただし、ext2fsのような従来のファイルシステム上で完全なディスクチェックを行うときは、主要なディスクデータ構造をすべて走査する必要があるので、非常に長い時間がかかる。矛盾を発見した場合、fsckは矛盾を解決しなければならない。たいていはこのプログラムが自力で矛盾を解決できるが、ときには人の手が必要になることもあるので、管理者は、クラッシュやその他のシステム障害が起きた後に特定のファイルシステムの問題をどのようにして解決するかについての面倒な質問に答えなければならない。この質問に答えなかったとしても、何ギガバイトもあるハードディスクのディスクチェックには長い時間がかかり、数時間かかることもある。この性質は、サーバのように最小限のダウンタイムが要求されるシステムでは許容しがたいだろう。

ここ10年来、このようなディスクチェック時間の問題を部分的に解決するものとしてジャーナリングファイルシステムが注目を集めている。ジャーナリングファイルシステムでは、未完了の操作をディスク上に記録する。OSがディスクにデータを書き込むときは、まずその操作を示すジャーナルエントリを記録し、それから操作を実行し、最後にジャーナルをクリアする。そのため、電力障害やクラッシュが起きたときには、未完了の可能性があるすべての操作がジャーナルに記録されていることになる。この情報により、ファイルシステムのチェック処理を大きく簡略化することができる。ディスク全体をチェックする代わりに、「未完了の操作に関係する領域」としてジャーナルに記録されている部分だけをチェックすれば済むからだ。そのため、ジャーナリングファイルシステムの場合は、システムクラッシュが発生してからマウントするまでの時間がわずか数秒で済む。もちろん、一部のデータは失われるかもしれないが、少なくとも、その事実を発見するまでに何分間あるいは何時間もかかることはない。

Linuxは次の4つのジャーナリングファイルシステムをサポートしている。

・ext3fs

このファイルシステムは、基本的に、ext2fsにジャーナルを追加しただけのものである。既に十分なテストがされているext2fsを基盤にしているため、信頼性がきわめて高い。また、ext3fsはext2fsのドライバを使って読み取ることができる(ただし、この方法でマウントしたときはジャーナルが無視される)。ext3fsのもう1つのメリットは、既存のext2fsをext3fsに変換するときに、バックアップ、パーティション再設定、復元というプロセスを経なくても済むということだ。

・ReiserFS

このファイルシステムは、Linuxカーネルに初めて追加されたジャーナリングファイルシステムである。そのため既に多数のテストが行われており、信頼性が非常に高い。これは最初からLinux用のジャーナリングファイルシステムとして設計されたものであり、小さいファイルを他のファイルシステムよりも小さなディスク空間に詰め込める機能など、設計上の変わった特徴をいくつか持っている。

・JFS

IBMのJFSは、もともとは1990年代の半ばにAIX用として開発され、OS/2に移植されたのちに、Linuxへと展開されたものである。その間に十分なテストを重ねてはいるが、LinuxバージョンのJFSは、非LinuxバージョンのJFSやLinux用のext3fsまたはReiserFSに比べてあまり使われていない。

・XFS

SGIのXFSは、IRIXプラットフォーム上では1990年代の半ばから使われているものであり、ファイルシステムの基盤は十分にテストされている。これはLinuxカーネルに公式に追加された最も新しいファイルシステムだが、そのずっと以前からアドオンとして人気を集めていた。XFSは、ext2fsとext3fsを除くどのファイルシステムよりも充実した付属ユーティリティを備えている。さらに、ACLなど、他の多くのファイルシステムではきちんとサポートされていない高度な機能に対するネイティブサポートも備えている(ACLについては、後出の節「ACLによるファイルシステム保護」を参照)。

たいていの場合は、ジャーナリングファイルシステムを使うことをお勧めする。ジャーナリングファイルシステムは起動時間が短くて済むので、停電などの問題が起きたときに有用である。一方、ジャーナリングファイルシステムには短所もある。最も重要なのは、ジャーナリングファイルシステムの癖に依存するプログラムがあるということだ。たとえば、2001年の終わりごろ、NFSサーバやWin4Linエミュレータなどのプログラムを一部のジャーナリングファイルシステムと併用すると問題が起きることがあった。もっとも、この問題は既に解消されており、2.5.54カーネルではめったに発生しなくなっている。しかし、実際にジャーナリングファイルシステムに切り替える前に、すべてのプログラム(特に、下位レベルあるいは通常とは異なる方法でディスクファイルを操作するプログラム)を徹底的にテストするべきである。この観点から見て最も安全なジャーナリングファイルシステムは、おそらくext2fsと密接な関係にあるext3fsだろう。

ReiserFSとJFSは、サポートプログラムという点でもやや分が悪い。たとえば、ReiserFSとJFSはどちらもdumpバックアップユーティリティを備えていない。XFSのdumpユーティリティ(xfsdump)はXFSの開発サイトから入手できるが、xfsprogs 2.2.1パッケージには含まれていない。いくつかのディストリビューションは、xfsdumpを独立したxfsdumpパッケージとして提供している。xfsdumpとext2fs/ext3fs dumpが作成するアーカイブには互換性がないので、これらのツールを使って一方のファイルシステムをバックアップし、それを他方のファイルシステムに復元することはできない。

ディスクスループットを最大限にする

最高のディスクパフォーマンスを実現するのはどのファイルシステムか、という質問をしたくてうずうずしている人もいるだろう。しかし、その質問に簡単に答えることは難しい。なぜなら、システムユーザが作り出すアクセスパターンが異なれば、適切なファイルシステム設計も異なってくるからだ。William von Hagenは著書『Linux Filesystems』(Sams, 2001)の中で数多くのベンチマークテストを実施し、どのLinuxファイルシステムもいずれかのテストでは最高の成績を収め得るということを発見した。もっとも、全般的に言えば、XFSとJFSは小さなファイル(100MB)で最善のスループットを発揮し、ext2fsとext3fs(そしてやや劣るがJFS)は大きなファイル(1GB)で最善のスループットを発揮した。いくつかのベンチマークテストでは、ディスク負荷の大きい操作を行うときのシステム応答速度に影響を与える要素として、CPU使用量を計測した。小さいファイルを使用した場合のテスト結果には大きなばらつきが現れ、特にどのファイルシステムが優れていると結論付けることはできなかった。一方、大きいファイルを使用した場合のテスト結果では、ext3fsとJFSが最も優れたパフォーマンスを示した。

残念ながら、ベンチマークテストはあくまで人工的なものであり、実世界でのパフォーマンスの優劣を正しく示しているとは限らない。たとえばvon Hagenのベンチマークテストでは、ファイル削除のテストにおいてext2fsが最高の成績を示し、ReiserFSが次点につけた。しかしvon Hagenは、この結果は彼の個人的な経験に反していると述べており、私もそれに同意する。多数のファイルを削除するときには、ext2fsよりもReiserFSの方が高速に感じられるのだ。この認識のずれはおそらく、von HagenのテストはCPU時間を計測したもので、我々ユーザはCPU時間よりもプログラムの応答時間の方に関心があるという違いによるのだろう。つまり、ベンチマークテストを盲目的に信じてはならないということだ。最高のディスクパフォーマンスを得ることが重要である場合は、自分自身で実験してみよう。テストを実施するときは、テスト全体を通して同じハードウェアとパーティションを使用しなければならない。次のファイルシステムに進むたびに前のファイルシステムを一掃し、毎回同じディスクとパーティションを使うようにする。新しいファイルシステム上に適切なアプリケーションまたはユーザファイルをインストールしたら、そのシステムが特定の作業をどのくらい高速に実行できるかを調査する。この手順は手間がかかりすぎるように思われる場合は、おそらくファイルシステム間のパフォーマンスの差異はあなたにとってまったく重要なものではないので、別の基準に従ってファイルシステムを選択するべきである。

ディスク空間の消費量を最小限にする

ほとんどのファイルシステムでは、ブロック単位でファイルにディスク領域を割り当てる。したがって、個々のファイルサイズは、通常は512バイトに2のべき乗を掛けたものになる(たとえば21 x 512、22 x 512、23 x 512、という具合である)。Linuxのファイルシステムの一般的なブロックサイズは1KB〜4KBである(ext2fsおよびext3fsでの範囲)。XFSは512バイト〜64KBのブロックサイズをサポートしているが、実際のブロックサイズはCPUアーキテクチャによって制限される(IA-32およびPowerPCは4KB、AlphaおよびSparcは8KB)。ReiserFSとLinux版JFSは、現在は4KBのブロックのみをサポートしているが、JFSのデータ構造は512バイトのブロックをサポートしている。ext2fsとext3fsを除くこれらのファイルシステムのデフォルトのブロックサイズはいずれも4KBであり、ext2fsとext3fsのデフォルトはファイルシステムのサイズによって異なる。

ブロックサイズを小さくすれば、1つのファイルが占める領域を最小限に抑え、ファイルシステム上に格納できるファイル数を最大限に増やすことができる。ただし、この方法を採用すると断片化が起こりやすくなり、ディスク上のファイルの所在を完全に表すポインタの数が増えるので、パフォーマンスが少々低下するおそれがある。

ReiserFSは、他のファイルシステムとは異なり、いくつものファイルの「テール」(tail:しっぽ)――ファイルの末尾で、1つのブロックを占めるには至らない部分――を集めて1つのブロックに格納するという機能を備えている。この機能により、ReiserFSでは、ニュースサーバのスプールディレクトリに見られるような小さなファイルを数多く格納することができる。XFSは、これと同様の機能を別のアプローチで実現している。つまり、小さなファイルを可能な限りinode(ディスク上のファイルを指し、ファイルのタイムスタンプなどの情報を保持するディスク構造)内に格納するというアプローチである。

これらの機能は、平均ファイルサイズが大きいときにはあまり大きな効果を発揮しない。たとえば、1つの割り当てブロックにファイルテールを格納して2KBを節約したとしても、ファイルシステム上に1GBのファイルが2つしかないのであれば効果はない。しかし、1KBのファイルが2,000,000個ある場合は、こうした領域節約機能を使用できるかどうかが、すべてのファイルを1つのディスク上に収められるか、新しいディスクを購入しなければならないかの分かれ目になることがある。

ディスク領域の消費量に関するもう1つの問題は、ジャーナルに使用される領域である。ほとんどのディスクではこれが大きな問題になることはないが、Zipディスクのように小さなディスクではこの点を考慮しなければならない。100MBのZipディスクがある場合、ReiserFSはジャーナルのために32MBを確保し、ext3fsおよびXFSは4MBを確保する。JFSは、最初の時点ではジャーナル用の領域を少なめに確保するが、使用している間にこの領域が大きくなることがある。

ext2fsとext3fsにはまた別の問題がある。これらのファイルシステムは、デフォルトではディスク領域の5%をルートのための非常用領域として予約している。これは、ファイルシステムがいっぱいになったときにルート用の作業領域を確保するための措置である。これはルートファイルシステムや/varのような重要なファイルシステムにとっては有用な対策だが、それ以外の場面では無意味である。たとえば、/homeやリムーバブルメディア上ではルート用の領域は必要ない。

大量のファイルに対応する

ある意味では、パーティション上にできるだけ多くのファイルを格納するということは、前述の「ディスク空間の消費量を最小限にする」で説明した、小さいファイルへの効率的な領域割り当ての問題に関係している。しかし、それとは別に、使用可能なinodesの数という要素がある。ほとんどのファイルシステムでは、ディスク上でサポートされるinodeの数に制限がある。このinodeの数により、ディスク上に格納できるファイル数が制限される。各ファイルはそれぞれ1つのinodeを必要とするので、ディスク上に小さなファイルを多数格納する場合は、inodeを使い果たしてしまうおそれがある。ext2fsおよびext3fsでは、ファイルシステムを作成するときにmke2fsコマンドに-iまたは-Nオプションを付けることで、inodeの数を変更できる。これらのオプションでは、それぞれinode当たりのバイト数(通常は2か4、この値を増やすとファイルシステム上のinodeの数が減る)と、inodeの絶対数を設定する。XFSでは、mkfs.xfsmaxpctオプションを付けることで、inodeに割り当てられるディスク領域の最大パーセンテージを指定できる。デフォルト値は25だが、ごく小さいファイルを数多く格納するファイルシステムの場合は、それよりも大きな値に設定することができる。

ReiserFSは、他のファイルシステムとは異なりinodeを動的に割り当てるので、inodeを使い果たすことを心配する必要はない。dfユーティリティは、通常は使用中のinodeと使用可能なinodeの統計を返すユーティリティだが、これに-iオプションを付けて実行すると、ReiserFSボリューム上で使用可能なinodeについての情報が返される。

ACLによるファイルシステム保護

Linuxでは、Unix全般と同様に、ファイルとディレクトリへのアクセスを制御する手段として伝統的にファイルの所有権と権限を使用する。ファイルへのアクセスを制御するもう1つの方法は、アクセス制御リスト(Access Control List:ACL)を使用することだ。ACLを使用すると、所有権と権限を使った場合よりも細かいアクセス制御が可能になる。ACLは、ファイルに追加情報(ユーザまたはグループの名前と、それぞれに付与する権限のリスト)を付加することで機能する。たとえば、あなたが機密データを含むファイルを持っているとする。このデータにはあなただけが書き込みを実行でき、特定のグループ(たとえばreaders)だけがこのデータを読み取れるようにしたいとする。この場合、あなたはこのファイルに対して、あなただけがファイルを読み書きでき、readersグループのメンバは誰でもファイルを読み取れるようにする所有権と権限を与えればよい(0640または-rw-r—–)。しかし、このファイルを別の1人のユーザと共有しなければならなくなったとする。他のファイルのセキュリティを守るためには、このユーザをreadersグループのメンバにすることはできない。そこで役に立つのがACLである。ACLを利用すれば、readersグループとは無関係にその1人のユーザに読み取り権限を与えることができる。もしもACLがなければ、readersグループの全メンバとその1人のユーザを含む新しいグループ(readers2など)を作成し、この追加グループを保守しなければならないだろう。また、ACLは普通のユーザでも操作できるが、通常、グループの場合はそうはいかない。したがって、ACLを利用すると、ユーザが他のファイルへのアクセス制限を維持しつつ、特定のファイルへのアクセス権をお互いに付与できる状況を実現したい場合に、話を非常に単純化することができる。

ACLを直接サポートしているLinuxネイティブファイルシステムはほとんどない。唯一これをサポートしているのがXFSである。しかし、ACLが必要な場合には、ext2fs、ext3fs、JFS用のアドオンパッケージを入手することができる。どのファイルシステムを使用する場合でも、同じサイトからサポートユーティリティを併せて入手する必要があるだろう。これらのツールを使ってACLを定義・修正することができる。たとえばgetfaclではファイルのACLを表示し、setfaclではファイルのACLを変更する。

ACLは、Linuxにおいてはまだ非常に新しい概念である。そのため、特定のプログラムやファイルシステムで使用したときに変わった問題にぶつかる可能性がある。普通のワークステーションや小規模なサーバであれば、ACLはおそらく必要ないだろう。しかし、複雑なグループ構造を持つマルチユーザシステムを管理している場合には、ACLについて詳しく調べてみた方がいいかもしれない。ACL対応のファイルシステムに切り替えることで、全体的な権限構造を簡略化できる可能性もある。

次回の記事では、ファイルシステムの最適化について述べたいと思う。