以下は、 RFC3530 の kanda.motohiro@gmail.com による抄訳です。編集が不便なので、一時的にファイルを分割します。他の nfsv4 RFC 訳は、ここを参照。
目次
8 ファイルロックと共有予約
9 クライアント側のキャッシュ
13 NFSv4 要求
14 NFS v4 プロトコル
16 セキュリティの考察
RFC3530 訳の8章以降は別ファイルです。
1. はじめに
1.1 RFC 3010 との違い 略
1.2 NFS バージョン 4 ゴール
NFS バージョン 4 プロトコル は、以前に バージョン 2 [RFC1094] と 3 [RFC1813] で定義された NFS プロトコルを拡張したものです。それは、以前のバージョンの主な特徴を引継ぎます。簡単なリカバリー、トランスポートプロトコル、オペレーティングシステム、そしてファイルシステムからの独立性、簡潔さ、そして高性能に注目した設計です。 NFS バージョン 4 のゴールは以下です。
o インターネットでの改善されたアクセスと高性能
プロトコルは、ファイアーウオールを容易に通過し、遅延が大きくて帯域が狭い環境でも性能が良く、そしてサーバーあたり非常に多数のクライアントでもスケールするように設計されました。
o 強いセキュリティ。ネゴシエーションはプロトコルに含まれます。
プロトコルは、 ONCRPC ワーキンググループの成果を使って、RPCSEC_GSS プロトコルをサポートします。 さらに、NFS バージョン 4 プロトコル は、クライアントとサーバーがセキュリティをネゴシエートできる機構を提供し、クライアントとサーバーが、最低限のセキュリティスキーマをサポートすることを要求します。
o 優れたクロスプラットフォーム相互運用性
このプロトコルは、 使いやすく、特定のファイルシステムやオペレーティングシステムを必要以上に優遇することのない、共通の機能セットを持つファイルシステムモデルを特徴とします。
o プロトコル拡張が簡単な設計
プロトコルは、下位互換性を損なうことなく、標準の拡張を許容するように設計されています。
1.3 この文書中の矛盾点と 18節(大意)
18節、RPC定義ファイルは、このプロトコルで使われる要素を XDR 言語で記述します。この文書中の他の部分と18節の記述がくいちがう場合は、18節の記述を正統とします。
1.4 NFS バージョン 4 の機能の概要
読者に十分な背景知識を提供するために、NFS バージョン 4 プロトコルの主な機能を簡単に説明します。以前の バージョンの NFS プロトコルをご存知の方にも、NFSが初めての方にも役に立つと思います。NFSプロトコルが初めての読者は、それ以外にも、必要とされる基本的知識があります。読者は、[RFC1831] と [RFC1832] に記述される、XDR と RPC を理解している必要があります。ファイルシステムと分散ファイルシステムの基本的知識も必要です。
1.4.1 RPC とセキュリティ
以前のバージョンのNFSと同様に、NFS バージョン 4 プロトコル で使用される External Data Representation (XDR) とRemote Procedure Call (RPC) 機構は、[RFC1831] と [RFC1832] に定義されているものです。エンドツーエンドのセキュリティ要件を満たすために、RPCSEC_GSS フレームワーク [RFC2203] が使用され、基本的なRPCセキュリティを拡張します。RPCSEC_GSS を使うことで、認証、改ざん防止、そして機密性をNFS バージョン 4 プロトコル に提供するための多くの機構を使うことができます。[RFC1964] にある Kerberos V5 を使って、1つのセキュリティフレームワークを提供させることができます。[RFC2847] にある LIPKEY GSS-API 機構を使って、NFS バージョン 4 プロトコル が使うユーザーパスワードやサーバーの公開鍵を提供することもできます。RPCSEC_GSS により、それ以外の機構を NFS バージョン 4 セキュリティのために指定し、使うことも可能です。
インバンドでのセキュリティネゴシエーションを可能とするため、NFSバージョン 4 プロトコルは、クライアントが、サーバーに、サーバーのファイルシステム資源をアクセスするためにはどんなセキュリティ機構を使う必要があるかというポリシーを問い合わせるための新しい操作を追加しました。これにより、クライアントはクライアントとサーバーの両方のポリシーに適合するセキュリティ機構をセキュアに選択することができます。
1.4.2 手続きと操作の構造
以前のバージョンのNFSプロトコルからの大きな決別は、COMPOUND 手続きの導入です。NFSv4では、2つのRPC手続きがあります。 NULL と COMPOUND です。COMPOUND 手続きは、操作により定義され、これらの操作が、以前のNFS手続きにより近いものです。
COMPOUND 手続きを使えば、クライアントは単純な要求も複雑な要求も作ることができます。COMPOUND 要求は、論理的なファイルシステム操作に必要なRPCの数を減らすのに役立ちます。例えば、それ以前にサーバーとコンタクトすることなく、クライアントは1つの要求でファイルからデータを読むことができます。1つの COMPOUND RPCに、LOOKUP, OPEN, そして READ を入れるのです。以前のバージョンのNFSでは、このタイプの単一の要求は不可能でした。
COMPOUND に使われるモデルはとても単純です。操作の論理的な OR や AND はありません。COMPOUND 要求の中の操作は、サーバーにより、順に評価されます。操作が失敗を返すと、評価は停止し、すべての評価の結果がクライアントに返ります。
NFSv4でも、クライアントは、サーバーにおけるファイルやディレクトリを、「ファイルハンドル」で参照します。COMPOUND 手続きには、操作のシーケンスの中で、1つの操作から別の操作にファイルハンドルを手渡す方法があります。「現在のファイルハンドル」と、「保存されたファイルハンドル」という概念があります。ほとんどの操作は、操作対象のファイルシステムオブジェクトに、「現在のファイルハンドル」を使います。「保存されたファイルハンドル」は、COMPOUND 手続き内での一時的なファイルハンドル領域として使われたり、特定の操作のための追加のオペランドとして使われます。
1.4.3 ファイルシステムモデル
NFSv4で使われる一般的なファイルシステムモデルは、以前のバージョンと同じです。サーバーファイルシステムは階層的で、レギュラーファイルはディレクトリの中にあって、構造のないバイト列です。
国際化のために、ファイル名とディレクトリ名は UTF-8 でエンコードされるところが違います。
NFSv4では、パス名とファイルハンドルの最初のマッピングを提供するための独立のプロトコルを必要としません。かつては、 MOUNT プロトコルが、そのために使われましたが、サーバーは ROOT ファイルハンドルをそのかわりに提供します。これは、論理的ルート、つまりサーバーの提供するファイルシステムツリーの頂上を表します。サーバーは、複数のファイルシステムを擬似ファイルシステムによってくっつけて提供することができます。この擬似ファイルシステムは、パス名で見たときの、実際のファイルシステムの間のあるかもしれないギャップを埋めるものです。
1.4.3.1 ファイルハンドル種別
以前のバージョンのNFSでは、サーバーが提供するファイルハンドルは、それが示すファイルが存在する限り、有効で、永続的であることが保証されていました。サーバー実装によっては、この永続性の要求はむつかしいものです。NFSv4では、揮発的ファイルハンドルを導入することで、この要求をゆるめました。永続的と揮発的ファイルハンドル種別で、サーバーは自分のファイルシステムの能力と実行環境に応じた実装が可能です。クライアントは、受け取ったファイルハンドルの種別を知ることができるので、それぞれのセマンティクスにあわせた扱いが可能です。
1.4.3.2 属性種別
NFSv4は、ファイルシステムとファイルの属性に、3種類を導入しました。ファイルハンドル種別の追加と同じように、属性の種類分けは、サーバー実装を簡単にすることと、NFSプロトコルの全体的な機能を拡張することを目的とします。この属性モデルは、新しい属性が追加されるときに、プロトコルの修正がわずかで済むように、拡張可能な構造になっています。
3つの種別は、必須、推奨、そして、名前つき、です。これは、以前のNFSの属性モデルからの大きな決別です。以前には、ファイルシステムとファイルの属性は、主に、UNIXの属性の固定のセットでした。サーバーあるいはクライアントがある属性をサポートしないときは、できる限り、それをシミュレートする必要がありました。
必須属性は、ファイルシステムとファイルの属性の最小限のセットで、サーバーはそれらをサポートし、適当に表現する必要があります。推奨属性は、異なるファイルシステムと実行環境のためで、相互運用性を高めます。この2つは、伝統的なものです。3つめの、名前つき属性は、ファイルあるいはディレクトリに関連付けられる不透明なバイト列で、文字列の名前で示されます。名前つき属性は、クライアントアプリケーションが、アプリケーション固有のデータを、ファイルやディレクトリにくっつけるためのものです。
推奨属性のうち、重要なのは、Access Control List (ACL) 属性です。これは、以前のNFSで使われたアクセス制御モデルを超えるものです。ACL定義は、ユーザーとグループレベルでのアクセス制御を可能とします。
1.4.3.3 ファイルシステム複製と移行
特別なファイル属性を使って、サーバーファイルシステムを移行したり複製したりするするのが、プロトコル内で可能となりました。ファイルシステム位置属性を使って、クライアントはファイルシステムの位置をサーバーに問い合わせることができます。ファイルシステム移行があったら、クライアントはファイルシステムを操作するときにエラーを受け取り、新しい位置を問い合わせます。複製も似たようなステップで行われます。クライアントは、サーバーに、あるファイルシステムの複数の可能な位置を教えてもらい、自分のポリシーに従って適当なファイルシステムをアクセスします。
1.4.4 OPEN と CLOSE
NFSv4は、OPEN と CLOSE 操作を導入しました。OPEN 操作は、それ1つでファイルの参照あるいは作成が可能で、共有セマンティクスを指定することもできます。CLOSE 操作は、OPEN で蓄積した状態を解放します。
1.4.5 ファイルロック
NFSv4では、バイトレンジファイルロックは、NFSプロトコルの一部です。ファイルロックのサポートは、RPCコールバックが不要なように作られています。これは、以前のNFSファイルロックプロトコル、Network Lock Manager (NLM) からの決別です。ファイルロックに伴う状態は、サーバーにおいて、リースを基本とするモデルにより維持されます。サーバーは、あるNFSクライアントのためのすべての状態に1つ、リース期間を決めます。クライアントが決められた時間内にリースを更新しないならば、サーバーはクライアントの状態を破棄することがあります。クライアントのリースの延長は、 RENEW 操作あるいは、他の操作(主に、 READ)をすることで暗黙的に行われます。
1.4.6 クライアントキャッシュと委譲
NFSv4のファイル、属性、そしてディレクトリのキャッシュは、以前のバージョンと似ています。属性とディレクトリ情報は、クライアントが決める期間、キャッシュされます。指定のタイムアウトの後、クライアントはサーバーに変更があったか聞きます。
ファイルデータについては、クライアントは、ファイルがオープンされるときに、キャッシュの有効性を調べます。ファイルが変更されたか、サーバーに問い合わせます。この結果で、クライアントは、キャッシュデータを保持するか捨てるか決めます。また、ファイルがクローズされるとき、すべての更新データはサーバーに書き込まれます。
アプリケーションがファイルデータへのアクセスをシリアライズしたいならば、ファイルロックを使うべきです。
NFSv4での、キャッシュに関する大きな追加は、サーバーがクライアントにいくらかの責任を委譲することができることです。サーバーがクライアントにあるファイルへの委譲を許可すると、クライアントは、他のクライアントとの間で、そのファイルの共用について、決められたセマンティクスを保証されます。 OPEN のときに、サーバーは、クライアントにそのファイルのリードあるいはライトの委譲をすることができます。リード委譲なら、委譲の期間は、他のクライアントはそのファイルに書き込みができません。ライト委譲なら、他のクライアントはそのファイルを読み書きできません。
サーバーは、委譲を回収できます。他のクライアントが、許可された委譲と競合するようなアクセスを要求した場合、サーバーは最初のクライアントに通知して、委譲を回収することができます。このためには、サーバーとクライアントの間に、コールバックのパスが必要です。パスがなければ、委譲は許可されません。委譲の要点は、クライアントがサーバーとやりとりすることなしに、OPEN, CLOSE, LOCK, LOCKU, READ, WRITE のような操作をローカルに行えるということです。
1.5 一般的な定義
読者が妥当なコンテキストを得られるように以下の定義を示します。
クライアント
「クライアント」は、NFSサーバーの資源をアクセスするものです。それは、NFSプロトコルを実装したアプリケーションプログラムかもしれませんが、普通は、オペレーティングシステムの分散ファイルシステムサービスのクライアント機能であり、その上で多くのアプリケーションが動きます。
ファイルロックの場合、クライアントは、複数のアプリケーションのために、ロックの集合を管理するものです。クライアントは、ロックの、クラッシュもしくは障害からの回復に責任を持ちます。
訳注。クライアントは、マシンです。委譲を得るのは、クライアントです。共有予約やバイトレンジファイルロックを得るのはアプリケーションです。
同じトランスポートを複数クライアントが共有することや、同じネットワークノードに複数クライアントが存在することがあります。
clientid
クライアントが提供したIDとベリファイアの短縮形となる、サーバーが発行する64ビットのもの。
リース
サーバーにより定義された時間の期間であり、クライアントはその間、ロックを許可され、無効にされることはありません。リース期間が終わるときに、リースが延長されていなければ、ロックは無効になることがあります。リース期間の後に競合するロックが許可されたときには、ロックは無効にされなくてはいけません。
サーバーが発行したすべてのリースは、同じ、固定の有効期間を持ちます。これは、サーバー障害を考えると、可変長のリースを維持するのが大変だからです。
ロック
バイトレンジロックのことにも、共有予約のことにも使われる言葉です。
サーバー
は、クライアントにファイルシステムの集合へのアクセスを提供するものです。
ステーブル記憶域
NFSv4 サーバーは、複数の電源障害、オペレーティングシステム障害、記憶域メディア以外のハードウエア障害があっても、データ喪失することなく回復しなくてはいけません。
NFS サーバーに許されるステーブル記憶域の例は、以下です。
1 データがメディアに達する。つまり、更新済みデータはディスクプラッターなどのディスクメディアに書き込みが成功する。
2 電池バックアップあるいは、無停止電源(UPS)で保証された、ドライブ内の一時的記憶域を持つディスク。
3 電池バックアップされた一時的記憶域と回復ソフトウエアを有するサーバーに達する。
4 無停止電源(UPS)と回復ソフトウエアを有するキャッシュに達する。
stateid
あるファイルを、あるアプリケーションが、オープンもしくはロックしていることを示す、サーバーが発行する128ビットのもの。
すべてのビットがゼロあるいは1のものは、予約値で、特別な意味を持ちます。
ベリファイア
クライアントが生成する64ビットのもので、クライアントがリブートして、以前のロック状態を忘れたかをサーバーが判断するために使います。
訳注。一般的でない訳語と原語の対応を示します。
委譲:delegation 失効:revoke 回収:recall 満了:expire
共有予約:share reservation
2 プロトコルデータ型
2.1 基本データ型
Data Type Definition
____________________________________________________________________
int32_t typedef int int32_t;
uint32_t typedef unsigned int uint32_t;
int64_t typedef hyper int64_t;
uint64_t typedef unsigned hyper uint64_t;
attrlist4 typedef opaque attrlist4<>;
ファイルとディレクトリの属性で使われます。
bitmap4 typedef uint32_t bitmap4<>;
属性配列のエンコードで使われます。
changeid4 typedef uint64_t changeid4;
change_info の定義で使われます。
clientid4 typedef uint64_t clientid4;
クライアント識別子の短縮参照です。
component4 typedef utf8str_cs component4;
パス名コンポーネントを表します。
count4 typedef uint32_t count4;
(READ, WRITE, COMMIT) などで使われる、バイト数です。
length4 typedef uint64_t length4;
ロックの長さを示します。
linktext4 typedef utf8str_cs linktext4;
シンボリックリンクの内容
mode4 typedef uint32_t mode4;
モード属性
nfs_cookie4 typedef uint64_t nfs_cookie4;
READDIR で使われる、不透明なクッキー値
nfs_fh4 typedef opaque nfs_fh4<NFS4_FHSIZE>;
ファイルハンドル定義; NFS4_FHSIZE は 128 です。
nfs_ftype4 enum nfs_ftype4;
いろいろなファイルタイプ
nfsstat4 enum nfsstat4;
操作の戻り値
offset4 typedef uint64_t offset4;
(READ, WRITE, LOCK, COMMIT) などで使われる、オフセット指定
pathname4 typedef component4 pathname4<>;
LOOKUP, OPEN などで使われる、パス名
qop4 typedef uint32_t qop4;
SECINFO で使われる保護の質
sec_oid4 typedef opaque sec_oid4<>;
セキュリティーオブジェクト識別子
sec_oid4 は、実は不透明ではなく、GSS-API である GSS_Init_sec_context の mech_type 引数で使われる、ASN.1 OBJECT IDENTIFIER です。詳しくは [RFC2743] を参照下さい。
seqid4 typedef uint32_t seqid4;
ファイルロックで使われる、シーケンスID
utf8string typedef opaque utf8string<>;
UTF-8 エンコードした文字列
utf8str_cis typedef opaque utf8str_cis;
大文字小文字を区別しない UTF-8 文字列
utf8str_cs typedef opaque utf8str_cs;
大文字小文字を区別する UTF-8 文字列
utf8str_mixed typedef opaque utf8str_mixed;
大文字小文字を区別するプレフィックスと大文字小文字を区別しないサフィックスを持つ
UTF-8 文字列
verifier4 typedef opaque verifier4[NFS4_VERIFIER_SIZE];
(COMMIT, CREATE, OPEN, READDIR, SETCLIENTID, SETCLIENTID_CONFIRM, WRITE) などの操作で使われるベリファイア。NFS4_VERIFIER_SIZE は 8 です。
2.2 構造のあるデータ型
nfstime4
struct nfstime4 {
int64_t seconds;
uint32_t nseconds;
}
nfstime4 は、Coordinated Universal Time (UTC) での1970年1月1日の深夜0時からの経過秒とナノ秒です。正の秒数は、1月1日以後、負は以前を示します。いずれの場合も、nseconds フィールドは最後の時刻表示において、秒数に加算されます。つまり、1月1日の0.5秒前を示すには、秒はー1で、ナノ秒は0.5秒つまり 500000000 にします。999,999,999 を超えるナノ秒は不正です。
このデータ型は、時刻と日付を示します。サーバーは自分のローカル表現との間で、できるだけ正確さを保ったまま、変換をします。ファイルシステムに保存されるタイムスタンプの精度がこれより悪いときは、正確さが損なわれることがあります。クライアントとサーバーの時刻スキューを減らすために、適当な時刻管理プロトコルがあるとよいでしょう。
time_how4
enum time_how4 {
SET_TO_SERVER_TIME4 = 0,
SET_TO_CLIENT_TIME4 = 1
};
settime4
union settime4 switch (time_how4 set_it) {
case SET_TO_CLIENT_TIME4:
nfstime4 time;
default:
void;
};
これは、時刻設定をするときの属性値で使われます。set_it が SET_TO_SERVER_TIME4
のとき、サーバーは自分のローカル時刻表現を使います。
specdata4
struct specdata4 {
uint32_t specdata1; /* major device number */
uint32_t specdata2; /* minor device number */
};
これは、NF4CHR と NF4BLK のデバイスファイルの情報です。
fsid4
struct fsid4 {
uint64_t major;
uint64_t minor;
};
必須属性で使われるファイルシステムのIDです。
fs_location4
struct fs_location4 {
utf8str_cis server<>;
pathname4 rootpath;
};
fs_locations4
struct fs_locations4 {
pathname4 fs_root;
fs_location4 locations<>;
};
ファイルシステムの移行と複製で使われる、fs_locations 推奨属性です。
fattr4
struct fattr4 {
bitmap4 attrmask;
attrlist4 attr_vals;
};
ファイルとディレクトリの属性を示します。
ビットマップは、個数つきの32ビット整数の配列です。ビット n のある整数の位置は、 n/32 で、その整数内のビット位置は、n mod 32 です。
0 1
+-----------+-----------+-----------+--
| count | 31 .. 0 | 63 .. 32 |
+-----------+-----------+-----------+--
change_info4
struct change_info4 {
bool atomic;
changeid4 before;
changeid4 after;
};
CREATE, LINK, REMOVE, RENAME 操作のときに、クライアントに、目的のファイルオブジェクトの親ディレクトリの change 属性を伝えるのに使われます。
clientaddr4
struct clientaddr4 {
/* see struct rpcb in RFC 1833 */
string r_netid<>; /* network id */
string r_addr<>; /* universal address */
};
SETCLIENTID 操作あるいはコールバック登録で、 clientid を使っているクライアントのアドレスを示すのに使われます。r_netid と r_addr は [RFC1833] で定義されていますが、そこでは、個々のプロトコルにおいて、どういうふうになるのかは書かれていません。IPv4 の上の TCP, UDP では、r_addr は US-ASCII 文字列で、
h1.h2.h3.h4.p1.p2
です。プレフィックス「h1.h2.h3.h4」は、IPv4 のアドレス、それは常に4バイトです、を表す、標準のテキスト形式です。ビッグエンディアンなので、h1, h2, h3, h4 はそれぞれ、1番目から4番目のバイトを10進数でアスキー表示したものです。p1, p2 は、ポート番号の最初と次のバイトを10進数でアスキー表示したものです。例えば、ホストが、ビッグエンディアンで示したアドレス 0x0A010307 を持ち、ビッグエンディアンで示したポート 0x020F (10進で 527) をリスンするサービスがあるならば、完全なユニバーサルアドレスは、"10.1.3.7.2.15" になります。
IPv4 の上の TCP では、r_netid は、文字列 "tcp"、UDP では、"udp" です。
IPv6 の上の TCP, UDP では、r_addr は US-ASCII 文字列で、
x1:x2:x3:x4:x5:x6:x7:x8.p1.p2
です。サフィックス p1.p2 は、前に述べたとおりです。プレフィックス "x1:x2:x3:x4:x5:x6:x7:x8" は [RFC2373] の2.2節で定義される、IPv6 アドレスをテキストで表示する標準の形式です。また、そこで述べられている2つの代替形式も受け付けられます。
r_netid は、文字列 "tcp6", “udp6” です。
cb_client4
struct cb_client4 {
unsigned int cb_program;
clientaddr4 cb_location;
};
クライアントがサーバーに、コールバックアドレスを与えるのに使われます。プログラム番号とクライアントアドレスを含みます。
nfs_client_id4
struct nfs_client_id4 {
verifier4 verifier;
opaque id<NFS4_OPAQUE_LIMIT>;
};
SETCLIENTID 操作の引数の1つです。NFS4_OPAQUE_LIMIT は 1024 です。
open_owner4
struct open_owner4 {
clientid4 clientid;
opaque owner<NFS4_OPAQUE_LIMIT>;
};
オープン状態の所有者を示します。NFS4_OPAQUE_LIMIT は 1024 です。
lock_owner4
struct lock_owner4 {
clientid4 clientid;
opaque owner<NFS4_OPAQUE_LIMIT>;
};
ファイルロック状態の所有者を示します。
open_to_lock_owner4
struct open_to_lock_owner4 {
seqid4 open_seqid;
stateid4 open_stateid;
seqid4 lock_seqid;
lock_owner4 lock_owner;
};
これは、open_owner4 が行う最初の LOCK で使われます。open_stateid とlock_owner を含み、有効な open_stateid シーケンスから、新しい lock_stateid シーケンスへの移行がされるようにします。この機構は、open_stateid/open_seqid の形で確立された状態に結びついているため、 lock_owner/lock_seqid ペアの確認を省くことができます。
stateid4
struct stateid4 {
uint32_t seqid;
opaque other[12];
};
これは、クライアントとサーバーの間のいろいろな状態の共有機構で使われます。クライアントには、これはリードオンリーです。seqid の初期値は未定義です。サーバーは、stateid の変化に伴い、seqid を単調増加する必要があります。クライアントは、OPEN の stateidに含まれる seqid を見て、サーバーで行われた OPEN の順序を調べるため、それは重要です。
3. RPCとセキュリティフレーバー
NFSv4プロトコルは、RPCバージョン2とXDRを使うアプリケーションです。NFSv4のセキュリティを強化するには、RPCSEC_GSS セキュリティフレーバーを使わなくてはいけません。
3.1 ポートとトランスポート
歴史的に、NFSv2 と 3 サーバーは、ポート2049にいました。NFSプロトコルのために登録されたポート2049 [RFC3232] が、デフォルトの設定であるべきでしょう。このポートを使えば、NFSクライアントは、[RFC1833] が記述するRPCバインディングプロトコルを使わないで済み、NFSはファイアウオールを通過することができます。
NFSv4を、IPの上で動かすとき、NFSとIPの間のトランスポートプロトコルは、IETF 承認の輻輳制御をサポートしなくてはいけません。TCP,SCTP などがそうです。相互運用性を高めるために、NFSv4実装は、TCPをサポートしなくてはいけません。少なくともRFCが、TCPに代わるプロトコルを提案するまではです。
TCPが使われる場合、クライアントとサーバーは、永続的コネクションを使うべきです。これにより、短時間のコネクションに関して、TCPの輻輳制御がうまく働かないのを回避できますし、WAN環境で、SYNハンドシェークをしないでよいために性能向上が可能です。
セキュリティーの考察の節で述べたように、NFSv4の認証モデルは、マシンベースから、プリンシパルベースに移行しました。しかし、これによって、TCPコネクション管理を、マシンベースからユーザーごとにしなくてはいけないという技術的な理由はありません。特に、TCP上のNFS実装は、歴史的に、複数ユーザーの通信を、サーバーとクライアントの間の1つの共通のTCPコネクションにマルチプレックスしてきました。これは、クライアントが、AUTH_SYS, AUTH_DH, RPCSEC_GSS いずれのセキュリティフレーバーを使っていても、同じ事です。また、サーバー実装は、そういうモデルを前提として、TCPコネクション管理の実装を、クライアントマシンの数に対してスケールするようにしてきました。NFSv4はこのコネクション管理モデルを変えるつもりはありません。この前提に従わないNFSv4クライアントは、サーバーでのスケーリング問題を起こすことがあるでしょう。
また、各種タイマーについて言うと、クライアントとサーバーは、タイマーの同期に気をつけるべきです。詳しくは、[Floyd] を参照下さい。
3.1.1 クライアント再送のふるまい
TCPのような信頼性のあるトランスポートから受け取った要求を処理するとき、NFSv4サーバーはトランスポートコネクションが切れた場合を除いて、何も言わずに要求をドロップしてはいけません。NFSv4サーバーとクライアントの約束がそういうことなので、クライアントは、以下の場合を除いて、要求を再送してはいけません。
o トランスポートコネクションが切れたとき
o NULL 手続きをリトライするとき
TCPのようなトランスポートは、片側がコネクションを切ったとき(例えば、NFSサーバーがリブートしたとき)に同時に反対側に通知をするとは限らないので、NFSv4クライアントは、コネクションが切れていないか、アクティブに「プローブ」したいことがあるでしょう。NULL手続きは、1つの、お勧めできる方法です。このため、もし、クライアントがRPCタイムアウト(実装による適当な時間)を検出したら、もとのRPCを再送するのではなく、NULL手続きをサーバーに送るのがよいでしょう。サーバーが落ちていれば、トランスポートコネクション切断がいずれ、クライアントに通知されます。クライアントは再接続して、もとの要求を再送します。もし、NULL手続きが応答を得たら、コネクションは切れていないので、クライアントはもとの要求の応答をもう少し待つか、コネクションを切ってつなぎなおしてから、もとの要求を再送するのがよいです。
サーバーからクライアントに行くコールバックについても、同じ規則があてはまります。ただ、役割が逆です。
3.2 セキュリティフレーバー
伝統的なRPC実装では、セキュリティフレーバーに、AUTH_NONE, AUTH_SYS, AUTH_DH, そして AUTH_KRB4 がありました。[RFC2203] で、RPCSEC_GSS が加わり、これは、GSS-API [RFC2743] の機能を使うものでした。これにより、RPCセキュリティフレーバーを追加する実装をせずに、RPC層でいろいろなセキュリティ機構を使うことが可能となりました。NFSv4では、強制的なセキュリティ機構を有効にするためには、RPCSEC_GSS セキュリティフレーバーを使わなくてはいけません。その他のフレーバー、AUTH_NONE, AUTH_SYS, AUTH_DH を実装するのはかまいません。
3.2.1 NFSv4 のセキュリティ機構
RPCSEC_GSS を使うときは、機構、保護の質、サービス(認証、改ざん防止、機密性)を選択します。この文書の以下では、この3つのパラメーターを、セキュリティトリプルと呼びます。
3.2.1.1 ケルベロスV5 をセキュリティトリプルとして使う
[RFC1964] にある、ケルベロスV5 GSS-API の実装は必須で、以下のセキュリティトリプルを提供します。
カラムの説明:
1 == number of pseudo flavor
2 == name of pseudo flavor
3 == mechanism's OID
4 == mechanism's algorithm(s)
5 == RPCSEC_GSS service
1 2 3 4 5
--------------------------------------------------------------------
390003 krb5 1.2.840.113554.1.2.2 DES MAC MD5 rpc_gss_svc_none
390004 krb5i 1.2.840.113554.1.2.2 DES MAC MD5 rpc_gss_svc_integrity
390005 krb5p 1.2.840.113554.1.2.2 DES MAC MD5 rpc_gss_svc_privacy
4のアルゴリズムは、改ざん防止のため。56ビット DES を暗号化のため。
スードフレーバーを示したのは、実装者へのマッピングの助けとなるようにです。この NFS プロトコルはセキュリティーのネゴシエーションの方法を含み、 GSS-API を理解できるため、スードフレーバーは必要ありません。NFS v3 では、セキュリティーネゴシエーションが MOUNT プロトコルで行われたため、スードフレーバーが必要でした。
NFS での RPCSEC_GSS の使用と、 Kerberos V5 については、 [RFC2623] を参照下さい。
ユーザーと実装者は、56ビット DES が、今や、ブルートフォースアタックに対して安全でないことに注意下さい。[RFC1964] が改定されて、AES サポートが追加されたならば、ユーザーも実装者も急いでそれを使うように。
3.2.1.2 LIPKEY をセキュリティトリプルとして使う
3.2.1.3 SPKM-3 をセキュリティトリプルとして使う
略
3.3 セキュリティネゴシエーション
NFSv4サーバーは多くのセキュリティ機構を提供するため、クライアントはどれを使うか決めるあるいはネゴシエートする方法が必要です。NFSサーバーはファイルシステムネームスペースの複数の点をクライアントに公開し、それぞれの点が異なるセキュリティ機構を使っていることもあるでしょう。
クライアントとサーバーのセキュリティネゴシエーションは、セキュアなチャネルで行われなくてはなりません。サードパーティがネゴシエーションシーケンスをのっとって、低いレベルのセキュリティを選択させてしまうことがあるからです。詳しくは、「セキュリティの考察」の節を参照下さい。
3.3.1 SECINFO
新しい、SECINFO 操作により、クライアントは、ファイルハンドルごとに、サーバーアクセスにどんなセキュリティトリプルが使われるか知ることができます。一般的には、これは、サーバーとの最初の通信のときか、ポリシーの境界を移動するときにだけ必要です。しかし、クライアントとやりとりしている途中で、サーバーのポリシーが変化することもあるので、クライアントが新しいセキュリティトリプルをネゴシエートしなおすこともありえます。
3.3.2 セキュリティエラー
すべての NFSv4 クライアントとサーバーは、前記の最小限のセキュリティをサポートする必要があるため、クライアントはサーバーとの通信を、最小限のセキュリティトリプルを使って開始することでしょう。サーバーと通信するうちに、クライアントは NFS4ERR_WRONGSEC を受けることがあるかもしれません。これは、サーバーが、クライアントに、サーバーのファイルシステム資源にアクセスするには現在のセキュリティトリプルが不適当だという事を伝えるものです。そこでクライアントは、サーバーで可能なセキュリティトリプルを調べて、使いたいものを選択します。詳しくは、「SECINFO」操作の節を参照下さい。
3.4 コールバック RPC の認証
この節で述べられている場合を除いて、コールバック RPC (後で説明します。)は、以前に、 clientid (これも、後で説明します。)を得たプリンシパルを使って、もとの SETCLIENTID 操作で使ったセキュリティフレーバーを使って、NFS サーバーと相互に認証しあわなくてはいけません。
AUTH_NONE では、プリンシパルというものがないので、問題にはなりません。
AUTH_SYS では、相互認証とか、サーバープリンシパルというものがありません。このため、サーバーが行うコールバックは、最初にユーザーが委譲をセットアップしたときのAUTH_SYS クレデンシャルを使います。
AUTH_DH では、よく行われる慣例は、サーバーがこの AUTH_DH プリンシパルに対応するクレデンシャルを使うことです。
unix.host@domain
ホストとドメインは、サーバーホスト名と、Network Information System や DNS のドメイン名です。
LIPKEY は、 SPKM-3 の上にあるので、クライアントが SETCLIENTID で LIPKEY を使った時に、サーバーが LIPKEY でなく SPKM-3 をコールバックで使うのはかまいません。
RPCSEC_GSS のどのセキュリティ機構が使われたとしても、サーバーは自身を、 GSS-API において、GSS_C_NT_HOSTBASED_SERVICE 名前タイプを使って身分証明しなくてはいけません。GSS_C_NT_HOSTBASED_SERVICE 名前の形式は、
service@hostname
で、NFS の場合サービスの部分は、
nfs
です。
セキュリティ機構の実装によっては、 nfs@hostname をいろいろな異なる形式に変換することがあります。Kerberos V5 と LIPKEY の場合、以下の形式が推奨されます。
nfs/hostname
Kerberos V5 の場合、nfs/hostnameは、Kerberos キー配布センターデータベースにあるサーバープリンシパルになります。これは、クライアントが SETCLIENTID 操作を発行した時に確保した GSS-API コンテキストの対象と同じプリンシパルです。このため、サーバープリンシパルのレルム名は、 SETCLIENTID のときとコールバックの時で同じでなければいけません。
LIPKEY の場合、これは、ターゲット(コールバックを受ける NFSv4 クライアント)に与えられるユーザー名です。
LIPKEY はコールバックの時には機能しないかもしれないことに注意下さい。LIPKEY クライアントはユーザーIDとパスワードを使うためです。コールバックを受けた NFS クライアントが NFS サーバーのユーザ名とパスワードの組による認証ができて、かつ、NFS サーバーが使ったユーザーが公開鍵の証明書を持っている場合に限り、機能します。
NFS クライアントが LIPKEY を使い、SETCLIENTID に LIPKEY を使うのでなく、ホストごとのプリンシパルを使う場合、相互認証付きの SPKM-3 を使うことを推奨します。これは実質的には、クライアントが、認証及び NFS サーバーにおいてイニシエーターをターゲットに資格証明するために証明書を使うことを意味します。
LIPKEY でなく SPKM-3 を使うことには、以下の利点があります。
o サーバーがコールバックをするとき、SETCLIENTID で使われたプリンシパルに対して資格証明しなくてはいけません。LIPKEY が使われていても、LIPKEY は SPKM-3 の上にあるため、NFS クライアントは SETCLIENTID で使われたプリンシパルに対応する証明書を持っている必要があります。管理という面からいうと、クライアントとサーバーの両方にユーザー名、パスワード、それに証明書を持つのは冗長です。
o LIPKEY は、ターゲットの証明書以上の追加のインフラ要求を最小にすることを目的としており、既存のパスワードインフラがイニシエーターのために使えるという前提です。ホスト毎のパスワードインフラが存在しない環境もあります。証明書が任意のホスト毎のプリンシパルに使われるならばそれ以上のパスワードインフラは不要です。
o ホストが NFS クライアントでありサーバーでもある場合、同じホストごとの証明書を使うことができます。
4. ファイルハンドル
NFSプロトコルにおけるファイルハンドルは、サーバーごとのファイルシステムオブジェクトのユニークな識別子です。ファイルハンドルの中身はクライアントにとっては不透明です。サーバーはファイルハンドルをファイルシステムオブジェクトの内部的な表現に翻訳します。
4.1 最初のファイルハンドルを得る
NFSでの操作は1つあるいはいくつかのファイルハンドルを使って定義されます。なので、クライアントは、サーバーと会話を始めるためにファイルハンドルが必要です。NFSv2と3では、MOUNT プロトコル、RPC プログラム番号100005、で、文字列であるファイルシステムのパス名から最初のファイルハンドルを得ました。
MOUNT プロトコルは、セキュリティとファイアウォール経由の使用の点で問題があり、これが、[RFC2054] と[RFC2055] で、パブリックファイルハンドルが導入された理由の1つでした。パブリックファイルハンドルと LOOKUP 操作をNFSv2 と 3 で使うことで、MOUNT プロトコルは不要であることが実証されました。
このため、NFSv4では、それを使いません。NFSクライアントにとって、2つの特別なファイルハンドルが、出発点として使われます。
4.1.1 ルートファイルハンドル
最初の特殊なファイルハンドルは、ROOT ファイルハンドルです。それは、NFSサーバーのファイルシステムネームスペースの「概念的な」ルートです。クライアントは、 PUTROOTFH 操作で、ROOT ファイルハンドルを使い始めます。それは、サーバーに、「現在の」ファイルハンドルを、サーバーのファイルツリーの ROOT とするように指示します。この後は、クライアントは、 LOOKUP で、ツリーのどこにでも移動できます。サーバーネームスペースについては、「NFS サーバーネームスペース」の節を参照ください。
4.1.2 パブリックファイルハンドル
2つめの特殊なファイルハンドルは、PUBLIC ファイルハンドルです。ROOT ファイルハンドルとは違って、PUBLIC ファイルハンドルはサーバーのファイルシステムの任意のオブジェクトを表すことができます。PUBLIC ファイルハンドルと、ROOT ファイルハンドルが同じものを指すこともあります。PUBLIC ファイルハンドルとファイルシステムオブジェクトのバインディングを決めるのは、サーバーの管理者と管理ソフトウエアであり、クライアントは推測をするべきではありません。クライアントは、 PUTPUBFH 操作で PUBLIC ファイルハンドルを使います。
4.2 ファイルハンドルタイプ
NFSv2 と 3 では、NFSv4でいう、「永続的」ファイルハンドルが使われました。NFSv4では、さらに、「揮発的」ファイルハンドルが追加されました。
4.2.1 ファイルハンドルの一般的な属性
同じファイルに対するファイルハンドルは同じでなくてはいけません。クライアントは、バイトごとの比較をして、ファイルハンドルが同じかを判断することができますが、中の構造を推測してはいけません。サーバーは、ファイルとファイルハンドルに、1対1の対応をつけるべきですが、必須ではありません。クライアントは、2つのファイルハンドルが同じファイルを指すのかわからない場合にも備えなくてはいけません。詳しくは、「データキャッシュとファイル識別子」の節を参照ください。
例えば、 異なるパス /a/b/c と /a/d/c が同じファイルを指すなら、サーバーはどちらのパス経由のアクセスにも、同じファイルハンドルを返すべきです。
4.2.2 永続的ファイルハンドル
ファイルが作られた以降、サーバーは、リブートしても、ファイルシステムが移行しても、同じファイルハンドルを返さなくてはいけません。
サーバーが、取り除かれたファイルシステムオブジェクトを参照する永続的ファイルハンドルを受け取ったときには、NFS4ERR_STALE を返さなくてはいけません。これには、ファイルシステムのアンマウントなども含まれます。
4.2.3 揮発的ファイルハンドル
サーバーは、揮発的ファイルハンドルが、明らかに、取り除かれたファイルシステムオブジェクトを参照していると判断できるときは、NFS4ERR_STALE を返すのがよいです。揮発的ファイルハンドルが使えないそれ以外のすべての場合は、NFS4ERR_FHEXPIRED を返すべきです。
必須属性の「fh_expire_type」が、クライアントに、ファイルハンドルがどういう種類なのかを伝えます。これは、ビットマスクで、以下の値を持ちます。
FH4_PERSISTENT
ファイルハンドルは、永続的です。以下のすべてのビットが立っていない状態、ゼロ、です。
FH4_VOLATILE_ANY
いつでも、無効になることがあります。
FH4_NOEXPIRE_WITH_OPEN
オープンしている間は、無効になりません。
FH4_VOL_MIGRATION
移行すると、無効になります。
FH4_VOL_RENAME
リネームすると無効になります。
略
4.2.4 揮発的ファイルハンドルの実装例
略
4.3 ファイルハンドルの失効からのクライアントの回復
クライアントは、NFS4ERR_FHEXPIRED エラーから回復するべきです。一般的な対策としては、ファイルの完全なパス名を記録しておくことで、パスの最初から評価しなおせば最新のファイルハンドルが得られます。
5 ファイル属性
拡張性と、UNIX 以外のプラットフォームとの相互運用性を向上させるために、属性は柔軟な扱いが必要です。NFSv3 の fattr3 構造体は、属性の固定のリストを持ち、それにはすべてのクライアントとサーバーがサポートあるいは、必要としないものも含まれました。fattr3 構造体は、新しい要求があっても拡張はできず、サポートしていないということを示すこともできませんでした。NFSv4では、クライアントは、サーバーがどんな属性をサポートしているかを問い合わせて、サポートされている属性だけを使うことができます。
このため、属性は、3つに分けられます。必須、推奨、名前つきです。必須と推奨は、専用できちんと決まったエンコーディングがあり、数字で区別されます。それらは、GETATTR 要求のビットベクトルで、対応するビットを立てることで要求されます。サーバーは、応答に、どの属性が返されたかを示すビットベクトルを含めます。必須と推奨属性を増やすには、番号とエンコーディングを決めればよいのですが、詳しくは、「マイナーバージョニング」の節を参照ください。
名前つき属性は、新しい OPENATTR 操作でアクセスされます。それは、ファイルシステムオブジェクトに対応する隠れた属性のディレクトリを操作するものです。OPENATTR 操作は、ファイルハンドルを得て、属性ツリーのファイルハンドルを返します。そのハンドルは、LOOKUP や READDIR で操作されます。例えば、
LOOKUP "foo" ; look up file
GETATTR attrbits
OPENATTR ; access foo's named attributes
LOOKUP "x11icon" ; look up specific attribute
READ 0,4096 ; read stream of bytes
名前つき属性は、アプリケーションのためにあります。NFS実装で必要な属性は、IETF 標準化プロセスにのせて、必須あるいは推奨属性にするように。
OPENATTR で、隠れたディレクトリが見えるといってもそれはプロトコルの上での方便で、サーバーにそういう実装がしてあるとは、クライアントは期待してはいけません。名前つき属性のディレクトリへの SETATTR やGETATTR は、無効です。
5.1 必須属性 は、必須です。(大意)
5.2 推奨属性(大意)
ないこともあるので、クライアントもサーバーもそれに備えるように。サポートしない属性を要求されたサーバーは、要求自体をエラーとするのでなく、その属性を返さないのがよいです。「うそをついてでも」何かそれらしいものを返すのがよいかは、びみょうなところです。
5.3 名前つき属性
は、NFSv4プロトコルでエンコードが決まっているわけではなく、文字列の名前でアクセスされます。
OPENATTR の結果のファイルハンドルをもとに、READDIR やLOOKUP ができます。READ 、WRITE、 CREATE も可能です。
サーバーは任意の名前つき属性をサポートしていることが推奨されます。クライアントがファイルのデータとメタデータを欠落なくコピーできるべきであることを考えると、クライアントが普通のファイル名に使える文字は、名前つき属性の名前としても有効であるべきでしょう。
属性の名前は、この文書でも、IETF 標準でもコントロールされていません。詳しくは、「IANA 考察」の節を参照ください。
5.4 属性の区別
必須と推奨属性は、サーバーごと、ファイルシステムごと、あるいはファイルシステムオブジェクトごと、のいずれかです。ファイルシステムごとに決まっている属性が、ファイルシステム内で変わることもあります。「homogeneous」属性の定義を参照下さい。time_access_set と time_modify_set 属性はここには載せてありません。それは、特別な SETATTR で使われる、time_access と time_modify に対応したライトオンリーの属性だからです。
o サーバーごとの属性は、
lease_time
o ファイルシステムごとの属性は、
supp_attr, fh_expire_type, link_support, symlink_support,
unique_handles, aclsupport, cansettime, case_insensitive,
case_preserving, chown_restricted, files_avail, files_free,
files_total, fs_locations, homogeneous, maxfilesize, maxname,
maxread, maxwrite, no_trunc, space_avail, space_free, space_total,
time_delta
o ファイルシステムオブジェクトごとの属性は、
type, change, size, named_attr, fsid, rdattr_error, filehandle,
ACL, archive, fileid, hidden, maxlink, mimetype, mode, numlinks,
owner, owner_group, rawdev, space_used, system, time_access,
time_backup, time_create, time_metadata, time_modify,
mounted_on_fileid
です。
quota_avail_hard, quota_avail_soft と quota_used の分類は、後述するそれらの定義を参照下さい。
5.5 必須属性の定義
Name # DataType Access Description
___________________________________________________________________
supp_attr 0 bitmap READ すべての、サポートされる必須と推奨属性を示すビットベクトル。同じ fsid のすべてのオブジェクトに適用されます。
type 1 nfs4_ftype READ オブジェクトのタイプ。(ファイル、ディレクトリ、シンボリックリンクなど)
fh_expire_type 2 uint32 READ ファイルハンドルが失効するふるまい。「ファイルハンドル」の節を参照下さい。
change 3 uint64 READ サーバーにより作られる値で、クライアントは、ファイルデータ、ディレクトリの内容、あるいはオブジェクトの属性が変化したかどうかを判断するために使うことができます。
サーバーは、オブジェクトの time_metadata の値を、この属性値として使っても良いですが、ファイルシステムオブジェクトが、 time_metadata の値より細かい粒度で更新されることがあるならば、そうしてはいけません。
size 4 uint64 R/W バイト単位のオブジェクトの長さ
link_support 5 bool READ ファイルシステムがハードリンクをサポートするなら真。
symlink_support 6 bool READ シンボリックリンクをサポートするなら真。
named_attr 7 bool READ オブジェクトが名前付き属性を持つなら真。つまり、名前付き属性ディレクトリがあります。
fsid 8 fsid4 READ ファイルシステムを識別するユニークなID 。メジャーとマイナーコンポーネントを持ち、それぞれは uint64 です。
unique_handles 9 bool READ 2つの異なるファイルハンドルが、2つの異なるファイルシステムオブジェクトを指すことが保証されるなら、真。
lease_time 10 nfs_lease4 READ サーバーでのリース期間を秒で示したもの。.
rdattr_error 11 enum READ readdir のとき、 getattr で返るエラー。
filehandle 19 nfs_fh4 READ このオブジェクトのファイルハンドル。(主に、readdir 要求で使われます。)
5.6 推奨属性の定義
Name # Data Type Access Description
_____________________________________________________________________
ACL 12 nfsace4<> R/W アクセスコントロールリスト
aclsupport 13 uint32 READ このファイルシステムでサポートされる ACL のタイプ。
archive 14 bool R/W 最後の更新移行、アーカイブされたなら真。(代わりに、time_backup を使うこと。)
cansettime 15 bool READ SETATTR で、各種時刻を設定できれば真。
case_insensitive 16 bool READ ファイル名の比較が、大文字小文字を区別しないなら真。
case_preserving 17 bool READ ファイル名の大文字小文字が保持されるなら真。
chown_restricted 18 bool READ コール元が特別なユーザー、(UNIX の"root" 、Windows 2000 の "Take Ownership" 権限など)を持たない限り、サーバーがファイルの所有者あるいはグループを変更することを拒否するなら真。
fileid 20 uint64 READ ファイルシステム内でファイルをユニークに識別する番号
files_avail 21 uint64 READ このユーザーがこのファイルシステムで使用出来るファイルスロットの数。なお、これは最小値です。
files_free 22 uint64 READ このファイルシステムの空きファイルスロットの数。
files_total 23 uint64 READ このファイルシステムのファイルスロットの合計数。
fs_locations 24 fs_locations READ このファイルシステムがあるかもしれない場所。サーバーが NFS4ERR_MOVED を返すならば、この属性はサポートされなくてはいけません。
hidden 25 bool R/W Windows API から見て、隠れたファイルなら、真。
homogeneous 26 bool READ ファイルシステムが均質なら真。つまり、すべてのファイルシステムオブジェクトで、ファイルシステム属性は同じか。
maxfilesize 27 uint64 READ ファイルの最大長。
maxlink 28 uint32 READ リンクの最大数。
maxname 29 uint32 READ ファイル名の最大長。
maxread 30 uint64 READ リードの最大長。
maxwrite 31 uint64 READ ライトの最大長。
mimetype 32 utf8<> R/W MIME body type/subtype
mode 33 mode4 R/W UNIX-スタイルの mode とパーミッション
no_trunc 34 bool READ name_max より長い名前が使われた時、エラーが返り、名前は切り詰められることはないなら真。
numlinks 35 uint32 READ ハードリンクの数。
owner 36 utf8<> R/W 所有者の文字列で表した名前。
owner_group 37 utf8<> R/W 所有グループの文字列で表した名前。
quota_avail_hard 38 uint64 READ 後述する「クオータ属性」を参照。
quota_avail_soft 39 uint64 READ 同上。
quota_used 40 uint64 READ 同上。
rawdev 41 specdata4 READ ローデバイス識別子。UNIX デバイスのメジャーとマイナー番号。type が NF4BLK と NF4CHR 以外の場合、これは無効。
space_avail 42 uint64 READ このユーザーがこのファイルシステムで使用出来るディスク容量のバイト数。なお、これは最小値です。
space_free 43 uint64 READ このファイルシステムの空きディスク容量のバイト数。
space_total 44 uint64 READ このファイルシステムのディスク容量の総バイト数。
space_used 45 uint64 READ このオブジェクトに割り当てられているバイト数。
system 46 bool R/W Windows API から見て、「システム」ファイルなら、真。
time_access 47 nfstime4 READ サーバーが受け付けたリードによる、そのオブジェクトの最後のアクセス時刻。
time_access_set 48 settime4 WRITE SETATTR でだけ使われる、最後のアクセス時刻設定。
time_backup 49 nfstime4 R/W 最後のバックアップ時刻。
time_create 50 nfstime4 R/W オブジェクトが作成された時刻。これは、伝統的な UNIX の "ctime" あるいは "change time" とは関係ありません。
time_delta 51 nfstime4 READ サーバーが可能な最小の時間粒度。
time_metadata 52 nfstime4 READ 最後のメタデータ変更時刻。
time_modify 53 nfstime4 READ 最後の変更時刻。
time_modify_set 54 settime4 WRITE SETATTR でだけ使われる、最後の変更時刻設定。
mounted_on_fileid 55 uint64 READ fileid に似ていますが、対象のファイルハンドルが、ファイルシステムのルートなら、下になっているディレクトリの fileid を返します。
5.7 アクセス時刻
time_access 属性は、リードによりアクセスされた最後の時刻を示します。「アクセス」が何かは、環境に依存します。POSIX セマンティクスに従うサーバーであれば、それは、READLINK, READ, そして READDIR により更新されます。オブジェクトの内容を変更する操作は除かれます。
サーバーは、性能向上のために、time_access 属性を遅延してディスクに書き戻してもよいです。
5.8 所有者と所有者グループの評価
推奨属性「owner」と「owner_group」(また、「acl」属性のユーザーとグループ)は、UTF-8 文字列で表現されます。クライアントあるいはサーバーの特定の実装に依存する表現を避けるために、UTF-8 文字列表現が選ばれました。[RFC2624] の6.1節に、別の理由が書いてあります。クライアントもサーバーも、所有者と所有者グループについて、ローカル記憶域もしくは、エンドユーザーへの表示のために、独自のローカル表現を持っていることでしょう。このため、クライアントとサーバーの間で、これらの属性が送受信されるときはローカル表現は、「user@dns_domain」のようなシンタックスを持つ形に変換されることでしょう。そうすれば、同じローカル表現を持たないクライアントとサーバー同士でも、共通のシンタックスへの変換が可能です。
同じように、セキュリティプリンシパルも、セキュリティ機構によって異なる表現がされるかもしれません。サーバーは、通常、その表現を、そのセキュリティプリンシパルに対応するユーザーを識別するためにローカル記憶域で使われる共通のフォーマットに変換します。このローカル識別子が所有者属性に変換されるときは、そのファイルの所有者に対応するセキュリティプリンシパルの標準の形式が使われます。
所有者とグループ文字列の評価法は、プロトコルの一部ではありません。これにより、いろいろなやり方が可能です。例えば、数字の ID と user@dns_domain シンタックスをマップするローカルな変換テーブルを使ってもいいでしょう。ネームサービスを使っても良いでしょう。単純な変換にとどまらない実装も可能です。変換が可能な場合はローカル表現を使い、そうでないもののために属性の完全な文字列をローカル記憶域に格納しておく、などです。
owner, owner_group 属性のすべての可能な値をサポートしないサーバーは、 SETATTR のときに、owner, owner_group あるいは acl 属性に設定するべき値として、変換ができない文字列を渡された時に NFS4ERR_BADOWNER エラーを返すべきです。サーバーが、 SETATTR あるいは、ACLにおいて、有効として受け入れた owner と owner_group 属性は、対応する GETATTR のときには、全く同じ文字列が返されるべきです。構成変更や、名前変換の設定誤り(別名がある場合)のために、そうならない場合もあるでしょう。サーバーは、これらの属性が、実際の所有者変更がないときには、変更されないという保証をするために十分な努力をするべきです。
所有者文字列の「 dns_domain」部分は、DNSドメイン名です。たとえば、user@ietf.org 。サーバーは、少なくとも1つのドメインのユーザーの集まりを、有効なものとして受け入れるべきです。サーバーは、それ以外のドメインを、有効な変換を持たないものとして扱ってもよろしい。サーバーが複数のドメインのユーザーを受け付けることができたり、あるセキュリティ条件の下ですべてのドメインのユーザーを受け付けることができるならば、より一般的なサービスを提供することができるでしょう。
クライアントあるいはサーバーで、使用可能な変換がない場合、属性値は、「@」なしに構成されなくてはいけません。この結果、owner あるいは owner_group 属性に @ がないということは、送信元で変換が不可能であったことを意味し、属性の受信側はその文字列を自分の内部的な形式の基準として使うべきではないということを意味します。属性値が変換可能でなかったとしても、それは役に立つことがあります。クライアントの場合、属性文字列は所有者のローカル表示に使うことができるでしょう。
以前のバージョンのNFS(v2, v3) は、ユーザーとグループを32ビットの符号なし整数の uid, gid で表現しましたから、それとの最大の互換性を提供するために、所有者とグループ文字列で、最初がゼロでない、10進数で構成される文字列は、そのようなサポートを提供しようとするクライアントとサーバーにとって特別に解釈されることがあります。受信側では、そのような所有者とグループ文字列を、 v2/v3 の uid, gid で対応する数値を持つユーザーとして扱うことになります。サーバーはそのような文字列を受け付ける義務はなく、NFS4ERR_BADOWNER を返してもよいです。クライアントがすべての所有者とグループを数字で指定することで、この機構を悪用して、ユーザーとグループの変換をすべて回避するようなことを防ぐために、サーバーは、このように指定されてきたユーザーあるいは所有者に有効な変換がない場合は、(訳注。原文 not がないと思う。)NFS4ERR_BADOWNER を返すべきです。その場合は、クライアントは互換性のためのこの特別な形式を使わずに、正しい、name@domain 文字列を使わなくてはいけません。
所有者文字列「nobody」は、匿名のユーザーを示すのに使われることがあります。通常の方法で、所有者属性とのマッピングができないセキュリティプリンシパルによって作成されたファイルのために使われます。
5.9 大文字小文字属性
case_insensitive と case_preserving 属性に関していうと、それぞれの UCS-4 文字 (それらは、 UTF-8 でエンコードされます) は、 "long descriptive name" [RFC1345] を持ち、それは "CAPITAL" あるいは "SMALL" 語を持つことも持たないこともあります。 SMALL あるいは CAPITAL がある場合、NFS サーバーは、大文字小文字を区別しない比較と、それを保持しない記憶域をあいまいさがなく、効率的なテーブルドリブンの実装をすることができます。一般的な、文字の処理と国際化の問題については、「国際化」の節を参照下さい。
5.10 クオータ属性
ファイルシステムのクオータに関連する属性の定義を以下に示します。
quota_avail_soft
ユーザーが警告を受けることなくこのファイルあるいはディレクトリに確保することのできる、追加のディスク容量を示すバイト数。この領域は、他のファイルやディレクトリに使用されることで消費されることがありますが、どのファイルとディレクトリが対象となるかについては規則があります。
quota_avail_hard
この限界値を超えると、それ以上の確保が許されません。
quota_used
このファイルあるいはディレクトリが使っているディスク容量のバイト数。ただし、「類似の」ファイルやディレクトリの分を含むことがあります。類似、というのは、その集合で行われる確保は、集合に属するファイルやディレクトリの「quota_avail_hard」を減らすことがある、ということです。
quota_used の値が維持されるファイルとディレクトリの集合は、複数、オーバーラップしていることがあります。(例えば、「ある所有者のすべてのファイル」、「あるグループが所有するすべてのファイル」などです。)
サーバーは、どの集合を使うかは任意です。ただ、反復可能な方法で行うこと。規則は、ファイルシステムごとに行われることも、「最小のクオータ」の集合を選択するということもあるでしょう。
訳注。古典的な UNIX では、特定ファイルシステム内の特定ユーザーの所有するファイルのバイト数の総和が制限できました。 Windows 2003 R2 では、特定ディレクトリ以下のファイルのバイト数の総和が制限できました。ユーザーは問いません。類似とか規則とか、あいまいな表現が多いですが、相互運用性というものはそういうものです。
5.11 アクセス制御リスト
NFSv4 ACL属性は、アクセス制御エントリー(ACE)の配列です。クライアントはACL属性を読み書きできますが、NFSv4モデルでは、サーバーが、自分の ACL 解釈に基づいてアクセス制御をします。クライアントは、OPEN, ACCESS 操作を使えば、実際にデータを読み書きすることなく、アクセス権をチェックできます。「ACE タイプ」節に示す、いろいろなアクセス制御エントリーがあります。サーバーは、aclsupport 属性のビットで、どの ACE タイプをサポートしているかを返します。「ACE アクセスマスク」節に示すように、それぞれのACE は、ファイルあるいはディレクトリに対する操作を規定します。「ACE フラグ」節に示すフラグが、ACE のセマンティクスを変更することがあります。
NFS ACE 属性は、以下に定義されます。
typedef uint32_t acetype4;
typedef uint32_t aceflag4;
typedef uint32_t acemask4;
struct nfsace4 {
acetype4 type;
aceflag4 flag;
acemask4 access_mask;
utf8str_mixed who;
};
要求が成功するかどうかを決めるために、それぞれの nfsace4 エントリーはサーバーによって、順に処理されます。「who」が要求の発行者と一致するエントリーだけが扱われます。ACE は、要求者のアクセスのすべてのビットが許可されるまで処理されます。ACCESS_ALLOWED_ACE によってあるビットが許可されたら、そのビットは以降のACE の処理では対象とされません。要求者のアクセスマスクに許可ビットが立っておらず、ACE の「access_mask」が立っているときに、ACCESS_DENIED_ACE が現れたならば、要求は拒否されます。一方、ALARM とAUDIT ACE タイプは、ALLOWED とDENIED ACE タイプとは異なり、要求者のアクセスに影響を与えるのでなく、アクセスの試みの結果としてイベントを発生させるためのものです。
このため、すべての ALARM とAUDIT ACE は、ACL の最後まで処理されます。ACL がすべて処理された時に、要求者のマスクにおいて、サーバーがアクセスを許可したのか拒否したのかどちらも決まっていないものがあれば、アクセスは、未定義です。ファイルにモード属性があるならば、これは起きません。モードの MODE4_*OTH ビットは EVERYONE@ にマップされ、要求者のアクセスをあいまいさなしに決定するはずだからです。
NFSv4 ACL モデルはとてもリッチです。サーバープラットフォームには、UNIX スタイルのモード属性を超えるアクセス制御を提供するものの、NFS ACL モデルほどリッチではないものがあります。ユーザーが、このような限定された機能を有効に使えるように、サーバーは、自分の ACL モデルと NFSv4 ACL モデルのマッピングについてのガイドラインに従うならば、ACL をサポートしているといってもかまいません。
サーバーが ACL を提供する複数のモジュールを持つときは、少しややこしくなります。例えば、NFSv4アクセス制御の実施は、ローカルアクセスとは異なり、さらにそれは SMB のような他のプロトコルを経由するアクセス制御の実施とは異なるでしょう。このため、サーバーは、自分のすべてのモジュールがサポートしていない場合も、ある ACL を受け入れる方がよいでしょう。
すべての場合に重要なのは、サーバーは、ファイルが、実際よりもセキュアに見えるような ACL を受け入れてはいけないということです。
5.11.1 ACE タイプ
Type Description
_____________________________________________________
ALLOW acemask4 で指定されるアクセスをあらわに許可する。
DENY 同じく、拒否する。
AUDIT acemask4 で指定されるアクセスをするものがあれば、システム依存のログを取る。
ALARM 同じく、警告をする。
サーバーは、上記すべての ACE をサポートする必要はありません。aclsupport 属性で使われるビットマスク定数は以下です。
const ACL4_SUPPORT_ALLOW_ACL = 0x00000001;
const ACL4_SUPPORT_DENY_ACL = 0x00000002;
const ACL4_SUPPORT_AUDIT_ACL = 0x00000004;
const ACL4_SUPPORT_ALARM_ACL = 0x00000008;
「type」 の意味は前記のとおりです。
acetype4 で使われる定数は以下です。
const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000;
const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001;
const ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002;
const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003;
クライアントは、サーバーがサポートしていない ACE タイプを設定してはいけません。その場合、サーバーは、自分が格納できないACE を受け取ったならば、NFS4ERR_ATTRNOTSUPP で要求を失敗させなくてはいけません。また、自分が格納できるけど、実施できないACE を受け取ったならば、NFS4ERR_ATTRNOTSUPP で要求を失敗させるべきです。
例:サーバーは、NFSアクセスに対してはNFS ACL を実施できるが、ローカルアクセスには ACL を実施できないとします。任意のプロセスがサーバーで動くことがあるならば、サーバーは ACL サポートを表明するべきではありません。一方、ローカルには、信頼できる管理プログラムだけが動作するならが、サーバーは ACL サポートを表明できます。
5.11.2 ACE アクセスマスク
access_mask は、以下の値を持ちます。
Access Description
_______________________________________________________________
READ_DATA ファイルのデータを読む権限
LIST_DIRECTORY ディレクトリの内容を表示する
WRITE_DATA ファイルのデータを変更する
ADD_FILE ディレクトリに新しいファイルを追加する
APPEND_DATA ファイルにデータを追加する
ADD_SUBDIRECTORY ディレクトリにサブディレクトリを作る
READ_NAMED_ATTRS ファイルの名前つき属性を読む
WRITE_NAMED_ATTRS 名前つき属性を変更する
EXECUTE ファイルを実行する
DELETE_CHILD ディレクトリ内のファイルあるいはディレクトリを削除する
READ_ATTRIBUTES ファイルの基本的(ACL でない)属性を読む
WRITE_ATTRIBUTES 基本的属性を変更する
DELETE ファイルを削除する
READ_ACL ACL を読む
WRITE_ACL ACL を書く
WRITE_OWNER 所有者を変更する
SYNCHRONIZE サーバーにおいて、ファイルをローカルに、同期リードとライトでアクセスする
access_mask で使われるビットマスク定数は以下です。
const ACE4_READ_DATA = 0x00000001;
const ACE4_LIST_DIRECTORY = 0x00000001;
const ACE4_WRITE_DATA = 0x00000002;
const ACE4_ADD_FILE = 0x00000002;
const ACE4_APPEND_DATA = 0x00000004;
const ACE4_ADD_SUBDIRECTORY = 0x00000004;
const ACE4_READ_NAMED_ATTRS = 0x00000008;
const ACE4_WRITE_NAMED_ATTRS = 0x00000010;
const ACE4_EXECUTE = 0x00000020;
const ACE4_DELETE_CHILD = 0x00000040;
const ACE4_READ_ATTRIBUTES = 0x00000080;
const ACE4_WRITE_ATTRIBUTES = 0x00000100;
const ACE4_DELETE = 0x00010000;
const ACE4_READ_ACL = 0x00020000;
const ACE4_WRITE_ACL = 0x00040000;
const ACE4_WRITE_OWNER = 0x00080000;
const ACE4_SYNCHRONIZE = 0x00100000;
サーバー実装は、このマスクのリストで提供される制御の粒度を提供する必要はありません。例えば、 POSIX ベースのシステムは、APPEND_DATA (追加書き)と、WRITE_DATA (既存データを上書き)の区別をしません。どちらのマスクも、1つの「ライト」権限に対応します。そのようなサーバーがクライアントに属性を返すときは、ライト権限が有効なときに限り、APPEND_DATA と、WRITE_DATA の両方を立てるのがよいでしょう。
サーバーが、正確に実装できない SETATTR 要求を受けた場合、よりアクセスが限られる方向にエラーとするべきです。例えば、前のパラグラフで述べたように、サーバーがデータの上書きと追加書きを区別できないとします。クライアントが、APPEND_DATA がオンで、WRITE_DATA がオフの ACE (あるいは、その逆)を送ってきた場合、サーバーは NFS4ERR_ATTRNOTSUPP エラーを返すべきです。一方、 ACE タイプが、 DENY ならば、サーバーは、黙って他のビットも立てて、APPEND_DATAと、WRITE_DATA が拒否されるようにすることができます。
5.11.3 ACE フラグ
「flag」 フィールドの意味は以下です。
ACE4_FILE_INHERIT_ACE
ディレクトリに設定することができ、新しく作成されたファイルには全て、この ACE が追加されます。.
ACE4_DIRECTORY_INHERIT_ACE
同じく、新しく作成されたディレクトリが対象
ACE4_INHERIT_ONLY_ACE
ディレクトリに設定することができ、新しく作成されたファイルとディレクトリには全て、この ACE が追加されます。元のディレクトリ自身には適用されません。
ACE4_NO_PROPAGATE_INHERIT_ACE
ディレクトリに設定することができます。通常は、新しいディレクトリが作成され、親ディレクトリに ACL4_DIRECTORY_INHERIT_ACE があるときは、新しいディレクトリには2つの ACE が設定されます。1つはディレクトリ自身のため、もうひとつは継承された ACE です。このフラグは、サーバーに、このディレクトリのサブディレクトリには、継承された ACE を追加しないように指示します。訳注。?
ACE4_SUCCESSFUL_ACCESS_ACE_FLAG
ACL4_FAILED_ACCESS_ACE_FLAG
ACE4_SUCCESSFUL_ACCESS_ACE_FLAG (SUCCESS) と
ACE4_FAILED_ACCESS_ACE_FLAG (FAILED) フラグビットは、
ACE4_SYSTEM_AUDIT_ACE_TYPE (AUDIT) と ACE4_SYSTEM_ALARM_ACE_TYPE
(ALARM) ACE タイプにだけ関係があります。
ファイルの ACL の処理の途中でサーバーが OPEN をしているプリンリパルに合った AUDIT あるいは ALARM ACE を見つけたら、サーバーはその事実と、 AUDIT あるいは ALARM ACE にもしあった場合 SUCCESS と FAILED のフラグの有無を記録します。
サーバーが ACL の処理と、共有予約と、OPEN を完了したとき、サーバーは OPEN が成功か失敗かを記録します。
OPEN が成功し、かつ、SUCCESS フラグのついた AUDIT あるいは ALARM があった場合、 AUDIT あるいは ALARM のイベントが発生します。OPEN が失敗し、かつ、 FAILED フラグがある場合、イベントが発生します。
SUCCESS と FAILED の片方、あるいは両方を指定することができます。どちらも指定しないこともできますが、それだと、 AUDIT あるいは ALARM としての用をなしません。
以上の議論は、 ACCESS 操作にもあてはまります。「成功」、「失敗」は、 NFS4_OK が返ったかどうかによりません。成功とは、 ACCESS が、要求され、かつサポートされているビットを返したことです。失敗は返さないビットがあったことです。
ACE4_IDENTIFIER_GROUP
「who」が、UNIX でいう GROUP であることを示します。
flag で使われるビットマスク定数は以下です。
const ACE4_FILE_INHERIT_ACE = 0x00000001;
const ACE4_DIRECTORY_INHERIT_ACE = 0x00000002;
const ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004;
const ACE4_INHERIT_ONLY_ACE = 0x00000008;
const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010;
const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020;
const ACE4_IDENTIFIER_GROUP = 0x00000040;
サーバーはこれらのフラグをサポートする必要はありません。もし、サーバーが、これらと似ているけど同じではないフラグをサポートしているなら、プロトコルと実装のフラグの対応をサーバーが定義するのが良いでしょう。繰り返しになりますが、ファイルが、実際よりもセキュアに見えてはいけないというのが、原則です。
例えば、クライアントが ACE4_FILE_INHERIT_ACE がオンで、ACE4_DIRECTORY_INHERIT_ACE がオフの ACE を設定しようとした場合を考えます。もし、サーバーが ACL の継承というものを全くサポートしないなら、要求は NFS4ERR_ATTRNOTSUPP で拒絶されるべきです。サーバーが、ファイルとディレクトリに適用される単一の「ACE 継承」フラグをサポートしているなら、サーバーは要求を拒絶しても良いでしょう。(つまり、クライアントに、ファイルとディレクトリ両方の継承フラグを立てることを要求するわけです。)あるいは、サーバーは何も言わずに要求を受け付けて、ACE4_DIRECTORY_INHERIT_ACE をオンにすることもできます。
5.11.4 ACE who
特別な ID 「who」がいくつかあり、特定の DNS ドメインの文脈でなくて一般的に扱われなくてはいけません。そのいくつかは、NFS クライアントがサーバーをアクセスするときには使われず、ローカルプロセスがファイルをアクセスするときしか意味を持ちません。これらの権限は、サーバーのアクセスメソッドがそれらの ID を理解しない時でも、NFS 経由で表示、設定できます。
Who Description
_______________________________________________________________
"OWNER" ファイル所有者
"GROUP" 関連するグループ
"EVERYONE" 世界
"INTERACTIVE" 対話的端末からのアクセス
"NETWORK" ネットワーク経由
"DIALUP" ダイアルアップ接続
"BATCH" バッチジョブ
"ANONYMOUS" 認証なし
"AUTHENTICATED" 認証された任意のユーザー。ANONYMOUS の逆。
"SERVICE" システムサービス
衝突を防ぐために、これらの特殊 ID は、「@」を後ろにつけて、「xxxx@」のように書かれます。(「@」の後に、ドメイン名がありません。)例えば、ANONYMOUS@
5.11.5 モード属性
NFSv4 モード属性は、UNIX モードビットを基本とします。以下のビットが定義されます。
const MODE4_SUID = 0x800; /* set user id on execution */
const MODE4_SGID = 0x400; /* set group id on execution */
const MODE4_SVTX = 0x200; /* save text even after use */
const MODE4_RUSR = 0x100; /* read permission: owner */
const MODE4_WUSR = 0x080; /* write permission: owner */
const MODE4_XUSR = 0x040; /* execute permission: owner */
const MODE4_RGRP = 0x020; /* read permission: group */
const MODE4_WGRP = 0x010; /* write permission: group */
const MODE4_XGRP = 0x008; /* execute permission: group */
const MODE4_ROTH = 0x004; /* read permission: other */
const MODE4_WOTH = 0x002; /* write permission: other */
const MODE4_XOTH = 0x001; /* execute permission: other */
MODE4_RUSR, MODE4_WUSR, とMODE4_XUSR は、 owner 属性が示すプリンリパルに適用されます。MODE4_RGRP, MODE4_WGRP, と MODE4_XGRPは、 owner_group が示すプリンリパルに適用されます。MODE4_ROTH, MODE4_WOTH, MODE4_XOTH は、owner にも owner_group にもマッチしないプリンリパルに適用されます。
これ以外のビットは使ってはいけません。使うときは、マイナーバージョンアップすること。
なお、UNIX では、sgid が立って、xgrp が立ってないときはマンダトリーファイルロックを意味します。
5.11.6 モードとACL 属性
の両方をサポートするサーバーは、 MODE4_*USR, MODE4_*GRP, と MODE4_*OTH ビットを、ACE の "OWNER@", "GROUP@", と "EVERYONE@" に読み替えて、クライアントが owner, owner_group と mode 属性を見た時と、ACL を見た時で、意味的に等しいアクセス権限が得られるようにすること。
sgid ビットのように、ACL に対応しないモード属性のビットもあるので、クライアントは、同じ SETATTR に、ACL とモードの両方を指定してもかまいません。しかし、SETATTR に指定される複数の属性を処理する順序は決まっていないため、クライアントは、どちらが先に処理されても同じ結果になるように、ACL とモードの内容に注意すること。
5.11.7 mounted_on_fileid
UNIX 環境では、ファイルシステムを既存のファイルオブジェクト、(マウントポイント。通常は、ディレクトリ)に接続して、ネームスペースに接続します。マウントポイントの親ディレクトリを、readdir などの API で読むと、コンポーネント名と fileid を含むディレクトリエントリーが得られます。しかし、マウントポイントを、stat したときの fileid は、readdir で返されるものと違って、ファイルシステムのルートのものとなります。
NFSv3 と違って、 NFSv4 は、クライアントの LOOKUP がファイルシステムをまたがるのを許します。クライアントは、 LOOKUP の結果が、 LOOKUP の引数と違う fileid を持っているときに、ファイルシステムをクロスしたことに気が付きます。UNIX ベースのクライアントは、これを、「マウントポイントクロス」と認識します。UNIX は、プロセスが現在の作業ディレクトリを知るための歴史的なスキーマを持っており、それが、前述の readdir と stat の結果に依存します。mounted_on_fileid 属性は、前記の readdir が返すべきである fileid に対応します。
NFSv4 クライアントは、mounted_on_fileid に相当する fileid を自分で適当に作り上げることもできます。(サーバーがそれをサポートしないこともあるので、そのときはそうするしかありません。)しかし、fileid が、ファイルシステムの他のオブジェクトに既に使われているものと当たる危険があります。サーバーがそれを提供するならば、問題はありません。
対象が、マウントポイントではないときは、mounted_on_fileid は普通の fileid と同じ値です。
mounted_on_fileid は推奨属性なので、サーバーは可能ならそれを提供するべきです。UNIX ベースのサーバーなら、簡単です。通常、mounted_on_fileid は READDIR 操作で要求されるので、UNIX ベースのサーバーが発行する readdir の結果をそのまま使えばよろしい。それが、 GETATTR で要求された時には、サーバーは親ディレクトリのエントリーにあるものを持って来るべきです。環境によっては、1つのマウントポイントに複数のファイルシステムをマウントすることができます。その場合、サーバーは、ベースのマウントポイントを探すべきで、中間のマウントポイントではいけません。
6 ファイルシステム移行と複製
推奨属性「fs_locations」を使うことで、NFSv4 サーバーは、ファイルシステム移行と複製サービスを提供することができます。移行と複製に関するとき、ファイルシステムとは、指定された fsidを持つ(メジャー番号とマイナー番号が同じ)すべてのファイルのことです。fs_locations 属性は、ファイルシステムの位置のリストを持ちます。位置は、サーバーの名前(DNS あるいは IP アドレス)と、ファイルシステムのルートのパス名で示されます。リストは、移行先あるいは、複数の複製先を示します。クライアントはこれを使って、新しいサーバーに要求をリダイレクトします。
6.1 複製
普通、ファイルシステム複製が使われるのは、リードオンリーのデータに限ります。ファイルシステムは2つ以上のサーバーに複製され、fs_locations はクライアントにこれらの位置のリストを与えます。クライアントは、最初のファイルシステムアクセスの時に、fs_locations 属性を取得することが期待されます。将来、サーバーが応答しない時には、クライアントはリストの他のサーバーを使います。
クライアントは、可能ならば、有効なファイルハンドルを新しいサーバーにおいて回復するための適切なステップを行わなくてはいけません。詳細は後述します。
6.2 移行
ファイルシステム移行は、ファイルシステムをあるサーバーから他のサーバーに移動するために行われます。移行は、典型的には、書き込み可能で単一のコピーを持つファイルシステムに使われます。移行の期待される用途は、負荷バランスと、一般的な資源の再配置です。このプロトコルでは、ファイルシステムがサーバー間でいかに移動するかは指定しません。サーバー間の転送機構はサーバー実装に任されています。そのかわりに、クライアントとサーバーの間での、移行イベントの通信方法がここで議論されます。
移行に関連しているサーバーが、ファイルシステムの移動を完了した時、元のサーバーが受信する以降の要求には、NFS4ERR_MOVED エラーが返ります。 PUTFH と GETATTR 以外のすべての操作に、NFS4ERR_MOVED エラーが返ります。クライアントはそのエラーを受けたら、fs_locations 属性を取得して、そこにあるサーバーに要求をリダイレクトします。GETATTR が可能なように、サーバーは、移行したファイルシステムのファイルハンドルについて、 PUTFH のような操作を許可しなくてはいけません。なお、サーバーは、NFS4ERR_MOVED を返したならば、fs_locations 属性をサポートしなくてはいけません。
クライアントが fs_locations 属性以外の属性も要求した場合、サーバーは、fs_locations だけを返すことがあります。ファイルシステムは移行してしまったので、サーバーはそれ以上の属性を知る手段がないため、これは当然です。
移行ソリューションを開発するサーバー実装は注意が必要です。サーバーは、クライアント達がサーバーにおいて持っている、すべての実行中状態の情報を考慮しなくてはいけません。これには、ロック、共有、委譲、WRITE と COMMIT ベリファイアで表現される非同期ファイル書き込みなどがあります。サーバーは、移行中とその後の、クライアントに与える影響を最小にする努力をするべきです。
6.3 fs_locations 属性の解釈
fs_locations 属性の構造は、以下です。
struct fs_location {
utf8str_cis server<>;
pathname4 rootpath;
};
struct fs_locations {
pathname4 fs_root;
fs_location locations<>;
};
fs_location 構造は、ファイルシステムの位置を、サーバー名とルートのパスによって示します。マルチホームのサーバーと、同じ rootpath を使うサーバーの集合では、サーバー名は配列になります。サーバー配列のエントリーは、UTF-8 文字列で、DNS ホスト名、IPv4, IPv6 アドレスのどれかです。同じ rootpath を使うサーバーが、1つの fs_location 構造に入る必要はなく、別の fs_location 構造にあってもかまいません。サーバー名の配列は、便宜のためにあります。
そして、 fs_locations 属性は、位置の配列です。それぞれのサーバーのネームスペースは、異なる作られ方をしているかもしれないので、「fs_root」フィールドがあります。それは、応答を返したサーバーのネームスペースでの、ファイルシステムのパスを示します。それは、クライアントがリストされているサーバーでファイルシステムを位置づける助けになると考えられます。
例えば、servA と servB に複製されているファイルシステムがあるとします。servA では、ファイルシステムは、パス「/a/b/c」に、servB では、ファイルシステムは、パス「/x/y/z」にあります。クライアントは、最初に、servA で、複数コンポーネントのルックアップ "/a/b/c/d" によってアクセスします。クライアントが "/a/b/c/d" のファイルハンドルを得るのに、複数コンポーネントのルックアップを使うため、ファイルシステムのルートが、servA のネームスペース "/a/b/c" にあることはわかりません。クライアントがservB にスイッチしたとき、servA で参照したディレクトリが、servB では、パス "/x/y/z/d" で表されることがわからなくてはいけません。このために、servA が返す fs_locations 属性は、fs_root に "/a/b/c" を持ち、 fs_location に2つのエントリーがあります。1つは、servA 自身のもので、もうひとつは、servB のもので、パス "/x/y/z" が入っています。これによって、クライアントは、アクセスパスの先頭の "/a/b/c" を "/x/y/z" に置換して、新しいサーバーで使う "/x/y/z/d" を構成することができます。
「 fs_location 」を要求する GETATTR で使うことが推奨されるセキュリティフレーバーについては、「セキュリティの考察」の章を参照下さい。
6.4 移行と複製でのファイルハンドル回復
移行あるいは複製されたファイルシステムのファイルハンドルは、一般的には、そうでないファイルシステムのものと比べて同じセマンティクスを持ちます。例えば、ファイルシステムが永続的ファイルハンドルを持ち、他のサーバーに移行したならば、ファイルハンドルの値は新しいサーバーでも有効です。
揮発的ファイルハンドルの場合、関連するサーバーの間で、ファイルハンドルの形式と内容を変換する機構があるとは思われません。このため、サーバーは、元のサーバーからの揮発的ファイルハンドルに対して、NFS4ERR_FHEXPIRED を返すべきか、判断に困ることがあるでしょう。このため、fh_expire_type 属性によって、クライアントは揮発的ファイルハンドルが、移行あるいは複製イベントによって無効となるかを知ることができます。FH4_VOL_MIGRATION が立っているときは、揮発的ファイルハンドルは、サーバーが NFS4ERR_FHEXPIRED を返したかのように扱われます。そのビットが立っている時の移行あるいは複製イベントにおいて、クライアントは元の古い揮発的ファイルハンドルを新しいサーバーに提示してはいけません。クライアントは、新しいサーバーとの会話を、退避してあるファイル名を使ってファイルハンドルを回復することから始めます。
7 NFS サーバーネームスペース
7.1 サーバーエクスポート
UNIXサーバーでは、ネームスペースは、ルートディレクトリ「 / 」の下にある、パス名によって到達できるすべてのファイルを示します。Windows NT サーバーでは、ネームスペースは、ドライブ文字で示されるディスク内のすべてのファイルです。NFS サーバー管理者がNFSクライアントに、サーバーのファイルシステムのネームスペースすべてを公開することは、ほぼありません。「エクスポート」機能により、ネームスペースの一部が公開される方が普通です。以前の バージョンの NFSプロトコルでは、エクスポートごとのルートファイルハンドルは、MOUNT プロトコルにより得られました。クライアントは、ネームスペースのエクスポートを示す文字列を送り、サーバーはそのルートファイルハンドルを返しました。MOUNT プロトコルは、EXPORTS 手続きをサポートし、それはサーバーのエクスポート一覧を返しました。
7.2 エクスポートをブラウズする
NFSv4では、ルートファイルハンドルがあり、クライアントはエクスポートに対応するファイルハンドルを、複数コンポーネントの LOOKUP によって得ます。一般的なユーザ体験として、GUI を使って、ディレクトリツリーをブラウズしながら、ファイルを探す、というものがあるでしょう。
NFSv2 と 3 では、こういうブラウジングはうまくサポートされていませんでした。LOOKUP はファイルシステムを超えることはできなかったのです。例えば、デバイス属性は同じでした。クライアントは、エクスポートをまたがるネームスペースパスを扱うことができませんでした。
クライアントで動く automounter を使えば、EXPORTS 手続きを使って、サーバーのネームスペースのスナップショットを得ることができました。サーバーが公開していないネームスペースの部分は、「擬似ファイルシステム」によって、埋められました。このようにして、ユーザーは、マウントされたファイルシステムの間をブラウズしてまわることができました。しかし、これには、欠点がありました。静的だという事です。サーバー管理者が新しいエクスポートを追加しても、クライアントには見えませんでした。
7.3 サーバー擬似ファイルシステム
NFSv4サーバーは、このネームスペースの矛盾を、1つのサーバーネームスペース内のフレームワークの中にすべてのエクスポートを表現することで解決しました。NFSv4クライアントは、LOOKUP と READDIR 操作を使って、エクスポートの間をシームレスにブラウズすることができます。サーバーネームスペースのうち、エクスポートされていない部分は、公開されるディレクトリを提供する「擬似ファイルシステム」によってブリッジされます。擬似ファイルシステムはユニークな fsid を持ち、通常のリードオンリーのファイルシステムとしてふるまいます。
サーバーのネームスペースの構成によって、複数の擬似ファイルシステムがあることがあります。例えば、
/a pseudo filesystem
/a/b real filesystem
/a/b/c pseudo filesystem
/a/b/c/d real filesystem
それぞれの擬似ファイルシステムは独立しており、別々の fsid を持ちます。
7.4 複数のルート
DOS と Windows オペレーション環境は「複数のルート」を持つといわれます。ファイルシステムはドライブ文字で表されることが一般的です。MacOS は、ファイルシステムを、トップレベルの名前の1つとして表現します。このようなプラットフォームの NFSv4サーバーは、これらのルートの上に擬似ファイルシステムを作って、ドライブ文字やボリューム名が擬似ルートのディレクトリとなるようにすることができます。
7.5 ファイルハンドルの揮発性
擬似ファイルシステムの性質からいって、それはサーバーがブートした時にダイナミックに作られるもので、永続的ファイルハンドルを提供できるようなディスク上のデータ構造はないかもしれません。クライアントは、「fh_expire_type」属性を見て、揮発に備える必要があります。
7.6 エクスポートされたルート
サーバーのルートファイルシステムがエクスポートされたら、擬似ファイルシステムはいらないでしょうか。いいえ。サーバーに以下のファイルシステムがあるとします。
/ disk1 (exported)
/a disk2 (not exported)
/a/b disk3 (exported)
ディスク2はエクスポートされていないので、ディスク3は単純な LOOKUP では到達できません。擬似ファイルシステムでギャップをうめる必要があります。
7.7 マウントポイントを越える
サーバーのファイルシステムは、あるファイルシステムが、別のファイルシステムに「カバーされる」 , mounted upon, ディレクトリを持つように構成されることがあります。例えば、
/a/b (filesystem 1)
/a/b/c/d (filesystem 2)
擬似ファイルシステムはこのようになるでしょう。
/ (place holder/not exported)
/a/b (filesystem 1)
/a/b/c/d (filesystem 2)
サーバーは擬似ファイルシステムがクライアントにとって完全であるように見せる必要があります。クライアントが 「/a/b/c/d」をルックアップしたら、応答は、ファイルシステム「/a/b/c/d」のファイルハンドルでしょう。以前のバージョンのNFSでは、応答は、ファイルシステム「/a/b」の中のディレクトリ「/a/b/c/d」のファイルハンドルでした。
クライアントは、マウントポイントを越えたかを、「fsid」属性の変化で知ることができます。
7.8 セキュリティポリシーとネームスペース公開
実装者は、サーバーのセキュリティポリシーの実施について、よく考えるべきです。アクセス権がないクライアントに、ネームスペースの一部を隠すというのはありがちですが、以下の問題があります。サーバーが複数のセキュリティ機構をサポートし、さらに、その使用を途中でもネゴシエートできることから、サーバーはあらかじめ、クライアントが十分なアクセス権を持っているか、判断できないことがあります。もし、サーバーが最初に擬似ファイルシステムの内容を制限するならば、本来正当なアクセス権を持つクライアントにそれを隠すことになるかもしれません。
おすすめの方法は、資源のセキュリティポリシーを、リソースの先祖に適用することです。例えば、
/
/a/b
/a/b/c
/a/b/c ディレクトリが実際のファイルシステムで共用される資源だとします。そのセキュリティポリシーは、改ざん防止つきのケルベロスです。サーバーは同じポリシーを、/, /a, と /a/b にも使うべきです。
サーバーの資源に、複数の、オーバーラップしないセキュリティ機構がある場合、あるオブジェクトのセキュリティ機構はそれのすべての直接の子孫の機構のユニオンであるべきです。
終わり。親文書、RFC3530の訳はこちら。