2.9. GFS2 のノードロック機能

GFS2 ファイルシステムでパフォーマンスを最適化するには、操作に関する基本的な理論をある程度理解しておくことが重要となります。単一ノードファイルシステムはキャッシュと共に実装され、頻繁に要求されるデータを使用する場合にディスクへのアクセスの待ち時間をなくすことを目的としています。Linux では、ページキャッシュ (および以前はバッファーキャッシュ) によりこのキャシング機能が提供されます。
GFS2 では各ノードに独自のページキャッシュがあり、オンディスクデータの一部が含まれていることがあります。 GFS2 は glocks (ジーロックスと発音) と呼ばれるロック機能のメカニズムを使用してノード間のキャッシュの整合性を維持します。glock サブシステムは、分散型ロックマネージャー (DLM) を下位の通信層として使用して実装される、キャッシュ管理機能を提供します。
glocks では、inode ごとにキャッシュの保護が提供されるため、ロックは 1 inode あたり 1 つとなり、キャッシング層の制御に使用されます。この glock が共有モード (DML ロックモード: PR) で許可されると、その glock 配下のデータは 1 ノードまたは複数のノードに同時にキャッシュすることができるため、全ノードがそのデータにローカルでアクセスできるようになります。
glock が排他モード (DLM ロックモード: EX) で許可された場合、その glock 配下では単一のノードしかデータをキャッシュすることができなくなります。このモードは、データを修正するすべての操作で使用されます (write システムコールなど)。
別のノードが即時に許可できない glock を要求した場合、DLM はそのノードまたは新規の要求をブロックしている glock を現在保持しているノードにメッセージを送り、ロックを削除するように要求します。glock を削除するプロセスは時間がかかる場合があります (大半のファイルシステム操作の基準で判断した場合)。共有 glock を削除する場合に必要となるのは、キャッシュの無効化のみで、比較的短時間で完了し、キャッシュされたデータ量に比例します。
排他的 glock を削除するには、ログをフラッシュして、変更されたデータをディスクに書き戻した後、共有 glock と同様に無効化を行う必要があります。
単一ノードファイルシステムと GFS2 で異なるのは、単一ノードファイルシステムのキャッシュは一つであるのに対して、GFS2 にはノードごとに別個のキャッシュがある点です。いずれの場合も、キャッシュ済みデータへのアクセスの待ち時間は同じ程度ですが、キャッシュされていないデータへのアクセスに関しては、別のノードが以前に同じデータをキャッシュしていた場合、GFS2 の方がはるかに長くなります。
共有 glock を必要とするのは、read (バッファ付き)、 statreaddir などの操作のみです。排他的な glock を必要とするのはwrite (バッファ付き)、 mkdirrmdirunlink などの操作のみです。ダイレクト I/O の読み書き操作には、割り当てが行われていないくても DF (deffered) 状態の glock が必要です。または、書き込みに割り合てが必要な場合は、EX (exclusive) 状態の glock が必要です。
この場合、パフォーマンスについて 2 つ主なことを考慮する必要があります。まず、読み込み専用操作は各ノード上で独立して実行されるため、クラスターにわたり非常にうまく並列処理できます。次に、同じ inode へのアクセスを奪い合うノードが複数ある場合は、EX 状態の glock を必要とする操作によってパフォーマンスが低下することがあります。例えば 「ファイルシステムのバックアップ」の説明にあるように、ファイルシステムのバックアップを行う場合などには、各ノードのワーキングセットを考慮することがGFS2 ファイルシステムパフォーマンスにおいて重要です。
これに加え、GFS2 では可能な限り、noatimenodiratime マウントオプションを使用することが推奨されます。これにより、read が atime タイムスタンプを更新するために排他的なロックを必要としなくなります。
ワーキングセットやキャッシング効率を懸念している場合でも、GFS2 では、GFS2 ファイルシステムのパフォーマンスを監視できる Performance Co-Pilot や GFS2 トレースポイントというツールを利用できます。これらはそれぞれ、付録A Performance Co-Pilot による GFS2 パフォーマンスの分析付録B GFS2 トレースポイントおよび debugfs glocks ファイル で説明されています。

注記

GFS2 のキャッシング機能の実装方法により、次のいずれかの場合にパフォーマンスが最適となります。
  • inode は全ノードにわたって読み取り専用で使用されます。
  • inode が単一ノードからのみ書き込みまたは修正される
ファイル作成時および削除時に行われるディレクトリーへのエントリの挿入や削除は、ディレクトリー inode への書き込みと見なされる点に注意してください。
このルールを違反することは可能ですが、比較的頻度が低いことが条件となります。このルールを無視しすぎるとパフォーマンスに深刻な影響を及ぼすことになります。
読み込み/書き込みのマッピングを用いて GFS2 上のファイルを mmap() しても、読み取りしか行わない場合は、読み取りのみと見なされますが、GFS 上では書き込みとして見なされるため、mmap() I/O では、GFS2 の方が拡張性がはるかに高くなります。
noatime mount パラメーターを指定していない場合は、読み取りによって、ファイルのタイムスタンプを更新するための書き込みも発生します。GFS2 を使用する場合、atime を特に必要としない限りは、noatime を指定してマウントすることを推奨します。

