JFS

提供: ArchWiki
2016年11月15日 (火) 21:19時点におけるKusakata (トーク | 投稿記録)による版 (言語間リンク修正)
ナビゲーションに移動 検索に移動

関連記事

この記事では JFS ファイルシステムを紹介します。特に、実装・メンテナンス・最適化の方法と、ファイルシステム自体の背景情報や不確かな実装の注意点を記載しています。

背景

Journaled File System (JFS) は1999年に IBM によってオープンソース化されたジャーナリングファイルシステムで、2002年から Linux カーネルでサポートされるようになりました。

  • 1990年、JFS1 (JFS) が AIX バージョン 3.1 向けにリリースされました。IBM の UNIX サーバーの AIX ラインと密接に関係しており、プロプライエタリな設計になっていました。
  • 1995年、スケーラビリティを改善したり機能を増やすなど、JFS を改良するための重点的な開発が開始されました。
  • 1997年、改良した JFS のソースを AIX に戻す開発が並行して開始されました。
  • 1999年、改良された JFS の設計が OS/2 向けにリリースされました。
  • 2001年、改良されたファイルシステム (新しく JFS2 と命名) が AIX 5L 向けにリリースされました。
  • 現在の GNU/Linux バージョンは OS/2 向けの JFS をベースにした移植です。
ノート: 潜在的な問題は存在しますが、OS/2 と GNU/Linux の JFS ファイルシステムは相互運用が可能です [1]

JFS と UNIX や UNIX ライクなオペレーティングシステムの他のファイルシステムを一概に比較するのは難しいですが、JFS は他の GNU/Linux ファイルシステムよりも CPU の使用量が少ないと謳われています [2]。最適化を使うことで、特定のファイル操作で、他の GNU/Linux ファイルシステムと比べて、JFS は高速に動作するとも言われています ([3], ベンチマークを参照)。

GNU/Linux 開発チーム

GNU/Linux の JFS 移植の開発を率いているのは:

技術的な特徴

JFS は多数の機能をサポートする近代的なファイルシステムです。以下はその一部です:

  • 完全に64ビット。
  • i-node の動的な容量割り当て。小さなファイルが多数存在してもファイルシステムの i-node が不足することはありません。
  • 速度と効率性にふったディレクトリ構造:
- 8以下のエントリしか存在しないディレクトリの中身はディレクトリの i-node 内にインライン保存されます。
- エントリが9以上あるディレクトリの中身は B+ 木による名前に保存されます。
  • JFS は巨大なファイルのブロック割り当てにエクステントを利用します。
  • 標準的な Unix のパーミッションに加えて拡張属性をサポート。
  • 内部・外部ログをサポート (下を参照)。
  • きわめてスケーラブル。最小ファイル容量から4ペタバイトまでパフォーマンスが変わらない。
  • 巨大なシステムで高い性能を発揮するように設計されたアルゴリズム。
  • GNU/Linux 向けにチューンされたパフォーマンス。
  • トランザクション/ログを提供するように根底から設計 (アドオンではない)。
  • システム喪失からの再起動は1秒以下。
  • 実績のあるジャーナリングファイルシステムテクノロジ (AIX で10年以上にわたって使用)。
  • 元の設計目標: パフォーマンス, 堅牢性, SMP。
  • オリジナルの AIX の JFS のチームメンバーが開発・設計したファイルシステム。
  • SMP ハードウェアで動作するように作られ、最低でも4コアの SMP マシンを想定してコードを最適化済み。
  • (カーネル 3.7 から) TRIM をサポート。
ノート: JFS uses a journal to maintain consistency of metadata only. Thus, only consistency of metadata (and not actual file contents) can be assured in the case of improper shutdown. This is also the case for XFS and ReiserFS. Ext3, on the other hand, does support journaling of both metadata and data [4], though with a significant performance penalty, and not by default.

開発者の Steve Best による、JFS の特徴のもっと詳しい (技術的な) 解説が JFS Overview にあります。

GNU/Linux での実装

JFS ファイルシステムの実装は GNU/Linux の他のファイルシステムと同じように実装されています。JFS は Linux カーネルのバージョン 2.4 でマージされました [5]。JFS のドライバーは Arch の標準カーネルパッケージでモジュールとしてビルドされています。JFS ファイルシステムを使用するマシンでカスタムカーネルをビルドする場合、カーネルコンフィグで JFS を有効にしてください:

