続・玩式草子 ―戯れせんとや生まれけん―

第1回 分け行っても分け行ってもバグの中

この記事を読むのに必要な時間:およそ 4 分

苦闘

「必要なドライバをカーネルに組み込んだから大丈夫」と思っていたのも束の間,インストール後に再起動するとやはりルートパーティションをマウントできずにカーネルパニックになってしまいます。

「カーネルを作り損ねたかな?⁠⁠,と考えて,内蔵HDDをルートパーティションに指定して,USB HDDにインストールしたカーネルを起動してみると問題なく起動します。さらにその状態なら,USB HDDも正しく認識し,マウントできました。

「まだ足りないドライバがあるのだろうか?」と考えて,USB HDDをマウントする前後で組み込まれるモジュール類を調べてみても違いはありません。

「カーネルにルートパーティションの情報が正しく渡せてないのかな?」と考えて,grub.cfgのカーネルパラメータをいろいろイジってみてもダメ,⁠パーティションテーブルやファイルシステムが影響しているのでは?」と,USB HDDを初期化し直してパーティションテーブルをGPTからMBRに変更してもダメ,インストールするパーティションをBtrfsからExt4やExt3にしてみてもダメ,悪あがきのつもりでカーネルのバージョンをあれこれ変えてみてもダメ,ドライバ類を半分以下に絞り込んでみてもダメでした。

確実に再現するし,その条件もわかっている,しかしながら,まる2日ほどカーネルのビルドやインストール作業を繰り返しても原因は皆目わからず,次第に出口のない迷路に迷い込んだような気になってきました。

光明

起動時のカーネルパニックが厄介なのは,メッセージが即座に流れて,途中経過が読み取れないことも一因です。もう少しメッセージの出力を遅くできないのかな,と調べてみると,"boot_delay=..."というカーネルパラメータを見つけました。このパラメータはカーネルがメッセージを出力するprintkごとに,指定した時間,待ち時間を設けるというものです。

これを使えばもう少し情報が得られるかも,と考えて,"boot_delay=100"を指定して起動してみたものの,今回のトラブルでは複数のprintkを経ていないようで,表示速度は変わりませんでした。

他に何か似たような機能はないだろうか…,とソースコードのDocumentation/admin-guideディレクトリにあるkernel-parameters.txtを"delay"をキーワードに検索してみると,"rootdelay=..."というパラメータに気がつきました。

このパラメータは「ルートファイルシステムをマウントする際,指定した秒数だけ待つ」という指定です。このパラメータを見た時,⁠ルートデバイス(ルートファイルシステムを置いているデバイス)が間に合わないのでは?」という可能性がひらめきました。その視点でもう少し読み進めると,"rootwait"という「ルートデバイスが見えるようになるまで待つ」というパラメータがありました。

これを使えば何とかなるかも,と考え,あれこれイジったカーネルやHDDパーティションを元に戻し,USB-3.0用のドライバを組み込んだカーネルをインストール,grub.cfgのカーネルパラメータに"rootwait"の一語を追加してやると,ビンゴ!⁠,USB-3.0なHDDをルートデバイスにしてきちんと起動するようになりました。

grubは問題なくカーネルを読み込んでいたため,⁠ルートデバイスが読めない」という可能性は思い浮かばなかったものの,改めて考え直してみると,grubがカーネルを読み込む際は制限時間がないのに対し,カーネルがルートパーティションをマウントする際は,マウントできなければ即座に「致命的エラー」としてカーネルパニックになります。

一方,USB-3.0では,データの転送速度が速い分,HDDは短時間に大量のデータを読み込む必要があります。そのため起動直後ではスピンアップ等の準備のため,カーネルのマウントリクエストへの対応が間に合わない,そう考えれば"rootwait"の一語で問題が解決したことも納得できます。

冒頭に紹介した"Jargon file"やウィキペディアによると,⁠ハイゼンベルクの不確定性原理」に由来する「ハイゼンバグ」「⁠⁠デバッガやprint文で)調べようとすると振舞いを変えるバグ⁠⁠,⁠ボーアの原子模型」に由来する「ボーアバグ」「特定の状況下で高い再現性を示すバグ」だそうなので,今回の問題は典型的な「ボーアバグ」と言えるでしょう。

カーネル開発者の名誉のために付言すると,USB-3.0用のドライバがモジュール化できるのも,ルートパーティションがマウントできなければ即座にカーネルパニックするのも,そういう作りになっている「仕様」です。ここで言っている「バグ」は,その仕様や回避策に気づけなかった「Plamo Linuxのバグ」という意味なので為念。

「ボーアバグ」の場合,発生する「特定の状況」を把握できれば解決は容易と言われています。しかしながら,今回のように,発生する状況にハードウェアが絡んでくると,ソフトとハードの双方を考慮しないといけなくなって,問題は指数関数的にややこしくなります。今回は何とか解決できたものの,視点や発想を柔軟に保つことの重要さを改めて思いしらされたトラブルでした。


かつての日本では,暑い夏の夜の肝試しに「百物語」が行われていました。⁠⁠百物語」では,灯しておいた100本のロウソクを,怪談や不思議な話をするごとに1本ずつ消してゆき,最後のロウソクが消えた時,本当の怪異が現れる,と語りつがれていました。

後代になると,本当の怪異が現れては困るから,という理由で,100話目はあえて語らず,99話で話を止めるスタイルが広まったそうです。

気付いている読者もいらっしゃるかと思いますが,本来,今回は「玩式草子」の100回目になる予定でした。しかしながら,バグやトラブル話を100回した結果,本当に解決できないトラブルに現れられても困るので⁠,⁠⁠百物語」のひそみに習い,99回で連載のタイトルを変えることにしました。

タイトル変更を機に,これからはLinuxやOSSだけでなく,よりさまざまな話題を取りあげて行きたいと思っているので,今後ともご愛読のほど,よろしくお願いします。

著者プロフィール

こじまみつひろ

Plamo Linuxとりまとめ役。もともとは人類学的にハッカー文化を研究しようとしていたものの,いつの間にかミイラ取りがミイラになってOSSの世界にどっぷりと漬かってしまいました。最近は田舎に隠棲して半農半自営な生活をしながらソフトウェアと戯れています。

URLhttp://www.linet.gr.jp/~kojima/Plamo/index.html