VHD (Virtual Hard Disk) の可能性

即死パーテーション

先月 Windows Vista を再インストールする羽目になったのですが (id:NyaRuRu:20070618:p1) そのときの症状というのが,なかなかに悲惨なものでした.
まず色々作業した後の再起動を終え,リブートしている途中に CLFS.SYS でのページフォルトブルースクリーンが発生しました.ちょうど以下の方と同じ症状です.

なんとなくの予想ですが,CLFS (Common Log File System) に格納された Transactional NTFS (TxF) か Transactional Registry (TxR) の後処理を,OS 再起動後に行っているときに,破損データをそのまま信じてドライバ内で変なアドレスを見に行ってしまい,そのままお亡くなりという感じです.
以下は,別の PC に USB-SATA 変換ケーブル経由で問題の HDD を接続して色々試してみた結果です.

  • OS を Windows Vista にして,起動時に接続 → BSOD
  • OS を Windows Vista にして,起動後に接続 → 問題のパーテーションは raw partition と表示され,正しく認識されない.
  • OS を Windows XP にして,起動時に接続 → 読み書き可能
  • OS を Windows XP にして,起動後に接続 → 読み書き可能
  • OS を Windows Server 2008 beta3 にして,起動時に接続 → 読み書き可能
  • OS を Windows Server 2008 beta3 にして,起動後に接続 → 読み書き可能

というわけで,素の Windows Vista に対してのみ即死攻撃可能というなかなか恐ろしいパーテーションが自然発生したようでした.
ちなみに上の方も書かれていますが,Vista のインストールディスクから再インストールを試みるときでさえ,パーテーションを認識した瞬間にクラッシュします.こういったパーテーションを USB メモリで持ち運べたらそれはそれで嫌な感じです.検体という意味込めてパーテーションのバックアップをとっておいたつもりだったのですが,どうも後で調べてみると,問題のデータすべてをバックアップできていなかったようで,即死毒は回収されることなくフォーマットされてしまったのでした.

"\\.\" プレフィックスによるデバイスへの直接アクセス

さて,今回の教訓をふまえ,物理 HDD のイメージ化について考えてみます.Unix 系であればとりあえず dd でデバイスファイルを直接ダンプという手を思いつきますが,実は Windows でも "\\.\" でデバイスファイルを直接開けば,/dev/sda1 に読み書きするのと同じことが可能です*1.ただしこの方法では,後で Virtual PC にディスクイメージをマウントし,BSOD の瞬間をカーネルデバッガで見たいというような用途には向きません.そこで今回は VHD 形式をとりあげることにします.

物理 HDD から VHD (Virtual Hard Disk) を作る

Windows Vista や Windows Server 2008 の標準バックアップツールは元々 VHD 形式を活用しているのですが,どうも全セクタコピーは選択できないようで,必要なファイルのみを含む可変要領ディスクを作成しているようでした.
物理ディスクをまるまるコピーするには,Virtual PC / Virtual Server のバーチャルディスクウィザードを使います.Technet の以下のホワイトペーパーが参考になります.

バーチャルディスクウィザードを管理者権限で起動すると,「ハードディスクへのリンク (高度)」というタイプの VHD ファイルを作成することができます.これはどういうものかというと,この VHD ファイルを通じた読み書きが,実際には物理ディスクにリダイレクトされるという特殊な形態です.
これを Virtual PC にマウントさせてもおもしろいのですが,今回はイメージの作成が主なので,そちらに話を進めます.このリンク形式の VHD ファイルを実体化させるには,バーチャルディスクウィザードから「既存のバーチャルディスクの編集」を選択します.このとき,読み出しを行うデバイスにバックグラウンドで書き込みが行われると危険なので,あらかじめパーテーションをアンマウントしておくことが推奨されています.

ホスト OS に VHD をマウントする

その筋ではよく知られた Vhdmount.exe というツールを使うと,ホスト OS である Windows Vista のドライブやフォルダとして,VHD ファイルをマウントすることができます.もちろん Windows Server 2003 でもマウントは可能ですが,XP では若干制限があるようです.
Vhdmount.exe は単体では公開されていません.Vhdmount.exe をインストールするには,無償で公開されている Virtual Server 2005 R2 SP1 をインストールするか,Virtual Server 2005 R2 SP1 のセットアップファイルから Vhdmount.exe のみを選択的にインストールするかを行います.
Vhdmount.exe のみをインストールする方法については,Dave Northey's Blog の以下の記事が参考になります.

Download the setup file for Virtual Servrer R2 SP1Beta 2 and follow these instructions (from the release notes):

  1. Extract Virtual Server 2005 Install.msi from Setup.exe by typing the following command:setup.exe /c /t <drive letter>:\<path to the .msi file>For example, to extract "Virtual Server 2005 Install.msi" to c:\SetupFiles, type:setup.exe /c /t c:\SetupFiles
  2. Start an unattended installation of VHD Mount by typing the following command:msiexec /i "Virtual Server 2005 Install.msi" /qn ADDLOCAL=VHDMount

