diff options
Diffstat (limited to 'kernel/trace/trace_functions_graph.c')
| -rw-r--r-- | kernel/trace/trace_functions_graph.c | 43 | 
1 files changed, 40 insertions, 3 deletions
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 4de3e57f723c..f0a0c982cde3 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -15,6 +15,33 @@  #include "trace.h"  #include "trace_output.h" +static bool kill_ftrace_graph; + +/** + * ftrace_graph_is_dead - returns true if ftrace_graph_stop() was called + * + * ftrace_graph_stop() is called when a severe error is detected in + * the function graph tracing. This function is called by the critical + * paths of function graph to keep those paths from doing any more harm. + */ +bool ftrace_graph_is_dead(void) +{ +	return kill_ftrace_graph; +} + +/** + * ftrace_graph_stop - set to permanently disable function graph tracincg + * + * In case of an error int function graph tracing, this is called + * to try to keep function graph tracing from causing any more harm. + * Usually this is pretty severe and this is called to try to at least + * get a warning out to the user. + */ +void ftrace_graph_stop(void) +{ +	kill_ftrace_graph = true; +} +  /* When set, irq functions will be ignored */  static int ftrace_graph_skip_irqs; @@ -92,6 +119,9 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,  	unsigned long long calltime;  	int index; +	if (unlikely(ftrace_graph_is_dead())) +		return -EBUSY; +  	if (!current->ret_stack)  		return -EBUSY; @@ -323,7 +353,7 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)  	return ret;  } -int trace_graph_thresh_entry(struct ftrace_graph_ent *trace) +static int trace_graph_thresh_entry(struct ftrace_graph_ent *trace)  {  	if (tracing_thresh)  		return 1; @@ -412,7 +442,7 @@ void set_graph_array(struct trace_array *tr)  	smp_mb();  } -void trace_graph_thresh_return(struct ftrace_graph_ret *trace) +static void trace_graph_thresh_return(struct ftrace_graph_ret *trace)  {  	if (tracing_thresh &&  	    (trace->rettime - trace->calltime < tracing_thresh)) @@ -445,6 +475,12 @@ static void graph_trace_reset(struct trace_array *tr)  	unregister_ftrace_graph();  } +static int graph_trace_update_thresh(struct trace_array *tr) +{ +	graph_trace_reset(tr); +	return graph_trace_init(tr); +} +  static int max_bytes_for_cpu;  static enum print_line_t @@ -1399,7 +1435,7 @@ static void __print_graph_headers_flags(struct seq_file *s, u32 flags)  	seq_printf(s, "               |   |   |   |\n");  } -void print_graph_headers(struct seq_file *s) +static void print_graph_headers(struct seq_file *s)  {  	print_graph_headers_flags(s, tracer_flags.val);  } @@ -1495,6 +1531,7 @@ static struct trace_event graph_trace_ret_event = {  static struct tracer graph_trace __tracer_data = {  	.name		= "function_graph", +	.update_thresh	= graph_trace_update_thresh,  	.open		= graph_trace_open,  	.pipe_open	= graph_trace_open,  	.close		= graph_trace_close,  | 
