Page suivante Page précédente Table des matières
3. Signaler une anomalie
Soumis à des contraintes de place, les développeurs des parties SCSI de Linux ne maintiennent pas obligatoirement les vieilles versions du code. Si vous ne tournez pas avec la dernière version du noyau (la plupart des distributions de Linux, (MCC, SLS, Yggdrasil, etc.) peuvent avoir jusqu'à une vingtaine de patches de retard sur le dernier noyau), il y a une forte probabilité pour que vous ne soyez pas capable de résoudre votre problème. Avant de signaler une anomalie, vérifiez si elle existe encore avec la toute dernière version du noyau.
Si après avoir mis à jour votre noyau et lu entièrement ce document, vous pensez vraiment avoir découvert un problème, envoyez par email un rapport d'anomalie à la liste de diffusion SCSI, où il aura des chances d'être lu par la plupart des personnes ayant participé au développement des pilotes SCSI pour Linux.
Mettez dans votre rapport d'anomalie le maximum d'information sur votre configuration matérielle, le texte exact des messages que Linux affiche au démarrage, le moment où l'erreur se produit et à quel endroit dans les sources l'erreur a été levée. Référez-vous aux chapitres Capture des messages SCSI et Localisation de l'origine d'un panic().
Des informations incomplètes peuvent conduire à de mauvais diagnostics ou à un classement vertical de la part du développeur du pilote, qui risque d'estimer qu'il a plus important à corriger.
Retenez bien ceci : si nous ne pouvons pas reproduire le problème et si vous ne pouvez pas nous dire ce qui ne marche pas, l'anomalie ne sera jamais corrigée.
3.1 Capture des messages SCSI
Si aucun archiveur (logger) de messages ne tourne, il va falloir en lancer un. Vérifiez que le système de fichiers
/procest monté :
grep proc /etc/mtabS'il ne l'est pas, il faut le monter :
mkdir /proc chmod 755 /proc mount -t proc /proc /procRecopiez ensuite la version du noyau et ses messages dans un fichier de log :
cat /proc/version > /tmp/log cat /proc/kmsg >> /tmp/logAttendez une seconde ou deux (le temps que le
cat /proc/kmsgse termine) puis tapez CTRL-C.Si un logger de messages tourne, vous allez devoir chercher dans le fichier de traces adéquat (jetez un oeil à
/etc/syslog.confpour trouver où se cache ce fichier). Vous pouvez aussi taper la commandedmesg.Si Linux n'est pas lancé, formatez une disquette sous DOS. Si votre distribution monte la disquette en tant que racine (root) plutôt qu'un disque RAM, vous allez devoir formater une disquette et la mettre dans le lecteur non utilisé par la racine (si vous disposez de deux lecteurs). Si vous n'avez pas de second lecteur, il vous faudra utiliser l'option de démarrage 'ramdisk'.
Maintenant, démarrez depuis la disquette de boot de votre distribution, de préférence en mode utilisateur simple (single user) et en demandant à placer la racine (root) dans un disque RAM.
mkdir /tmp/dosInsérez la disquette dans un lecteur non utilisé pour monter la racine et montez-la :
mount -t msdos /dev/fd0 /tmp/dosou
mount -t msdos /dev/fd1 /tmp/dosCopiez-y ensuite votre fichier de traces :
cp /tmp/log /tmp/dos/logDémontez votre disquette DOS
umount /tmp/doset arrêtez Linux.
shutdownRedémarrez sous DOS puis incluez le fichier de traces dans votre mail.
3.2 Localisation de l'origine d'un
panic()Ainsi que d'autres Unix le font, Linux appelle la fonction du noyau panic() lorsqu'une erreur fatale est détectée. Par contre, contrairement à d'autres Unix, Linux ne produit pas un fichier de dump dans la swap. Il ne redémarre pas non plus. Il laisse dans le fichier de traces des informations intéressantes. Par exemple :
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 syncingPrenez la valeur hexadécimale du registre EIP (le compteur de programme ; ici, en l'occurence, 19c905). Cherchez ensuite dans le fichier
/usr/src/linux/zSystem.map(ou le fichierSystem.mapcorrespondant au noyau que vous êtes en train d'exécuter) la plus grande valeur inférieure à la valeur du registre EIP. Par exemple,
0019a000 T _fix_pointers 0019c700 t _intr_scsi 0019d000 t _NCR53c7x0_intrindique dans quelle fonction l'erreur fatale s'est produite. Recompilez ce fichier en ayant autorisé les options de debug (vous pouvez aussi les autoriser à un niveau plus global en éditant le fichier
/usr/src/linux/Makefileet en ajoutant l'option "-g" à la variable CFLAGS).
# # standard CFLAGS #Par exemple :
CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipedevient
CFLAGS = -g -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipeRegénérez le noyau, incrémentalement ou en tapant
make clean makeRendez le noyau démarrable (bootable) en créant une entrée dans le fichier
/etc/lilo.conf:
image = /usr/src/linux/zImage label = experimentalN'oubliez pas de relancer LILO en tant que root (
/sbin/lilo). Vous pouvez aussi créer une disquette de démarrage :
make zImageRedémarrez et notez le nouvel EIP pour l'erreur.
Si vous avez installé script, lancez-le ; il va tracer toute votre session dans un fichier.
Maintenant, lancez
gdb /usr/src/linux/tools/zSystemet tapez
info line *<votre EIP>Par exemple,
info line *0x19c905GDB devrait répondre quelque chose du genre
(gdb) info line *0x19c905 Line 2855 of "53c7,8xx.c" starts at address 0x19c905 <intr_scsi+641&> and ends at 0x19c913 <intr_scsi+655>.Mémorisez cette information. Entrez ensuite
list <numéro de ligne>Par exemple,
(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",
quitvous permet de sortir de GDB.Sauvegardez également cette information, car elle permettra de fournir le contexte dans lequel l'erreur s'est produite, pour le cas où les développeurs n'auraient pas exactement la même arborescence.
Page suivante Page précédente Table des matières