2.9. GFS2 のノードロック機能
GFS2 ファイルシステムでパフォーマンスを最適化するには、操作に関する基本的な理論をある程度理解しておくことが重要となります。単一ノードのファイルシステムはキャッシュと共に実装されます。キャッシュは、頻繁に要求されるデータを使用する場合にディスクへのアクセスの待ち時間をなくすことを目的としています。Linux では、ページキャッシュ (および以前のバッファーキャッシュ) により、このキャシング機能が提供されます。
GFS2 では各ノードに独自のページキャッシュがあり、ここにオンディスクデータの一部が含まれている場合があります。GFS2 は glocks (ジーロックスと発音) と呼ばれるロック機能のメカニズムを使用してノード間のキャッシュの整合性を維持します。glock サブシステムは、分散型ロックマネージャー (DLM) を下位の通信層として使用して実装される、キャッシュ管理機能を提供します。
glock は、inode ごとにキャッシュを保護するため、キャッシング層を制御するのに使用されるロックが各 inode に 1 つあります。glock が共有モード (DLM ロックモード: PR) で付与されると、その glock の下のデータは、同時に 1 つまたは複数のノードにキャッシュすることができるため、すべてのノードはそのデータへのローカルアクセスを有することができます。
glock が排他モード (DLM ロックモード: EX) で許可されると、単一ノードのみがその glock でデータをキャッシュできます。このモードは、データを修正するすべての操作で使用されます (write システムコールなど)。
別のノードが即時に許可できない glock を要求すると、DLM は、その glock 現在を保持している 1 つまたは複数のノードに、新しい要求をブロックしてロックを解除するように依頼するメッセージを送信します。glock の削除の処理は、(ほとんどのファイルシステム操作の標準では) 長くなる可能性があります。共有 glock を削除するには、キャッシュを無効にすることだけが必要となりますが、それは比較的速く、キャッシュされたデータの量に比例します。
排他的 glock を削除するには、ログをフラッシュして、変更されたデータをディスクに書き戻した後は、共有 glock と同様に無効化を行う必要があります。
単一ノードのファイルシステムと GFS2 の違いは、単一ノードのファイルシステムにはキャッシュが 1 つだけあり、GFS2 には各ノードに個別のキャッシュがあることです。どちらの場合も、キャッシュされたデータへのアクセスのレイテンシーの長さは同じようになりますが、別のノードが以前同じデータをキャッシュしていると、キャッシュされていないデータにアクセスする場合のレイテンシーは、GFS2 の方がかなり長くなります。
共有 glock を必要とするのは、
read
(バッファー付き)、stat
、readdir
などの操作のみです。排他的な glock を必要とするのは、write
(バッファー付き)、mkdir
、rmdir
、unlink
などの操作のみです。ダイレクト I/O の読み書き操作では、割り当てが行われていない場合は DF (deffered) 状態の glock が必要です。また、書き込みに割り合てが必要な場合は (つまりファイルの拡張または穴埋めには)、EX (exclusive) 状態の glock が必要です。
この場合、パフォーマンスに関する主な考慮事項が 2 つがあります。まず、読み込み専用操作は各ノードで独立して実行できるため、クラスター全体で並列処理が極めてよく機能します。次に、同じ inode へのアクセスを競うノードが複数あると、排他 glock を必要とする操作によりパフォーマンスが低下する場合があります。たとえば 「ファイルシステムのバックアップ」 の説明にあるように、ファイルシステムのバックアップを行う場合などには、各ノードのワーキングセットを考慮することが GFS2 ファイルシステムパフォーマンスにおいて重要です。
これに加え、GFS2 では可能な限り、
noatime
と nodiratime
マウントオプションを使用することが推奨されます。これにより、read が atime
タイムスタンプを更新する際に排他的なロックが必要なくなります。
ワーキングセットやキャッシング効率を懸念している場合でも、GFS2 では、GFS2 ファイルシステムのパフォーマンスを監視できる Performance Co-Pilot や GFS2 トレースポイントというツールを利用できます。これらはそれぞれ、付録A Performance Co-Pilot による GFS2 パフォーマンスの分析、付録B GFS2 トレースポイントおよび debugfs glocks ファイル で説明されています。
注記
GFS2 のキャッシング機能の実装方法により、次のいずれかの場合にパフォーマンスが最適となります。
- inode は全ノードにわたって読み取り専用で使用されます。
- inode は、1 つのノードからのみ書き込みまたは変更されます。
ファイルの作成中および削除中に、ディレクトリーにエントリーを挿入したりディレクトリーからエントリーを削除すると、ディレクトリーの inode への書き込みとしてカウントされます。
比較的頻度が低い場合は、このルールを無視できます。ただし、このルールを無視しすぎると、パフォーマンスが大幅に低下します。
読み書きのマッピングがある GFS2 のファイルに mmap() を行い、そこからのみ読み込む場合のみ、これは読み込みとしてのみカウントされます。GFS は書き込みとしてカウントされるため、GFS2 は mmap() I/O でスケーラビリティーがはるかに高くなります。
noatime
mount パラメーターを指定していない場合は、読み取りによって、ファイルのタイムスタンプを更新するための書き込みも発生します。すべての GFS2 ユーザーは、atime
に特定の要件がない限り、noatime
を使用してマウントすることが推奨されます。
2.9.1. POSIX ロックの問題
POSIX ロックを使用する場合は、以下の点を考慮する必要があります。
- flock を使用すると、POSIX ロックを使用するより処理が速くなります。
- GFS2 で Posix ロックを使っているプログラムは、
GETLK
の機能を使用しないようにする必要があります。これは、クラスター環境では、プロセス ID がクラスター内の別のノードに対するものである可能性があるためです。