File systems
        ---> [*/M] JFS filesystem support

拡張属性を使う場合、"JFS POSIX Access Control Lists" や "JFS Security Labels" も有効にする必要があります:

File systems
    ---> [*/M] JFS filesystem support 
        ---> [*] JFS POSIX Access Control Lists
        ---> [*] JFS Security Labels

次に、ファイルシステム関連の作業をするために jfsutils パッケージが必要になります。

実際に JFS ファイルシステムを作成するには以下を実行します:

# mkfs.jfs /dev/target_dev

または:

# jfs_mkfs /dev/target_dev

どちらのコマンドも動作は同じです。

最適化

JFS ファイルシステムでは性能をブーストする複数の方法があります:

  • ファイルシステムの定期的なデフラグメンテーション。
  • deadline I/O スケジューラの使用。
  • 外部ジャーナルの利用。
  • /etc/fstab のファイルシステムに noatime 属性を付与。

JFS のデフラグメンテーション

他のファイルシステムと同じように、長い間使用しているとファイルの断片化が起こって JFS のパフォーマンスは劣化します [6]。JFS ユーティリティにはデフラグメンテーションのコードが存在しますが、このコードは OS/2 移植から持ち越されたもので手動で実行する必要があります [7]。暫くの間、ファイルシステムがオフライン状態になってもかまわない場合、以下のようなスクリプトを実行することで JFS ファイルシステムをデフラグできます。

警告: This script is dangerous and may result in the wiping of an entire hard disk, if arguments get switched! Doing this type of operation is only recommended for people who have confidence in doing backups and file system operations.
umount /dev/hdc1
dd bs=4k if=/dev/hdc1 of=/dev/hdj1
jfs_fsck /dev/hdj1
mount -o ro /dev/hdj1 /fs/hdj1
jfs_mkfs /dev/hdc1
mount -o rw /dev/hdc1 /fs/hdc1
(cd /fs/hdj1 && tar -cS -b8 --one -f - .) | (cd /fs/hdc1 && tar -xS -b8 -p -f -)
umount /dev/hdj1

上記の例では、/dev/hdc1 デバイスにあるデータを /dev/hdj1 デバイスにバックアップしています。

おおまかに言うと、上記のスクリプトは JFS ファイルシステムのデータをバックアップドライブにコピーして、元の JFS ファイルシステムをフォーマットしてからバックアップからデータを書き戻して、最終的に、新しくフォーマットされたドライブに非断片化されたアロケーションツリーを JFS で書き込みます。

警告: If a VMWare session is sitting on an underlying JFS partition that is highly fragmented, performance of the virtual machine may be significantly degraded.

Deadline I/O スケジューラ

カーネルが Deadline I/O Scheduler を使うように設定されているときに JFS はより良いパフォーマンスを発揮します。事実、このスケジューラを使えば他の GNU/Linux ファイルシステムよりも JFS のほうが高い性能を発揮できます [8]。Deadline I/O スケジューラを使用する方法は複数存在します。Deadline I/O スケジューラをデフォルトに設定してリコンパイルする方法が一つです:

Block layer
    ---> I/O Schedulers
        ---> [*] Deadline I/O scheduler
        ---> Default I/O scheduler (Deadline) --->

一般的な Arch パッケージのカーネルを使っている場合、カーネルコマンドラインに elevator=deadline を追加するか、あるいは同じ設定を /etc/default/grub に追加して grub-mkconfig -o /boot/grub/grub.cfg を実行することで永続的に設定できます。カーネルエントリは以下のようになります:

# (0) Arch 2.6.22
title   Arch Linux
root    (hd0,0)
kernel  /vmlinuz-linux root=/dev/sda3 elevator=deadline
initrd /initramfs-linux.img

以下のコマンドを実行することで、特定のデバイスで Deadline I/O スケジューラを有効にすることもできます:

echo deadline > /sys/block/sda/queue/scheduler 

上記のコマンドでは /dev/sda (物理デバイス全体) のデフォルトとして Deadline スケジューラが設定されます。

外部ジャーナル

警告: As this is a relatively new feature to the GNU/Linux port of JFS, it is recommended to upgrade to the very latest version of jfsutils before attempting to implement an external journal (earlier versions seem to give errors when trying to create the journal device).

