1. 序論 (Introduction)
Sunの NFSプロトコル (NFS Protocol) は、ネットワーク全体で共有ファイルシステムへの透過的なリモートアクセスを提供します。NFSプロトコルは、マシン、オペレーティングシステム、ネットワークアーキテクチャ、トランスポートプロトコルから独立するように設計されています。この独立性は、外部データ表現 (eXternal Data Representation, XDR) の上に構築されたリモートプロシージャコール (Remote Procedure Call, RPC) プリミティブを使用することで実現されます。NFSバージョン2プロトコルの実装は、パーソナルコンピュータからスーパーコンピュータまで、さまざまなマシンに存在します。NFSプロトコルの初期バージョンは、Network File System Protocol Specification [RFC1094] で規定されています。初期実装の説明は [Sandberg] にあります。
サポートする MOUNT プロトコルは、クライアントがリモートディレクトリツリーをローカルファイルシステム内のポイントにアタッチすることを可能にする、オペレーティングシステム固有の機能を実行します。マウントプロセスは、エクスポート制御を介して、制限されたクライアントセットにリモートアクセス権限を付与することもサーバーに許可します。
ロックマネージャ (Lock Manager) は、NFS環境で使用される場合にファイルロックのサポートを提供します。Network Lock Manager (NLM) プロトコルは、ファイルロックの本質的にステートフルな側面を別のプロトコルに分離します。
上記のプロトコルとその実装の完全な説明は [X/OpenNFS] にあります。
このドキュメントの目的は:
-
NFSバージョン3プロトコルを規定すること。
-
アノテーションと意図された実装の説明を通じてプロトコルのセマンティクスを記述すること。
-
MOUNTバージョン3プロトコルを規定すること。
-
NLMバージョン3プロトコルとNLMバージョン4プロトコル間の変更を簡単に説明すること。
規範的テキストは、RPCプロシージャとその引数および結果の記述であり、これはオーバーザワイヤプロトコル (over-the-wire protocol) とこれらのプロシージャのセマンティクスを定義します。実装実践を記述する資料は、プロトコル仕様の理解を助け、いくつかの可能な実装の問題と解決策を説明します。すべての実装を記述することは不可能であるため、NFSバージョン3プロトコルのUNIXオペレーティングシステム実装が例を提供するために最もよく使用されます。このため、実装の議論は、オーバーザワイヤプロトコルの記述自体の権威を持ちません。
1.1 NFSバージョン3プロトコルの範囲 (Scope of the NFS version 3 protocol)
このNFSプロトコルの改訂は、新しい要件に対処します。より大きなファイルとファイルシステムをサポートする必要性により、64ビットファイルサイズとオフセットを許可する拡張が促されました。この改訂は、サーバー上でアクセスチェックを実行するサポートを追加することでセキュリティを強化します。パフォーマンスの変更は3つのタイプがあります:
-
特定のファイル操作セットのオーバーザワイヤパケット数は、すべての操作でファイル属性を返すことで削減され、変更された属性を取得する呼び出し数が減少します。
-
NFSバージョン2プロトコルでの書き込みの同期定義によって引き起こされる書き込みスループットのボトルネックは、NFSサーバーが安全でない書き込み (unsafe writes) を実行できるようにサポートを追加することで対処されました。安全でない書き込みとは、操作が返される前に安定したストレージにコミットされていない書き込みです。この仕様は、これらの安全でない書き込みを信頼性の高い方法で安定したストレージにコミットする方法を定義します。
-
転送サイズの制限が緩和されました。
RPCでプロトコルの複数バージョンをサポートする機能により、NFSバージョン3プロトコルの実装者は、既存のNFSバージョン2プロトコル実装の基盤と下位互換性を提供するクライアントとサーバーを定義できます。
ここで説明する拡張は、既存のNFSプロトコルの進化を表しており、[Sandberg] で説明されているNFSプロトコルの設計機能のほとんどは維持されています。この改訂で導入された変更の詳細な要約については、11ページの「NFSバージョン2プロトコルからの変更」を参照してください。
1.2 有用な用語 (Useful terms)
この仕様では、"サーバー (server)" はネットワークにリソースを提供するマシンです; "クライアント (client)" はネットワーク経由でリソースにアクセスするマシンです; "ユーザー (user)" はクライアントにログインしている人です; "アプリケーション (application)" はクライアント上で実行されるプログラムです。
1.3 リモートプロシージャコール (Remote Procedure Call)
Sun Remote Procedure Call仕様は、リモートサービスへのプロシージャ指向インターフェースを提供します。各サーバーはプログラム、つまりプロシージャのセットを提供します。NFSサービスはそのようなプログラムの1つです。ホストアドレス、プログラム番号、バージョン番号、プロシージャ番号の組み合わせが1つのリモートサービスプロシージャを指定します。サーバーは、異なるプロトコルバージョン番号を使用することで、プログラムの複数のバージョンをサポートできます。
NFSプロトコルは、下位レベルから特定のレベルの信頼性を必要としないように設計されているため、多くの基礎となるトランスポートプロトコルで使用される可能性があります。NFSサービスはRPCに基づいており、これは下位レベルのネットワークおよびトランスポートプロトコルの上に抽象化を提供します。
このドキュメントの残りの部分は、NFS環境がSun RPCの上に実装されていることを前提としています。Sun RPCは [RFC1057] で規定されています。完全な議論は [Corbin] にあります。
1.4 外部データ表現 (External Data Representation)
外部データ表現 (eXternal Data Representation, XDR) 仕様は、ネットワーク上でデータ型のセットを表現する標準的な方法を提供します。これにより、異なる通信マシン間でのバイトオーダー、構造体アラインメント、データ型表現の違いの問題が解決されます。
このドキュメントでは、RPCデータ記述言語 (RPC Data Description Language) を使用して、NFSサーバーが提供する各RPCサービスプロシージャのXDR形式パラメータと結果を指定します。RPCデータ記述言語は、Cプログラミング言語の宣言に似ています。いくつかの新しい構造が追加されています。表記:
string name[SIZE];
string data<DSIZE>;
は、name を定義します。これはSIZEバイトの固定サイズブロックであり、data は最大DSIZEバイトの可変サイズブロックです。この表記は、固定長配列と固定最大値までの可変数の要素を持つ配列を示します。サイズが指定されていない可変長定義は、フィールドに最大サイズがないことを意味します。
判別共用体 (discriminated union) の定義:
union example switch (enum status) {
case OK:
struct {
filename file1;
filename file2;
integer count;
}
case ERROR:
struct {
errstat error;
integer errno;
}
default:
void;
}
は、ネットワーク上の最初のものがstatusという列挙型である構造を定義します。statusの値がOKの場合、ネットワーク上の次のものはfile1、file2、countを含む構造になります。そうでなく、statusの値がERRORの場合、ネットワーク上の次のものはerrorとerrnoを含む構造になります。statusの値がOKでもERRORでもない場合、構造にはそれ以上のデータはありません。
XDR型 hyper は8バイト (64ビット) の量です。整数型と同じ方法で使用されます。例えば:
hyper foo;
unsigned hyper bar;
fooは8バイトの符号付き値であり、barは8バイトの符号なし値です。
RPCデータ記述言語入力からクライアントとサーバースタブを生成するRPC/XDRコンパイラが存在しますが、NFS実装ではそれらの使用は必要ありません。XDRで定義されたデータの正規ネットワーク順序と同等のエンコードとデコードを提供するソフトウェアは、他のNFS実装と相互運用するために使用できます。
XDRは [RFC1014] で説明されています。
1.5 認証と権限チェック (Authentication and Permission Checking)
RPCプロトコルには、すべての呼び出しで認証パラメータのスロットが含まれています。認証パラメータの内容は、サーバーとクライアントが使用する認証のタイプによって決定されます。サーバーは、複数の異なる認証フレーバーを同時にサポートできます。AUTH_NONEフレーバーはヌル認証を提供します。つまり、認証情報は渡されません。AUTH_UNIXフレーバーは、各呼び出しでUNIXスタイルのユーザーID、グループID、およびグループを提供します。AUTH_DESフレーバーは、ネットワーク全体の名前に基づくDES暗号化認証パラメータを提供し、公開鍵スキームを介してセッション鍵を交換します。AUTH_KERBフレーバーは、Kerberos秘密鍵を介してセッション鍵を交換するネットワーク全体の名前に基づくDES暗号化認証パラメータを提供します。
NFSサーバーは、各リモート要求のRPC認証情報から資格情報を取得して権限をチェックします。例えば、AUTH_UNIXフレーバーの認証を使用して、サーバーは各呼び出しでユーザーの有効ユーザーID、有効グループID、およびグループを取得し、それらを使用してアクセスをチェックします。ユーザーIDとグループIDを使用することは、クライアントとサーバーが同じIDリストを共有するか、ローカルユーザーおよびグループIDマッピングを実行することを意味します。一貫したユーザーIDとグループIDスペースを実装していないサイトの場合、サーバーとクライアントは、ユーザーからuidへ、グループからgidへのマッピングについて合意する必要があります。実際には、このようなマッピングは通常、静的マッピングスキームまたはマウント時にクライアントからユーザーによって確立されたマッピングに従って、サーバー上で実行されます。
AUTH_DESおよびAUTH_KERBスタイルの認証は、ネットワーク全体の名前に基づいています。AUTH_DESの場合はDES暗号化と公開鍵の使用により、AUTH_KERBの場合はDES暗号化とKerberos秘密鍵 (およびチケット) により、より高いセキュリティを提供します。繰り返しますが、サーバーとクライアントは、ネットワーク上の特定の名前のアイデンティティについて合意する必要がありますが、名前からアイデンティティへのマッピングは、AUTH_UNIXのuidとgidマッピングよりもオペレーティングシステムに依存しません。また、認証パラメータが暗号化されているため、悪意のあるユーザーがそのユーザーになりすますには、別のユーザーのネットワークパスワードまたは秘密鍵を知っている必要があります。同様に、サーバーが返すベリファイアも暗号化されているため、サーバーになりすますにはネットワークパスワードを知っている必要があります。
NULLプロシージャは通常、認証を必要としません。
1.6 設計哲学 (Philosophy)
この仕様は、NFSバージョン3プロトコル、つまりクライアントがサーバーにアクセスするオーバーザワイヤプロトコルを定義します。プロトコルは、サーバーのファイルリソースへの明確に定義されたインターフェースを提供します。クライアントまたはサーバーはプロトコルを実装し、ローカルファイルシステムのセマンティクスとアクションをNFSバージョン3プロトコルで定義されたものへのマッピングを提供します。実装は、特定の環境がNFSバージョン3プロトコルで定義されたすべての操作とセマンティクスをサポートできる程度に応じて、さまざまな程度で異なる場合があります。実装が存在し、NFSバージョン3プロトコルのさまざまな側面を説明するために使用されますが、プロトコル仕様自体がクライアントがサーバーリソースにアクセスする方法の最終的な記述です。
NFSバージョン3プロトコルはオペレーティングシステムに依存しないように設計されているため、必ずしも既存のシステムのセマンティクスと一致するわけではありません。サーバー実装は、プロトコルをサポートするために最善を尽くすことが期待されます。サーバーが特定のプロトコルプロシージャをサポートできない場合、操作がサポートされていないことを示すエラーNFS3ERR_NOTSUPを返すことができます。例えば、多くのオペレーティングシステムはハードリンクの概念をサポートしていません。ハードリンクをサポートできないサーバーは、LINK要求に対してNFS3ERR_NOTSUPを返す必要があります。FSINFOは、プロパティビットマップで最も一般的にサポートされていないプロシージャを記述します。あるいは、サーバーは特定の操作をネイティブにサポートしていない場合がありますが、より大きな機能を提供するためにNFSバージョン3プロトコル実装でエミュレートできます。
場合によっては、サーバーはプロトコルで説明されているセマンティクスのほとんどをサポートできますが、すべてではありません。例えば、fattr構造のctimeフィールドは、ファイルの属性が最後に変更された時刻を示します。多くのシステムはこの情報を保持していません。この場合、サーバーはGETATTR操作をサポートしないのではなく、ctimeの代わりに最終変更時刻を返すことでシミュレートできます。サーバーは、クライアントに対する副作用の可能性があるため、属性情報をシミュレートする際には注意する必要があります。例えば、多くのクライアントは、キャッシュ一貫性スキームの基礎としてファイル変更時刻を使用します。
NFSサーバーは単純で、NFSクライアントはスマートです。サーバーが提供する一般化されたファイルアクセスを、アプリケーションとユーザーにとって有用なファイルアクセス方法に変換するために必要な作業を行うのはクライアントです。上記のLINKの例では、サーバーからNFS3ERR_NOTSUPエラーを受信したUNIXクライアントは、アプリケーションにリンク要求が成功したように見せるか、合理的なエラーを返すために必要なリカバリを実行します。一般的に、リカバリの負担はクライアントにあります。
NFSバージョン3プロトコルは、ステートレスサーバー実装を前提としています。ステートレスとは、サーバーが正しく機能するためにクライアントに関する状態を維持する必要がないことを意味します。ステートレスサーバーは、クラッシュ時にステートフルサーバーよりも明確な利点があります。ステートレスサーバーの場合、クライアントはサーバーが応答するまで要求を再試行するだけでよく、クライアントはサーバーがクラッシュしたことを知る必要さえありません。詳細については、99ページの「重複要求キャッシュ」を参照してください。
サーバーが有用であるためには、不揮発性状態を保持します: ファイルシステムに格納されたデータ。NFSバージョン3プロトコルでの変更されたデータを安定したストレージにフラッシュすることに関する設計上の前提により、データ損失が発生する可能性のある障害モードの数が削減されます。この方法で、NFSバージョン3プロトコル実装は、ネットワークの一時的な障害を含む一時的な障害を許容できます。一般的に、NFSバージョン3プロトコルのサーバー実装は、安定したストレージ自体の非一時的な障害を許容できません。ただし、このような問題に対処しようとするフォールトトレラントな実装が存在します。
これは、NFSバージョン3プロトコルサーバーが非クリティカルな状態を維持できないということではありません。多くの場合、サーバーはパフォーマンスを向上させるために、以前の操作に関する状態 (キャッシュ) を維持します。例えば、クライアントのREAD要求は、クライアントが順次読み取りを実行していることを予測して、ファイルの次のブロックをサーバーのデータキャッシュに先読みすることをトリガーする可能性があり、次のクライアントREAD要求は、ディスクからではなくサーバーのデータキャッシュから満たされます。サーバー上の先読みは、サーバーディスクI/Oとクライアント要求を重ね合わせることでパフォーマンスを向上させます。ここで重要な点は、先読みブロックが正しいサーバー動作に必要ではないということです。サーバーがクラッシュして読み取りバッファのメモリキャッシュを失った場合、再起動時のリカバリは簡単です - クライアントはサーバーディスクからデータを取得する読み取り操作を継続します。
NFSプロトコルのほとんどのデータ変更操作は同期的です。つまり、データ変更プロシージャがクライアントに戻ると、クライアントは操作が完了し、要求に関連付けられた変更されたデータが安定したストレージ上にあると想定できます。例えば、同期クライアントWRITE要求により、サーバーはデータブロック、ファイルシステム情報ブロック、およびファイル属性情報を更新する可能性があります - 後者の情報は通常メタデータ (metadata) と呼ばれます。WRITE操作が完了すると、クライアントは書き込みデータが安全であると想定し、それを破棄できます。これは、サーバーのステートレス性の非常に重要な部分です。サーバーがクライアントに戻る前にダーティデータを安定したストレージにフラッシュしない場合、クライアントは変更されたデータを安全に破棄できるタイミングを知る方法がありません。次のデータ変更プロシージャは同期的です: WRITE (安定フラグがFILE_SYNCに設定されている場合)、CREATE、MKDIR、SYMLINK、MKNOD、REMOVE、RMDIR、RENAME、LINK、およびCOMMIT。
NFSバージョン3プロトコルは、WRITEプロシージャをCOMMITプロシージャと組み合わせて使用する場合に、サーバー上で安全な非同期書き込みを導入します。COMMITプロシージャは、クライアントが以前の非同期WRITE要求からのデータをサーバー上の安定したストレージにフラッシュし、データを再送信する必要があるかどうかを検出する方法を提供します。49ページのWRITEと92ページのCOMMITのプロシージャ記述を参照してください。
LOOKUPプロシージャは、クライアントが複数コンポーネントのファイル名 (パス名) をトラバースするために使用されます。各LOOKUP呼び出しは、パス名の1つのセグメントを解決するために使用されます。LOOKUPを単一のセグメントに制限する理由は2つあります: 階層ファイル名の共通形式を標準化することは困難であり、クライアントとサーバーはパス名からファイルシステムへの異なるマッピングを持つ可能性があります。これは、クライアントがファイルシステムアタッチメントポイントでパス名を分割する必要があるか、サーバーがクライアントのファイルシステムアタッチメントポイントについて知っている必要があることを意味します。NFSバージョン3プロトコル実装では、クライアントがマウントを使用して階層を構築することで階層ファイル名空間を構築します。Automounterなどのサポートユーティリティは、クライアントマウントプロセスによって駆動されながら、ファイル名空間の共有された一貫したイメージを管理する方法を提供します。
クライアントは、さまざまな方法でキャッシングを実行できます。NFSバージョン2プロトコルでの一般的な実践は、時間ベースのクライアントサーバーキャッシュ一貫性メカニズムを実装することでした。NFSバージョン3プロトコル実装は、同様のメカニズムを使用することが期待されます。NFSバージョン3プロトコルには、明示的な属性チェックを排除するために、追加の属性情報の形式でいくつかの明示的なサポートがあります。ただし、キャッシングは必要なく、プロトコルによってキャッシングポリシーも定義されていません。NFSバージョン2プロトコルとNFSバージョン3プロトコルはどちらも、厳密なクライアントサーバー一貫性 (および、暗黙的に、クライアントキャッシュ全体の一貫性) を維持する手段を提供しません。
1.7 NFSバージョン2プロトコルからの変更 (Changes from the NFS Version 2 Protocol)
ROOTおよびWRITECACHEプロシージャは削除されました。MKNODプロシージャは、特殊ファイルの作成を許可するために定義され、CREATEのオーバーロードを排除しました。クライアント上のキャッシングは、プロトコルによって定義または指示されませんが、キャッシングを実装するクライアントがキャッシュをより効果的に管理できるように、追加の情報とヒントがプロトコルに追加されました。ファイルまたはディレクトリの属性に影響を与えるプロシージャは、操作完了後に新しい属性を返すことができるようになり、属性キャッシュの検証に使用される後続のGETATTRを最適化します。さらに、ターゲットオブジェクトが存在するディレクトリを変更する操作は、ディレクトリの古い属性と新しい属性を返し、クライアントがより賢明なキャッシュ無効化プロシージャを実装できるようにします。ACCESSプロシージャはサーバー上でアクセス権限チェックを提供し、FSSTATプロシージャはファイルシステムに関する動的情報を返し、FSINFOプロシージャはファイルシステムとサーバーに関する静的情報を返し、READDIRPLUSプロシージャはディレクトリエントリに加えてファイルハンドルと属性を返し、PATHCONFプロシージャはファイルに関するPOSIX pathconf情報を返します。
以下は、NFSバージョン2プロトコルとNFSバージョン3プロトコル間の重要な変更のリストです。
ファイルハンドルサイズ (File handle size)
ファイルハンドルは、32バイトの固定配列から最大64バイトの可変長配列に拡張されました。これにより、やや大きなファイルハンドルサイズのいくつかの既知の要件に対処します。ファイルハンドルは、64バイトの長さ全体を使用しないシステムのローカルストレージとネットワーク帯域幅要件を削減するために、固定長から可変長に変換されました。
最大データサイズ (Maximum data sizes)
READおよびWRITEプロシージャで使用されるデータ転送の最大サイズは、FSINFO戻り構造の値によって設定されるようになりました。さらに、推奨転送サイズもFSINFOによって返されます。プロトコルは、最大転送サイズに人為的な制限を課しません。
ファイル名とパス名は、可変長の文字列として指定されるようになりました。実際の長さ制限は、クライアントとサーバーの実装によって適切に決定されます。プロトコルは、長さに人為的な制限を課しません。エラーNFS3ERR_NAMETOOLONGは、サーバーが処理するには長すぎるパス名を受信したことをクライアントに返すための表示をサーバーが返すことを許可するために提供されます。
エラー戻り値 (Error return)
一部のインスタンスでは、エラー戻り値がデータ (例: 属性) を返すようになりました。nfsstat3は、サーバーが返すことができるエラーの完全なセットを定義するようになりました。他の値は許可されません。
ファイルタイプ (File type)
ファイルタイプには、特殊ファイル用のNF3CHRとNF3BLKが含まれるようになりました。これらのタイプの属性には、UNIXメジャーおよびマイナーデバイス番号のサブフィールドが含まれます。ファイルシステム内のソケットとFIFO用にNF3SOCKとNF3FIFOが定義されるようになりました。
ファイル属性 (File attributes)
blocksize (ファイル内のブロックのサイズ(バイト単位)) フィールドは削除されました。modeフィールドには、ファイルタイプ情報が含まれなくなりました。sizeおよびfileidフィールドは、4バイト整数から8バイト符号なし整数に拡張されました。メジャーおよびマイナーデバイス番号情報は、異なる構造で提示されるようになりました。blocksフィールド名はusedに変更され、ファイルが使用する合計バイト数が含まれるようになりました。これも8バイト符号なし整数です。
ファイル属性の設定 (Set file attributes)
NFSバージョン2プロトコルでは、設定可能な属性はファイル属性構造のサブセットで表されていました; クライアントは、対応するフィールドを-1に設定することで、変更しない属性を示し、一部の符号なしフィールドをオーバーロードしました。ファイル属性設定構造は、各フィールドに判別共用体を使用して、そのフィールドを設定するかどうか、またはどのように設定するかを伝えるようになりました。atimeおよびmtimeフィールドは、サーバーの現在時刻またはクライアントが提供する時刻のいずれかに設定できます。
LOOKUP
LOOKUP戻り構造には、検索されたディレクトリの属性が含まれるようになりました。
ACCESS
明示的なオーバーザワイヤ権限チェックを許可するために、ACCESSプロシージャが追加されました。これにより、多くのサーバー実装でのスーパーユーザーIDマッピング機能の既知の問題 (ルートユーザーのマッピングにより、ファイルの読み取りまたは書き込み中に予期しない権限拒否エラーが発生する可能性がある) に対処します。これにより、NFSバージョン2プロトコルでの、ファイルへのアクセスがUNIXスタイルのモードビットのみに基づいているという仮定も削除されます。
READ
応答構造には、READでファイルの終わりに遭遇した場合にTRUEとなるブール値が含まれます。これにより、クライアントはファイルの終わりを正しく検出できます。
WRITE
beginoffsetおよびtotalcountフィールドは、WRITE引数から削除されました。必要に応じて、応答にはカウントが含まれるようになり、サーバーは要求されたデータ量よりも少ない量を書き込むことができます。クライアントが必要とするキャッシュ同期のレベルをサーバーに指示するために、引数にインジケータが追加されました。
CREATE
通常ファイルの排他的作成のために、排他フラグと作成ベリファイアが追加されました。
MKNOD
特殊ファイルの作成をサポートするために、このプロシージャが追加されました。これにより、一部のNFSバージョン2プロトコル実装で行われたように、CREATEのオーバーロードが回避されます。
READDIR
READDIR引数には、サーバーがCookieを検証できるようにするベリファイアが含まれるようになりました。Cookieは、NFSバージョン2プロトコルで使用されていた4バイト配列ではなく、64ビット符号なし整数になりました。これにより、相互運用性の問題を軽減できます。
READDIRPLUS
拡張ディレクトリリストでファイルハンドルと属性を返すために、このプロシージャが追加されました。
FSINFO
ファイルシステムに関する不揮発性情報を提供するために、FSINFOが追加されました。応答には、推奨および最大読み取り転送サイズ、推奨および最大書き込み転送サイズ、およびリンクまたはシンボリックリンクがサポートされているかどうかを示すフラグが含まれます。また、READDIRプロシージャ応答の推奨転送サイズ、サーバー時間粒度、およびSETATTR要求で時刻を設定できるかどうかも返されます。
FSSTAT
Unix systemのdfコマンドなどのユーティリティで使用するために、ファイルシステムに関する揮発性情報を提供するために、FSSTATが追加されました。応答には、バイト単位で指定されたファイルシステムの合計サイズと空き容量、ファイルシステム内のファイルの総数と空きファイルスロット数、およびファイルシステム変更間の時間推定 (キャッシュ一貫性チェックアルゴリズムで使用) が含まれます。
COMMIT
COMMITプロシージャは、非同期WRITE操作と共に使用される同期メカニズムを提供します。