aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-03-23 17:17:01 -0400
committerIngo Molnar <mingo@elte.hu>2009-03-23 18:25:32 -0400
commit1618536961d31f9b3f55767b22d4a897f4204c26 (patch)
treef1396f4c869328dc5d6e677f6fdde571d2c6e4d7 /kernel
parentc4cff064be678f1e8344d907499f2a81282edc19 (diff)
tracing/function-graph-tracer: fix functions call traces imbalance
Impact: fix traces output Sometimes one can observe an imbalance in the traces between function calls and function return traces: func1() { } } The curly brace inside func1() is the return of another function nested inside func1. The return trace have been inserted in the buffer but not the entry. We are storing a return address on the function traces stack while we haven't inserted its entry on the buffer, hence the imbalance on the traces. This is because the tracers doesn't check all failures that can happen on buffer insertion. This patch reports the tracing recursion failures and the ring buffer failures. In such cases, we now restore the original return address for the function, giving up its return trace. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> LKML-Reference: <1237843021-11695-1-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 6bad12819eb6..89f0c2544ad0 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -924,7 +924,7 @@ trace_function(struct trace_array *tr,
924} 924}
925 925
926#ifdef CONFIG_FUNCTION_GRAPH_TRACER 926#ifdef CONFIG_FUNCTION_GRAPH_TRACER
927static void __trace_graph_entry(struct trace_array *tr, 927static int __trace_graph_entry(struct trace_array *tr,
928 struct ftrace_graph_ent *trace, 928 struct ftrace_graph_ent *trace,
929 unsigned long flags, 929 unsigned long flags,
930 int pc) 930 int pc)
@@ -933,15 +933,17 @@ static void __trace_graph_entry(struct trace_array *tr,
933 struct ftrace_graph_ent_entry *entry; 933 struct ftrace_graph_ent_entry *entry;
934 934
935 if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled)))) 935 if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled))))
936 return; 936 return 0;
937 937
938 event = trace_buffer_lock_reserve(&global_trace, TRACE_GRAPH_ENT, 938 event = trace_buffer_lock_reserve(&global_trace, TRACE_GRAPH_ENT,
939 sizeof(*entry), flags, pc); 939 sizeof(*entry), flags, pc);
940 if (!event) 940 if (!event)
941 return; 941 return 0;
942 entry = ring_buffer_event_data(event); 942 entry = ring_buffer_event_data(event);
943 entry->graph_ent = *trace; 943 entry->graph_ent = *trace;
944 ring_buffer_unlock_commit(global_trace.buffer, event); 944 ring_buffer_unlock_commit(global_trace.buffer, event);
945
946 return 1;
945} 947}
946 948
947static void __trace_graph_return(struct trace_array *tr, 949static void __trace_graph_return(struct trace_array *tr,
@@ -1162,6 +1164,7 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
1162 struct trace_array_cpu *data; 1164 struct trace_array_cpu *data;
1163 unsigned long flags; 1165 unsigned long flags;
1164 long disabled; 1166 long disabled;
1167 int ret;
1165 int cpu; 1168 int cpu;
1166 int pc; 1169 int pc;
1167 1170
@@ -1177,15 +1180,18 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
1177 disabled = atomic_inc_return(&data->disabled); 1180 disabled = atomic_inc_return(&data->disabled);
1178 if (likely(disabled == 1)) { 1181 if (likely(disabled == 1)) {
1179 pc = preempt_count(); 1182 pc = preempt_count();
1180 __trace_graph_entry(tr, trace, flags, pc); 1183 ret = __trace_graph_entry(tr, trace, flags, pc);
1184 } else {
1185 ret = 0;
1181 } 1186 }
1182 /* Only do the atomic if it is not already set */ 1187 /* Only do the atomic if it is not already set */
1183 if (!test_tsk_trace_graph(current)) 1188 if (!test_tsk_trace_graph(current))
1184 set_tsk_trace_graph(current); 1189 set_tsk_trace_graph(current);
1190
1185 atomic_dec(&data->disabled); 1191 atomic_dec(&data->disabled);
1186 local_irq_restore(flags); 1192 local_irq_restore(flags);
1187 1193
1188 return 1; 1194 return ret;
1189} 1195}
1190 1196
1191void trace_graph_return(struct ftrace_graph_ret *trace) 1197void trace_graph_return(struct ftrace_graph_ret *trace)