[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Stored(FIXME-J:ストアード?)ファイルシステムにより、 ユーザはハード・ディスク、 フロッピ・ディスク、 CD-ROMのようなランダム・アクセス可能なメディアをターゲットにして、 パーシステント(永続的)なデータをセーブしたりロードしたりすることができる。 Stored(FIXME-J:ストアード?)ファイルシステムは、 スタンドアロンなワークステーションをbootstrap(FIXME-J:ブートストラップ?)する場合にも必要になる。
9.1 ファイルシステムの修復 | ||
9.2 Linux Extended 2 FS | ポピュラーなLinuxファイルシステム・フォーマット。 | |
9.3 BSD Unix FS | BSD Unix 4.xのFast File System。 | |
9.4 ISO-9660 CD-ROM FS | 標準的なCD-ROMフォーマット。 | |
9.5 Diskfsライブラリ | 新しいファイルシステム・サーバの実装。 |
FIXME: finish
FIXME: finish
FIXME: finish
FIXME: finish
diskfsライブラリは<hurd/diskfs.h>
に宣言されており、
stored(FIXME-J:ストアード?)ファイルシステムの実装に係わる多くの仕事を行っている。
libdiskfs
は、
threads、ports、iohelp、fshelp、storeの各ライブラリを必要とする。
diskfsを使おうと試みる前に、
これらすべてのライブラリのことを理解するべきである。
また、
pagerライブラリについても熟知しているべきである(see section ページャ・ライブラリ)。
昔からのしがらみで、
stored(FIXME-J:ストアード?)ファイルシステムを実装するライブラリはlibstorefs
ではなくlibdiskfs
と呼ばれている。
しかしながら、
diskfsはI/Oを行うのにstoreライブラリを使っているので、
ブロック単位にアドレス付けされるものでさえあれば、
どのような記憶デバイス上に実装されているファイルシステムにとっても有用なものであるということを覚えておいていただきたい。
diskfsのコールバック・インターフェイスは単純ではないので、 stored(FIXME-J:ストアード?)ファイルシステムを実装するのは手の込んだ作業となる可能性がある。 本当のところは、 ゼロから書き始めようとするよりも、 既存のファイルシステム・サーバのうち類似のもののソース・コードを調べて、 それを例として模倣するのが最も良いのである。
9.5.1 Diskfsスタートアップ | stored(FIXME-J:ストアード?)ファイルシステムの初期化。 | |
9.5.2 Diskfs引数 | コマンドライン引数の解析。 | |
9.5.3 Diskfsグローバル関数、グローバル変数 | グローバルな振る舞いの変更。 | |
9.5.4 Diskfsノード管理 | 割り当て、リファレンス・カウンティング、 キャッシング、その他のディスク・ノード・ルーチン。 | |
9.5.5 Diskfsコールバック | 必須のユーザ定義diskfs関数。 | |
9.5.6 Diskfsオプション | 任意選択のユーザ定義diskfs関数。 | |
9.5.7 Diskfsの内部詳細 | diskfsの細部の再実装。 |
このサブセクションでは、 ファイルシステム・サーバを実装する際の一般的なステップの概要を示す。 これはチュートリアルというよりはむしろ、 読者が記憶を新たにするのを助けたり、 解説を提供したりしようとするものである。
ファイルシステム・サーバが最初にしなければならないのは、 コマンドライン引数を解析することである (see section Diskfs引数)。 その後に、 それがブートストラップ・ファイルシステムであれば、 標準出力ストリームと標準エラー・ストリームをコンソールにリダイレクトして、 エラー・メッセージが失われることがないようにしなければならない。
エラー・メッセージがユーザに見えるようにコンソールへリダイレクトする。
以下に、 サーバの初期化処理の残りの部分で呼出されるであろう関連する関数のリストを示す。 繰り返しになるが、 これらの関数がどのように使われるべきであるかという点に関してなにか疑問があるなら、 既に動いているファイルシステムの実装を参照するべきである。
引数の解析後に、ライブラリを初期化するためにこの関数を呼出す。 diskfsオプションの解析が終了したら、 他の任意のdiskfs関数を呼出す前に、 この関数を呼出さなければならない。
(diskfs_root_node
の設定を除く)
フォーマット固有のすべての初期化処理の完了後にこの関数を呼出す。
この時点で、
ページャを起動する準備ができているはずである。
ファイルシステムの初期化が完全に終了した後にこの関数を呼出す。
これは、
新しいファイルシステムcontrol port(FIXME-J:コントロール・ポート、制御ポート?)のことを親ファイルシステムに通知するためである。
もしbootstrapがセットされていれば、
diskfsはそのポートに対して適宜fsys_startup
を呼出し、
その呼出しによって返されたrealnodeを返す。
bootstrapがセットされていなければ、
この関数はdiskfs_start_bootstrap
を呼出し、
MACH_PORT_NULL
を返す。
(O_*の集合の要素を値として取る)flagsは、
realnodeをどのようにオープンするかを指定する。
以下の関数を直接呼出す必要はないはずである。
なぜなら、
diskfs_startup_diskfs
が必要に応じてこの関数を呼出してくれるからである。
このファイルシステムがあたかもブートストラップ・ファイルシステムであるかのように、 Hurdのbootstrap sequence(FIXME-J:ブートストラップ・シーケンス?)を開始する。 この関数を呼出す前に、 ファイルシステムの初期化処理はすべて完了していなければならない。
以下の関数は、 argp (see (libc)Argp section `Argp' in The GNU C Library Reference Manual) を使って、 標準的なdiskfsコマンドライン引数と実行時引数の解析処理を実装している。
argzとargz_lenにより指定される実行時オプションを解析して実行する。
認識できないオプションがあればEINVAL
が返される。
このルーチンのデフォルトの定義では、
diskfs_runtime_argp
を使用して実行時オプションが解析される。
mallocされた領域にある、
長さ*argz_len
の文字列*argz
の末尾に、
このトランスレータに渡された引数をNULで区切られたリストにしたものを追加する。
このルーチンのデフォルトの定義では、
単にdiskfs_append_std_options
が呼出される。
標準的なdiskfsオプション状態を説明する情報とともに、
NULで区切られたオプションをargzの末尾に追加し、
argz_lenの値を適宜増加させる。
diskfs_get_options
とは異なり、
argzとargz_lenには既にまともな値が入っていなければならない点に注意すること。
これが定義されているか、
もしくは、
argp構造体を指すようセットされていると、
デフォルトのdiskfs_set_options
が実行時オプションの解析処理にこれを使うことになる。
デフォルトの定義では、
diskfs_std_runtime_argp
へのポインタとして初期化されている。
標準的なdiskfs実行時オプション用のargp。
diskfs_runtime_argp
のデフォルトの定義はこれを指す。
ただし、
ユーザがこれを独自のargpにつなぐよう再定義することは可能である。
標準的なdiskfsコマンドライン引数用のargp構造体。
ユーザは、
コマンドラインを解析するためにこれを使用してargp_parse
を呼出すこともできるし、
これを独自のargp構造体の末尾につなぐこともできる。
また、
これを完全に無視することもできる。
標準的なdiskfsコマンドライン引数用、
および、
store specification(FIXME-J:指定、仕様?)用のargp構造体。
結果として作成されるstruct store_parsed
構造体を返すべき場所のアドレスが、
argp_parse
への入力引数として渡されなければならない。
FIXME xref the declaration for STORE_ARGP.
以下の関数や変数は、 このライブラリの全般的な振舞いを制御する。 あなたの書くコールバック関数はこれらを参照する必要があるかもしれないが、 これらを変更したり再定義したりする必要はないはずである。
これらはそれぞれ、 デフォルト・ページャ、 execserverのcontrol port(FIXME-J:コントロール・ポート、制御ポート?)、 execserverそれ自身、 authserverへのsend rights(FIXME-J:センド・ライト?)である。
ファイルシステムのio_identity
identity port(FIXME-J:アイデンティティ・ポート?)。
デフォルトの引数パーサによりセットされた、 diskfsの起動コマンドライン。 あなたが引数パーサを使わないのであれば、 これを自分でセットすること。 これはprocserverに与えるために、 ブートストラップ・ファイルシステムによってのみ使用される。
ブートストラップ・ファイルシステムの場合、 カーネルから渡されたコマンドライン・オプション。 ブートストラップ・ファイルシステムでない場合は、 この2つのケースを区別するのに使えるようゼロが入る。
ファイルシステム・レベルの操作を行っている間はこのロックを保有すること。 特に害のない操作を行うユーザは単にreader lock(FIXME-J)を保有するだけで良いが、 他のスレッドに悪影響を及ぼす可能性のある操作ではwriter lock(FIXME-J)を保有するべきである。
diskfsルーチンによって使用されている現在のシステム時刻。
これは、
Cのライブラリ関数maptime_read
によってstruct timeval
に変換される(FIXME xref)。
すべての操作が同期的に行われなければならない場合のみ真となる。 これがセットされている場合、 アロケーション(FIXME-J:割当て?)情報が永遠に同期されるようにするのはフォーマット固有のコードの責任である。 これ以外のことはフォーマット非依存のコードにより実行される。
interval秒ごとにファイルシステムに対してsync(FIXME-J)を実行するため、 スレッドを生成する。 intervalがゼロの場合は、 スレッドの生成を行わない。 スレッドの生成時にエラーが発生した場合は、 エラー値が返される。 エラーが発生しなかった場合はゼロが返される。 2回目以降の呼出し時にも新しいスレッドが生成され、 古いスレッドは(最終的には)取り除かれる。 いずれにしろ古いスレッドはこれ以上sync(FIXME-J)を実行することはない。
ページャのリファレンス・カウント・ロック。
ファイルシステムが現在書込み可能であればゼロがセットされる。
アクティブなファイルシステムのモードを、 読込みのみ可能なモード、 もしくは、 書込み可能なモードに変更する。 同時に現在のモードを反映するようグローバル変数diskfs_readonlyをセットする。 エラーが返された場合は、 何も変更されていない。 このルーチンを呼出している間は、 diskfs_fsys_lockを保有していなければならない。
ファイルシステムに書込みを行う操作の前に、 そのファイルシステムが読込みのみ可能かどうかをチェックする。 読込みのみ可能であればゼロ以外の値を返し、 そうでなければゼロを返す。
すべてのin-core(FIXME-J)データ構造をディスクから再度読込む。 この関数の呼出しは、 diskfs_readonlyが真である場合しか成功することはありえない。 このルーチンを呼出している間は、 diskfs_fsys_lockを保有していなければならない。
ファイルシステムをシャットダウンする。
flagsの意味は、
fsys_shutdown
の場合と同様である。
すべてのファイルやディレクトリはdiskfsノードである。 以下の関数は、 あなたの書いたdiskfsコールバックがノードやノードへのreference(FIXME-J:リファレンス、参照?)を管理するのを支援してくれるものである。
ノードnpはもはやreference(FIXME-J:リファレンス、参照?)を持たないので、 すべてをクリーンな(FIXME-J)状態にする。 diskfs_node_refcnt_lockは保有されていなければならず、 この関数から復帰する際に解放される。 npはロックされていなければならない。
np->dn_stat
の情報を使用して、
disk fields(FIXME-J:ディスク・フィールド?)をセットする。
必要であればctime、atime、mtimeを更新する。
waitが真であれば、
物理的なメディアの更新が完全に終了するまで復帰しない。
ノードnpに対してhard reference(FIXME-J)を追加する。 ノードにhard reference(FIXME-J)があらかじめ存在しない場合、 そのノードをロックすることはできない (なぜなら、 ロックを保有するためにはhard reference(FIXME-J)を保有していなければならないのであるから)。
ノードnpのロックを解除し、 hard reference(FIXME-J)を解放する。 これが最後のhard reference(FIXME-J)であり、 かつ、 そのファイルに対するリンクが存在しなければ、 light reference(FIXME-J)を除去するよう要求する。
npのhard reference(FIXME-J)を解放する。 npが何者かによってロックされていれば、 これが最後のhard reference(FIXME-J)であることはありえない (なぜなら、 ロックを保有するためにはhard reference(FIXME-J)を保有していなければならないのであるから)。 これが最後のhard reference(FIXME-J)であり、 かつ、 リンクが存在しなければ、 light reference(FIXME-J)を除去するよう要求する。
ノードに対してlight reference(FIXME-J)を追加する。
ノードnpのロックを解除し、 light reference(FIXME-J)を解放する。
npに対するlight reference(FIXME-J)を解放する。 npが何者かによってロックされていれば、 これが最後のreference(FIXME-J:リファレンス、参照?)であることはありえない (なぜなら、 ロックを保有するためにはhard reference(FIXME-J)を保有していなければならないのであるから)。
これは、
ファイルの読み書きを行う場合や自動的なファイル・サイズの拡張が必要である場合に、
他のファイルシステム・ルーチンから呼出されるものである。
npは読み書きされるノードであり、
ロックされていなければならない。
dataの指すデータがファイルに書込まれたり、
あるいは、
ファイルから読込まれたデータがdataの指す領域に書込まれたりする。
offは、
I/Oが実際に行われるべきファイル中の場所を示す
(負の値は許されない)。
amtはdataのサイズであり、
どれだけのデータをコピーするべきかを示す。
dirは、
読込みの場合はゼロであり、
書込みの場合はゼロ以外の値である。
credは、
アクセスを行っているユーザを示す
(ファイルを拡張しようとする試みの正当性を判断するためだけに使われる)。
読込みの場合、
実際に読込まれたデータのサイズが*amtread
に入れられる。
dir_notice_changes
によってディレクトリdpに関するnotification(FIXME-J)を要求したユーザに対して、
notification(FIXME-J)を送信する。
変更の種類と変更により影響を受けた名前が、
それぞれtypeとnameである。
これは、
diskfs_direnter
、diskfs_dirremove
、diskfs_dirrewrite
、
および、
そのディレクトリを変更する任意の関数から、
その変更が完全に終了した後に呼出されるべきものである。
dnを物理的なdisknode(FIXME-J)とする新しいnode構造体を作成する。 新しく作成されたノード(node)は、 hard reference(FIXME-J)を1個持ち、 light reference(FIXME-J)は持たない。
以下のノード操作関数群は一般的には有用ではないが、 diskfs関数を再定義する必要がある場合には便利であるかもしれない。
新しいノードを作成し、
そのモードをmodeとする。
modeにIFDIR
が含まれていれば、
新しいディレクトリ中の`.'と`..'も初期化する。
作成されたノードはnppに入れて返す。
credは、
この関数の呼出しに責任を負うユーザを識別する。
nameがゼロ以外の値であれば、
新しく作成されたノードをnameという名前でdirにリンクする。
dsは、
ノード作成のために事前に呼出されたdiskfs_lookup
の結果である
(dirは、
diskfs_lookup
の呼出し以降ロックされたままである)。
dirは、
少なくともディスク・アロケーション(FIXME-J:割当て?)方針のヒントとして、
常にこの関数に渡されなければならない。
np->dn_set_ctime
がセットされていれば、
しかるべくnp->dn_stat.st_ctime
を変更する。
atimeとmtimeについても同じような操作を行う。
キャッシュの中からdirの中のnameを探す。 既知の範囲でそのようなエントリが存在しなければゼロを返す。 そのようなエントリが存在しないことが確実であれば-1を返す。 これ以外の場合は、 新しく割当てられたreference(FIXME-J:リファレンス、参照?)とともに、 エントリに対応するnpを返す。
*npp
の中のcache_idに対応するノードを返す。
ノードnpは、 dirの中でnameという名前で見つけられたものである。 npがNULLであれば、 この名前のエントリがディレクトリの中に存在しないことが確認されたということを意味する。
ディレクトリdpの中のノードとしてnpを参照する、 キャッシュ内のすべてのreference(FIXME-J:リファレンス、参照?)を除去する。
ほかのいくつかのHurdライブラリと同様、
libdiskfs
もあなたがアプリケーション固有のコールバック関数を実装することをあてにしている。
あなたは以下の関数と変数を定義しなければならない。
また、
いくつかのdiskfsオプションのデフォルト値は、
良いファイルシステム・サポートを提供するためには変更するべきであるので、
Diskfsオプションも参照するべきである。
この型はあなたが定義しなければならない。
この型が、
diskfs_lookup
の呼出しからdiskfs_direnter
、diskfs_dirremove
、diskfs_dirrewrite
のいずれか1つの呼出しまでの間、
情報を保有することになる。
これらの呼出しが以下に説明するように機能するために十分な情報が、
この型の中に保持されなければならない。
これはstruct dirstat
のバイト単位のサイズでなければならない。
これは、
1個のファイルに対して存在することのできるリンクの最大個数であり、
正の整数でなければならない。
dir_rename
の実装は、
許されるリンク数がただの1個である場合に処理を成功させる方法を知らない。
そのようなフォーマットの場合、
あなたは自分でdir_rename
を再実装する必要がある。
これは、
1回のdir_pathtrans
の呼出しでたどることのできるシンボリック・リンクの最大数を示す正の整数である。
この値を超過すると、
dir_pathtrans
はELOOP
を返すことになる。
ここにはファイルシステムのルート・ノードをセットする。
ここにはファイルシステム・サーバの名前をセットする。
ここにはサーバのバージョンを示す文字列をセットする。
これは、 このファイルシステムが解釈している特定のディスクを何らかの形で識別する文字列でなければならない。 通常これは、 メッセージを表示したり、 同一のファイルシステム・タイプの複数のインスタンスを区別するためにのみ使用される。 このファイルシステムが外部メディアに一切アクセスしないのであれば、 これをゼロとして定義する。
ファイルシステムの現在の状態を反映するよう適切な値を*statfsbuf
にセットする。
あなたはdiskfs_lookup
を定義するべきではない。
なぜなら、
これは単にdiskfs_lookup_hard
に対するラッパーに過ぎず、
既にlibdiskfs
の中で定義されているからである。
(ロックされている)ディレクトリdpの中で名前nameを捜し出す(ルックアップする)。
typeは、
LOOKUP
、CREATE
、RENAME
、REMOVE
のいずれかである。
credは、
呼出しを行ったユーザを識別する。
名前nameが見つかればゼロを返し、
(npの値がゼロ以外であれば)
それに対応するノードを指すように*np
をセットする
このノードはロックされなければならない。
その名前が見つからない場合はENOENT
を返し、
(npの値がゼロ以外であれば)
*np
にゼロをセットする。
npがゼロであれば、
見つかったノードは一時的にであれロックされてはならない。
(見つかったノードに対するパーミションのチェックがしばしば実行されなければならない)
REMOVE
とRENAME
のためのルックアップの場合、
npは常にセットされる。
dsの値がゼロ以外であれば、 要求されたルックアップ種別typeによって振舞いが変わることになる。
LOOKUP
diskfs_drop_dirstat
によって無視されるよう*ds
をセットする。
CREATE
成功した場合は、
diskfs_drop_dirstat
によって無視されるよう*ds
をセットする。
失敗した場合は、
将来のdiskfs_direnter
の呼出し用に*ds
をセットする。
RENAME
成功した場合は、
将来のdiskfs_dirrewrite
の呼出し用に*ds
をセットする。
失敗した場合は、
将来のdiskfs_direnter
の呼出し用に*ds
をセットする。
REMOVE
成功した場合は、
将来のdiskfs_dirremove
の呼出し用に*ds
をセットする。
失敗した場合は、
diskfs_drop_dirstat
によって無視されるよう*ds
をセットする。
この関数の呼出し側は、
次の2つのことを保証する。
まず第1に、
dsがゼロ以外であれば、
ディレクトリdpのロックが解除される前に、
上にリストされた適切な呼出しが行われること、
もしくは、
diskfs_drop_dirstat
がdsを引数として呼出されることを保証する。
第2に、
今回ルックアップ関数を呼出してから*DSを使用する
(もしくは、破棄する)
までの間に、
このディレクトリに対してルックアップ関数は一切呼出されないことを保証する。
あなたがdiskfs_rename_dir
、diskfs_clear_directory
、diskfs_init_dir
のライブラリ・バージョンを使うのであれば、
`..'に対するルックアップでは、
フラグSPEC_DOTDOT
がORされているかもしれない。
要求されたルックアップ種別typeによっては、
これが特別な意味を持つ。
LOOKUP
復帰する前に、 dpのロックは解除されなければならず、 また、 そのreference(FIXME-J:リファレンス、参照?)は除去されなければならない。
CREATE
SPEC_DOTDOT
が与えられないことは保証されているので、
このケースは無視してよい。
RENAME
REMOVE
どちらの場合も、
見つかったノード(*np
)は既にロックされている。
したがって、
それをさらにロックしたり、
reference(FIXME-J:リファレンス、参照?)を追加したりしないこと。
名前nameがディレクトリの中に存在しない場合はENOENT
を返す。
nameが、
このファイルシステムのルートの`..'を指している場合は、
EAGAIN
を返す。
EIO
を返すことが適切な場合には、
EIO
を返す。
あなたはdiskfs_direnter
を定義するべきではない。
なぜなら、
これは単にdiskfs_direnter_hard
に対するラッパーに過ぎず、
既にlibdiskfs
の中で定義されているからである。
ディレクトリdpにnameという名前でnpを追加する。
これは、
CREATE
、
もしくは、
RENAME
のdiskfs_lookup
呼出しが失敗した後にのみ呼出されることになる。
dpは、
このdiskfs_lookup
の呼出し以降ロックされたままであり、
dsの内容は、
diskfs_lookup
の呼出しによってセットされたままの状態である。
また、
npはロックされている。
credは、
この関数の呼出しに責任を負うユーザを識別する
(ディレクトリ拡張の正当性を判断するためだけに使われる)。
あなたはdiskfs_dirrewrite
を定義するべきではない。
なぜなら、
これは単にdiskfs_dirrewrite_hard
に対するラッパーに過ぎず、
既にlibdiskfs
の中で定義されているからである。
これは、
RENAME
のdiskfs_lookup
呼出しが成功した後にのみ呼出されることになる。
この呼出しにより、
ディレクトリdpに見つかった名前は、
それが以前に参照していたノードに換わって、
ノードnpを指すように変更されているはずである。
dpは、
このdiskfs_lookup
の呼出し以降ロックされたままであり、
dsの内容は、
diskfs_lookup
の呼出しによってセットされたままの状態である。
また、
npはロックされている。
diskfs_dirrewrite
については、
さらに追加仕様がある。
nameは、
dpの中で以前参照されていたノードoldnpに対応していた名前である。
更新されるのはこのreference(FIXME-J:リファレンス、参照?)である。
dp->dirmod_reqs
がゼロ以外であれば、
diskfs_dirrewrite
はdiskfs_notice_dirchange
も呼出す。
あなたはdiskfs_dirremove
を定義するべきではない。
なぜなら、
これは単にdiskfs_dirremove_hard
に対するラッパーに過ぎず、
既にlibdiskfs
の中で定義されているからである。
これは、
REMOVE
のdiskfs_lookup
呼出しが成功した後にのみ呼出されることになる。
この呼出しにより、
ディレクトリdsに見つかった名前は削除されているはずである。
dpは、
このdiskfs_lookup
の呼出し以降ロックされたままであり、
dsの内容は、
diskfs_lookup
の呼出しによってセットされたままの状態である。
diskfs_dirremove
については、
さらに追加仕様がある。
dp->dirmod_reqs
がゼロ以外であれば、
このルーチンはdiskfs_notice_dirchange
も呼出さなければならない。
削除されるエントリは、
nameという名前を持ち、
npを参照している。
dsは、
ディレクトリdpに対するdiskfs_lookup
の前回の呼出しによってセットされたものである。
diskfs_direnter
、diskfs_dirrewrite
、diskfs_dirremove
が以前に呼出されていなければ、
この関数が呼出されることは保証されている。
この関数は、
struct dirstat
により保持されているどのような状態も解放するべきである。
dpは、
diskfs_lookup
の呼出し以降ロックされたままの状態である。
diskfs_drop_dirstat
が無視するようにdsを初期化する。
ロックされたディレクトリ・ノードdpのentryから始まるn個のディレクトリ・エントリを返す。
これらのエントリは、
現在*datacnt
バイトの領域を指す*data
に入れられる。
このサイズが十分でない場合には、
*data
に対してvm_allocate
を呼出す。
*datacnt
には、
実際に使用された総サイズをセットする。
amtにはコピーされたエントリの数を入れる。
ただし、
bufsizバイトを超えてコピーしないこと。
bufsizがゼロであれば、
*datacnt
の上限はない。
nが-1であれば、
amtの上限はない。
ロックされたディレクトリdpが空であれば、
ゼロ以外の値を返す。
ユーザが、
diskfs_clear_directory
とdiskfs_init_directory
を再定義していなければ、
「空」とは「`.'というラベルのエントリと`..'というラベルのエントリだけを持つ」という意味である。
credは、
この呼出しを行ったユーザを識別する…
そのディレクトリを探索することがこのユーザにはできない場合、
このルーチンの呼出しは失敗しなければならない。
(diskfs_node_translated
が真であるような)
ロックされたノードnpについて、
そのトランスレータの名前を捜し出す。
新たにmallocにより獲得された領域にその名前を格納し、
その名前全体の長さを*namelen
にセットする。
ロックされたノードnpについて、 そのトランスレータの名前としてnameの値を、 また、 その名前のバイト長としてnamelenの値を、 それぞれセットする。 credは、 この関数の呼出しに責任を負うユーザを識別する。
ロックされたノードnpの長さをsizeバイトに切り詰める。
npの長さが既にsizeバイト以下であれば、
何もしない。
これがsymlink(FIXME-J:シンボリック・リンク?)である
(かつ、
diskfs_shortcut_symlink
がセットされている)
場合は、
diskfs_create_symlink_hook
がリンクのターゲットをどこか別の場所にセットしている場合でも、
そのsymlink(FIXME-J:シンボリック・リンク?)は除去されなければならない。
ロックされたノードnpに対して割当てられたディスクを、
少なくともsizeバイト以上になるようサイズを拡張し、
実際に割当てられたサイズをnp->allocsize
にセットする。
割当てられているサイズが既にsizeバイトである場合には、
何もしない。
credは、
この関数の呼出しに責任を負うユーザを識別する。
この関数は、 ディスクに対して一切書込みを行うことなく、 ディスクからノードnodeに固有なデータをすべて再読込みしなければならない。 これは常に、 diskfs_readonlyが真にセットされた状態で呼出される。
この関数は、
キャッシュされているすべてのグローバルな状態を無効にしなければならない。
また、
ディスクに対して一切書込みを行うことなく、
必要に応じてディスクからそれを再読込みしなければならない。
これは常に、
diskfs_readonlyを真にセットした状態で呼出される。
常に、
この関数の呼出しに続いて、
すべてのアクティブなノードに対してdiskfs_node_reload
が呼出されるので、
この関数ではノード固有のデータを再読込みする必要はない。
アクティブなノードnpの1つ1つについて、 funを呼出す。 ノードは、 funの呼出しの間はロックされる。 funが任意のノードについてゼロ以外の値を返した場合は、 即座に処理を停止し、 その値を返す。
ロックされたディレクトリdpの中でモードmodeを持つノードとするために新しいノードを割当てる。
ただし、
実際にそのモードをセットしたり、
ディレクトリを変更したりすることはしない。
これらは、
呼出し側によって行われるからである。
このリクエストに責任を負うユーザは、
credにより識別することができる。
新しく割当てられたノードを*np
にセットする。
ノードnpを解放する。
(np->dn_stat.st_mode
がゼロであったものについては)
ディスク上のコピーは既にdiskfs_node_update
によって同期が取られている。
npのかつてのモードがmodeである。
ロックされたノードnpは、 まだいくつかlight reference(FIXME-J)は持つものの、 ちょうど最後のhard reference(FIXME-J)を失ったところである。
ロックされたノードnpはこれまでhard reference(FIXME-J)を持たなかったが、 ちょうど1つ獲得したところである。 したがって、 実際にユーザがいなくてもlight reference(FIXME-J)を持つことができるようになった。
ノードnpは、
まだいくつかlight reference(FIXME-J)は持つものの、
ちょうど最後のhard reference(FIXME-J)を失ったところである。
light reference(FIXME-J)に解放可能なものがあれば、
それを解放するような手段を講じる。
diskfs_node_refcnt_lockとnpはどちらもロックされている。
この関数は、
diskfs_lost_hardrefs
の後に呼出される。
ノードnpはもはやreference(FIXME-J:リファレンス、参照?)を持たない。
*np
が保持されるべきでなければ、
それも含めてローカルな状態を解放する。
diskfs_node_refcnt_lockは保有されている。
フォーマット固有のバッファにある、 ページングされていないメタデータをディスクに書込む。 この書込みは、 waitの値がゼロであれば、 非同期に行われる。 cleanの値がゼロ以外であれば、 この書込みが行われた後にファイルシステムは完全にクリーンな状態になり、 ページングされていないメタデータがその事実を示すことができなければならない。
np->dn_stat
の中の情報とそれに関連するフォーマット固有の情報をディスクに書込む。
waitが真であれば、
物理的なメディアが完全に更新された後にはじめて復帰する。
ファイルNPの内容とそれに関連するすべてのメタデータをディスクに書込む。
一般にこれは、
メタデータのほとんどの部分に関してdiskfs_node_update
を呼出すことになる。
waitが真であれば、
物理的なメディアが完全に更新された後にはじめて復帰する。
npのファイル内容に対応するメモリ・オブジェクトのポート(send right(FIXME-J:センド・ライト?))を返す。
protは、
許容される最大限のアクセスを示す。
エラーが発生した場合には、
MACH_PORT_NULL
を返し、
errno
をセットする。
ロックされたノードNPに対してdiskfs_get_filemapが返したページャを参照するstruct pager *
を返す。
この戻り値は、
pager_memcpy
の引数として使うのに適している。
すべてのアクティブなユーザ・ページャに設定された最大限のprot
パラメータ
(diskfs_get_filemap
の第2引数)
のビットごとのORを返す。
ユーザによって使用されているかもしれないエクスポートされたページャ・ポートが存在すればゼロ以外の値を返す。 この関数がゼロを返すまでは、 それ以上のページャの生成はブロックされるべきである。
すべてのページャをsync(FIXME-J)して、 hypermetadata(FIXME-J:ハイパメタデータ?)を除き、 ディスク上に存在するべきデータをすべて書込む。 waitが真であれば、 物理的なメディアが完全に更新された後にはじめて復帰する。
すべてのページャをシャットダウンする。 これは一度始めると元に戻すことはできず、 ファイルシステムが終了する時に実行される。
このサブセクションで説明する関数や変数には既にlibdiskfs
の中にデフォルトの実装があるため、
それらを再定義するよう強制されることはない。
ケース・バイ・ケースで、
それらを再定義しても構わない。
オプション(任意選択)の変数はいずれも、 プログラムが起動したらすぐに (例えば引数解析のようなdiskfs関数の呼出しを行うよりも前に) 値をセットしなければならない。
ファイルシステムのメディアを決して書込み可能にすることができないのであれば、 この変数にゼロ以外の値をセットするべきである。
-versionオプションが使われた際に表示されるべき追加的なバージョン情報をここにセットする。
これは、
ファイルシステム・フォーマットがショートカットのためのシンボリック・リンクtranslation(FIXME-J:翻訳、トランスレーション?)をサポートしている場合に限り、
ゼロ以外の値を取るべきである。
ライブラリは、
ユーザがこのノードの内容を直接読み書きできないことを保証する。
ライブラリがこのような保証を行うのは、
symlink hook(FIXME-J:シンボリック・リンクをフックする、シンボリック・リンクのフック?)関数
(diskfs_create_symlink_hook
とdiskfs_read_symlink_hook
)
がEINVAL
を返す場合か、
それらの関数が定義されていない場合だけである。
たとえhook function(FIXME-J:フック関数?)が使われている場合でも、
ライブラリは、
dn_stat.st_size
フィールドがsymlink(FIXME-J:シンボリック・リンク?)の長さであることを知っている。
これらの変数は、 ファイルシステム・フォーマットが、 ショートカットのためのキャラクタ・デバイス・ノード、 ブロック・デバイス・ノード、 FIFO、 UNIXドメイン・ソケットのtranslation(FIXME-J:翻訳、ランスレーション?)をそれぞれサポートしている場合にのみ、 ゼロ以外の値を取るべきである。
最初のdiskfsスレッドが(diskfs_spawn_first_thread
の中で)起動された時に、
この値を引数としてdiskfs_set_sync_interval
が呼出される。
この変数のデフォルトの値は30であり、
このデフォルトでは、
ディスク・バッファは少なくとも30秒ごとにフラッシュされることになる。
ノードnpが要求されたとおりに変更可能であればゼロを返す。 これはすなわち、 npのモードをmodeに、 オーナをuidに、 グループをgidに、 author(FIXME-J:作成者?)をauthorに、 フラグをflagsに、 ロー・デバイス番号をrdevに、 それぞれ変更可能である場合を指す。 変更可能でない場合はエラー・コードを返す。
モードやフラグをクリアすることは常に可能でなければならない。 diskfsは、 これらをクリアする前に許可を求めることはしない。
これは、 ディスクが読込みのみ可能なモードから読み書き可能なモードに変更された時、 あるいは、 その逆の変更が行われた時に呼出される。 readonlyは新しい状態を表す (これはdiskfs_readonlyにも反映される)。 ファイルシステムが書込み可能なものとなる場合、 この関数は初期起動時にも呼出される。
この関数ポインタがゼロ以外の値である場合
(かつ、diskfs_shortcut_symlink
がセットされている場合)、
symlink(FIXME-J:シンボリック・リンク?)をセットするためにその関数が呼出される。
その関数がEINVAL
を返した場合、
あるいは、
そもそも関数がセットされていない場合、
通常の方式
(すなわち、ファイル・データへの書込み)
が使われる。
これ以外のエラーが返された場合は、
そのエラーはユーザに返される。
この関数ポインタがゼロ以外の値である場合
(かつ、diskfs_shortcut_symlink
がセットされている場合)、
symlink(FIXME-J:シンボリック・リンク?)の内容を読込むためにその関数が呼出される。
その関数がEINVAL
を返した場合、
あるいは、
そもそも関数がセットされていない場合、
通常の方式
(すなわち、ファイル・データの読込み)
が使われる。
これ以外のエラーが返された場合は、
そのエラーはユーザに返される。
(fdpを親ディレクトリ・ノードとして持ち、 そのディレクトリの中でfromnameという名前を持つ) ディレクトリ・ノードfnpを、 ディレクトリtdpの中でtonameという名前を持つように、 名前変更する。 これらのノードはどれもロックされておらず、 関数の復帰時にどれもロックされていてはならない。 このルーチンはserialize(FIXME-J:シリアライズ?)されるので、 再入可能である必要はない。 ディレクトリがこのルーチン以外によって名前変更されることは決してない。 fromcredはfdpとfnpに対して責任を負うユーザである。 また、 tocredはtdpに対して責任を負うユーザである。 このルーチンは、 `.'と`..'は普通の慣例どおり通常のリンクによって表されるものと想定している。 あなたが実装するフォーマットにおいてこの想定が正しくない場合、 あなたはこの関数を再定義しなければならない。
ディレクトリdpから`.'と`..'のエントリをクリア(FIXME-J:削除?)する。 dpの親ディレクトリがpdpであり、 この親ディレクトリに対して責任を負うユーザはcredにより識別される。 どちらのディレクトリもロックされていなければならない。 このルーチンは、 `.'と`..'は普通の慣例どおり通常のリンクによって表されるものと想定している。 あなたが実装するフォーマットにおいてこの想定が正しくない場合、 あなたはこの関数を再定義しなければならない。
ロックされたノードdpは新規ディレクトリである。
これに構造体(FIXME-J:構造?)を提供するために必要なリンクをすべて追加する。
このノードの親ノードが(ロックされている)pdpである。
このルーチンは、
pdpに対してdiskfs_lookup
を呼出さないこともある。
この新規ディレクトリは、
diskfs_dirempty
の意味する範囲においてクリア(FIXME-J:?)でなければならない。
このルーチンは、
`.'と`..'は普通の慣例どおり通常のリンクによって表されるものと想定している。
あなたが実装するフォーマットにおいてこの想定が正しくない場合、
あなたはこの関数を再定義しなければならない。
credは、
この関数呼出しをおこなったユーザを識別する。
このライブラリは以下の関数群もエクスポートしている。 ただし、 このライブラリが提供している他の関数群を再定義するのでなければ、 これらは一般的には有用ではない。
ユーザuserを指すcredの中の既存のperopen poに対応するprotidを作成して返す。
ノードpo->np
はロックされていなければならない。
peropen poに対応する、
ユーザ識別情報を持たないprotidをcredの中に構築して返す。
ノードpo->np
はロックされていなければならない。
diskfs_start_protid
により開始されたprotid credの構築を終了させる。
protidに組み込まれるユーザがuserである。
protid credがもはやreference(FIXME-J:リファレンス、参照?)を持たなくなった時に呼出される。 protidへのreference(FIXME-J:リファレンス、参照?)はポート管理ライブラリによって保守されるため、 これはクリーンな(FIXME-J:?)ルーチンの一覧に含められる。 ポート・ライブラリがこの構造体を解放する。
ノードnp上にオープン・フラグflagsを持つ新しいperopen構造体を作成して返す。
root_parent
、
shadow_root
、
shadow_root_parent
の各フィールドの初期値は、
contextがゼロ以外であればそこからコピーされる。
contextがゼロであれば、
これらの値はいずれもゼロにセットされる。
poに対するreference(FIXME-J:リファレンス、参照?)・カウントをデクリメントする。
この関数は、
execserverのブートストラップのためにS_fsys_startup
により呼出される。
execserverは本物のノードがなくても機能することができるので、
このようなぺてんが可能である(FIXME-J:?)。
引数は<hurd/fsys.defs>
の中のfsys_startup
と同様である。
diskfsポートに対して入ってくるlibports
メッセージをdemultiplex(FIXME-J:?)する。
diskfsライブラリは、
fs、io、fsys、interrupt、notifyの各インターフェイスをdemultiplex(FIXME-J:?)するための関数群も提供している。
すべてのサーバ・ルーチンは、
diskfs_S_
という接頭辞を持つ。
これらのルーチンについては、
file_t
型、もしくは、io_t
型のin
(入力)引数は、
スタブからはstruct protid *
として見える。
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated by Akihiro Sagawa on June, 15 2005 using texi2html 1.70.