はじめに
Linuxでは、設定ファイル、ログ、アプリケーション、画像、データベースなど、さまざまなデータがファイルとして保存されています。
しかし、SSDやHDDなどのストレージが、ファイル名やディレクトリを理解しているわけではありません。ストレージはアドレスで指定された領域に対してデータを読み書きします。
このストレージ上の領域をブロック単位で管理し、ファイルやディレクトリという形で利用できるようにするのがファイルシステムです。ファイルシステムは、「どのファイルのデータがどこにあるのか」「誰がアクセスできるのか」「どの領域が空いているのか」といった情報を管理します。
ファイルシステムの内部では、Inode、Directory Entry、Data Block、Extent、ジャーナルなど、さまざまな仕組みが連携しています。これらの関係を理解すると、ファイルの作成や削除、ハードリンク、削除したのに容量が減らない現象、障害発生後の復旧など、Linuxのファイル操作をより深く理解できます。
本記事では、Linuxで利用される代表的なファイルシステムを紹介するとともに、ファイル名から実データへ到達する仕組みや、ファイルの作成・削除、ジャーナリングの仕組みについて分かりやすく解説します。
ファイルシステムとは
ファイルシステムの役割
ファイルシステムは、ストレージ上のデータをファイルやディレクトリとして管理する仕組みです。データの保存場所だけでなく、ファイル名、サイズ、所有者、アクセス権限、更新時刻、空き領域なども管理します。
- ファイルとディレクトリの階層を管理する
- ファイルの属性やアクセス権限を管理する
- 実データが保存された領域を管理する
- 使用中の領域と空き領域を管理する
- 障害発生後に整合性を回復できるようにする
なぜファイルシステムが必要なのか
ファイルシステムがなければ、ApplicationはデータがStorageの何番目の領域に保存されているかを自分で記録しなければなりません。複数のApplicationが安全に領域を共有したり、データへ分かりやすい名前を付けたりすることも困難です。
ファイルシステムは、物理的な保存位置をファイルとディレクトリという扱いやすい形へ抽象化します。ユーザーは/home/user/report.txtのようなパスを指定するだけで、実際のブロック位置を意識せずにデータへアクセスできます。
ファイルとストレージの関係
ファイルは連続した一つのデータに見えますが、Storage上では複数の領域へ分かれて保存されることがあります。ファイルシステムは、ファイル内の論理的な位置とStorage上の物理的または論理的なブロックを対応付けます。
Applicationがファイルを読み書きすると、VFSを介して対象のファイルシステムへ処理が渡されます。ファイルシステムは保存位置を特定し、必要に応じてPage CacheやBlock Layerを通じてStorageへI/Oを要求します。
Linuxで利用される主なファイルシステム
ext4
ext4は、ext2、ext3から発展した汎用的なジャーナリングファイルシステムです。長い利用実績があり、多くのLinuxディストリビューションで広く利用されています。
Extent、遅延割り当て、ジャーナルチェックサムなどを備え、性能と信頼性のバランスに優れています。オフラインでの縮小にも対応しますが、実行前にはバックアップを用意し、正しい手順でアンマウントや検査を行う必要があります。
XFS
XFSは、大容量のファイルやファイルシステム、高いI/O並行性を考慮して設計された64ビットのジャーナリングファイルシステムです。大規模なサーバや高スループットのワークロードで広く利用されています。
オンラインでファイルシステムを拡張できますが、一般的な運用手段として縮小することはできません。ファイルシステムを選ぶ際は、性能だけでなく、将来の容量変更や運用方法も考慮する必要があります。
Btrfs
Btrfsは、Copy-on-Writeを採用したファイルシステムです。スナップショット、サブボリューム、チェックサム、圧縮、複数デバイスの管理など、多くの高度な機能を備えています。
ただし、利用できる機能や推奨構成、ディストリビューションによるサポート状況は異なります。導入時は、使用するLinuxディストリビューションの公式情報と対象ワークロードでの検証が必要です。
tmpfs
tmpfsは、仮想メモリを利用する一時的なファイルシステムです。高速にアクセスできますが、通常は再起動やアンマウントによって内容が失われるため、永続的なデータの保存には向きません。
Linuxでは/runや/dev/shmなどで利用されます。必要に応じてSwapが関係する場合もあり、常に物理RAMだけへ固定されるという意味ではありません。使用量の上限を設定し、Memoryを圧迫しないように管理することが重要です。
RHEL系Linuxでのファイルシステム
RHEL 9ではXFSが既定のローカルファイルシステムであり、特別な理由がなければXFSの利用が推奨されています。ext4もローカルファイルシステムとしてサポートされます。
一方、BtrfsはRHELの標準的なローカルファイルシステムとして位置付けられていません。RHEL系という名称には派生ディストリビューションも含まれ、それぞれの対応状況が同じとは限らないため、製品バージョンとベンダーのサポートポリシーを確認して選択します。
| 主な用途 | 選択肢 | 特徴 |
|---|---|---|
| 一般的なRHELサーバ | XFS | 既定で、大容量・並行I/Oに適する |
| 互換性や縮小が必要な構成 | ext4 | 広い利用実績があり、オフライン縮小に対応する |
| 一時データ | tmpfs | 主にMemoryを利用し、再起動後の永続性を持たない |
ファイルシステムはデータをどう管理するのか
ストレージをブロック単位で管理する
ファイルシステムは、利用できるStorage領域を一定サイズのブロック単位で管理します。ブロックサイズはファイルシステム作成時の設定などによって決まり、4KiBが使われる構成も一般的です。
どのブロックが使用中で、どのブロックが空いているかをビットマップやツリーなどの管理構造で記録します。新しいデータを保存するときは空き領域を割り当て、削除されたときは再利用できる状態へ戻します。
ファイルのメタデータと実データ
ファイルシステムは、ファイルの内容である実データと、そのファイルを管理するためのメタデータを分けて扱います。Linuxの一般的なファイルシステムでは、Inodeが主要なメタデータを保持し、Data Blockがファイル内容を保持します。
| 種類 | 内容 |
|---|---|
| メタデータ | ファイル種別、権限、所有者、サイズ、時刻、リンク数、データ位置など |
| 実データ | テキスト、画像、プログラムなど、ファイルとして保存した内容 |
ファイル名とデータの関係
ファイル名は通常、対象ファイルのInodeそのものではなく、親ディレクトリのデータとして管理されます。ディレクトリエントリがファイル名とInode番号を対応付け、InodeがData Blockの位置を示します。