(Virtual Servrer R2 SP1 のリンク先は正式版に変更しました)
うまくいけば,以下の場所に Vhdmount がインストールされるはずです.同ディレクトリには,プログラムから VHD ファイルをマウント・アンマウントする DLL とそのヘッダファイルも含まれています.

C:\Program Files\Microsoft Virtual Server\Vhdmount

うまくいかないときは,/qn オプションを /qf や /qb に変えて,エラーメッセージを確かめてみたり,/l log.txt などしてログをチェックしてみて下さい.たとえば,Virtuap Server / Virtual PC の実行中プロセスが存在する環境で上のコマンドを実行すると,インストーラがそれを検地してインストールを中止してしまうのですが,/qn オプションを指定しているとエラーが表示されないのでそのことがわかりません.
その他のオプションに関しては,Installing Virtual Server from the command line に詳しく解説されています.
Vhdmount.exe の実際の使用方法については,『Windows XPスマートチューニング: (236) VHD形式ファイルをコンテキストメニューからマウントする』が参考になるでしょう.

VHD の復元ディスクによるオーバーレイ ファイルシステム

Virtual PC で復元ディスクを使用したことがある方はご存じでしょうが,使用中の OS に VHD ファイルをマウントするときにも,復元ディスクの仕組みを使うことができます.というより,Vhdmount はデフォルトでは復元ディスクを有効にした状態で VHD をマウントしようとします.
復元ディスクについては,@IT の以下の記事がよくまとまっているので,何となく知っているよという方もぜひ一度目を通してみて下さい.

ポイントだけ引用しておきます.

まずゲストOSがインストールされた仮想ディスク・ファイルを用意し、これをベースにしてテスト環境構築用の差分ディスク(を使った)環境を作成する。この上にテスト用のアプリケーションなどをインストールし、準備する。準備が完了したら、今度は復元ディスク機能を有効にしてテストを実施する。1回実行したら、次は復元ディスクの内容を破棄して(これで元の状態に戻る)、また次のテストを実施すればよい。

この例で分かるように、差分ディスクは環境の構築用に利用できるし、復元ディスクは実行結果をキャンセルして元に戻すために利用できる。

差分ディスクは元の(親の)仮想ディスクと一体になって利用されるものであるから、結局のところ、機能的には容量固定の仮想ディスクや容量可変の拡張仮想ディスクと同じものと見なすことができる。

これに対して復元ディスクは、仮想マシン環境のセッション情報を保存するための一時的な記憶領域にすぎないといえる。実行終了後に、それを「破棄」すれば元の仮想ディスク・ファイルには何ら変更を与えることはないが、それを「反映」すればオリジナルの仮想ディスク・ファイルに対して恒久的な変更を加えることになる。ワープロでいえば、編集中のファイルを破棄して終了するか、書き込んで終了するかの違いと同じである。

大ざっぱにいえば差分ディスクは、既存の仮想ディスクをベースにして、新しく仮想マシン環境を構築したい場合に利用し、復元ディスク機能は、後で実行結果をキャンセルして(アンドゥして)元に戻したい場合に利用するとよい。実際には、容量可変/固定/差分ディスクは環境の構築用に利用し、出来上がった環境上での(テスト)実行では復元ディスクを活用するとよいだろう。もちろん環境構築時であっても、復元ディスク機能を使えば最初の状態にすぐに戻せるので、試行錯誤するようなケースでは復元ディスク機能を活用するとよい。

この議論は,あくまで「仮想 PC」をどう運用するかという視点でのものですが,Vhdmount によって VHD ファイルをホスト OS の論理ストレージとみなせるようになると,だいぶアイディアの応用場面が広がってきます.
例えば,以前紹介したものの,RTM までにドロップしてしまった TxF の応用シナリオは,Vhdmount と VHD ファイルによって十分実現できると考えられます.

これを利用すると,例えば一時的にデータを書き換えて処理プログラムを実行し,後でオリジナル状態に戻すといった作業で,いちいちオリジナルデータのバックアップをとる必要が無くなります.

例えばこういう場合ですね.

これで,オリジナルのソースコードは一切変更されません.

LeopardZFS の例のように,利用中のファイルシステムのスナップショットを簡単に残すというわけにはいきませんが*2,様々なパラメータを順番に変えながらのストレステストや,ビルドサーバによる夜間ビルドなど,あらかじめ作業内容が予想できる場面では,おもしろい利用方法が考えられるのではないでしょうか?

*1:たとえば DVD デバイスから読み込めば ISO イメージを得ることができます.

*2:id:NyaRuRu:20070702:p1