JFS

提供: ArchWiki
2015年11月27日 (金) 20:32時点における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).

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.

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

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].

ノート:
  • 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.

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
ノート: 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 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.

警告: 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.

注意事項

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.

ノート: 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.

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.

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

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.

参照