3. Comptes-rendus de bogues (Bug Reports)

Contenu de cette section

Les développeurs SCSI de Linux ne maintiennent pas forcément les anciennes révisions du code en raison de contraintes d'espace. Si donc vous n'utilisez pas le dernier noyau Linux diffusé publiquement (remarquez que de nombreuses distributions, comme MCC, SLS, Yggdrasil, etc. restent souvent un ou même vingt patches en arrière), il y a de grandes chances pour que nous soyons incapables de résoudre votre problème. En conséquence, avant de rendre compte d'un bug, veuillez vérifier s'il persiste avec le dernier noyau publiquement disponible.

Si après vous être mis à jour, et après avoir lu ce document en détail, vous pensez toujours être en présence d'un bug, envoyez un compte-rendu (bug report) au canal SCSI de la liste de diffusion où il sera lu par de nombreuses personnes ayant contribué aux pilotes SCSI de Linux.

Dans votre compte-rendu, veuillez fournir le plus d'informations possible concernant votre configuration matérielle, le texte exact et tous les messages que Linux affiche au moment du démarrage, quand la condition d'erreur se produit, ainsi que l'endroit de l'erreur dans le code source. Utilisez les procédures indiquées en Section 2.1 : Capture des messages et en Section 2.2 : Localisation de la source d'un panic().

Une quantité insuffisante d'informations peut conduire à un mauvais diagnostic de votre problème, ou à ce que les développeurs décident qu'il existe d'autres problèmes plus intéressants à résoudre.

En conclusion, si nous ne pouvons pas reproduire votre bug, et que vous ne pouvez pas nous dire ce qui ne va pas, il ne sera pas résolu.

3.1 Capture des messages

Si vous n'avez pas lancé de système de trace de messages du noyau :

Assurez-vous que le système de fichiers /proc est monté.

grep proc /etc/mtab

Si ce n'est pas le cas, montez-le

mkdir /proc
chmod 755 /proc
mount -t proc /proc /proc

Copiez la révision et les messages du noyau dans un fichier log

cat /proc/version >/tmp/log
cat /proc/kmsg >>/tmp/log

Faites Ctrl-C après une seconde ou deux.

Si vous faites tourner un traceur, vous devrez chercher dans les fichiers de trace appropriés (/etc/log/sylog.conf devrait vous aider à les localiser), ou utiliser dmesg.

Si Linux n'est pas encore démarré, formatez une disquette sous DOS. Notez que si vous avez une distribution qui monte la disquette racine depuis le lecteur et non depuis un disque virtuel en RAM, vous devrez formatter une disquette lisible dans le lecteur non utilisé, ou utiliser leur option de démarrage par disque virtuel.

Lancez Linux depuis la disquette de démarrage de votre distribution, de préférence en mode mono-utilisateur en utilisant un disque RAM comme racine.

mkdir /tmp/dos

Insérez la disquette dans un lecteur libre pour monter la racine, et montez- la. Par ex.

mount -t msdos /dev/fd0 /tmp/dos

ou

mount -t msdos /dev/fd1 /tmp/dos

Copiez-y votre trace

cp /tmp/log /tmp/dos/log

Démontez votre disquette DOS

umount /tmp/dos

Et arrêtez Linux

shutdown

Redémarrez sous DOS, et insérez votre fichier de trace dans un message en utilisant votre logiciel de communications favori.

3.2 Localisation de la source d'un panic()

Comme d'autres unix, quand une erreur fatale se produit, Linux appelle la fonction panic(). A l'inverse d'autres unix, Linux ne produit pas de core dump vers le périphérique de swap ou de dump avant de redémarrer automatiquement. Un résumé d'informations utiles est affiché afin que l'utilisateur le copie à la main. Par ex. :

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

Prenez le nombre hexadécimal figurant à la ligne EIP:, dans ce cas 19c905, et cherchez dans /usr/src/ linux/zSystem.map le nombre le plus grand inférieur ou égal à cette adresse.

0019a000 T _fix_pointers
0019c700 t _intr_scsi
0019d000 t _NCR53c7x0_intr

Ceci vous indique dans quelle fonction l'erreur se trouve. Recompilez le fichier source qui définit cette fonction en activant les informations de debug, ou le noyau entier si vous le préférez en éditant /usr/src/linux/Makefile et en ajoutant un ``-g'' à la définition de CFLAGS.

##standard CFLAGS
#

Par exemple,

CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe

devient

CFLAGS = -g -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe

Reconstruisez le noyau, de façon incrémentale ou en faisant un

make clean
make

Rendez le noyau démarrable en lui créant une entrée dans votre /etc/lilo.conf

image = /usr/src/linux/zImage
label = experimental

et en relançant LILO en tant que root, ou en créant une disquette de démarrage

make zImage

Redémarrez et enrregistrez le nouveau EIP de l'erreur.

Si script est installé, vous pouvez le démarrer, et il tracera votre session de mise au point dans le fichier typescript.

Maintenant, lancez

gdb /usr/src/linux/tools/zSystem

et entrez

info line *<votre EIP>

Par exemple,

info line *0x19c905

A quoi GDB répondra quelque chose comme

(gdb) info line *0x19c905
Line 2855 of ``53c7,8xx.c'' starts at address 0x19c905 <intr_scsi+641>and ends 
at 0x19c913 <intr_scsi+655>.

Enregistrez cette information. Entrez ensuite list < numéro de ligne>

Par ex.,


(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",

Bien sûr, quit vous sortira de GDB.

Enrtegistrez aussi cette information, car elle fournira un contexte au cas où les noyaux des développeurs diffèrent du vôtre.


Chapitre suivant, Chapitre Précédent

Table des matières de ce chapitre, Table des matières générale

Début du document, Début de ce chapitre