openSUSE:Bugreport kernel

Pacchetti · Kernel del giorno · Segnalare un bug del kernel · Kernel GIT · Kernel team


Questo articolo è stato creato per aiutare gli utenti e i tester nella diagnosi e risoluzione dei problemi del kernel.

Introduzione al debug del Kernel Linux

Diagnosticare un bug del Kernel è un compito difficile ma alcune semplici categorie possono aiutare ad identificarlo:

  • Problemi legati ai driver dell'hardware - driver mancanti, caratteristiche mancanti, ecc.
  • Corruzione del filesystem - corruzione dei dati, file mancanti, ecc.
  • Hard locks - blocchi di sistema, o freeze, vedere tasto SysRq
  • Kernel oops - stampati in dmesg oppure in /var/log/messages
  • Problemi di performance o stabilità

Questo documento è inteso per:

  • Sostenitori e consulenti, i quali sanno come creare rapporti di bug utili e ricchi di informazioni.
  • Sviluppatori, che hanno bisogno di sapere di più riguardo la struttura di debug messa a disposizione dal Kernel Linux.

Classificazione dei Bug del Kernel

I bug del Kernel possono essere divisi in un certo numero di categorie differenti (per esempio in base all'impatto sulla sicurezza, sull'integrità dei dati, ecc.). Dato che questo documento riguarda il debug, ordiniamole in base alla complessità.

  • Non funziona come dovrebbe.
    Alcuni bug del kernel sono abbastanza facili da scovare e riprodurre, senza intaccare la stabilità del sistema. Per esempio, una scheda di rete può non funzionare con certe configurazioni, o NFS può produrre strani errori ecc. .

    Questi, spesso, sono abbastanza semplici da debuggare. Tutto ciò che serve è una descrizione precisa di ciò che accade, e la descrizione dettagliata di come riprodurre il problema. E ovviamente un hacker del kernel che ha una buona conoscenza del sottosistema. :)
  • Kernel Oops.
    Se il kernel viene avviato in una condizione inattesa di errore (per esempio quando dereferenzia un puntatore non valido), il gestore dell'eccezione catturerà questo errore, fermerà il processo corrente e proverà a registrare un messaggio che descriva l'eccezione in dettaglio. Normalmente, i messaggi oops vengono registrati dal sistema di log. È anche possibile mostrare il messaggio in una console testuale, ma quest'ultima viene disabilitata di default, rendendo necessaria l'abilitazione manuale.

    Dato che questo tipo di messaggio inizia con le parole "Kernel Ooops", ci si riferisce all'intero evento come "oopsing" (in inglese).

    Quando si verifica un oops, il processo che l'ha causato era solitamente nel bel mezzo di un affare molto importante all'interno del kernel e teneva uno o più blocchi. Poiché il processo viene terminato immediatamente, nessuno di questi blocchi verrà rilasciato, quindi gli altri processi che stavano tentando di accedervi successivamente resteranno bloccati per sempre.

    Se l'utente è in una sessione di X Windows quando l'oops si verifica, la macchina può sembrare che si stia bloccando completamente, perché il server X stesso è rimasto bloccato su alcuni blocchi vecchi del kernel e non reagisce più.
  • Kernel panic.
    Se un oops si verifica in un gestore di interrupt, il kernel proverà ad emettere un messaggio oops bloccandosi completamente, perché non esiste un modo "sano" per recuperare i blocchi dopo un crash. Questo è chiamato kernel panic.

    In caso di kernel panic, gli oops non saranno scritti nei syslog, semplicemente perché il demone syslog non verrà più programmato.
  • Blocchi leggeri.
    Alcuni bug del kernel non attivano gli oops, ma semplicemente fanno bloccare la macchina. Possono essere causati, tra le altre cose, da deadlock e livelock. Nella maggior parte dei casi (a meno che qualche stupido bug non costringa il gestore degli interrupt ad attendere ciclicamente su un blocco), questi blocchi leggeri non impediranno la consegna degli interrupt

    Se la consegna dell'interrupt è ancora possibile, la macchina reagirà alle richieste (ping), e l'input della tastiera sarà inviato alla console testuale. Comunque, i processi non avanzeranno più.

    Ripeto ancora, la macchina sarà per lo più bloccata e non fornirà risposte all'input, perché i processi non avanzeranno più.

    Un buon modo per verificare ciò è premere i tasti numlock o capslock; se i LED sulla tastiera si accendono e spengono hai un deadlock da qualche parte.
  • Blocchi pesanti (hard lockups)
    Si può verificare anche un blocco pesante; questi sono dovuti a problemi hardware o all'abuso di risorse hardware da parte di driver scritti male. Se capita ciò, sei nei guai. Puoi fermarti a leggere qui e ti auguriamo buona fortuna per debuggare questo problema.

