diff options
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 65 |
1 files changed, 57 insertions, 8 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 216bbe7547a4..a3f7ae9cd8e1 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -244,13 +244,6 @@ unsigned long nsecs_to_usecs(unsigned long nsecs) | |||
244 | return nsecs / 1000; | 244 | return nsecs / 1000; |
245 | } | 245 | } |
246 | 246 | ||
247 | /* | ||
248 | * TRACE_ITER_SYM_MASK masks the options in trace_flags that | ||
249 | * control the output of kernel symbols. | ||
250 | */ | ||
251 | #define TRACE_ITER_SYM_MASK \ | ||
252 | (TRACE_ITER_PRINT_PARENT|TRACE_ITER_SYM_OFFSET|TRACE_ITER_SYM_ADDR) | ||
253 | |||
254 | /* These must match the bit postions in trace_iterator_flags */ | 247 | /* These must match the bit postions in trace_iterator_flags */ |
255 | static const char *trace_options[] = { | 248 | static const char *trace_options[] = { |
256 | "print-parent", | 249 | "print-parent", |
@@ -810,6 +803,35 @@ trace_function(struct trace_array *tr, struct trace_array_cpu *data, | |||
810 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); | 803 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); |
811 | } | 804 | } |
812 | 805 | ||
806 | #ifdef CONFIG_FUNCTION_RET_TRACER | ||
807 | static void __trace_function_return(struct trace_array *tr, | ||
808 | struct trace_array_cpu *data, | ||
809 | struct ftrace_retfunc *trace, | ||
810 | unsigned long flags, | ||
811 | int pc) | ||
812 | { | ||
813 | struct ring_buffer_event *event; | ||
814 | struct ftrace_ret_entry *entry; | ||
815 | unsigned long irq_flags; | ||
816 | |||
817 | if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled)))) | ||
818 | return; | ||
819 | |||
820 | event = ring_buffer_lock_reserve(global_trace.buffer, sizeof(*entry), | ||
821 | &irq_flags); | ||
822 | if (!event) | ||
823 | return; | ||
824 | entry = ring_buffer_event_data(event); | ||
825 | tracing_generic_entry_update(&entry->ent, flags, pc); | ||
826 | entry->ent.type = TRACE_FN_RET; | ||
827 | entry->ip = trace->func; | ||
828 | entry->parent_ip = trace->ret; | ||
829 | entry->rettime = trace->rettime; | ||
830 | entry->calltime = trace->calltime; | ||
831 | ring_buffer_unlock_commit(global_trace.buffer, event, irq_flags); | ||
832 | } | ||
833 | #endif | ||
834 | |||
813 | void | 835 | void |
814 | ftrace(struct trace_array *tr, struct trace_array_cpu *data, | 836 | ftrace(struct trace_array *tr, struct trace_array_cpu *data, |
815 | unsigned long ip, unsigned long parent_ip, unsigned long flags, | 837 | unsigned long ip, unsigned long parent_ip, unsigned long flags, |
@@ -1038,6 +1060,29 @@ function_trace_call(unsigned long ip, unsigned long parent_ip) | |||
1038 | raw_local_irq_restore(flags); | 1060 | raw_local_irq_restore(flags); |
1039 | } | 1061 | } |
1040 | 1062 | ||
1063 | #ifdef CONFIG_FUNCTION_RET_TRACER | ||
1064 | void trace_function_return(struct ftrace_retfunc *trace) | ||
1065 | { | ||
1066 | struct trace_array *tr = &global_trace; | ||
1067 | struct trace_array_cpu *data; | ||
1068 | unsigned long flags; | ||
1069 | long disabled; | ||
1070 | int cpu; | ||
1071 | int pc; | ||
1072 | |||
1073 | raw_local_irq_save(flags); | ||
1074 | cpu = raw_smp_processor_id(); | ||
1075 | data = tr->data[cpu]; | ||
1076 | disabled = atomic_inc_return(&data->disabled); | ||
1077 | if (likely(disabled == 1)) { | ||
1078 | pc = preempt_count(); | ||
1079 | __trace_function_return(tr, data, trace, flags, pc); | ||
1080 | } | ||
1081 | atomic_dec(&data->disabled); | ||
1082 | raw_local_irq_restore(flags); | ||
1083 | } | ||
1084 | #endif /* CONFIG_FUNCTION_RET_TRACER */ | ||
1085 | |||
1041 | static struct ftrace_ops trace_ops __read_mostly = | 1086 | static struct ftrace_ops trace_ops __read_mostly = |
1042 | { | 1087 | { |
1043 | .func = function_trace_call, | 1088 | .func = function_trace_call, |
@@ -1285,7 +1330,7 @@ seq_print_sym_offset(struct trace_seq *s, const char *fmt, | |||
1285 | # define IP_FMT "%016lx" | 1330 | # define IP_FMT "%016lx" |
1286 | #endif | 1331 | #endif |
1287 | 1332 | ||
1288 | static int | 1333 | int |
1289 | seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags) | 1334 | seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags) |
1290 | { | 1335 | { |
1291 | int ret; | 1336 | int ret; |
@@ -1738,6 +1783,10 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) | |||
1738 | trace_seq_print_cont(s, iter); | 1783 | trace_seq_print_cont(s, iter); |
1739 | break; | 1784 | break; |
1740 | } | 1785 | } |
1786 | case TRACE_FN_RET: { | ||
1787 | return print_return_function(iter); | ||
1788 | break; | ||
1789 | } | ||
1741 | } | 1790 | } |
1742 | return TRACE_TYPE_HANDLED; | 1791 | return TRACE_TYPE_HANDLED; |
1743 | } | 1792 | } |