[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

9. Stored(FIXME-J:ストアード?)ファイルシステム

Stored(FIXME-J:ストアード?)ファイルシステムにより、 ユーザはハード・ディスク、 フロッピ・ディスク、 CD-ROMのようなランダム・アクセス可能なメディアをターゲットにして、 パーシステント(永続的)なデータをセーブしたりロードしたりすることができる。 Stored(FIXME-J:ストアード?)ファイルシステムは、 スタンドアロンなワークステーションをbootstrap(FIXME-J:ブートストラップ?)する場合にも必要になる。


9.1 ファイルシステムの修復

FIXME: finish


9.2 Linux Extended 2 FS

FIXME: finish


9.3 BSD Unix FS

FIXME: finish


9.4 ISO-9660 CD-ROM FS

FIXME: finish


9.5 Diskfsライブラリ

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スタートアップ

このサブセクションでは、 ファイルシステム・サーバを実装する際の一般的なステップの概要を示す。 これはチュートリアルというよりはむしろ、 読者が記憶を新たにするのを助けたり、 解説を提供したりしようとするものである。

ファイルシステム・サーバが最初にしなければならないのは、 コマンドライン引数を解析することである (see section Diskfs引数)。 その後に、 それがブートストラップ・ファイルシステムであれば、 標準出力ストリームと標準エラー・ストリームをコンソールにリダイレクトして、 エラー・メッセージが失われることがないようにしなければならない。

Function: void diskfs_console_stdio (void)

エラー・メッセージがユーザに見えるようにコンソールへリダイレクトする。

以下に、 サーバの初期化処理の残りの部分で呼出されるであろう関連する関数のリストを示す。 繰り返しになるが、 これらの関数がどのように使われるべきであるかという点に関してなにか疑問があるなら、 既に動いているファイルシステムの実装を参照するべきである。

Function: error_t diskfs_init_diskfs (void)

引数の解析後に、ライブラリを初期化するためにこの関数を呼出す。 diskfsオプションの解析が終了したら、 他の任意のdiskfs関数を呼出す前に、 この関数を呼出さなければならない。

Function: void diskfs_spawn_first_thread (void)

(diskfs_root_nodeの設定を除く) フォーマット固有のすべての初期化処理の完了後にこの関数を呼出す。 この時点で、 ページャを起動する準備ができているはずである。

Function: mach_port_t diskfs_startup_diskfs (mach_port_t bootstrap, int flags)

ファイルシステムの初期化が完全に終了した後にこの関数を呼出す。 これは、 新しいファイルシステムcontrol port(FIXME-J:コントロール・ポート、制御ポート?)のことを親ファイルシステムに通知するためである。 もしbootstrapがセットされていれば、 diskfsはそのポートに対して適宜fsys_startupを呼出し、 その呼出しによって返されたrealnodeを返す。 bootstrapがセットされていなければ、 この関数はdiskfs_start_bootstrapを呼出し、 MACH_PORT_NULLを返す。 (O_*の集合の要素を値として取る)flagsは、 realnodeをどのようにオープンするかを指定する。

以下の関数を直接呼出す必要はないはずである。 なぜなら、 diskfs_startup_diskfsが必要に応じてこの関数を呼出してくれるからである。

Function: void diskfs_start_bootstrap (void)

このファイルシステムがあたかもブートストラップ・ファイルシステムであるかのように、 Hurdのbootstrap sequence(FIXME-J:ブートストラップ・シーケンス?)を開始する。 この関数を呼出す前に、 ファイルシステムの初期化処理はすべて完了していなければならない。


9.5.2 Diskfs引数

以下の関数は、 argp (see (libc)Argp section `Argp' in The GNU C Library Reference Manual) を使って、 標準的なdiskfsコマンドライン引数と実行時引数の解析処理を実装している。

Function: error_t diskfs_set_options (char *argz, size_t argz_len)

argzargz_lenにより指定される実行時オプションを解析して実行する。 認識できないオプションがあればEINVALが返される。 このルーチンのデフォルトの定義では、 diskfs_runtime_argpを使用して実行時オプションが解析される。

Function: error_t diskfs_append_args (char **argz, unsigned *argz_len)

mallocされた領域にある、 長さ*argz_lenの文字列*argzの末尾に、 このトランスレータに渡された引数をNULで区切られたリストにしたものを追加する。 このルーチンのデフォルトの定義では、 単にdiskfs_append_std_optionsが呼出される。

Function: error_t diskfs_append_std_options (char **argz, unsigned *argz_len)

標準的なdiskfsオプション状態を説明する情報とともに、 NULで区切られたオプションをargz末尾に追加し、 argz_lenの値を適宜増加させる。 diskfs_get_optionsとは異なり、 argzargz_lenには既にまともな値が入っていなければならない点に注意すること。

Variable: struct argp * diskfs_runtime_argp

これが定義されているか、 もしくは、 argp構造体を指すようセットされていると、 デフォルトのdiskfs_set_optionsが実行時オプションの解析処理にこれを使うことになる。 デフォルトの定義では、 diskfs_std_runtime_argpへのポインタとして初期化されている。

Variable: const struct argp diskfs_std_runtime_argp

標準的なdiskfs実行時オプション用のargp。 diskfs_runtime_argpのデフォルトの定義はこれを指す。 ただし、 ユーザがこれを独自のargpにつなぐよう再定義することは可能である。

Variable: const struct argp diskfs_startup_argp

標準的なdiskfsコマンドライン引数用のargp構造体。 ユーザは、 コマンドラインを解析するためにこれを使用してargp_parseを呼出すこともできるし、 これを独自のargp構造体の末尾につなぐこともできる。 また、 これを完全に無視することもできる。

Variable: const struct argp diskfs_store_startup_argp

標準的なdiskfsコマンドライン引数用、 および、 store specification(FIXME-J:指定、仕様?)用のargp構造体。 結果として作成されるstruct store_parsed構造体を返すべき場所のアドレスが、 argp_parseへの入力引数として渡されなければならない。 FIXME xref the declaration for STORE_ARGP.


9.5.3 Diskfsグローバル関数、グローバル変数

以下の関数や変数は、 このライブラリの全般的な振舞いを制御する。 あなたの書くコールバック関数はこれらを参照する必要があるかもしれないが、 これらを変更したり再定義したりする必要はないはずである。

Variable: mach_port_t diskfs_default_pager
Variable: mach_port_t diskfs_exec_ctl
Variable: mach_port_t diskfs_exec
Variable: auth_t diskfs_auth_server_port

これらはそれぞれ、 デフォルト・ページャ、 execserverのcontrol port(FIXME-J:コントロール・ポート、制御ポート?)、 execserverそれ自身、 authserverへのsend rights(FIXME-J:センド・ライト?)である。

Variable: mach_port_t diskfs_fsys_identity

ファイルシステムのio_identity identity port(FIXME-J:アイデンティティ・ポート?)。

Variable: char ** diskfs_argv

デフォルトの引数パーサによりセットされた、 diskfsの起動コマンドライン。 あなたが引数パーサを使わないのであれば、 これを自分でセットすること。 これはprocserverに与えるために、 ブートストラップ・ファイルシステムによってのみ使用される。

Variable: char * diskfs_boot_flags

ブートストラップ・ファイルシステムの場合、 カーネルから渡されたコマンドライン・オプション。 ブートストラップ・ファイルシステムでない場合は、 この2つのケースを区別するのに使えるようゼロが入る。

Variable: struct rwlock diskfs_fsys_lock

ファイルシステム・レベルの操作を行っている間はこのロックを保有すること。 特に害のない操作を行うユーザは単にreader lock(FIXME-J)を保有するだけで良いが、 他のスレッドに悪影響を及ぼす可能性のある操作ではwriter lock(FIXME-J)を保有するべきである。

Variable: volatile struct mapped_time_value * diskfs_mtime

diskfsルーチンによって使用されている現在のシステム時刻。 これは、 Cのライブラリ関数maptime_readによってstruct timevalに変換される(FIXME xref)。

Variable: int diskfs_synchronous

すべての操作が同期的に行われなければならない場合のみ真となる。 これがセットされている場合、 アロケーション(FIXME-J:割当て?)情報が永遠に同期されるようにするのはフォーマット固有のコードの責任である。 これ以外のことはフォーマット非依存のコードにより実行される。

Function: error_t diskfs_set_sync_interval (int interval)

interval秒ごとにファイルシステムに対してsync(FIXME-J)を実行するため、 スレッドを生成する。 intervalがゼロの場合は、 スレッドの生成を行わない。 スレッドの生成時にエラーが発生した場合は、 エラー値が返される。 エラーが発生しなかった場合はゼロが返される。 2回目以降の呼出し時にも新しいスレッドが生成され、 古いスレッドは(最終的には)取り除かれる。 いずれにしろ古いスレッドはこれ以上sync(FIXME-J)を実行することはない。

Variable: spin_lock_t diskfs_node_refcnt_lock

ページャのリファレンス・カウント・ロック。

Variable: int diskfs_readonly

ファイルシステムが現在書込み可能であればゼロがセットされる。

Function: error_t diskfs_set_readonly (int readonly)

アクティブなファイルシステムのモードを、 読込みのみ可能なモード、 もしくは、 書込み可能なモードに変更する。 同時に現在のモードを反映するようグローバル変数diskfs_readonlyをセットする。 エラーが返された場合は、 何も変更されていない。 このルーチンを呼出している間は、 diskfs_fsys_lockを保有していなければならない。

Function: int diskfs_check_readonly (void)

ファイルシステムに書込みを行う操作の前に、 そのファイルシステムが読込みのみ可能かどうかをチェックする。 読込みのみ可能であればゼロ以外の値を返し、 そうでなければゼロを返す。

Function: error_t diskfs_remount (void)

すべてのin-core(FIXME-J)データ構造をディスクから再度読込む。 この関数の呼出しは、 diskfs_readonlyが真である場合しか成功することはありえない。 このルーチンを呼出している間は、 diskfs_fsys_lockを保有していなければならない。

Function: error_t diskfs_shutdown (int flags)

ファイルシステムをシャットダウンする。 flagsの意味は、 fsys_shutdownの場合と同様である。


9.5.4 Diskfsノード管理

すべてのファイルやディレクトリはdiskfsノードである。 以下の関数は、 あなたの書いたdiskfsコールバックがノードやノードへのreference(FIXME-J:リファレンス、参照?)を管理するのを支援してくれるものである。

Function: void diskfs_drop_node (struct node *np)

ノードnpはもはやreference(FIXME-J:リファレンス、参照?)を持たないので、 すべてをクリーンな(FIXME-J)状態にする。 diskfs_node_refcnt_lockは保有されていなければならず、 この関数から復帰する際に解放される。 npはロックされていなければならない。

Function: void diskfs_node_update (struct node *np, int wait)

np->dn_statの情報を使用して、 disk fields(FIXME-J:ディスク・フィールド?)をセットする。 必要であればctime、atime、mtimeを更新する。 waitが真であれば、 物理的なメディアの更新が完全に終了するまで復帰しない。

Function: void diskfs_nref (struct node *np)

ノードnpに対してhard reference(FIXME-J)を追加する。 ノードにhard reference(FIXME-J)があらかじめ存在しない場合、 そのノードをロックすることはできない (なぜなら、 ロックを保有するためにはhard reference(FIXME-J)を保有していなければならないのであるから)。

Function: void diskfs_nput (struct node *np)

ノードnpのロックを解除し、 hard reference(FIXME-J)を解放する。 これが最後のhard reference(FIXME-J)であり、 かつ、 そのファイルに対するリンクが存在しなければ、 light reference(FIXME-J)を除去するよう要求する。

Function: void diskfs_nrele (struct node *np)

npのhard reference(FIXME-J)を解放する。 npが何者かによってロックされていれば、 これが最後のhard reference(FIXME-J)であることはありえない (なぜなら、 ロックを保有するためにはhard reference(FIXME-J)を保有していなければならないのであるから)。 これが最後のhard reference(FIXME-J)であり、 かつ、 リンクが存在しなければ、 light reference(FIXME-J)を除去するよう要求する。

Function: void diskfs_nref_light (struct node *np)

ノードに対してlight reference(FIXME-J)を追加する。

Function: void diskfs_nput_light (struct node *np)

ノードnpのロックを解除し、 light reference(FIXME-J)を解放する。

Function: void diskfs_nrele_light (struct node *np)

npに対するlight reference(FIXME-J)を解放する。 npが何者かによってロックされていれば、 これが最後のreference(FIXME-J:リファレンス、参照?)であることはありえない (なぜなら、 ロックを保有するためにはhard reference(FIXME-J)を保有していなければならないのであるから)。

Function: error_t diskfs_node_rdwr (struct node *np, char *data, off_t off, size_t amt, int direction, struct protid *cred, size_t *amtread)

これは、 ファイルの読み書きを行う場合や自動的なファイル・サイズの拡張が必要である場合に、 他のファイルシステム・ルーチンから呼出されるものである。 npは読み書きされるノードであり、 ロックされていなければならない。 dataの指すデータがファイルに書込まれたり、 あるいは、 ファイルから読込まれたデータがdataの指す領域に書込まれたりする。 offは、 I/Oが実際に行われるべきファイル中の場所を示す (負の値は許されない)。 amtdataのサイズであり、 どれだけのデータをコピーするべきかを示す。 dirは、 読込みの場合はゼロであり、 書込みの場合はゼロ以外の値である。 credは、 アクセスを行っているユーザを示す (ファイルを拡張しようとする試みの正当性を判断するためだけに使われる)。 読込みの場合、 実際に読込まれたデータのサイズが*amtreadに入れられる。

Function: void diskfs_notice_dirchange (struct node *dp, enum dir_changed_type type, char *name)

dir_notice_changesによってディレクトリdpに関するnotification(FIXME-J)を要求したユーザに対して、 notification(FIXME-J)を送信する。 変更の種類と変更により影響を受けた名前が、 それぞれtypenameである。 これは、 diskfs_direnterdiskfs_dirremovediskfs_dirrewrite、 および、 そのディレクトリを変更する任意の関数から、 その変更が完全に終了した後に呼出されるべきものである。

Function: struct node * diskfs_make_node (struct disknode *dn)

dnを物理的なdisknode(FIXME-J)とする新しいnode構造体を作成する。 新しく作成されたノード(node)は、 hard reference(FIXME-J)を1個持ち、 light reference(FIXME-J)は持たない。

以下のノード操作関数群は一般的には有用ではないが、 diskfs関数を再定義する必要がある場合には便利であるかもしれない。

Function: error_t diskfs_create_node (struct node *dir, char *name, mode_t mode, struct node **newnode, struct protid *cred, struct dirstat *ds)

新しいノードを作成し、 そのモードをmodeとする。 modeIFDIRが含まれていれば、 新しいディレクトリ中の`.'と`..'も初期化する。 作成されたノードはnppに入れて返す。 credは、 この関数の呼出しに責任を負うユーザを識別する。 nameがゼロ以外の値であれば、 新しく作成されたノードをnameという名前でdirにリンクする。 dsは、 ノード作成のために事前に呼出されたdiskfs_lookupの結果である (dirは、 diskfs_lookupの呼出し以降ロックされたままである)。 dirは、 少なくともディスク・アロケーション(FIXME-J:割当て?)方針のヒントとして、 常にこの関数に渡されなければならない。

Function: void diskfs_set_node_times (struct node *np)

np->dn_set_ctimeがセットされていれば、 しかるべくnp->dn_stat.st_ctimeを変更する。 atimeとmtimeについても同じような操作を行う。

Function: struct node * diskfs_check_lookup_cache (struct node *dir, char *name)

キャッシュの中からdirの中のnameを探す。 既知の範囲でそのようなエントリが存在しなければゼロを返す。 そのようなエントリが存在しないことが確実であれば-1を返す。 これ以外の場合は、 新しく割当てられたreference(FIXME-J:リファレンス、参照?)とともに、 エントリに対応するnpを返す。

Function: error_t diskfs_cached_lookup (int cache_id, struct node **npp)

*nppの中のcache_idに対応するノードを返す。

Function: void diskfs_enter_lookup_cache (struct node *dir, struct node *np, char *name)

ノードnpは、 dirの中でnameという名前で見つけられたものである。 npがNULLであれば、 この名前のエントリがディレクトリの中に存在しないことが確認されたということを意味する。

Function: void diskfs_purge_lookup_cache (struct node *dp, struct node *np)

ディレクトリdpの中のノードとしてnpを参照する、 キャッシュ内のすべてのreference(FIXME-J:リファレンス、参照?)を除去する。


9.5.5 Diskfsコールバック

ほかのいくつかのHurdライブラリと同様、 libdiskfsもあなたがアプリケーション固有のコールバック関数を実装することをあてにしている。 あなたは以下の関数と変数を定義しなければならない。 また、 いくつかのdiskfsオプションのデフォルト値は、 良いファイルシステム・サポートを提供するためには変更するべきであるので、 Diskfsオプションも参照するべきである。

Structure: struct dirstat

この型はあなたが定義しなければならない。 この型が、 diskfs_lookupの呼出しからdiskfs_direnterdiskfs_dirremovediskfs_dirrewriteのいずれか1つの呼出しまでの間、 情報を保有することになる。 これらの呼出しが以下に説明するように機能するために十分な情報が、 この型の中に保持されなければならない。

Variable: size_t diskfs_dirstat_size

これはstruct dirstatのバイト単位のサイズでなければならない。

Variable: int diskfs_link_max

これは、 1個のファイルに対して存在することのできるリンクの最大個数であり、 正の整数でなければならない。 dir_renameの実装は、 許されるリンク数がただの1個である場合に処理を成功させる方法を知らない。 そのようなフォーマットの場合、 あなたは自分でdir_renameを再実装する必要がある。

Variable: int diskfs_maxsymlinks

これは、 1回のdir_pathtransの呼出しでたどることのできるシンボリック・リンクの最大数を示す正の整数である。 この値を超過すると、 dir_pathtransELOOPを返すことになる。

Variable: struct node * diskfs_root_node

ここにはファイルシステムのルート・ノードをセットする。

Variable: char * diskfs_server_name

ここにはファイルシステム・サーバの名前をセットする。

Variable: char * diskfs_server_version

ここにはサーバのバージョンを示す文字列をセットする。

Variable: char * diskfs_disk_name

これは、 このファイルシステムが解釈している特定のディスクを何らかの形で識別する文字列でなければならない。 通常これは、 メッセージを表示したり、 同一のファイルシステム・タイプの複数のインスタンスを区別するためにのみ使用される。 このファイルシステムが外部メディアに一切アクセスしないのであれば、 これをゼロとして定義する。

Function: error_t diskfs_set_statfs (fsys_statfsbuf_t *statfsbuf)

ファイルシステムの現在の状態を反映するよう適切な値を*statfsbufにセットする。

Function: error_t diskfs_lookup (struct node *dp, char *name, enum lookup_type type, struct node **np, struct dirstat *ds, struct protid *cred)
Function: error_t diskfs_lookup_hard (struct node *dp, char *name, enum lookup_type type, struct node **np, struct dirstat *ds, struct protid *cred)

あなたはdiskfs_lookupを定義するべきではない。 なぜなら、 これは単にdiskfs_lookup_hardに対するラッパーに過ぎず、 既にlibdiskfsの中で定義されているからである。

(ロックされている)ディレクトリdpの中で名前nameを捜し出す(ルックアップする)。 typeは、 LOOKUPCREATERENAMEREMOVEのいずれかである。 credは、 呼出しを行ったユーザを識別する。

名前nameが見つかればゼロを返し、 (npの値がゼロ以外であれば) それに対応するノードを指すように*npをセットする このノードはロックされなければならない。 その名前が見つからない場合はENOENTを返し、 (npの値がゼロ以外であれば) *npにゼロをセットする。 npがゼロであれば、 見つかったノードは一時的にであれロックされてはならない。 (見つかったノードに対するパーミションのチェックがしばしば実行されなければならない) REMOVERENAMEのためのルックアップの場合、 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_dirstatdsを引数として呼出されることを保証する。 第2に、 今回ルックアップ関数を呼出してから*DSを使用する (もしくは、破棄する) までの間に、 このディレクトリに対してルックアップ関数は一切呼出されないことを保証する。

あなたがdiskfs_rename_dirdiskfs_clear_directorydiskfs_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を返す。

Function: error_t diskfs_direnter (struct node *dp, char *name, struct node *np, struct dirstat *ds, struct protid *cred)
Function: error_t diskfs_direnter_hard (struct node *dp, char *name, struct node *np, struct dirstat *ds, struct protid *cred)

あなたはdiskfs_direnterを定義するべきではない。 なぜなら、 これは単にdiskfs_direnter_hardに対するラッパーに過ぎず、 既にlibdiskfsの中で定義されているからである。

ディレクトリdpnameという名前でnpを追加する。 これは、 CREATE、 もしくは、 RENAMEdiskfs_lookup呼出しが失敗した後にのみ呼出されることになる。 dpは、 このdiskfs_lookupの呼出し以降ロックされたままであり、 dsの内容は、 diskfs_lookupの呼出しによってセットされたままの状態である。 また、 npはロックされている。 credは、 この関数の呼出しに責任を負うユーザを識別する (ディレクトリ拡張の正当性を判断するためだけに使われる)。

Function: error_t diskfs_dirrewrite (struct node *dp, struct node *oldnp, struct node *np, char *name, struct dirstat *ds)
Function: error_t diskfs_dirrewrite_hard (struct node *dp, struct node *np, struct dirstat *ds)

あなたはdiskfs_dirrewriteを定義するべきではない。 なぜなら、 これは単にdiskfs_dirrewrite_hardに対するラッパーに過ぎず、 既にlibdiskfsの中で定義されているからである。

これは、 RENAMEdiskfs_lookup呼出しが成功した後にのみ呼出されることになる。 この呼出しにより、 ディレクトリdpに見つかった名前は、 それが以前に参照していたノードに換わって、 ノードnpを指すように変更されているはずである。 dpは、 このdiskfs_lookupの呼出し以降ロックされたままであり、 dsの内容は、 diskfs_lookupの呼出しによってセットされたままの状態である。 また、 npはロックされている。

diskfs_dirrewriteについては、 さらに追加仕様がある。 nameは、 dpの中で以前参照されていたノードoldnpに対応していた名前である。 更新されるのはこのreference(FIXME-J:リファレンス、参照?)である。 dp->dirmod_reqsがゼロ以外であれば、 diskfs_dirrewritediskfs_notice_dirchangeも呼出す。

Function: error_t diskfs_dirremove (struct node *dp, struct node *np, char *name, struct dirstat *ds)
Function: error_t diskfs_dirremove_hard (struct node *dp, struct dirstat *ds)

あなたはdiskfs_dirremoveを定義するべきではない。 なぜなら、 これは単にdiskfs_dirremove_hardに対するラッパーに過ぎず、 既にlibdiskfsの中で定義されているからである。

これは、 REMOVEdiskfs_lookup呼出しが成功した後にのみ呼出されることになる。 この呼出しにより、 ディレクトリdsに見つかった名前は削除されているはずである。 dpは、 このdiskfs_lookupの呼出し以降ロックされたままであり、 dsの内容は、 diskfs_lookupの呼出しによってセットされたままの状態である。

diskfs_dirremoveについては、 さらに追加仕様がある。 dp->dirmod_reqsがゼロ以外であれば、 このルーチンはdiskfs_notice_dirchangeも呼出さなければならない。 削除されるエントリは、 nameという名前を持ち、 npを参照している。

Function: error_t diskfs_drop_dirstat (struct node *dp, struct dirstat *ds)

dsは、 ディレクトリdpに対するdiskfs_lookupの前回の呼出しによってセットされたものである。 diskfs_direnterdiskfs_dirrewritediskfs_dirremoveが以前に呼出されていなければ、 この関数が呼出されることは保証されている。 この関数は、 struct dirstatにより保持されているどのような状態も解放するべきである。 dpは、 diskfs_lookupの呼出し以降ロックされたままの状態である。

Function: void diskfs_null_dirstat (struct dirstat *ds)

diskfs_drop_dirstatが無視するようにdsを初期化する。

Function: error_t diskfs_get_directs (struct node *dp, int entry, int n, char **data, u_int *datacnt, vm_size_t bufsiz, int *amt)

ロックされたディレクトリ・ノードdpentryから始まるn個のディレクトリ・エントリを返す。 これらのエントリは、 現在*datacntバイトの領域を指す*dataに入れられる。 このサイズが十分でない場合には、 *dataに対してvm_allocateを呼出す。 *datacntには、 実際に使用された総サイズをセットする。 amtにはコピーされたエントリの数を入れる。 ただし、 bufsizバイトを超えてコピーしないこと。 bufsizがゼロであれば、 *datacntの上限はない。 nが-1であれば、 amtの上限はない。

Function: int diskfs_dirempty (struct node *dp, struct protid *cred)

ロックされたディレクトリdpが空であれば、 ゼロ以外の値を返す。 ユーザが、 diskfs_clear_directorydiskfs_init_directoryを再定義していなければ、 「空」とは「`.'というラベルのエントリと`..'というラベルのエントリだけを持つ」という意味である。 credは、 この呼出しを行ったユーザを識別する… そのディレクトリを探索することがこのユーザにはできない場合、 このルーチンの呼出しは失敗しなければならない。

Function: error_t diskfs_get_translator (struct node *np, char **namep, u_int *namelen)

(diskfs_node_translatedが真であるような) ロックされたノードnpについて、 そのトランスレータの名前を捜し出す。 新たにmallocにより獲得された領域にその名前を格納し、 その名前全体の長さを*namelenにセットする。

Function: error_t diskfs_set_translator (struct node *np, char *name, u_int namelen, struct protid *cred)

ロックされたノードnpについて、 そのトランスレータの名前としてnameの値を、 また、 その名前のバイト長としてnamelenの値を、 それぞれセットする。 credは、 この関数の呼出しに責任を負うユーザを識別する。

Function: error_t diskfs_truncate (struct node *np, off_t size)

ロックされたノードnpの長さをsizeバイトに切り詰める。 npの長さが既にsizeバイト以下であれば、 何もしない。 これがsymlink(FIXME-J:シンボリック・リンク?)である (かつ、 diskfs_shortcut_symlinkがセットされている) 場合は、 diskfs_create_symlink_hookがリンクのターゲットをどこか別の場所にセットしている場合でも、 そのsymlink(FIXME-J:シンボリック・リンク?)は除去されなければならない。

Function: error_t diskfs_grow (struct node *np, off_t size, struct protid *cred)

ロックされたノードnpに対して割当てられたディスクを、 少なくともsizeバイト以上になるようサイズを拡張し、 実際に割当てられたサイズをnp->allocsizeにセットする。 割当てられているサイズが既にsizeバイトである場合には、 何もしない。 credは、 この関数の呼出しに責任を負うユーザを識別する。

Function: error_t diskfs_node_reload (struct node *node)

この関数は、 ディスクに対して一切書込みを行うことなく、 ディスクからノードnodeに固有なデータをすべて再読込みしなければならない。 これは常に、 diskfs_readonlyが真にセットされた状態で呼出される。

Function: error_t diskfs_reload_global_state (void)

この関数は、 キャッシュされているすべてのグローバルな状態を無効にしなければならない。 また、 ディスクに対して一切書込みを行うことなく、 必要に応じてディスクからそれを再読込みしなければならない。 これは常に、 diskfs_readonlyを真にセットした状態で呼出される。 常に、 この関数の呼出しに続いて、 すべてのアクティブなノードに対してdiskfs_node_reloadが呼出されるので、 この関数ではノード固有のデータを再読込みする必要はない。

Function: error_t diskfs_node_iterate (error_t (*fun) (struct node *np))

アクティブなノードnpの1つ1つについて、 funを呼出す。 ノードは、 funの呼出しの間はロックされる。 funが任意のノードについてゼロ以外の値を返した場合は、 即座に処理を停止し、 その値を返す。

Function: error_t diskfs_alloc_node (struct node *dp, mode_t mode, struct node **np)

ロックされたディレクトリdpの中でモードmodeを持つノードとするために新しいノードを割当てる。 ただし、 実際にそのモードをセットしたり、 ディレクトリを変更したりすることはしない。 これらは、 呼出し側によって行われるからである。 このリクエストに責任を負うユーザは、 credにより識別することができる。 新しく割当てられたノードを*npにセットする。

Function: void diskfs_free_node (struct node *np, mode_t mode)

ノードnpを解放する。 (np->dn_stat.st_modeがゼロであったものについては) ディスク上のコピーは既にdiskfs_node_updateによって同期が取られている。 npのかつてのモードがmodeである。

Function: void diskfs_lost_hardrefs (struct node *np)

ロックされたノードnpは、 まだいくつかlight reference(FIXME-J)は持つものの、 ちょうど最後のhard reference(FIXME-J)を失ったところである。

Function: void diskfs_new_hardrefs (struct node *np)

ロックされたノードnpはこれまでhard reference(FIXME-J)を持たなかったが、 ちょうど1つ獲得したところである。 したがって、 実際にユーザがいなくてもlight reference(FIXME-J)を持つことができるようになった。

Function: void diskfs_try_dropping_softrefs (struct node *np)

ノードnpは、 まだいくつかlight reference(FIXME-J)は持つものの、 ちょうど最後のhard reference(FIXME-J)を失ったところである。 light reference(FIXME-J)に解放可能なものがあれば、 それを解放するような手段を講じる。 diskfs_node_refcnt_locknpはどちらもロックされている。 この関数は、 diskfs_lost_hardrefsの後に呼出される。

Function: void diskfs_node_norefs (struct node *np)

ノードnpはもはやreference(FIXME-J:リファレンス、参照?)を持たない。 *npが保持されるべきでなければ、 それも含めてローカルな状態を解放する。 diskfs_node_refcnt_lockは保有されている。

Function: error_t diskfs_set_hypermetadata (int wait, int clean)

フォーマット固有のバッファにある、 ページングされていないメタデータをディスクに書込む。 この書込みは、 waitの値がゼロであれば、 非同期に行われる。 cleanの値がゼロ以外であれば、 この書込みが行われた後にファイルシステムは完全にクリーンな状態になり、 ページングされていないメタデータがその事実を示すことができなければならない。

Function: void diskfs_write_disknode (struct node *np, int wait)

np->dn_statの中の情報とそれに関連するフォーマット固有の情報をディスクに書込む。 waitが真であれば、 物理的なメディアが完全に更新された後にはじめて復帰する。

Function: void diskfs_file_update (struct node *np, int wait)

ファイルNPの内容とそれに関連するすべてのメタデータをディスクに書込む。 一般にこれは、 メタデータのほとんどの部分に関してdiskfs_node_updateを呼出すことになる。 waitが真であれば、 物理的なメディアが完全に更新された後にはじめて復帰する。

Function: mach_port_t diskfs_get_filemap (struct node *np, vm_prot_t prot)

npのファイル内容に対応するメモリ・オブジェクトのポート(send right(FIXME-J:センド・ライト?))を返す。 protは、 許容される最大限のアクセスを示す。 エラーが発生した場合には、 MACH_PORT_NULLを返し、 errnoをセットする。

Function: struct pager * diskfs_get_filemap_pager_struct (struct node *np)

ロックされたノードNPに対してdiskfs_get_filemapが返したページャを参照するstruct pager *を返す。 この戻り値は、 pager_memcpyの引数として使うのに適している。

Function: vm_prot_t diskfs_max_user_pager_prot (void)

すべてのアクティブなユーザ・ページャに設定された最大限のprotパラメータ (diskfs_get_filemapの第2引数) のビットごとのORを返す。

Function: int diskfs_pager_users (void)

ユーザによって使用されているかもしれないエクスポートされたページャ・ポートが存在すればゼロ以外の値を返す。 この関数がゼロを返すまでは、 それ以上のページャの生成はブロックされるべきである。

Function: void diskfs_sync_everything (int wait)

すべてのページャをsync(FIXME-J)して、 hypermetadata(FIXME-J:ハイパメタデータ?)を除き、 ディスク上に存在するべきデータをすべて書込む。 waitが真であれば、 物理的なメディアが完全に更新された後にはじめて復帰する。

Function: void diskfs_shutdown_pager (void)

すべてのページャをシャットダウンする。 これは一度始めると元に戻すことはできず、 ファイルシステムが終了する時に実行される。


9.5.6 Diskfsオプション

このサブセクションで説明する関数や変数には既にlibdiskfsの中にデフォルトの実装があるため、 それらを再定義するよう強制されることはない。 ケース・バイ・ケースで、 それらを再定義しても構わない。

オプション(任意選択)の変数はいずれも、 プログラムが起動したらすぐに (例えば引数解析のようなdiskfs関数の呼出しを行うよりも前に) 値をセットしなければならない。

Variable: int diskfs_hard_readonly

ファイルシステムのメディアを決して書込み可能にすることができないのであれば、 この変数にゼロ以外の値をセットするべきである。

Variable: char * diskfs_extra_version

-versionオプションが使われた際に表示されるべき追加的なバージョン情報をここにセットする。

Variable: int diskfs_shortcut_symlink

これは、 ファイルシステム・フォーマットがショートカットのためのシンボリック・リンクtranslation(FIXME-J:翻訳、トランスレーション?)をサポートしている場合に限り、 ゼロ以外の値を取るべきである。 ライブラリは、 ユーザがこのノードの内容を直接読み書きできないことを保証する。 ライブラリがこのような保証を行うのは、 symlink hook(FIXME-J:シンボリック・リンクをフックする、シンボリック・リンクのフック?)関数 (diskfs_create_symlink_hookdiskfs_read_symlink_hook) がEINVALを返す場合か、 それらの関数が定義されていない場合だけである。 たとえhook function(FIXME-J:フック関数?)が使われている場合でも、 ライブラリは、 dn_stat.st_sizeフィールドがsymlink(FIXME-J:シンボリック・リンク?)の長さであることを知っている。

Variable: int diskfs_shortcut_chrdev
Variable: int diskfs_shortcut_blkdev
Variable: int diskfs_shortcut_fifo
Variable: int diskfs_shortcut_ifsock

これらの変数は、 ファイルシステム・フォーマットが、 ショートカットのためのキャラクタ・デバイス・ノード、 ブロック・デバイス・ノード、 FIFO、 UNIXドメイン・ソケットのtranslation(FIXME-J:翻訳、ランスレーション?)をそれぞれサポートしている場合にのみ、 ゼロ以外の値を取るべきである。

Variable: int diskfs_default_sync_interval

最初のdiskfsスレッドが(diskfs_spawn_first_threadの中で)起動された時に、 この値を引数としてdiskfs_set_sync_intervalが呼出される。 この変数のデフォルトの値は30であり、 このデフォルトでは、 ディスク・バッファは少なくとも30秒ごとにフラッシュされることになる。

Function: error_t diskfs_validate_mode_change (struct node *np, mode_t mode)
Function: error_t diskfs_validate_owner_change (struct node *np, uid_t uid)
Function: error_t diskfs_validate_group_change (struct node *np, gid_t gid)
Function: error_t diskfs_validate_author_change (struct node *np, uid_t author)
Function: error_t diskfs_validate_flags_change (struct node *np, int flags)
Function: error_t diskfs_validate_rdev_change (struct node *np, dev_t rdev)

ノードnpが要求されたとおりに変更可能であればゼロを返す。 これはすなわち、 npのモードをmodeに、 オーナをuidに、 グループをgidに、 author(FIXME-J:作成者?)をauthorに、 フラグをflagsに、 ロー・デバイス番号をrdevに、 それぞれ変更可能である場合を指す。 変更可能でない場合はエラー・コードを返す。

モードやフラグをクリアすることは常に可能でなければならない。 diskfsは、 これらをクリアする前に許可を求めることはしない。

Function: void diskfs_readonly_changed (int readonly)

これは、 ディスクが読込みのみ可能なモードから読み書き可能なモードに変更された時、 あるいは、 その逆の変更が行われた時に呼出される。 readonlyは新しい状態を表す (これはdiskfs_readonlyにも反映される)。 ファイルシステムが書込み可能なものとなる場合、 この関数は初期起動時にも呼出される。

Variable: error_t (* diskfs_create_symlink_hook ) (struct node *np, char *target)

この関数ポインタがゼロ以外の値である場合 (かつ、diskfs_shortcut_symlinkがセットされている場合)、 symlink(FIXME-J:シンボリック・リンク?)をセットするためにその関数が呼出される。 その関数がEINVALを返した場合、 あるいは、 そもそも関数がセットされていない場合、 通常の方式 (すなわち、ファイル・データへの書込み) が使われる。 これ以外のエラーが返された場合は、 そのエラーはユーザに返される。

Variable: error_t (* diskfs_read_symlink_hook ) (struct node *np, char *target)

この関数ポインタがゼロ以外の値である場合 (かつ、diskfs_shortcut_symlinkがセットされている場合)、 symlink(FIXME-J:シンボリック・リンク?)の内容を読込むためにその関数が呼出される。 その関数がEINVALを返した場合、 あるいは、 そもそも関数がセットされていない場合、 通常の方式 (すなわち、ファイル・データの読込み) が使われる。 これ以外のエラーが返された場合は、 そのエラーはユーザに返される。

Function: error_t diskfs_rename_dir (struct node *fdp, struct node *fnp, char *fromname, struct node *tdp, char *toname, struct protid *fromcred, struct protid *tocred)

fdpを親ディレクトリ・ノードとして持ち、 そのディレクトリの中でfromnameという名前を持つ) ディレクトリ・ノードfnpを、 ディレクトリtdpの中でtonameという名前を持つように、 名前変更する。 これらのノードはどれもロックされておらず、 関数の復帰時にどれもロックされていてはならない。 このルーチンはserialize(FIXME-J:シリアライズ?)されるので、 再入可能である必要はない。 ディレクトリがこのルーチン以外によって名前変更されることは決してない。 fromcredfdpfnpに対して責任を負うユーザである。 また、 tocredtdpに対して責任を負うユーザである。 このルーチンは、 `.'と`..'は普通の慣例どおり通常のリンクによって表されるものと想定している。 あなたが実装するフォーマットにおいてこの想定が正しくない場合、 あなたはこの関数を再定義しなければならない。

Function: error_t diskfs_clear_directory (struct node *dp, struct node *pdp, struct protid *cred)

ディレクトリdpから`.'と`..'のエントリをクリア(FIXME-J:削除?)する。 dpの親ディレクトリがpdpであり、 この親ディレクトリに対して責任を負うユーザはcredにより識別される。 どちらのディレクトリもロックされていなければならない。 このルーチンは、 `.'と`..'は普通の慣例どおり通常のリンクによって表されるものと想定している。 あなたが実装するフォーマットにおいてこの想定が正しくない場合、 あなたはこの関数を再定義しなければならない。

Function: error_t diskfs_init_dir (struct node *dp, struct node *pdp, struct protid *cred)

ロックされたノードdpは新規ディレクトリである。 これに構造体(FIXME-J:構造?)を提供するために必要なリンクをすべて追加する。 このノードの親ノードが(ロックされている)pdpである。 このルーチンは、 pdpに対してdiskfs_lookupを呼出さないこともある。 この新規ディレクトリは、 diskfs_diremptyの意味する範囲においてクリア(FIXME-J:?)でなければならない。 このルーチンは、 `.'と`..'は普通の慣例どおり通常のリンクによって表されるものと想定している。 あなたが実装するフォーマットにおいてこの想定が正しくない場合、 あなたはこの関数を再定義しなければならない。 credは、 この関数呼出しをおこなったユーザを識別する。


9.5.7 Diskfsの内部詳細

このライブラリは以下の関数群もエクスポートしている。 ただし、 このライブラリが提供している他の関数群を再定義するのでなければ、 これらは一般的には有用ではない。

Function: error_t diskfs_create_protid (struct peropen *po, struct iouser *user, struct protid **cred)

ユーザuserを指すcredの中の既存のperopen poに対応するprotidを作成して返す。 ノードpo->npはロックされていなければならない。

Function: error_t diskfs_start_protid (struct peropen *po, struct protid **cred)

peropen poに対応する、 ユーザ識別情報を持たないprotidをcredの中に構築して返す。 ノードpo->npはロックされていなければならない。

Function: void diskfs_finish_protid (struct protid *cred, struct iouser *user)

diskfs_start_protidにより開始されたprotid credの構築を終了させる。 protidに組み込まれるユーザがuserである。

Function: void diskfs_protid_rele (void *arg)

protid credがもはやreference(FIXME-J:リファレンス、参照?)を持たなくなった時に呼出される。 protidへのreference(FIXME-J:リファレンス、参照?)はポート管理ライブラリによって保守されるため、 これはクリーンな(FIXME-J:?)ルーチンの一覧に含められる。 ポート・ライブラリがこの構造体を解放する。

Function: struct peropen * diskfs_make_peropen (struct node *np, int flags, struct peropen *context)

ノードnp上にオープン・フラグflagsを持つ新しいperopen構造体を作成して返す。 root_parentshadow_rootshadow_root_parentの各フィールドの初期値は、 contextがゼロ以外であればそこからコピーされる。 contextがゼロであれば、 これらの値はいずれもゼロにセットされる。

Function: void diskfs_release_peropen (struct peropen *po)

poに対するreference(FIXME-J:リファレンス、参照?)・カウントをデクリメントする。

Function: error_t diskfs_execboot_fsys_startup (mach_port_t port, int flags, mach_port_t ctl, mach_port_t *real, mach_msg_type_name_t *realpoly)

この関数は、 execserverのブートストラップのためにS_fsys_startupにより呼出される。 execserverは本物のノードがなくても機能することができるので、 このようなぺてんが可能である(FIXME-J:?)。 引数は<hurd/fsys.defs>の中のfsys_startupと同様である。

Function: int diskfs_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp)

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.