Inodeの仕組み
Inodeとは
Inodeは、ファイルシステム内のファイルやディレクトリを表す管理情報です。同じファイルシステム内ではInode番号によって識別されます。ls -i コマンドを使うと、ファイルに対応するInode番号を確認できます。

一番左の「2097161」がInode番号となります。
Inodeが保持する情報
- 通常ファイルやディレクトリなどのファイル種別
- アクセス権限
- 所有者のUIDとグループのGID
- ファイルサイズ
- アクセス・更新・状態変更などの時刻
- Link Count
- データの保存場所を特定するための情報
具体的な項目や保存形式はファイルシステムによって異なります。statコマンドを使うと、ユーザーから見える主要なメタデータを確認できます。
ファイル名がInodeに保存されない理由
ファイル名をInodeから分離することで、複数の名前から同じInodeを参照するハードリンクを実現できます。名前はディレクトリエントリに保存され、各エントリが同じInode番号を指します。
ファイル名を変更するrenameでは、同じファイルシステム内であれば、主にディレクトリエントリの対応を変更できます。実データ全体を別の場所へコピーする必要はありません。
Inodeとデータブロックの関係
Inodeは、ファイル内容が保存されたブロックへ到達するためのマッピング情報を持ちます。小さなファイルでも大きなファイルでも、Applicationからは先頭から末尾まで連続したバイト列として見えますが、実際のブロックはStorage上で分かれている場合があります。
ディレクトリの仕組み
ディレクトリもファイルの一種
Linuxでは、ディレクトリも専用の形式を持つファイルの一種です。ディレクトリには、その配下にある名前とInode番号を対応付けるエントリが保存されます。ただし、通常のファイルのようにApplicationが任意の形式で直接書き換えるものではなく、mkdir、link、unlink、renameなどを通じてファイルシステムが整合性を保ちながら更新します。
ファイル名とInode番号の対応
例えばdocsディレクトリにreport.txtがある場合、docsのディレクトリデータには「report.txt → Inode番号」という対応が記録されます。そのInodeを参照することで、権限やサイズ、Data Blockの位置を確認できます。
ハードリンクを作成すると、別のディレクトリエントリが同じInode番号を指します。どちらか一方の名前を削除しても、もう一方から同じデータへアクセスできます。
パスからファイルを特定する流れ
/home/user/report.txtを開く場合、VFSとファイルシステムはルートからhome、user、report.txtの順にディレクトリエントリを探索します。各段階で名前に対応するInodeを特定し、そのInodeがディレクトリであれば次の名前を探索します。

