彷徨えるフジワラ

年がら年中さまよってます

Solaris で NTFS/ext2 をマウント

USB ブートした Linux から ext2 ファイルシステムfsck が完了したので、肝心のデータ吸出し@Solaris の実施などを。

とは言っても、作業手順の基本は瀧さんのエントリに書いてある通り。

まずは、Belenix から FSWpartFSWfsmisc を入手して、パッケージのインストール。

$ gtar zxf FSWpart.tar.gz
$ gtar zxf FSWfsmisc.tar.gz
$ pkgadd -d . FSWpart FSWfsmisc

通常のマウントの場合、マウント対象スライス(≠ fdisk パーティション)を特定する必要があるのだが、fdisk パーティション領域内部にスライスを切る x86 Solaris と違い、Linux はプライマリパーティションとか拡張パーティションを直に使っているので、スライス指定とかってどうするの?という不安が。

しかしありがたいことに、prtpart コマンドは指定したデバイス配下の認識可能なスライス等を表示してくれるので、デバイスさえ特定できれば問題無い。

$ prtpart /dev/rdsk/c11t0d0p0 -ldevs
....(省略)....
/dev/dsk/c11t0d0p1      Linux native
/dev/dsk/c11t0d0p2      Linux native
/dev/dsk/c11t0d0p3      Linux native
/dev/dsk/c11t0d0p4      WIN95 Extended(LBA)
/dev/dsk/c11t0d0p5      Linux native
/dev/dsk/c11t0d0p6      Linux native
/dev/dsk/c11t0d0p7      Linux native
/dev/dsk/c11t0d0p8      Linux swap
/dev/dsk/c11t0d0p9      Linux native

$

なんだ、プライマリパーティションと論理パーティションは、通し番号が割り当てられるのね。

なお、デバイスが特定できない場合でも、prtpart コマンドを引数無しで実行すると、候補のデバイス一覧が表示されるので、以下の様な情報を元に絞り込みが可能。

  1. "zpool status" 実行で、zpool に組み込み済みのデバイスを確認可能
  2. SCSI/SATA 系ディスクなら "cfgadm -al" でデバイス名を確認可能
  3. "format" 起動直後のメニューで、認識されているデバイス一覧を確認可能
  4. "prtconf -v" で詳細情報を確認できるが、情報量が多いのでちょっと面倒

※ 他に有用な情報入手の方法をご存知の方、是非ご一報ください

ここまでくれば、後は通常のマウントと同様に、以下の要領でマウント完了。

$ mount -F ext2fs /dev/dsk/c11t0d0p5 /mnt

さて、実はここからが本題(笑)。

パッケージインストール前後で /usr/lib/fs 配下を比較すると、ファイルシステム固有の実行ファイルを格納するディレクトリが追加されていることがわかる。

$ ls -F /usr/lib/fs
autofs/   dev/     hsfs/   nfs/    pcfs/     smb/    udfs/
cachefs/  ext2fs/  lofs/   ntfs/   proc/     smbfs/  ufs/
ctfs/     fd/      mntfs/  objfs/  sharefs/  tmpfs/  zfs/
$

しかしその一方で、ファイルシステム固有のカーネルモジュールを格納する /kernel/fs 配下には、何も追加インストールされていない。

この謎を解くヒントは、先述した瀧さんのブログエントリ中の以下の記述。

ntfsファイルシステムドライバは、通常の実装とは異なるようで、マウントすると自分自身がNFSサーバ?になるようです。

実はこの挙動、NTFS だけでなく ext2 等にも共通だったりする。

腐ってもファイルシステム開発者なので、ここまで来ると鈍い自分でもピンと来た。

  1. mount コマンドが、サーバソケット作成(= ポート番号決定)
  2. mount コマンドが、fork(2) でプロセス生成
  3. 子プロセスは、 NFS サーバとして稼動
  4. NFS サーバは、上記のサーバソケットで要求待ち
  5. 親プロセスは、 NFS クライアントとして mount(2) を発行(+ ポート番号指定)
  6. NFS クライアントのカーネルモジュールは、子プロセスの NFS サーバに接続
  7. 親プロセスは、mount(2) が完了したなら終了
  8. 以後は、NFS 経由で ext2 にアクセス

という流れなのだな。

で、この方式の重要なメリットがバイナリ互換性。

カーネルの内部実装は意外と(Linux などは「予想通り」なのかもしれないけど....)仕様変更が発生していて、エンタープライズ向けに互換性を重視してそうな Solaris10 ですら、update6 以前の環境でビルドしたカーネルモジュールが、update7 で稼動させると PANIC する(場合がある)、という非互換があったりする。

OS 添付のモジュールであれば、リリース時点で再ビルドされるから問題無いけど、サードパーティ製品の場合は、対応の即時性が下がらざるを得ない。

今回の FSWpart と FSWfsmisc の導入の際にも、実はその点(カーネルモジュールの非互換)が非常に気になっていたのだけれど、上記の様な NFS 経由での実現であれば、稼動環境が特に限定されていないのも納得。

RPC による NFS を経由するため、性能的なペナルティは大きいけど、一種の FUSE と言えなくも無い(笑)。

例えば新規にファイルシステムを実装する場合、純粋にロジック実装の検証をするのであれば、「障害即パニック」なカーネル空間で稼動させるよりも、このような手法によるユーザ空間での稼動の方が有利だと思われる(「デバッガでステップ実行@ファイルシステム」なんてことも!)。

もっとも、キャッシュ等を含めたメモリ管理周辺の機能は、カーネル〜ユーザ空間での可搬性のための抽象化が難しい部分でもあるので、基本的にはフィージビリティ検証とかプロトタイプ段階までしか無理だとは思うけどね > ユーザ空間稼動

とは言いつつも、door 連携による仲介専用ファイルシステムを作成して、論理部分(= door server)をユーザ空間で適宜切り替え可能!とかだと、コンテキストスイッチコストもある程度抑えられるだろうから、実験用のベースとしてはそこそこ面白くなりそうな予感が。

ちなみに、READLINK RPC の実装が不十分なのか、シンボリックリンクの読み出しが I/O エラーで失敗する .... > ext2fs

ソースで確認しようと思ったけど、GPL ライセンスだったので断念(※ 仕事の関係上、カーネル絡みの GPL 感染は避けなければならないため)。誰か、詳細をご存知の方、ご一報ください。

# ひょっとして、古い版をダウンロードしちゃったとか?