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.
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.
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