問題発生
ビルドが成功したら、1つ上のディレクトリにdebファイルができているが、それをdpkg -iで導入して再起動をする前に、/boot/grub/menu.lstを編集しておくべきだ、ということに気がついたのは作成したカーネルがフリーズしたおかげだ(笑)。
導入したカーネルをパッケージとしてインストールした場合、そのカーネルがデフォルトとして登録される。timeoutパラメータはデフォルトでは3(秒)なので、導入したカーネルが動かない場合は大変困ったことになる。なので、今後の作業に備えてtimeoutの値は15秒程度に増やしておき、かつdefaultは0(導入した新しいカーネル)でなく、古い(動作する安全な)カーネルを指すようにしておくと良い。また、他はわからないが、Ubuntuではsplashとquietが勝手に追加されるので、起動に失敗した場合何も見えないから、新たに追加したエントリーについてはそれらを削除したほうが良い。
「フリーズ」の症状は、Ubuntuのおなじみの起動画面が表示されて、プログレスバーの最初の目盛りが表示されたところでだんまりになり、そのまま10分くらい放っておくと、「BusyBox v1.1.3」としてBusyBoxのシェルが表示される。プロンプトは、「(initramfs)」となっている。lsを実行したり、BusyBoxのヘルプを見るだけならこれでも良いが、残念ながらこれではやりたいことができない。「フリーズ」の原因は二つで、ひとつはごく初歩的な、もうひとつはえらく複雑な話だった。
- VMwareではHDをSCSIとして見せるので、configには該当するオプションを指定しなければいけないがしていなかった(笑)
- 少なくともVMwareの5.4以前のバージョンでは、Linuxカーネル2.6.21以降のSCSIの変更に追随しておらず、その結果、configで必要なオプションを追加していたとしてもHD(root fs)を認識できず死んでしまうらしい*1
後者についてこんな情報が見つかった。
- http://kumaneko-sakura.sblo.jp/article/4982575.html
- http://www.vmware.com/community/message.jspa?messageID=661783
- http://lkml.org/lkml/2007/3/23/345
事態は複雑かつややこしい。ひと言で言うと「VMware側のバグ」ということのようだが、どうやら6.0でもまだ対応されていないらしい。3番目のリンクに含まれているパッチは、2番目のVMwareの掲示板の上のほうに含まれているものと同じで、drivers/message/fusion/mptbase.cに対するもので、試してみたら無事起動できた。
--- linux/drivers/message/fusion/mptbase.c.orig 2007-03-20 13:47:28.000000000 -0700 +++ linux/drivers/message/fusion/mptbase.c 2007-03-23 17:45:51.000000000 -0700 @@ -2564,6 +2564,16 @@ pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus); pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo); pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices); + /* + * VMware emulation is broken, its PortFact's MaxDevices reports value + * programmed by IOC Init, so if you program IOC Init to 256 (which is 0, + * as that field is only 8 bit), it reports back 0 in port facts, instead + * of 256... And unfortunately using 256 triggers another bug in the + * code (parallel SCSI can have only 16 devices). + */ + if (pfacts->MaxDevices == 0) { + pfacts->MaxDevices = 16; + } pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID); pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags); pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
(但し、このスレッドには「これより良い」という違うパッチも投稿されている)
動作を確認した環境は、
- Ubuntu 7.04Desktop(このページの上にリンクがある仮想マシンデータ)
- 2.6.22.5カーネル
- configは、さらからmake menuconfigして、SELinuxとKnernel Hackingを無効にしたもの
本来VMware側の問題なのにカーネル側で暫定*2対処するのは好ましくないかもしれないが、「とにかくVMwareで2.6.21以降のカーネルをコンパイルしたい」という方は、下記パッチを当てると良い。