他のジャーナリングファイルシステムと同じように、ディスクの活動に従ってジャーナルには断続的にアクセスが行われます。ファイルシステムと同じデバイスにジャーナルログを保存すると I/O スループットが低下してしまいます。ジャーナルログを別のデバイスに配置することでこのスループットの低下を軽くすることが可能です。

ジャーナルデバイスを作成するには、まず 128MB のパーティションを作成してください。128MB 以上のパーティションを使用しても、超過分は mkfs.jfs によって無視されます。以下のコマンドを実行することで既存の JFS ファイルシステムの外部ログを作成することができます:

# mkfs.jfs -J journal_dev /dev/external_journal             # creates a journal on device /dev/external_journal
# mkfs.jfs -J device=/dev/external_journal /dev/jfs_device  # attaches the external journal to the existing file 
                                                          #   system on /dev/jfs_device

もしくは新しい外部ジャーナルの作成と JFS ファイルシステムの作成を同時に実行することもできます:

# mkfs.jfs -j /dev/external_journal /dev/jfs_device

最後のコマンドは外部ジャーナルと JFS ファイルシステムの両方をフォーマットします。

ノート: Obviously, an external journal is only effective if the journal and its file system exists on separate physical devices.

noatime fstab 属性

大抵のファイルシステムではデフォルトで、ファイルにアクセス (読み取りまたは書き込み) するたびにファイルに関連付けられたメタデータのアクセス日時が更新されます。そのため、読み取り操作だけでもファイルシステムに書き込みを行うオーバーヘッドが発生します。場合によってパフォーマンスに大きな影響を与えることがあります。noatime を fstab の行に追加することで JFS ファイルシステムはアクセス日時の記録を止めます。アクセス日時は基本的にあまり重要ではないため、これはハードウェアのパフォーマンスを上げることができると広くうたわれています。Linus Torvalds もこの最適化の支持者です [9]

ノート:
  • One may also specify a relatime option which updates the atime if the previous atime is older than the mtime or ctime [10]. In terms of performance, this will not be as fast as the noatime mount option, but is useful if using applications that need to know when files were last read (like mutt).
  • Using the noatime/relatime option can improve disk performance with any file system, not just JFS.

noatime タグを付けた /etc/fstab エントリの例:

/dev/sdb1 /media/backup jfs rw,users,noauto,noatime 0  0

もしくは以下のようにして noatime 属性を付けてファイルシステムをマウントすることもできます:

# mount -o noatime -t jfs /dev/jfs_dev /mnt/jfs_fs
ノート: Access time is NOT the same as the last-modified time. Disabling access time will still enable you to see when files were last modified by a write operation.

ジャーナルモード

JFS は ext3 のように様々なジャーナルモードをサポートしているわけではありません。そのため、mount/etc/fstabdata=writeback マウントオプションを指定しても JFS ファイルシステムに影響はありません。JFS の現在のジャーナリングモードは ext3 のデフォルトのジャーナリングモードである ordered と似ています[11]

可変ブロックサイズ

JFS の OS/2 移植は 512, 1024, 2048, 4096 バイトのブロックサイズをサポートしていますが JFS の Linux 移植は 4k ブロックしか使用できません。JFS ユーティリティのコードでは可変サイズブロックを使用していますが、手動で実装する必要があります [12]。基本的にブロックサイズを大きくすると性能も向上します (ブロックサイズを小さくするとディスクの使用効率が上がります)。JFS 開発者による実装では Linux の JFS で小さいブロックサイズを使用することは優先度が低くなっていました。

fsck とリカバリ

電源が落ちる前にファイルシステムが正しくアンマウントされていなかった場合、再マウントする前に JFS ファイルシステムで fsck を実行する必要があります。ログにダメージがなければ、数秒程度しかかかりません。fsck を実行して謎のファイルシステムエラーが返ってきた場合、問題のデバイスで fsck.jfs を実行してみてください。通常は、fsck だけで十分です。

ファイルシステムのスーパーブロックが破壊された場合、ファイルシステムの一部を復元できる可能性があります。現在、復元することができるツールは jfsrec という名前のユーティリティだけです。JFSrec は AUR の jfsrec-svnAUR パッケージでインストールできます。

jfsrec という AUR パッケージも存在しますが、JFSrec の SVN の変更履歴は今のところ7回しかないので jfsrec-svn のプレースホルダにすぎません。インストールしたら以下を実行することでユーティリティの使用方法を説明するヘルプメニューが表示されます:

