Linux の SCSI 開発者たちは、古いコードを取っておいているとは限りません。 したがって、リリースされた最新の Linux カーネル以外では (MCC、SLS、 Yggdrasil などのパッケージは最新カーネルから1つから12個も古い場合が あります) 問題解決が不可能な場合があります。 ですから、バグレポートを送る前に、リリースされた最新のカーネルでも その問題が起こるかどうか確かめて下さい。
カーネルをバージョンアップした後でも、またこの文書をよく読んだ後でも、 まだバグが存在すると信じられる場合には、Linux メーリング リストの SCSI チャネルにバグレポートを送ってください。 ここには Linux SCSI ドライバの作成に協力している多くの人々が参加しています。
バグレポートには、 ハードウェア構成、ブート時に Linux が表示する正確なメッセージ、 エラーが発生する場合、それにエラーが存在するソースコードの位置 など、なるべく多くの情報を書いてください。 メッセージの取得 や <tt>panic()</tt> の位置を特定する に記述されている手続きに従ってください。
最大限の情報が提供されないと、開発者が問題を誤って診断したり、 他の問題を修正することがより重要だと判断することになってしまうかも しれません。
要するに、我々がバグを再現させることができない場合、 どこがおかしいのかを具体的に指摘してくれなければ、 バグを修正することはできないということです。
カーネルメッセージロギングシステムを実行していない場合:
/proc
ファイルシステムがマウントされていることを確かめて
ください。
grep proc /etc/mtab
/proc
ファイルシステムがマウントされていなければ、マウント
してください。
mkdir /proc
chmod 755 /proc
mount -t proc /proc /proc
カーネルのバージョンとメッセージをログファイルにコピーします。
cat /proc/version > /tmp/log
cat /proc/kmsg >> /tmp/log
1秒から2秒後に CNTRL-C を打ってください。
ロギングシステムを実行している場合、適当なログファイル (ログファイルの
情報は /etc/syslog.conf
にあります) を覗くか、
dmesg
コマンドを使用してください。
Linux が起動していない場合、DOS 上でフロッピーディスクをフォーマット
してください。RAM ドライブではなく、ルートディスケットを直接マウント
するパッケージを使っている場合には、ルートとしてマウントされるドライブ
以外で読み書き可能なディスケットを用意するか、
ramdisk
ブートオプションの使用が必要であることに
注意して下さい。
Linux をパッケージのブートフロッピーからブートします。できればシングル ユーザモードで RAM ドライブをルートとしてマウントしてください。そして、
mkdir /tmp/dos
とし、さっきフォーマットしたディスケットを挿入し、マウントしてください。
mount -t msdos /dev/fd0 /tmp/dos
あるいは
mount -t msdos /dev/fd1 /tmp/dos
とします。
ログファイルをフロッピーにコピーします。
cp /tmp/log /tmp/dos/log
DOS フロッピーをアンマウントします。
umount /tmp/dos
そして Linux をシャットダウンします。
shutdown now
リブートして DOS を起動し、好みの通信ソフトを使ってログファイルを メールしてください。
panic()
の位置を特定する
他の Unix と同じように、Linux は致命的なエラーが生じるとカーネルの
panic()
関数を呼び出します。他の Unix とは違って、Linux は
コアをスワップあるいはダンプデバイスにダンプして自動的にリブート
することはありません。その代わり、ユーザが手で書き写すことができる
ように有用なステート情報のサマリが表示されます。
Unable to handle kernel NULL pointer dereference at virtual address c0000004
current->tss,cr3 = 00101000, %cr3 = 00101000
*pde = 00102027
*pte = 00000027
Oops: 0000
EIP: 0010:0019c905
EFLAGS: 00010002
eax: 0000000a ebx: 001cd0e8 ecx: 00000006 edx: 000003d5
esi: 001cd0a8 edi: 00000000 ebp: 00000000 esp: 001a18c0
ds: 0018 es: 0018 fs: 002b gs: 002b ss: 0018
Process swapper (pid: 0, process nr: 0, stackpage=001a09c8)
Stack: 0019c5c6 00000000 0019c5b2 00000000 0019c5a5 001cd0a8 00000002 00000000
001cd0e8 001cd0a8 00000000 001cdb38 001cdb00 00000000 001ce284 0019d001
001cd004 0000e800 fbfff000 0019d051 001cd0a8 00000000 001a29f4 00800000
Call Trace: 0019c5c6 0019c5b2 0018c5a5 0019d001 0019d051 00111508 00111502
0011e800 0011154d 00110f63 0010e2b3 0010ef55 0010ddb7
Code: 8b 57 04 52 68 d2 c5 19 00 e8 cd a0 f7 ff 83 c4 20 8b 4f 04
Aiee, killing interrupt handler
kfree of non-kmalloced memory: 001a29c0, next= 00000000, order=0
task[0] (swapper) killed: unable to recover
Kernel panic: Trying to free up swapper memory space
In swapper task - not syncing
EIP: 行の16進数 (この場合 19c905) を書き留め、
/usr/src/linux/zSystem.map
を探してこのアドレス以下で最も大きな
数字を見つけてください。
0019a000 T _fix_pointers
0019c700 t _intr_scsi
0019d000 t _NCR53c7x0_intr
これによってどの関数を実行中に panic()
が呼ばれたかが分かります。
この関数を含むソースファイルをデバッグオプションつきでコンパイルし直すか、
/usr/src/linux/Makefile
を編集して -g
オプションを
CFLAGS
の定義に追加してカーネル全体をコンパイルし直してください。
#
# standard CFLAGS
#
つまり、次の行を
CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe
このように変更します。
CFLAGS = -g -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe
カーネルを再構築します。
make clean
make
/etc/lilo.conf
にエントリを作成してカーネルをブートできるように
します。
image = /usr/src/linux/zImage
label = experimental
そして root で LILO を再実行するか、ブートフロッピーを作成します。
make zImage
リブートし、エラー発生時の EIP を記録します。
script
がインストールされている場合、これを起動して
以下のデバッグの記録をタイプスクリプトファイルに記録して
おくのが良いでしょう。
次のように gdb
を実行します。
gdb /usr/src/linux/tools/zSystem
そして次のように入力します。
info line *<your EIP>
例えば以下のように。
info line *0x19c905
これに対して gdb
は次のような情報を出力します。
(gdb) info line *0x19c905
Line 2855 of "53c7,8xx.c" starts at address 0x19c905 <intr_scsi+641&>
and ends at 0x19c913 <intr_scsi+655>.
この情報を記録して下さい。それから以下のように入力します。
list <line number>
次のような出力が得られるでしょう。
(gdb) list 2855
2850 /* printk("scsi%d : target %d lun %d unexpected disconnect\n",
2851 host->host_no, cmd->cmd->target, cmd->cmd->lun); */
2852 printk("host : 0x%x\n", (unsigned) host);
2853 printk("host->host_no : %d\n", host->host_no);
2854 printk("cmd : 0x%x\n", (unsigned) cmd);
2855 printk("cmd->cmd : 0x%x\n", (unsigned) cmd->cmd);
2856 printk("cmd->cmd->target : %d\n", cmd->cmd->target);
2857 if (cmd) {;
2858 abnormal_finished(cmd, DID_ERROR << 16);
2859 }
2860 hostdata->dsp = hostdata->script + hostdata->E_schedule /
2861 sizeof(long);
2862 hostdata->dsp_changed = 1;
2863 /* SCSI PARITY error */
2864 }
2865
2866 if (sstat0_sist0 & SSTAT0_PAR) {
2867 fatal = 1;
2868 if (cmd && cmd->cmd) {
2869 printk("scsi%d : target %d lun %d parity error.\n",
quit
と入力して gdb
から抜けます。
上の情報も記録してください。開発者のカーネルがあなたのカーネルと違って いる場合に役立つコンテキスト情報が得られます。