LinuxはDentry CacheやInode Cacheを利用し、同じパスを繰り返し探索する処理を高速化します。キャッシュに情報がない場合は、ファイルシステムのディレクトリデータから対応を検索します。
ファイルのデータはどこに保存されるのか
Data Blockとは
Data Blockは、ファイルの実際の内容を保存する領域です。テキストファイルであれば文字列、画像ファイルであれば画像データ、実行ファイルであれば機械語や関連データが格納されます。
ファイル末尾のブロックが完全には埋まらない場合、その未使用部分が内部フラグメンテーションになることがあります。一方、Sparse Fileでは、論理的なファイルサイズの一部にData Blockを割り当てず、読み込み時にゼロとして扱うこともできます。
Inodeからデータを特定する
read()が実行されると、ファイルシステムはInodeのマッピング情報を使用し、ファイル内の論理オフセットに対応するData Blockを特定します。Page Cacheに必要なデータがなければ、Block Layerを通じて該当領域を読み込みます。
ext4とXFSのExtent
ext4とXFSは、どちらもファイルのブロック配置を管理するためにExtentを使用します。
Extentは、連続する複数のブロックを「開始位置と長さ」でまとめて表す仕組みです。例えば1000番から1999番までの1000ブロックが連続していれば、各ブロック番号を個別に記録するのではなく、一つの範囲として管理できます。
ext4では、inode内をルートとするExtent TreeでExtentを管理します。Extentが少ない場合はinode内にExtentを直接保持できます。Extentが増えてinode内に収まらなくなると、外部のファイルシステムブロックを使ってExtent Treeを拡張します。
XFSもExtentを利用して、ファイル内の論理的な位置とストレージ上のブロック範囲を対応付けます。Extentが少ない場合はinode内にExtentレコードを保持し、inode内に収まらなくなるとBtree形式に切り替えて管理します。

このように、ext4とXFSはどちらも、少数のExtentであればinode内に情報を保持できます。
違いはExtentが増えた場合の管理方法です。ext4はinode内をルートとするExtent Treeを外部ブロックへ拡張するのに対し、XFSはinode内のExtent形式からBtree形式へ切り替えて管理します。
どちらもExtentによって連続するブロックをまとめて表現することで、ブロックマッピングに必要なメタデータを抑え、効率的にデータブロックを管理しています。
ファイルを作成すると何が起こるのか
Inodeの作成
Applicationがopen()にO_CREATを指定したり、creat()を呼び出したりすると、VFSは親ディレクトリとファイル名を特定し、権限を確認してファイルシステムへ作成を依頼します。
ファイルシステムは新しいInodeを割り当て、ファイル種別、所有者、アクセス権限、タイムスタンプ、Link Countなどの初期メタデータを設定します。
ディレクトリエントリの追加
親ディレクトリへ、新しいファイル名とInode番号の対応が追加されます。これにより、パスを使って新しいInodeへ到達できるようになります。同じ名前がすでに存在する場合の動作は、open()のフラグや操作内容によって異なります。
Data Blockの割り当て
空のファイルを作成しただけであれば、ファイル内容のData Blockがまだ割り当てられないことがあります。その後write()でデータが追加されると、必要なData Blockが割り当てられます。遅延割り当てを行うファイルシステムでは、実際のブロック決定がWritebackまで遅れる場合があります。
メタデータの更新
ファイルサイズ、更新時刻、状態変更時刻、ブロックマッピング、親ディレクトリなどのメタデータが更新されます。ジャーナリングファイルシステムでは、整合性を保つために関連する変更がトランザクションとしてジャーナルで管理されます。
ファイルを削除すると何が起こるのか
ディレクトリエントリの削除
rmコマンドなどによってunlink()が実行されると、ファイルシステムは親ディレクトリから対象のディレクトリエントリを削除します。つまり、最初に削除されるのは名前とInode番号の対応です。
unlink()は一般に通常ファイルの名前を取り除く操作です。空のディレクトリを削除する場合はrmdir()が使用され、内容が残るディレクトリを誤って削除しないための検査が行われます。
Link Count
Inodeには、そのInodeを参照するハードリンク数を表すLink Countがあります。ディレクトリエントリを削除すると、対応するLink Countが減少します。
複数のハードリンクがある場合、一つのファイル名を削除してもLink Countは0になりません。残った名前から同じInodeとデータへ引き続きアクセスできます。
InodeとData Blockが解放されるタイミング
通常、Link Countが0になり、さらにどのProcessからも開かれていない状態になると、InodeとData Blockを解放できます。解放された領域は将来のファイル作成や書き込みで再利用されます。
削除は、データ内容を必ずゼロで上書きする操作ではありません。ファイルシステム上で領域を再利用可能にする処理です。そのため、機密データの安全な消去では、Storageの種類、暗号化、SSDのウェアレベリングなどを含めた別の方法を検討する必要があります。
開いたまま削除されたファイル
Processがファイルを開いている間にその名前を削除しても、File Descriptorからファイルへの参照は残ります。Processは引き続き読み書きでき、Link Countが0でも最後の参照が閉じられるまでInodeとData Blockは解放されません。
補足:ファイルを削除したのに容量が減らない
Linuxでは、ファイルをrmで削除しても、dfで確認したファイルシステムの使用量がすぐに減らないことがあります。
代表的な原因は、削除したファイルをProcessがまだ開いたままにしているケースです。