# jfsrec
警告: As stated above, JFSrec is only in its seventh SVN revision; and it is not known how actively the project is maintained. So use JFSrec with caution.

注意事項

JFS の今の開発状態はとても安定していますが、ファイルシステムの使用にあたっては注意事項がいくつかあります。

起動時に JFS root が読み取り専用でマウントされる

ときどき、JFS root パーティションが通常の読み書きモードでマウントできなくなることがあります。大抵はシャットダウンが正常に終了しなかったために JFS root ファイルシステムが fsck で引っかかっているのが原因です。fsck 以外で JFS が使えなくなるのは稀です。

この場合、比較的新しい Arch Linux LiveCD でマシンを起動する必要があります。Arch Linux livecd を起動すると JFS ユーティリティを使用して JFS ファイルシステムを認識できるカーネルがロードされます。CD の起動後 JFS root で fsck (もしくは fsck.jfs) を実行すればリカバリされます (おそらくログが破損しているために通常よりも fsck の実行時間は長くなります)。fsck が完了したら、通常通りにマシンを起動できるようになります。

ノート: This scenario happens less than 10% of the time in the case of an improper shutdown.

JFS と安全な削除

ノート: This section applies to any journaled file system, not just JFS.

(shred などのユーティリティを使って) ファイルシステムブロックをランダムなデータを上書きするだけではファイルが確実に削除される保証はありません [13]。ジャーナリングファイルシステムの設計では、メンテナンス性やパフォーマンスが優先されて、ファイルを安全に削除する方法はあまり優先されません。

JFS root ファイルシステムで強制的に fsck

以下を入力して再起動することで root ファイルで強制的に fsck ファイルシステムチェックを行うことができます:

touch /forcefsck

device-mapper の制御下にあるパーティションで JFS root を使っている Arch Linux 環境では (つまり root デバイスが lvm や LUKS 暗号化デバイスの場合)、fsck を強制的に実行すると /usr/man/man3 ディレクトリが削除されてしまうことがあります。この問題の原因は定かではありませんが、再現可能な問題です [14]

/usr/man/man3 を使用する Arch パッケージのリストを取得するには以下のようなコマンドを実行します:

find /var/lib/pacman/local/ -name files | xargs fgrep /man/man3/ | cut -d: -f1 | sort -u | awk -F/ '{print $6}' > man3_pkg_list

JFS root パーティションで強制的に fsck をする前に実行してみてください ([15] post #1)。/usr/man/man3 が消えてしまったら、man3_pkg_list に含まれているパッケージを全て再インストールしてください。

ノート: If this problem does indeed happen, reinstalling all the packages using /usr/man/man3 does appear to fix the issue ([16] post #4).

上述のとおり、今のところ問題の原因ははっきりしていませんが、パーティションの不適切なアンマウントによって JFS のログが破損した場合にファイルシステムのチェックを行うのと何か関係があるようです。

JFS でファイルが消失する

JFS では、メモリが少なくなったりアンマウント操作などを行わない限り、ジャーナルの書き込みは無期限に延期されます。クラッシュすると数分・数時間前に書き込んだデータも飛んでしまうことがあるので、この無期限の書き込み遅延は信頼性を損ねます [17]

ベンチマーク

ファイルシステムのパフォーマンスのベンチマークは特定の種類のディスク利用法に限られるため、他のファイルシステムと JFS を一般的に比較付けするのは簡単ではありません。先に書いたとおり、JFS は他の GNU/Linux ファイルシステムよりも (適切な最適化を行えば) CPU の使用量が少なくて、特定のファイル操作においては他の GNU/Linux ファイルシステムよりも高速だとされています。ただし、多数のファイルを扱うようなときは JFS は遅くなるとも言われています [18][19]。下の参照セクションにベンチマークのリンクがあります。といっても、自分の作業環境でテストして結果を確認するのが一番良いでしょう。

結論

JFS は安定していて機能豊富なファイルシステムですが、他の Linux ファイルシステムと比べると知名度が劣ります。最適化によって、JFS は安定でありながらも CPU の使用量が抑えられ高速に動作します。特に、VMWare セッションで (適切に最適化・デフラグされた) JFS ファイルシステムを使用すると多大な利益が得られる可能性があります。

参照