2.9.1. POSIX ロックの問題

POSIX ロックを使用する場合、以下の点を考慮する必要があります。
  • フロックを使用すると、POSIX ロックを使用するより処理が早い
  • クラスター環境では指定のプロセス ID が別のノード用である場合もあるため、GFS2 で POSIX ロックを使用するプログラムは、GETLK 関数の使用を避けるべきです。

2.9.2. GFS2 によるパフォーマンスチューニング

通常は、問題を引き起こすアプリケーションのデータ格納方法を変更すると、パフォーマンスを大幅に向上させることができます。
問題を引き起こすアプリケーションの典型的な例が Email サーバーです。各ユーザー用ファイルを含むスプールディレクトリー (mbox)、または各メッセージ用のファイルを格納する各ユーザー用のディレクトリー (maildir) などで構成されているのが一般的です。IMAP 経由で要求が到着した場合、特定のノードに対するアフィニティーを各ユーザーに提供するのが理想的な設定となります。 これにより、Email メッセージの表示と削除の要求は、その単一ノードのキャッシュから提供される傾向になります。そのノードに障害が発生した場合は、当然、別のノードでセッションを再起動させることができます。
メールが SMTP 経由で到着した場合も、デフォルトで特定のユーザーのメールが特定のノードに渡されるようノードを個別に設定することが可能です。デフォルトのノードが稼働していない場合、メッセージは受信ノードによりユーザーのメールスプールに直接保存されます。これも、通常の場合は特定のファイルセットが単一のノードにキャッシュされ、そのノードの障害時には直接アクセスができるようにすることを目的として設計されています。
この設定により GFS2 のページキャッシュを最大限に活用し、imap または smtp にかかわらず、アプリケーションに対して障害の発生を透過的にすることができます。
バックアップは、難しいことが多いもう一つの領域です。可能であれば、特定の inode セットをキャッシュしているノードから直接、各ノードの作業セットをバックアップしておくことを強く推奨します。定時に実行するバックアップスクリプトを使用していて、それが GFS2 で実行しているアプリケーションの応答時間の急増と同時に発生している場合には、クラスターがページキャッシュを効率的に使用していない可能性が高くなります。
当然ながら、バックアップを実行するためにアプリケーションを停止することができるような優位な立場にある場合は問題はありません。しかし、バックアップが 1 つのノードだけで実行される場合は、そのバックアップが完了するとファイルシステムの大部分がそのノードにキャッシュされ、他のノードからアクセスする際のパフォーマンスが低下します。この問題は、次のコマンドでバックアップ完了後にバックアップノードにある VFS ページキャッシュを削除することにより、ある程度軽減することができます。
echo -n 3 >/proc/sys/vm/drop_caches
ただし、この方法は、各ノードの作業セットが、大半は読み取り専用としてクラスター全体で共有される、もしくは大部分が単一のノードからアクセスされるかのいずれかとなるように注意するほどは、よい解決策ではありません。

2.9.3. GFS2 ロックダンプを使用した GFS2 パフォーマンスのトラブルシューティング

GFS2 キャシングの使用効率が悪いためにクラスターのパフォーマンスが影響を受けている場合、I/O の待機時間が長く延長される可能性があります。GFS2 のロックダンプ情報を利用すると、この問題の原因を究明することができます。
本セクションには、GFS2 ロックダンプの概要を記載しています。GFS2 ロックダンプについての詳しい説明は、付録B GFS2 トレースポイントおよび debugfs glocks ファイル を参照してください。
GFS2 ロックダンプ情報は debugfs ファイルから収集することができます。このファイルのパス名は以下のとおりです (debugfs/sys/kernel/debug/ にマウントされていることが前提です)。
/sys/kernel/debug/gfs2/fsname/glocks
ファイルの内容は、一連の行から構成されています。G: で始まる行は、それぞれひとつの glock を表し、その下の 1 文字分字下げしてある行はファイル内の直前の行の glock に関連する情報アイテムを表しています。
debugfs ファイルの最適な使用方法は、アプリケーションに問題の発生中に cat コマンドを使ってファイルの全内容のコピーをとり (RAM が大容量で、かつキャッシュされた inode が多数ある場合には長時間がかかる可能性があります)、後日に結果データを確認する方法です。

注記

