A causa di problemi di spazio non sempre gli sviluppatori del Linux SCSI conservano vecchie revisioni del codice. Perciò se non state usando l'ultimo versione del kernel di Linux rilasciata al pubblico (notate che molte delle distribuzioni Linux, come MCC, SLS, Yggdrasil, ecc. restano a volte indietro anche di una ventina di patch) ci sono molte probabilità che non saremo in grado di risolvere il vostro problema. Perciò prima di segnalare un problema, controllate per favore che si presenti anche con la versione più recente del kernel.
Se dopo l'aggiornamento del kernel e la lettura approfondita di questo documento siete ancora convinti di aver trovato un errore, inviatene una descrizione al canale SCSI della mailing list, dove molte delle persone che hanno contribuito ai driver Linux SCSI la potranno vedere.
Nel segnalare il bug, fornite più informazioni che potete a proposito della vostra configurazione hardware, il testo esatto di tutti i messaggi che Linux stampa quando esegue il boot e quando l'errore si verifica, e in che punto del codice sorgente si trova l'errore. Utilizzate le procedure elencate in Catturare i messaggi e Determinare la provenienza di una ``panic()''.
Se non fornite la maggior quantità possibile di informazioni può risultare difficile diagnosticare correttamente il vostro problema, e gli sviluppatori potrebbero decidere che ci sono problemi più interessanti da risolvere.
Insomma, se non siamo in grado di riprodurre il vostro difetto, e voi non siete in grado di indicarci cos'è che non funziona, il problema non verrà risolto.
Se non state usando un sistema di registrazione ("log") dei messaggi del kernel, assicuratevi che il filesystem /proc sia montato.
grep proc /etc/mtab
Se il filesystem /proc non è montato, montatelo
mkdir /proc
chmod 755 /proc
mount -t proc /proc /proc
Copiate il numero di revisione e i messaggi del kernel in un file di log
cat /proc/version > /tmp/log
cat /proc/kmsg >> /tmp/log
Premete CONTROL-C dopo un paio di secondi.
Se state eseguendo un qualche logger, dovrete ``sbirciare'' tra i logfile giusti (/etc/syslog.conf dovrebbe essere utile per localizzarli), o usare dmesg.
Se Linux non ha ancora eseguito il bootstrap, formattate un dischetto floppy sotto DOS. Notate che se avete una distribuzione che monta il dischetto di root da floppy piuttosto che dal RAM drive, dovrete formattare un dischetto leggibile nel drive non usato per montare la root o usare la loro opzione boot da ramdisk.
Eseguite il boot di Linux dal vostro floppy di distribuzione di boot, preferibilmente in modalità utente singolo usando un RAM disk come root.
mkdir /tmp/dos
Inserite il dischetto in un drive non usato per montare la root, e montatelo. Ad esempio
mount -t msdos /dev/fd0 /tmp/dos
o
mount -t msdos /dev/fd1 /tmp/dos
Copiateci il vostro log
cp /tmp/log /tmp/dos/log
Smontate il floppy DOS
umount /tmp/dos
e chiudete Linux
shutdown
Eseguite nuovamente un boot in DOS, e usando il vostro software di comunicazione preferito scrivete un messaggio e-mail includendo in esso il file di log.
Come altri unix, quando si imbatte in un errore fatale, Linux chiama la funzione kernel panic(). A differenza di altri unix, Linux, piuttosto che salvare il core sul dispositivo di swap o di dump ed eseguire il reboot, stampa per l'utente un utile elenco di informazioni riguardanti lo stato del sistema che deve essere copiato a mano. Ad esempio:
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
Prendete il numero esadecimale sulla riga EIP:, in questo caso 19c905, e cercate in /usr/src/linux/zSystem.map il numero più alto non più grande di quell'indirizzo. Ad esempio:
0019a000 T _fix_pointers
0019c700 t _intr_scsi
0019d000 t _NCR53c7x0_intr
Questo vi dice in quale funzione è. Ricompilate il file sorgente che definisce quel file di funzione con la funzione di debugging attivata, o tutto il kernel se preferite e aggiungete un ``-g'' alla definizione CFLAGS in /usr/src/linux/Makefile.
#
# standard CFLAGS
#
Ad esempio,
CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe
diventa
CFLAGS = -g -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe
Ricompilate il kernel, in maniera incrementale o facendo un
make clean
make
Modificate il vostro /etc/lilo.conf in modo da poter eseguire il boot del kernel
image = /usr/src/linux/zImage
label = experimental
ed eseguite nuovamente LILO come root, o create un floppy per il boot
make zImage
Riavviate il sistema e registrate il nuovo EIP per l'errore.
Se avete script installato, potreste voler eseguirlo, perché tiene un log della vostra sessione di debugging nel file typescript.
Adesso eseguite
gdb /usr/src/linux/tools/zSystem
e inserite
info line *<il vostro EIP>
ad esempio,
info line *0x19c905
A cui GDB risponderà qualcosa del tipo
(gdb) info line *0x19c905
Line 2855 of "53c7,8xx.c" starts at address 0x19c905 <intr_scsi+641&>
and ends at 0x19c913 <intr_scsi+655>.
Scrivetevi queste informazioni, poi inserite
list <numero di linea>
Ad esempio:
(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",
Ovviamente, ``quit'' vi porterà fuori da GDB.
Segnatevi anche queste informazioni, poiché fornisce un contesto nel caso in cui i kernel degli sviluppatori differiscano dal vostro.