Avanti Indietro Indice

3. Segnalazione di Bug

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.

3.1 Catturare i messaggi

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.

3.2 Determinare la provenienza di una ``panic()''

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.


Avanti Indietro Indice