debugfs ファイルのコピーを 2 つ作成すると、役に立つことがあります (2 つ目のコピーを最初のコピーの数秒後または数分後に作成します)。同じ glock 番号に関連する 2 つのトレースでホルダー情報を比較すると、ワークロードが処理されているか (単に処理速度が遅い)、または処理が停止しているか (この場合は必ずバグであり、Red Hat サポートに直ちに報告してください) がわかります。
debugfs ファイルの H: (ホルダー) で始まる行は、承認済みまたは承認待機中のロック要求を表します。ホルダー行のフラグフィールド f: には、待機中の要求を示す「W」フラグ、または承認済み要求を示す「H」フラグが表示されます。待機中の要求が多数ある glocks は特定の競合が発生している可能性が高くなります。
各 glock フラグの意味は 表2.1「glock フラグ」 に、また各 glock ホルダーフラグの意味は 表2.2「Glock ホルダーフラグ」 にまとめています。

表2.1 glock フラグ

フラグ名前意味
bBlockingロックされたフラグが設定されている場合に有効であり、DLM から要求された操作がブロックされる可能性があることを示します。このフラグは、降格の操作と「try」ロックに対して消去されます。このフラグの目的は、ロックを降格するために他のノードでかかる時間とは別の DLM 応答時間に関する統計情報の収集を許可することです。
dPending demote遅延された (リモートの) 降格要求
DDemote降格要求 (ローカルまたはリモート)
fLog flushこの glock を解放する前にログをコミットする必要があります
FFrozenリモートノードからの返信が無視されます (復元は進行中)。このフラグは、異なるメカニズムを使用するファイルシステムのフリーズとは関係がなく、復元中にしか使用されません。
iInvalidate in progressこの glock のページの無効化が進行中です
IInitialDLM がこの glock と関連付けられる場合に指定します
lLockedglock は状態の変更中です
LLRUglock が LRU リストにあるときに設定されます
oオブジェクトglock がオブジェクト (タイプ 2 glock の場合は inode、タイプ 3 glock の場合はリソースグループ) に関連付けられた場合に設定されます。
pDemote in progressglock は降格要求に応答中です
qキュー待ちglock に対してホルダーがキューに格納された場合に設定され、glock が保持された場合に消去されます (ただし、残りのホルダーはありません)。glock の最小保持時間を計算するアルゴリズムの一部として使用されます。
rReply pendingリモートノードから受信した返信の処理の待機中です
yDirtyこの glock を解放する前にデータをディスクにフラッシュする必要があります

表2.2 Glock ホルダーフラグ

フラグ名前意味
aAsyncglock の結果を待ちません (結果を後でポールします)
AAny互換性のあるロックモードはすべて受け入れ可能です
cNo cacheロック解除時に DLM ロックを即時に降格します
eNo expire後続のロック取り消し要求を無視します
Eexact完全一致するロックモードでなければなりません
FFirstホルダーがこのロックに最初に許可される場合に指定します
HHolder要求したロックが許可されたことを示します
pPriorityキューの先頭にある待機ホルダー
tTry「try」ロックです
TTry 1CBコールバックを送信する「try」ロックです
WWait要求完了の待機中にセットされます
問題の原因となっている glock を特定したら、次はそれに関連している inode を見つけます。これは、glock 番号 (G: 行にある n:) に示されています。 type/number の形式で記載されており、type が 2 の場合は glock は inode glock で number は inode 番号になります。 find -inum number のコマンドを実行すると、inode をトラッキングすることができます。glocks ファイルにある 16 進形式から 10 進形式に変換した inode 番号が number になります。

警告

ロックの競合が発生しているときにファイルシステムで find を実行すると、事態が悪化する可能性が高くなります。競合している inode を探している場合は、まずアプリケーションを停止してから find を実行することが推奨されます。
表2.3「glock のタイプ」 には、異なる glock のタイプの意味をまとめています。

表2.3 glock のタイプ

タイプ番号ロックタイプ用途
1Transトランザクションのロック
2InodeInode のメタデータとデータ
3Rgrpリソースグループのメタデータ
4Metaスーパーブロック
5Iopen最後に inode をクローズしたプロセスの検出
6Flockflock(2) syscall
8Quotaクォータ操作
9Journalジャーナルミューテックス
特定された glock が異なるタイプだった場合に、最も可能性が高いのはタイプ 3: (リソースグループ) です。通常の負荷であるときに別のタイプの glock を待機しているプロセスが大量にある場合は、Red Hat サポートにご報告ください。
リソースグループロックのキューに格納された待機要求が複数ある場合は、この状況に対して複数の理由があることが考えられます。その 1 つの理由は、ファイルシステム内のリソースグループの数よりもノード数が多いことです。別の理由は、ファイルシステムがほぼ完全に満杯であることです (平均すると空きブロックの検索に時間がかかる)。いずれの状況も、ストレージを追加し gfs2_grow コマンドを使用してファイルシステムを拡張することで改善することができます。