Recentemente sto giocando con ftrace per monitorare alcune caratteristiche di comportamento del mio sistema. Ho gestito la commutazione della traccia on/off tramite un piccolo script. Dopo aver eseguito lo script, il mio sistema si bloccava e si riavviava da solo. Inizialmente, credevo che potesse esserci un errore con lo script stesso, ma da allora ho determinato che il crash e il riavvio sono il risultato di echo
un tracciante in/sys/kernel/debug/tracing/current_tracer quando current_tracer
è impostato su function_graph .ftrace: arresto anomalo del sistema quando si cambia current_tracer da function_graph via echo
Cioè, la seguente sequenza di comandi produrrà l'arresto/reboot:
echo "function_graph" > /sys/kernel/debug/tracing/current_tracer
echo "function" > /sys/kernel/debug/tracing/current_tracer
Durning il riavvio dopo l'incidente causato dalle suddette echo
dichiarazioni, vedo un sacco di uscita che recita:
compensazione orfano node
<inode>
ho cercato di riprodurre questo problema sostituendo il valore da function_graph a qualcosa d'altro in un programma C current_tracer
:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int openCurrentTracer()
{
int fd = open("/sys/kernel/debug/tracing/current_tracer", O_WRONLY);
if(fd < 0)
exit(1);
return fd;
}
int writeTracer(int fd, char* tracer)
{
if(write(fd, tracer, strlen(tracer)) != strlen(tracer)) {
printf("Failure writing %s\n", tracer);
return 0;
}
return 1;
}
int main(int argc, char* argv[])
{
int fd = openCurrentTracer();
char* blockTracer = "blk";
if(!writeTracer(fd, blockTracer))
return 1;
close(fd);
fd = openCurrentTracer();
char* graphTracer = "function_graph";
if(!writeTracer(fd, graphTracer))
return 1;
close(fd);
printf("Preparing to fail!\n");
fd = openCurrentTracer();
if(!writeTracer(fd, blockTracer))
return 1;
close(fd);
return 0;
}
Stranamente, il programma C non in crash il sistema.
Originariamente ho riscontrato questo problema durante l'utilizzo di Ubuntu (Unity environment) 16.04 LTS e ho confermato che si trattava di un problema nei kernel 4.4.0 e 4.5.5. Ho anche testato questo problema su una macchina che esegue Ubuntu (ambiente Mate) 15.10, sui kernel 4.2.0 e 4.5.5, ma non è stato in grado di riprodurre il problema. Questo mi ha solo confuso ulteriormente.
Qualcuno può darmi una visione di ciò che sta accadendo? In particolare, perché dovrei essere in grado di write()
ma non echo
in/sys/kernel/debug/tracing/current_tracer?
Aggiornamento
Come Vielmetti sottolineato, altri hanno avuto un problema simile (come visto here).
Il
ftrace_disable_ftrace_graph_caller()
modifica istruzione JMP aftrace_graph_call
supponendo che è un 5 byte vicino JMP (e9). Tuttavia è un breve jmp composto da solo 2 byte (eb). Eftrace_stub()
si trova appena sotto laftrace_graph_caller
modo modifica precedente rompe l'istruzione conseguente kernel oops sul laftrace_stub()
con il codice operativo non valido come di seguito:
Il cerotto (mostrato di seguito) risolto il problema echo
, ma ancora non capisco perché echo
si è rotto in precedenza quando write()
non lo era.
diff --git a/arch/x86/kernel/mcount_64.S b/arch/x86/kernel/mcount_64.S
index ed48a9f465f8..e13a695c3084 100644
--- a/arch/x86/kernel/mcount_64.S
+++ b/arch/x86/kernel/mcount_64.S
@@ -182,7 +182,8 @@ GLOBAL(ftrace_graph_call)
jmp ftrace_stub
#endif
-GLOBAL(ftrace_stub)
+/* This is weak to keep gas from relaxing the jumps */
+WEAK(ftrace_stub)
retq
END(ftrace_caller)
via https://lkml.org/lkml/2016/5/16/493
Hai provato a riprodurre utilizzando un singolo programma C (senza chiamate 'exec' tranne che per la chiamata a' dd')? A volte le shell fanno cose strane. – o11c
Hai mai pensato di porre la tua domanda su uno dei siti Linux Stack Exchange? – ashes999
@ o11c, l'errore sembra verificarsi solo durante la scrittura in '/ sys/kernel/debug/tracing/current_tracer'. Dico questo perché posso produrre questo problema senza invocare l'intero script, ma semplicemente "echo" su quel file. Ho ascoltato il tuo suggerimento con questo in mente, e ho aggiornato il mio post. – buratino