Ottenere le giuste informazioni

Gli utenti hanno la tendenza ad incolpare i problemi software in quella parte del sistema che sembra essere più complicata o misteriosa dal loro punto di vista. Che nella maggior parte dei casi è il kernel.

Questo non vuol dire che si sbagliano. Ma spesso questo vuol dire che i loro rapporti di bug sono inaccurati, o omettono importanti dettagli.

Quindi quando hai il compito di debuggare un bug del Kernel Linux (o che qualcuno crede essere tale), ci sono un certo numero di domande sui sintomi che ti dovresti porre prima:

  • Sospensione vs crash
    La macchina è in sospensione? O è crashata del tutto? Oppure ancora, sembra essere crashata?

    Per fino gli utenti con più esperienza non si ricordano di controllare la presenza di oops nei registri di sistema (syslog), specialmente se il kernel si comporta "in modo strano" senza crashare o bruciare in maniera vistosa. Infatti, puoi risparmiarti un sacco di lavoro se gli chiedi di verificare i messaggi di oops nei syslog.

    Come descritto sopra, se il kernel è andato in oops mentre l'utente sta usando X, può sembrare che la macchina si stia sospendendo.

    Nel kernel 2.4, c'e' un indicatore che ti dirà se il kernel è andato in panic, anche se sei in una sessione di X: i LED numlock inizieranno a lampeggiare. La versione 2.6 del kernel non ha ancora questa caratteristica.

    In questo caso, è sempre di aiuto riprodurre il problema dopo aver cambiato la console testuale. Se la macchina non è in un blocco totale, il kernel accetterà almeno l'input da tastiera. Sulla console, inoltre, sarà anche possibile catturare informazioni addizionali sul crash. Come minimo, devi dire al kernel di mostrare il messaggio di oops anche in una console usando il comando
# klogconsole -r0 -l8
Se l' oops non è scritto nei syslog (per esempio quando si verifica in un interrupt), catturare l'output con una videocamera digitale può ancora essere d'aiuto (facendo attenzione che la grandezza della foto non superi i 512k).

Alternativamente, si può provare a catturare l'oops da una console seriale.

Oppure, puoi abilitare le combinazioni di tasti sysrq e catturare le informazioni di alcune richieste di sistema, come descritto nella sezione apposita di questa pagina.

  • Eliminare problemi noti.
    Ci sono certe classi di problemi che sono comuni quanto la sporcizia. Cerca di esserne consapevole e portali fuori "dall'equazione" il prima possibile.
