要約

  • クライアントの回復完了宣言は、対象範囲でまだ回復していない古いロックを後から再要求する余地を閉じる。全クライアントの猶予期間を終わらせる指示ではない。
  • 自分の回復を終えた後でも、新しいロックの要求に猶予期間中のエラーが返ることがある。サーバーには、ほかの回復要求との衝突を避ける義務が残る。
  • ネットワーク分断と再起動が重なると、現在は空いているロックでも過去の連続性を認められない場合がある。永続的な回復記録が足りなければ、保守的な拒否が必要になる。

復旧会議で答えが食い違う理由

二つのクライアントが使っていたファイルサーバーが再起動し、ロック状態を失ったとする。一方はすぐ接続し直し、以前のオープン状態とバイト範囲ロックを回復する。もう一方はネットワーク障害で戻れない。先に戻った側の担当者は、復旧が終わったと報告できる。しかしサーバーの担当者には、まだ新しい仕事を無条件に受け付けられない理由がある。

遅れているクライアントが、以前持っていたロックを取り戻しに来るかもしれない。そこで先に新しい競合ロックを与えてしまえば、回復のために設けた機会が意味を失う。先着したクライアントの完了と、全体の受付再開は別の判断だ。

これは特定企業の障害事例ではなく、プロトコル上の状況を示す例である。RFC 8881の第8.4節、第9.11節、第18.51節を読むと、誰が何を終了できるかが明確になる。回復を終えたクライアントでも、新規ロックの取得時に NFS4ERR_GRACE を受け取る可能性がある。その二つの結果は矛盾しない。

古い状態を戻す操作には、別の意味がある

サーバーがロック状態を失ったとき、クライアントには以前の状態を再構成する機会が必要になる。猶予期間は、競合する新しい割当てにその機会を奪われないために設けられる。単に全員が起動するまで待つ休憩時間ではない。

既存のオープン状態を回復する操作は、CLAIM_PREVIOUS を指定した OPEN である。対象ファイルを現在のファイルハンドルで指定し、ディレクトリから新しい名前を開く操作とは区別する。バイト範囲ロックの回復には、reclaimを真とした LOCK を使う。

古い要求だと申告すれば、通常の権限確認を通らなくてよいわけではない。アクセス制御と競合条件は引き続き適用される。回復という目的は、持っていない権限を取得する抜け道ではない。

また、猶予期間中の要求がすべて止まるわけでもない。回復のためのクライアント識別子やセッションの確立は必要になる。後から来る回復要求と競合しないと確認できるだけの情報があれば、サーバーは新規ロックや読み書きを認められる場合がある。必要なのは一律の停止ではなく、後続の回復を無効にしない条件である。

完了宣言は、残った選択肢を手放す

クライアント全体の回復完了は、rca_one_fs を偽にした RECLAIM_COMPLETE で伝える。新しいクライアント識別子を確立した後は、以前のロックが一つもなくても、最初の新規ロック要求より先にこの宣言が必要になる。「戻すものがない」と「何も通知しなくてよい」は同じではない。

この通知には、進捗報告より重い効果がある。宣言の対象範囲でまだ回復されていない古いロックは、その後に再取得を求める資格を失う。同じ復旧中だけでなく、後のサーバーインスタンスや関連するサーバー移転後に持ち出して回復することもできない。

だからこそ、サーバーはその宣言を判断材料として使える。少なくとも、このクライアントから別の古い要求が追加される可能性を考え続けなくてよくなる。ただし、その確定は宣言者に限られる。まだ戻っていない相手の要求まで消えるわけではない。

操作には、移行に関連するファイルシステム単位の形式もある。そちらは現在のファイルハンドルを必要とし、新しいクライアント識別子に伴う全体の完了宣言を代用しない。対象の移行状態にないファイルシステムでは、成功を返しても、それ以外の作用をしない場合が仕様に定められている。本稿はサーバー再起動の回復を扱い、移行手順には踏み込まない。

