olaris で擬似ファイルシステムをつくろう/其の1目次†ご注意†ここで紹介しているプログラムは、カーネルモジュールを含んでいます。そのため、プログラム上に問題があった場合(可能性大)にはシステムが PANIC し、場合によってはファイルシステムに重大な障害を引き起こす可能性があります。以下のプログラムはテストプログラムで、十分な検証を行ってはいません。したがってあくまで個人の検証ためにお使いいただき、重要なシステム上では動作させないでください。本プログラムの使用により発生したトラブルなど、いかなる損害についても一切の責任を負いかねます。ご利用は自己責任にてお願いいたします。 概要†今回は Solaris 上でマウントが可能な自作の擬似ファイルシステムを作成します。 ソースファイルとダウンロード†
各ソースコードはこちらから参照していただけます 動作確認済み Solaris バージョン†OpenSolaris 対応の変更を行った後(2010/4/29) の iumfs ファイルシステム の動作確認状況は以下のようになっています。
プログラムの解説†IUMFS ファイルシステムモジュール†カーネルインターフェース†Solaris 上のファイルシステムは、デバイスドライバや、STREAMS モジュールのように、ロード可能な
カーネルモジュールとして実装されています。ローダブルなカーネルモジュールである以上、カーネル
とのインターフェースさえ実装していれば、デバイスドライバのように後からシステムにインストール
し、カーネルにロードすることが可能になるはずです。
しかし問題となるのがこの「カーネルとのインターフェース」という部分なのです。
このファイルシステムを作成しようと思い立った時は、Solaris でロード可能なファイルシステムで、
コードが参照可能なものとしては XFS ぐらいしかなかったのですが、現在は
オープン Solarisで Solairs 10 相当のコード(実際には次期バージョン Solaris であ
る Nevada ベースですが)を参照することができます。これは大きなアドバンテージです。 コンフィギュレーションエントリポイント†Solaris でファイアーウォールを作ろうや、Solaris で SoftEther もどきを動かそうにて デバイスドライバや、STREAM モジュールのコードをご紹介してきましたが、ローダブルモジュールである ファイルシステムモジュールも、カーネルからのエントリポイントはこれらのカーネルモジュールと同様に _init(9E), _info(9E), _fini(9E) になります。
カーネルが、ロードしようとしているモジュールがドライバなのか、ファイルシステムなのかを判断して
いるのが、_init(9E) 内で mod_install(9F) に渡している modlinkage 構造体です。
カーネルは、この modlinkage 構造体からリンクされている modlfs 構造体(システムモジュール用の
リンケージ構造体 sys/modctl.h参照)からモジュールがファイルシステムモジュールであることがわかり、
またそのファイルシステムモジュールでサポートされている操作を知ることができます。 _init() { int err; err = mod_install(&modlinkage); ^^^^^^^^^^^^^^^^^^^^^^^^^ return (err); } ・・・と、ここまでの流れは Solaris 9 と Solaris 10 で同じなのですが、実はここから Solaris10
とそれ以前の Solaris(少なくとも Solaris 9)の実装が異なっています。正直私も最初は Solaris 9
上でファイルシステムを書けば、それを Solaris 10 でも動かせるだろうと思っていたのですが、
Solaris 10 のヘッダーファイル(sys/vfs.h、sys/vnode.h)を見て愕然としました。先に書いた modlfs
構造体が変更されていて、この構造体から参照されるデータ構造体も一新されていたのです。Solaris 10
のヘッダーファイルのコメントを見る限り、これらの変更は、各ファイルシステムからカーネル側の
構造体への依存性を無くし、カーネル側が変更されてもファイルシステムの再コンパイル
が必要ないようにすることが目的のようです。(具体的には vfsops 構造体、vnode 構造体等の
ファイルシステムからの直接の確保・開放を禁止し、カーネルが提供しているインターフェースを介して
のみ確保・開放
を行い、またこれらの構造体のメンバーの参照も一部に限定し、万一構造体が patch などで変更された
場合にもファイルシステム側に影響ないようになっているようです) Solaris 9 の場合 modlinkage (modlinkage 構造体) | +--- modlfs (modlfs 構造体) | +--- mod_fsops (mod_ops 構造体) | +--- iumfs_vfssw (vfssw 構造体) | +--- iumfs_init (初期化ルーチン) | +--- iumfs_vfsops (vfsops 構造体) | +--- iumfs_mount(MOUNT オペレーション) | +--- iumfs_unmount(UMOUNT オペレーション) | ... Solaris 10 の場合 modlinkage (modlinkage 構造体) | +--- modlfs (modlfs 構造体) | +--- mod_fsops (mod_ops 構造体) | +--- iumfs_vfsdef (vfsdef 構造体) | +--- iumfs_init (初期化ルーチン) Solaris 9 の場合、modlfs 構造体に vfsops 構造体がメンバーとして含まれており、この vfsops 構造体
のなかに、VFS オペレーション(mount や umount など)へのポインターがセットされています。 err = vfs_setfsops(fstype, iumfs_vfs_ops_def_array, &iumfs_vfsops); ~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~ カーネルに渡す VFS カーネルが作成した オペレーションがリスト vfsops構造体のポインタ された配列 がセットされる ここで紹介している IUMFS ファイルシステムでは 「SOL10」が define されているかどうかによってビルドする モジュールが Solaris 10 用か Solaris 用9 かを判断しこれらのコードが変更されるようにしています。 VFS オペレーションと VNODE オペレーション†概要のところでお話したように、Solaris には大きく分けて「擬似ファイルシステム」と
「ディスクファイルシステム」の2種類のファイルシステムがあり、UFS, NFS, PCFS, TMPFS,
PROCFS ・・などさまざまなファイルシステムが存在します。これらのファイルシステムはそれぞれ別々の
ファイルシステムモジュールとして存在し、それぞれ独自に実装されています。 以下に本 IUMFS ファイルシステムが現在サポートしている VFS および VNODE のインターフェースのオペレーション をリストします。(比較のため、UFS でサポートしているオペレーションについても載せます。) VFS オペレーション
VNODE オペレーション
全部が必須では無いとはいえ、ファイルシステムとしてサポートすべき操作があまりにも多すぎます・・ とても全てをサポートするファイルシステムを書くことはできないので、とりあえず「最低限」の操作を ができるようにすることにしました。簡単に言うと・・ できること
できないこと
IUMFS ファイルシステム用 mount コマンド†IUMFS ファイルシステム専用の mount コマンドです。 iumfs_mount.c main(int argc, char *argv[]) { if (argc != 3){ printf("Usage: %s -F iumfs strings mount_point\n", argv[0]); exit(0); } if ( mount(argv[1], argv[2], MS_DATA, "iumfs", NULL, 0) < 0 ){ perror("mount"); exit(0); } return(0); } "iumfs" という文字列がファイルシステムタイプとして渡されるので、mount(2) システムコールは IUMFS ファイルシステムモジュール固有の VFS_MOUNT オペレーション (=iumfs_mount) を呼び出し、実際のマウント処理は この iumfs_mount() という関数内にて行われます。 インストール†コンパイル&インストール†configure, make 実行すると環境に応じて 64bit/32bit のファイルシステムモジュールである iumfs と mount コマンドが作成されます。 OpenSolaris での例) $ ./configure checking for gcc... gcc checking for C compiler default output file name... a.out checking whether the C compiler works... yes checking whether we are cross compiling... no checking for suffix of executables... checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed checking for a BSD-compatible install... /bin/ginstall -c checking for isainfo... yes configure: creating ./config.status config.status: creating Makefile # make gcc -c -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -g -O2 -Wall -DOPENSOLARIS -DSOL10 -m64 -mcmodel=kernel -mno-red-zone -D_KERNEL -I. iumfs.c -o iumfs.o gcc -c -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -g -O2 -Wall -DOPENSOLARIS -DSOL10 -m64 -mcmodel=kernel -mno-red-zone -D_KERNEL -I. iumfs_vnode.c -o iumfs_vnode.o ld -dn -r iumfs.o iumfs_vnode.o -o iumfs gcc -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -g -O2 -Wall -DOPENSOLARIS -DSOL10 -m64 iumfs_mount.c -o mount gcc -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -g -O2 -Wall -DOPENSOLARIS -DSOL10 -m64 fstest.c -o fstest # make install /bin/ginstall -c -m 0644 -o root -g sys iumfs /kernel/fs/amd64 /usr/sbin/modload iumfs /bin/ginstall -c -d -m 0755 -o root -g bin /usr/lib/fs/iumfs /bin/ginstall -c -m 0755 -o root -g bin mount /usr/lib/fs/iumfs アンインストール†ファイルシステムモジュールおよびコマンドのアンインストールは make uninstall で行います。 # make uninstall /usr/sbin/modunload -i `modinfo |grep iumfs | awk '{print }'` rm /kernel/fs/amd64/iumfs rm /usr/lib/fs/iumfs/mount rm -rf /usr/lib/fs/iumfs IUMFS ファイルシステムが利用中(マウントされている)の場合、ファイルの削除は可能ですが、モジュール のアンロードは失敗します。この場合システムのリブート後に完全に削除されます。 # make uninstall /usr/sbin/modunload -i `modinfo |grep iumfs | awk '{print }'` can't unload the module: Device busy *** Error code 16 (ignored) rm /kernel/fs/amd64/iumfs rm /usr/lib/fs/iumfs/mount rm -rf /usr/lib/fs/iumfs 使い方†IUMFS ファイルシステムの利用方法についてご説明します。 ファイルシステムのマウント†IUMFS ファイルシステムのマウントには通常の mount(1M) コマンドを利用します。 Usage: mount -F iumfs strings mount_point strings : 任意の文字列 mount_point : IUMFS ファイルシステムをマウントするマウントポイント strings は空白を含まなければどのような文字列でもかまいません。ただし、省略はできません。 以下に /mnt ディレクトリに IUMFS ファイルシステムをマウントする例を示します。 # /usr/sbin/mount -F iumfs hoge /mnt # 確認 # mount ... ... /mnt on hoge read/write/setuid/devices/dev=ffffffff on Thu Nov 10 00:20:14 2005 ^^^^ ファイル・ディレクトリの作成・削除†あえて実行例を書くことも無いのですが、ファイルやディレクトリの作成・削除が行えます。もちろん、他の ファイルシステム上のファイルをコピーしてくることもできます。 ディレクトリ情報の表示 # cd /mnt # ls -lai 合計 3 1 drwxr-xr-x 1 root root 64 11月 10日 00:37 . 1514 drwxr-xr-x 26 root root 1024 10月 9日 13:40 .. 新規ファイルと新規ディレクトリの作成 # echo "sample text" > file.txt # mkdir dir # ls -lai 合計 4 1 drwxr-xr-x 1 root root 128 11月 10日 00:38 . 1514 drwxr-xr-x 26 root root 1024 10月 9日 13:40 .. 4 drwxr-xr-x 1 root root 64 11月 10日 00:38 dir 3 -rw-r--r-- 1 root root 12 11月 10日 00:38 file.txt ファイルのオープン、読み込み # cat file.txt sample text ファイルとディレクトリの削除 # rm file.txt # rm -r dir # ls -lia 合計 3 1 drwxr-xr-x 1 root root 64 11月 10日 00:39 . 1514 drwxr-xr-x 26 root root 1024 10月 9日 13:40 .. 他のファイルシステムからのファイルのコピー # cp /etc/motd /mnt # ls -lai 合計 3 1 drwxr-xr-x 1 root root 96 11月 10日 00:48 . 1514 drwxr-xr-x 26 root root 1024 10月 9日 13:40 .. 2 -rw-r--r-- 1 root root 54 11月 10日 00:48 motd # cat motd Sun Microsystems Inc. SunOS 5.10 Generic January 2005 ファイルの属性変更†touch コマンドや、chmod コマンドを使って、ファイルシステム上のファイルの更新日や、アクセス権を 変更できます。ただし、アクセス権を変更しても実際にはアクセスの可否の判定には利用されていませんので、 権限のない一般ユーザでもファイルに対する全ての操作が可能です。また、ファイルのオーナーの変更はサポートされていません。 # cd /mnt # touch file.txt # ls -li file.txt 3 -rw-r--r-- 1 root root 0 11月 10日 00:53 file.txt ファイルのアクセス権の変更 # chmod 777 file.txt # ls -li file.txt 3 -rwxrwxrwx 1 root root 0 11月 10日 00:53 file.txt ファイルの更新日時を変更 # touch file.txt # ls -li file.txt 3 -rwxrwxrwx 1 root root 0 11月 10日 00:54 file.txt ファイルのオーナーを変更 # chown nobody file.txt chown: file.txt: サポートしていない操作です。 # ファイルシステムのアンマウント†IUMFS ファイルシステムのアンマウントには通常の umount(1M) コマンドを利用します。 Usage: umount mount_point mount_point : ファイルシステムがマウントされているマウントポイント 他のファイルシステムでもおなじですが、だれかがそのファイルシステム上のファイルを 利用中の場合には BUSY が返り、umount(1M) は失敗します。 アンマウントの成功例) # umount /mnt # ファイルシステムが利用中である為にアンマウントが失敗する例) # pwd /mnt # umount /mnt umount: /mnt 使用中です。 ファイルシステムのアンマウント後は、ファイルシステム上に作成されたファイル・ディレクトリは 自動的に削除されます。(カーネル空間内でファイルやディレクトリ用に確保されていた メモリの開放が行われます。) 今後の課題†
|