rmを実行すると、ファイル名を管理するDirectory Entryが削除されます。しかし、Processがそのファイルを開いている場合は、File DescriptorからFileオブジェクト、Inodeへの参照が残ります。
そのため、ファイル名は見えなくなっていても、データブロックはまだ解放されません。このようなファイルは、以下のようにlsofコマンドを実行することで確認できます。
# lsof |grep deleted

上記は、削除済みかつProcessから参照されているファイルのリストとなります。
Processがファイルをclose()するか、Processが終了して最後の参照がなくなると、InodeやData Blockを解放できるようになり、dfで確認できる空き容量も増えます。
そのため、「rmでファイル名を削除すること」と「データブロックが解放されること」は必ずしも同じタイミングではありません。
ジャーナリングの仕組み
ジャーナリングとは
ジャーナリングは、ファイルシステムの重要な変更を本来の管理領域へ反映する前後に、ジャーナルと呼ばれる領域でトランザクションとして記録する仕組みです。ext4やXFSはジャーナリングファイルシステムです。
どの情報をどの順序で記録するかはファイルシステムやモードによって異なります。一般にメタデータの整合性保護が中心であり、ジャーナリングが有効だからといって、直前にwrite()したすべてのユーザーデータが必ず残るわけではありません。
なぜジャーナルが必要なのか
ジャーナルに変更内容をトランザクションとして記録しておくことで、障害後の再起動時にジャーナルを確認し、コミット済みのトランザクションを必要に応じてReplayできます。
これにより、ファイルシステムのメタデータを整合した状態へ回復できます。ファイルシステム全体を最初から検査する場合と比べて、障害からの復旧時間を短縮できます。
障害発生時のファイルシステム保護
システムが再起動すると、ファイルシステムはジャーナルを確認し、必要なトランザクションをReplayして整合した状態へ戻します。これにより、割り当て済みブロックが空き領域として扱われるなどのメタデータ不整合を防ぎやすくなります。
ただし、ジャーナルはバックアップではありません。誤って削除したファイル、Applicationが書き込んだ誤データ、Storage自体の故障などからデータを復元するものではないため、別途バックアップや冗長化が必要です。永続化が必要なApplicationでは、fsync()なども適切に使用します。
ファイルシステムの構造を整理する
これまで説明してきた流れを改めて整理すると以下の通りです。

FilesystemはStorage上の領域全体を管理します。Directory Entryはファイル名とInode番号を結び付け、Inodeはファイルのメタデータと実データへのマッピング情報を保持します。
Extentやその他のBlock Mappingをたどることで、ファイル内の位置に対応するData Blockを特定できます。Data Blockは最終的にStorage上の領域へ保存されます。
この図は一般的なローカルファイルシステムを理解するために簡略化したものです。tmpfsは主にMemoryを利用し、BtrfsはCopy-on-Writeや独自のツリー構造を使うなど、具体的なデータ構造や更新方法はファイルシステムによって異なります。
まとめ
Linuxのファイルシステムは、ストレージ上の領域を管理し、ファイルやディレクトリという形でApplicationから利用できるようにする仕組みです。
ファイル名はDirectory EntryによってInode番号と対応付けられ、Inodeにはファイルの権限、所有者、サイズなどのメタデータと、Data Blockへ到達するためのマッピング情報が保持されます。ext4やXFSでは、Extentを利用して連続するData Blockを効率的に管理しています。
また、ファイルを削除しても、Processがそのファイルを開いている場合はすぐにData Blockが解放されるとは限りません。Link Countが0になり、Processからの参照もなくなることで、InodeやData Blockを解放できるようになります。
さらに、ext4やXFSではジャーナリングによってメタデータの変更を管理し、障害発生後にファイルシステムの整合性を回復しやすくしています。
Linuxのファイルシステムを理解するうえでは、まず次の関係を押さえておくことが重要です。
ファイル名 → Directory Entry → Inode → Extent / Block Mapping → Data Block
この基本構造を理解すると、ファイルの作成・読み書き・削除だけでなく、ハードリンクや「削除したのに容量が減らない」といったLinux特有の挙動も理解しやすくなります。


コメント