MOUNT_NULL(8)

名称
mount_null - ループバックファイルシステムサブツリーをマウントする; 何もしない(null)ファイルシステム層の利用のデモ

書式
mount_null [-o options] target mount_point

解説
mount_null は、null 層を作ります。これは、 ファイルシステムの名前空間の部分木を、グローバルなファイルシステムの名前空間 の別の場所にエイリアスします。 これにより、既存のファイルとディレクトリが別のパス名にてアクセス可能 となります。

ファイルシステムの仮想的コピーとシンボリックリンクとの第 1 の違いは、 getcwd(3) 関数が仮想コピーでは正しく動作する点と、 別のファイルシステムを仮想コピー上にマウントしてもオリジナルには影響がない点 です。 stat(2) は、仮想コピーに対して別のデバイス番号が返しますが、 別の側面においてはオリジナルとの区別はつきません。

歴史的な ループバックファイルシステムと異なるのは、次の2つの点です: 1つは、ファイル システムのスタック化可能層(stackable layers)という技術を使って 実装されている点、もう1つはディレクトリの vnode だけでなく、 すべての下位層の vnode の上に ``null-node''が積み重なっているという点です。

オプションは以下のものがあります:

-o  -o のあとに、オプション文字列をコンマで区切って指定すること ができます。指定可能なオプションとその意味は mount(8) を参照してください。

この null 層は2つの目的を持っています。1つは、何もしない層 を提供することでファイルシステムの層の構築のデモを示すことです(実際には 何も行わないというわけではなく、 ループバックファイルシステムが提供することはすべて行います)。 もう1つはプロトタイプ層を提供することで す。層のフレームワークとして必要なことはすべて提供しているので、 ここから新しいファイルシステム層を簡単に作り出すことができます。

このマニュアルの以下の部分では、新しいファイルシステム層を構築するための 基礎として null 層を調べます。

新しい null 層の例示
新しい null 層は mount_null(8) で作られます。 mount_null(8) は 2つの引数をとります。 1つは下位層の vfs のパス名(target-pn)で、 もう1つは null 層が現れる名前空間内のパス名(mount-point-pn)です。 null 層が適切な場所に置かれた後、 目的のディレクトリ階層(target-pn)の中身が マウント先(mount-point-pn)にエイリアスされます。

null 層の操作
null 層は最小のファイルシステム層であり、 すべての操作を下位層に処理させるためにバイパスするだけです。 ほとんどすべてのvnodeに対する操作はパスすることですが、 その動作のほとんどはバイパスルーチンに集中します。

バイパスルーチンは下位層における任意の vnode に対する操作を受け付けます。 まず、vnodeに対する操作の引数を検査し、 null-node を下位層において等価となるものに置き換えることから始めます。 次に、下位層の操作を起動します。 最後に、引数中の null-node を置き換えます。 もしその操作によってvnodeが返ってきたら、 その返ってきたvnodeの上に null-node を積みます。

ほとんどの操作をバイパスしますが、 vop_getattr, vop_inactive, vop_reclaim, や vop_print はバイパスしません。 vop_getattr は戻り値の fsid を替えなければなりません。 vop_inactive と vop_reclaim は、null 層特有のデータを解放するためにバイパスしません。 vop_print は過度のデバッグ情報を避けるためにバイパスしません。

vnodeスタックの概説
マウントは null 層を下位層に関連づけます。 その結果 2 つの VFS が積み重なります。 vnode スタックはファイルがアクセスされるたびに必要に応じて作成されます。

最初のマウントでは新しい null 層の根として単一の vnode スタックを作ります。 他のすべての vnode スタックは根の vnode スタックや他の null vnode スタックの 操作の結果として作られます。

vnode を返す操作の結果として新しい vnode スタックが生まれます。 バイパスルーチンは、呼出し側に vnode を返す前に新しい vnode の上に null-node を積みます。

例えば、null 層を以下のようにマウントする例を想像します。

    mount_null /usr/include /dev/layer/null

/dev/layer/null にチェンジディレクトリすると、根の null-node (null 層をマウントした時 に作られたもの) が割り当てられます。 ここで sys をオープンすることを考えてみます。 vop_lookup は根の null-node で行なわれます。 この操作は下位層にバイパスされ、下位層が UFS の sys を表す vnode を返します。 それから null_bypass は UFS sys にエイリアスする null-node を構築し、呼出元にこれを返します。 null-node sys に対する以降の操作で他のvnodeスタックを構築する時には この処理が繰り返されます。

他のファイルシステム層の作成
新しいファイルシステム層を構築する一番簡単な方法は、 null 層のコピーを作り、すべてのファイル、変数の名前を付け直し、 そしてそのコピーを変更することです。 すべての変数の名前を変えるのには sed(1) が良く使われます。

umap 層は null 層の子孫の 1 例です。

下位層の操作の起動
操作が完全にはバイパスできない時に 下位層にある操作を起動するための方法が 2 つあります。 それぞれの方法は違った状況に対して適切に使われます。 両方の場合とも、 その操作の引数を下位層のために正しく作るのはエイリアスする層の責任であり、 vnode 引数を下位層にマッピングします。

最初の方法はエイリアスする層のバイパスルーチンを呼ぶことです。 この方法は、下位層で現在扱われている操作を起動したい時に最も適しています。 これはバイパスルーチンがすでにマッピングされているという利点があります。 この例として、 null_getattrs が null 層にあります。

2 つ目の方法は、 VOP_OPERATIONNAME インタフェースを用いて下位層のvnodeの操作を直接起動することです。 この方法の利点は、下位層の任意の操作を起動するのが簡単ということにあります。 欠点は、vnode 引数は手動でマッピングされなければならないことです。

関連項目
mount(8)

UCLA Technical Report CSD-910056, Stackable Layers: an Architecture for File System Development.

歴史
mount_null は、 4.4BSD から登場しました。