戻ってきた人数だけでは、全員を数えられない

サーバーが、以前ロックを持っていた可能性のあるクライアントを安定した記録として保持していれば、誰の完了を確認すべきかが分かる。関係する全員が完了したと判断できれば、漫然と待つより早く猶予を終えられる。

反対に、接続し直したクライアントだけを数えても、不在者がいないとは証明できない。完了数を意味のある分母と結び付けるのが、再起動を越えて残る記録の役割だ。

サーバーは、全員が完了する前に猶予期間を終了することもある。ただし、好きな長さに短縮してよいわけではない。第8.4.2.1節はリース期間より早く終了しないことを推奨し、リース値の変更を論じる箇所では、以前のインスタンスのリース期間以上の猶予を要求している。すべての環境で同じ秒数を設定する規則に置き換えることはできない。

ここには、個別クライアントが果たす手続きと、サーバーが守る回復機会という二本の時間軸がある。片方の完了だけを見て、もう片方の待機を異常と決めつけると、正しく働いている保護を故障と取り違える。

空いているロックにも、失われた過去がある

さらに難しいのは、遅れたクライアント自身が、以前の保護が途切れていないと思い込む場合である。RFCは、ネットワーク分断によってリースを更新できなくなったクライアントを例にする。リースが切れてロックが解放され、別のクライアントが競合するロックを取得して作業し、解放する。その後にサーバーが再起動する。

分断が解消し、最初のクライアントが新しい猶予期間中に戻ってくる。この瞬間、現在のロック表には競合が見当たらないかもしれない。それでも古いロックの回復を認めるのは誤りになり得る。ほかのクライアントが対象を変更していれば、以前の保護が続いているという前提はすでに壊れている。

二度の再起動をまたぐ例もある。最初の猶予期間中に一部のロックを回復できず、その後に別のクライアントが競合ロックを使用する。再びサーバーが起動し直した後で元のクライアントが戻っても、新しい猶予期間は、前回の未完了を帳消しにはしない。

そのため、サーバーは二つの方法のいずれかを採る必要がある。すべての回復要求を NFS4ERR_NO_GRACE で拒否するか、再起動に関する既知の危険な条件を検出するだけの状態を安定したストレージに残すかである。より詳しい情報があれば認められた要求を、情報不足のため保守的に拒否することは許される。回復記録が修復不能に損なわれていれば、影響を受ける可能性のある要求は拒否しなければならない。

仕様に出てくる最小限のクライアント記録は、一つの実装例である。識別情報、未確認の取消し、以前の未完了の回復などを記録する考え方であって、全製品に同じデータベース構造を強いるものではない。履歴の精度が低いほど、寛容な回復を約束する根拠も弱くなる。

プロトコルの復旧は、業務の継続を決めない

回復を拒否された後、通常の要求で新しいロックを取れても、保護が途切れた間に誰も操作しなかったとは限らない。現在の取得成功は、過去の連続性を復元しない。

NFS4ERR_NO_GRACE を受けたクライアントの対応は、実行環境に依存すると仕様は述べる。対象の変更属性を調べ、通常のオープンやロック取得を検討する方法も示すが、環境の意味論に照らして可能な場合の選択肢である。あらゆるアプリケーションがそのまま処理を続けてよいという保証ではない。

公式の文書情報によれば、RFC 8881は2020年8月の標準化過程の文書で、RFC 5661を置き換える。正誤情報も確認した。取得した一覧に、本稿の中心となる三つの節を直接変更する訂正はないが、確認済みの訂正と報告段階の提案は区別する必要がある。仕様全体の無欠陥や、実製品の適合を確認したわけではない。

Lu Hengの代理関係を論じたNote 32は、決める側と損失を負担する側の関係を問う視点を与える。現実の記述を重視するNote 36は、仕組みの説明を善悪の物語に置き換えない姿勢を示す。ここでの技術的根拠はRFCであり、これらの筆記は編集上の視点である。特定の事業者の動機を実証した資料として扱ってはならない。