JFS
関連記事
この記事では 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 をベースにした移植です。
JFS と UNIX や UNIX ライクなオペレーティングシステムの他のファイルシステムを一概に比較するのは難しいですが、JFS は他の GNU/Linux ファイルシステムよりも CPU の使用量が少ないと謳われています [2]。最適化を使うことで、特定のファイル操作で、他の GNU/Linux ファイルシステムと比べて、JFS は高速に動作するとも言われています ([3], ベンチマークを参照)。
GNU/Linux 開発チーム
GNU/Linux の JFS 移植の開発を率いているのは:
- Dave Kleikamp (dave dot kleikamp at oracle dot com)
- HP: http://jfs.sourceforge.net/
技術的な特徴
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 をサポート。
開発者の 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 ファイルシステムをデフラグできます。
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 で書き込みます。
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 with any journaled file system, a journal is constantly accessed in accordance with disk activity. Having the journal log on the same device as the its corresponding file system thus can cause a degradation in I/O throughput. This degradation can be alleviated by putting the journal log on a separate device all together.
To make a journal device, first create a partition that is 128MB. Using a partition that is bigger than 128MB results in the excess being ignored, according to mkfs.jfs. You can either create an external log for an already-existing JFS file system by executing the following:
# 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
or a command can be issued to create both a new external journal and its corresponding JFS file system:
# mkfs.jfs -j /dev/external_journal /dev/jfs_device
This last command formats BOTH the external journal and the JFS file system.
noatime fstab 属性
Every time a file is accessed (read or write) the default for most file systems is to append the metadata associated with that file with an updated access time. Thus, even read operations incur an overhead associated with a write to the file system. This can lead to a significant degradation in performance in some usage scenarios. Appending noatime to the fstab line for a JFS file system stops this action from happening. As access time is of little importance in most scenarios, this alteration has been widely touted as a fast and easy way to get a performance boost out of one's hardware. Even Linus Torvalds seems to be a proponent of this optimization [9].
Here is an example /etc/fstab
entry with the noatime tag:
/dev/sdb1 /media/backup jfs rw,users,noauto,noatime 0 0
One may also mount a file system with the noatime attribute by invoking something similar to the following:
# mount -o noatime -t jfs /dev/jfs_dev /mnt/jfs_fs
ジャーナルモード
JFS does not support various journal modes like ext3. Thus, passing the mount option data=writeback with mount or in /etc/fstab
will have no effect on a JFS file system. JFS's current journaling mode is similar to Ext3's default journaling mode: ordered [11].
可変ブロックサイズ
While the OS/2 port of JFS supports block sizes of 512, 1024, 2048, and 4096 bytes, the Linux port of JFS is only able to use 4k blocks. Even though code exists in JFS utilities that correspond to file systems using variable size blocks, this has yet to be implemented [12]. As larger block sizes tend to favor performance (smaller ones favor efficient space usage), implementing smaller block sizes for JFS in Linux has been given a low priority for implementation by JFS developers.
fsck とリカバリ
In the event that the file system does not get properly unmounted before being powered down, one will usually have to run fsck on a JFS file system in order to be able to remount it. This procedure usually only takes a few seconds, unless the log has been damaged. If running fsck returns an unrecognized file system error, try running fsck.jfs on the target device. Normally, fsck is all that is needed.
If the superblock on your file system gets destroyed, it may be possible to recover some parts of the file system. Currently, the only tool able to do this is a utility called jfsrec. JFSrec is currently available from the AUR using the jfsrec-svnAUR package.
There is also an AUR package called jfsrec, but this is merely a placeholder for jfsrec-svn as JFSrec is currently only in its seventh SVN revision. Once installed, one simply need to type:
# jfsrec
to get a help menu explaining how to use this utility.
注意事項
While JFS is very stable in its current stage of development, there are some cautionary notes on using this file system.
起動時に JFS root が読み取り専用でマウントされる
Occasionally, a JFS root partition will be unable to mount in normal read-write mode. This is usually due to the fact that the JFS root file system fails its fsck after an unclean shutdown. It is rare that JFS fails out of fsck, and it's usually due to the JFS log itself being corrupted.
All that is required in this scenario is to boot your machine with a relatively recent Arch Linux LiveCD. Booting an Arch Linux livecd will give you access to all the JFS utilities and will load a kernel that is able to recognize JFS file systems. After booting the CD simply run fsck (or possibly fsck.jfs) on your JFS root and it should recover just fine (even though the fsck will probably take longer than normal due to the log probably being damaged). Once the fsck finishes, you should be able to boot your machine like normal.
JFS と安全な削除
The effectiveness of deleting files by overwriting their corresponding file system blocks with random data (i.e. using utilities like shred) can not be assured [13]. Given the design of journaled file systems, maintenance issues, and performance liabilities; reliable shredding of files as a deletion method does not sit highly on the priority list for implementation on any journaled file system.
JFS root ファイルシステムで強制的に fsck
One may force a fsck file system check on the root file system by entering:
touch /forcefsck
and rebooting. On Arch linux systems with a JFS root on a partition under control of device-mapper (i.e. the root device is a lvm or a LUKS encrypted one), forcing an fsck can sometimes remove the /usr/man/man3 directory. The reason for this issue is not clear, but the problem has been able to be replicated [14].
It is suggested to get a list of Arch Packages that use /usr/man/man3
by issuing a command similar to
find /var/lib/pacman/local/ -name files | xargs fgrep /man/man3/ | cut -d: -f1 | sort -u | awk -F/ '{print $6}' > man3_pkg_list
before attempting a forced fsck on a JFS root partition ([15] post #1). If /usr/man/man3
does indeed disappear, simply reinstall all the packages listed in man3_pkg_list.
As stated above, the reason for this issue isn't clear at the moment; but it may have something to do with the fact that a forced fsck runs through higher phases of file system checks that only happen when a JFS log gets damaged in an improper dismounting of the partition.
JFS でファイルが消失する
In JFS; journal writes are indefinitely postponed until there is another trigger such as memory pressure or an unmount operation. This infinite write delay limits reliability, as a crash can result in data loss even for data that was written minutes or hours before.[17]
ベンチマーク
As benchmarks measuring file system performance tend to be focused at specific types of disk usage, it is difficult to decipher good general comparisons rating how well JFS performs against other files systems. As mentioned before, it has been noted that JFS has a tendency to use less CPU resources than other GNU/Linux file systems and (with the right optimizations) is faster than other GNU/Linux file systems for certain types of file operations. It has been noted that JFS slows down when working with many files, however[18][19]. In the references are some links to benchmarks; but as always, it is best to test and see what works best for your own system and work load.
結論
JFS is a stable, feature-rich file system that hasn't been publicized as much as some of the other Linux file systems. With optimizations, JFS is stable, CPU efficient and fast. In particular, VMWare sessions stand to benefit enormously from a properly optimized and defragmented, underlying JFS file system.
参照
- A more technical overview of JFS
- 30 days with JFS
- JFS Sourceforge page
- Note on defragmenting JFS file systems
- JFS Recovery Sourceforge page
- Presentation on JFS given by Steve Best (pdf)
- Debian file system comparison
- Wikipedia:JFS (file system)
- Some filesystem benchmarks