Il primo elemento della lista dei problemi noti è probabilmente ACPI:
La maggior parte delle volte che un utente riporta un problema con la macchina che non si avvia propriamente, o l'hardware non viene configurato correttamente, è dovuto a delle cattive tabelle ACPI del BIOS.
Prova ad avviare il sistema con acpi=off per disabilitarlo completamente.
[TODO: la lista dei comandi del kernel relativi all'ACPI va qui.]
Altri problemi molto comuni?
  • Eliminare i dettagli non essenziali.
    I rapporti di bug degli utenti, spesso, descrivono scenari abbastanza precisi, come "Stavo usando un disco USB con reiserFS esportato via NFS mentre ascoltavo i miei mp3 e tutto a un tratto la macchina è crashata".

    Questo rapporto simpatico e accurato coinvolge almeno ogni parte del sottosistema che ha il kernel (block device layer, VM, VFS, rete, audio, ...).

    Per aiutarti a circoscrivere il problema, qui ci sono un po' di cose che puoi provare:
    • il problema si verifica allo stesso modo con versione vecchie/nuove del kernel?
    • Se cambi una certa componente con un'altra equivalente (per esempio rimpiazzando il filesystem reiserFS con ext3), il problema persiste?
    • Se il problema implica la corruzione della memoria o guasti casuali dell'hardware: può essere riprodotto su una macchina differente?
    • Specialmente per macchine di grandi dimensioni, la corruzione casuale della memoria può essere causata da problemi hardware relativi alla RAM. Per diagnosticare la RAM guasta, usa il CD/DVD di installazione, seleziona memtest86 e avvialo per 24 ore.

Catturare le informazioni dell'oops

Come descritto precedentemente, un crash del kernel risulterà in un oops che verrà scritto nei log di sistema. Il messaggio oops contiene una grande quantità di informazioni che possono aiutare almeno a diagnosticare il problema.

In un caso benigno (relativamente parlando), il kernel sarà in grado di continuare, nonostante la condizione di errore, e il sistema sarà stabile abbastanza da scrivere almeno l'oops nei log di sistema. Se il kernel va in panic, è tutt'altro che banale registrare un oops, comunque.

Il tuo peggior nemico è il desktop. Un qualsiasi messaggio del kernel stampato sulla console mentre il server X è avviato non verrà mostrato sullo schermo. Il server X ha un modo suo di catturare i messaggi inviati su /dev/console e di mostrarteli, ma se il bug è abbastanza grave da impedire a syslogd e klogd di scrivere l'oops nei syslog, le chance che X sia in grado di mostrare qualcosa di utile sono molto basse.

Quindi se sei capace di riprodurre il problema in un certo modo, la prima cosa che dovresti fare è passare alla console testuale e avviare la visualizzazione nella console delle informazioni di log:

klogconsole -r0 -l8

Questo cambierà il livello di visualizzazione dei log del kernel nella console mostrando tutto ciò che invia al syslogd. Questo include qualsiasi oops del kernel; se riesci ad attivare il bug del kernel ora, otterrai almeno uno schermo pieno di informazioni sull'oops.

Nota: se lo stai facendo frequentemente, per favore fai riferimento alla sezione apposita, sulle console seriali sottostante - questo metodo è preferibile, ma come primo tentativo, già essere in grado di leggere gli oops è una grande vittoria. Per imparare a leggere gli oops, fai riferimento all'apposito file.

Usare ksymoops

Un kernel oops solitamente include un dump dello stato attuale del processore, includendo registri, puntatori alle istruzioni e funzioni di call back trace. Per questo per essere di qualche utilità agli sviluppatori del kernel, questi indirizzi devono essere mappati in nomi di funzioni e/o variabili, quando possibile.

I kernel attuali di SUSE supportano una caratteristica chiamata "kallsyms" dove il kernel in uso include un tabella di simboli di se stesso, che gli permette di risolvere gli indirizzi automaticamente quando stampa a video un oops.

I kernel più vecchi non hanno questa caratteristica, quindi gli oops stampati conterranno solo gli indirizzi grezzi, che avranno bisogno di essere convertiti da un'applicazione utente apposita.

Ecco a cosa server ksymoops: tu puoi dare in pasto a ksymoops gli indirizzi grezzi dello standard input, e date le giuste informazioni sul simbolo, ti offrirà una versione "cucinata" di quello che l'oops mappa e una lista disassembly delle istruzioni esadecimali. Questo software NON deve essere usato quando kallsyms è attivo (ovvero nei kernel recenti di openSUSE).

Il nocciolo della questione è fornire a ksymoops le giuste informazioni sui simboli. Queste informazioni vengono prese, solitamente, dall'immagine vmlinux e dal file System.map nella directory /boot, che deve combaciare esattamente con la versione del kernel che ha generato l'oops. Altrimenti, può essere una buona idea avviare ksymoops sulla macchina dove è avvenuto il crash.

Se risolve il modulo dei simboli propriamente, ksymoops ha bisogno anche della lista dei moduli del kernel e della loro locazione in memoria. Un buon modo per ottenerli è copiare il file /proc/modules immediatamente prima o dopo che l'oops si è verificato e specificare questa copia a ksymoops usando l'opzione da linea di comando -l:

# ksymoops -l /tmp/proc-modules-copy < /tmp/my-oops

Fortunatamente, gran parte del lavoro è già stato fatto automaticamente quando l'oops è stato catturato da syslogd, perché quest'ultimo farà tutte le traduzioni per te. Questo ha il grande vantaggio di usare sempre la lista corretta dei simboli.

Naturalmente, gli oops catturati dalla console seriale non avranno i loro indirizzi "massaggiati" da syslogd, quindi, in tal caso, dovrai avviare manualmente ksymoops.

Usare sysrq

sysrq sta per "system request" (richiesta di sistema). Questo è il nome di un gruppo di combinazioni chiave che diranno al kernel di mostrare vari tipi di informazioni interne, sincronizzare il filesystem o uccidere un processo. Dato che ciò è alquanto sensibile alla sicurezza ( soprattutto la parte che permette di uccidere i processi ), i comandi sysrq sono disabilitati di default.

Un modo per abilitare sysrq è eseguire il seguente comando da un prompt di shell:

echo 1 > /proc/sys/kernel/sysrq

Inoltre, dovresti modificare /etc/sysconfig/sysctl e cambiare la variabile ENABLE_SYSRQ a "yes" (senza virgolette ovviamente). Questo garantirà l'abilitazione di sysrq dopo aver riavviato il sistema.

Per usare sysrq, hai bisogno di premere una combinazione "magica" di tasti più uno di comando. Questa combinazione magica dipende dalla piattaforma hardware in uso, ma sulla maggior parte di queste, di solito, è ALT-SysRQ (su alcune tastiere, il tasto SysRQ è etichettato come "PtrScr", "Print" o "Stamp", ed è situato solitamente a destra dei tasti funzione).

La maggior parte dei tasti sysrq faranno riportare, al kernel, informazioni sullo stato alla console seriale. Nella configurazione di default, un sistema con SUSE invia l'output generato dal kernel alla tty10, quindi avrai bisogno di andare nella console 10, oppure dovrai redirigerlo ad un'altra tty usando klogconsole.

Il comando più utile è "h", che mostra un piccolo testo di aiuto:

SysRq : HELP : loglevel0-8 reBoot tErm kIll saK showMem powerOff showPc
		unRaw Sync showTasks Unmount

Di seguito, una descrizione dei comandi più importanti:

0-8	These keys change the console log level to the indicated 
        level. 8 will display everything on the console, 1 will be 
        critical messages only, and 0 turns console logging off entirely.
M	Display current memory statistics
P	Display current processor registers, instruction counter, call 
        trace and list of loaded modules. This is essentially the process 
        related information that would get printed as part of an oops.
T	Shows a listing of all tasks, including the back trace of their 
        current kernel stack. Beware, this list can be very long.
U	Try to re-mount all currently mounted file systems read-only.
E	Send a TERM signal to all processes except init.
I	Send a KILL signal to all processes except init.

Sono disponibili anche altri tasti sysrq; una lista completa è disponibile in Documentation/sysrq.txt, nei sorgenti del kernel.

È anche possibile lanciare i comandi sysrq dalla linea di comando, che è molto utile se non hai accesso alla tastiera (per esempio quando si sta debuggando un problema da remoto). In questo caso, semplicemente, puoi inviare la lettera tramite echo verso /proc/sysrq-trigger e leggere, successivamente, le informazioni che ti ritorna dmesg o direttamente i log di sistema:

# echo t > /proc/sysrq-trigger

Usare lkcd

[TBD]

Usare nmi_watchdog

[TBD]

Usare la console seriale

Alcuni kernel oops (specialmente quelli che riguardano la fase di boot) possono occorrere quando la console di sistema è inusabile. Per ottenere un dump report affidabile può tornare utile una console seriale. Avrai bisogno di un secondo computer e un cavo null-modem (i.e. un cavo seriale con due connettori identici), rendendo, quindi, necessaria la presenza, su entrambe le macchine, della porta seriale stessa. Questo purtroppo mette da parte tutti i computer moderni sprovvisti di tale porta. In questa sfortunata ipotesi puoi provare ad usare la netconsole.

Una volta collegato il cavo dovresti aggiungere

console=ttyS0,115200 console=tty0

alla linea di comando del debugger. Ciò permette alla console di inviare messaggi attraverso la ttySO così come avviene con quella standard. L'ultimo parametro console= determina da dove deve prendere l'input la console, quindi se vuoi che la console seriale accetti l'input dall'altra macchina dovrai cambiare questi parametri.

Fatto ciò, sulla macchina ricevente dovrai semplicemente lanciare il comando seguente come root:

# screen -T vt100 /dev/ttyS0 115200

(assumendo che la connessione serial sia attiva sulla prima porta seriale). A questo punto riavvia (dai un reboot) e stai a vedere.

Ora per catturare un qualsiasi oops è più facile registrando tutto dallo schermo. Per sapere come farlo controlla il manuale dello schermo.

Autori

Olaf Kirch <okir [at] suse [dot] de>
Hannes Reinecke <hare [at] suse [dot] de>

Cosa dovrei fare con un Kernel OOPS?

Leggi il documento apposito dalla documentazione di Novell: OOPS reading (in inglese).


Come posso debuggare un problema del kernel?

Leggi il documento apposito dalla documentazione di Novell: Introduzione al debug del kernel (in inglese).