aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2008-10-02 07:26:05 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-14 04:39:12 -0400
commit5601020feb0c3010e9e3e0131e9697ac6a06777b (patch)
tree99d1a70dbf3bba2b5ae1007c4828c28e6480214a
parentcb5ab74204a6e2579d1119bf1348eb806526b12b (diff)
tracing/fastboot: get the initcall name before it disappears
After some initcall traces, some initcall names may be inconsistent. That's because these functions will disappear from the .init section and also their name from the symbols table. So we have to copy the name of the function in a buffer large enough during the trace appending. It is not costly for the ring_buffer because the number of initcall entries is commonly not really large. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--include/linux/ftrace.h7
-rw-r--r--init/main.c3
-rw-r--r--kernel/trace/trace_boot.c14
3 files changed, 15 insertions, 9 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 4455490d91bd..e672e51c40a9 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -7,6 +7,7 @@
7#include <linux/fs.h> 7#include <linux/fs.h>
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/kallsyms.h>
10 11
11extern int ftrace_enabled; 12extern int ftrace_enabled;
12extern int 13extern int
@@ -213,7 +214,7 @@ ftrace_init_module(unsigned long *start, unsigned long *end) { }
213 214
214struct boot_trace { 215struct boot_trace {
215 pid_t caller; 216 pid_t caller;
216 initcall_t func; 217 char func[KSYM_NAME_LEN];
217 int result; 218 int result;
218 unsigned long long duration; 219 unsigned long long duration;
219 ktime_t calltime; 220 ktime_t calltime;
@@ -221,10 +222,10 @@ struct boot_trace {
221}; 222};
222 223
223#ifdef CONFIG_BOOT_TRACER 224#ifdef CONFIG_BOOT_TRACER
224extern void trace_boot(struct boot_trace *it); 225extern void trace_boot(struct boot_trace *it, initcall_t fn);
225extern void start_boot_trace(void); 226extern void start_boot_trace(void);
226#else 227#else
227static inline void trace_boot(struct boot_trace *it) { } 228static inline void trace_boot(struct boot_trace *it, initcall_t fn) { }
228static inline void start_boot_trace(void) { } 229static inline void start_boot_trace(void) { }
229#endif 230#endif
230 231
diff --git a/init/main.c b/init/main.c
index 61eb66159391..8e96a0ef17f4 100644
--- a/init/main.c
+++ b/init/main.c
@@ -712,7 +712,6 @@ int do_one_initcall(initcall_t fn)
712 712
713 if (initcall_debug) { 713 if (initcall_debug) {
714 it.caller = task_pid_nr(current); 714 it.caller = task_pid_nr(current);
715 it.func = fn;
716 printk("calling %pF @ %i\n", fn, it.caller); 715 printk("calling %pF @ %i\n", fn, it.caller);
717 it.calltime = ktime_get(); 716 it.calltime = ktime_get();
718 } 717 }
@@ -725,7 +724,7 @@ int do_one_initcall(initcall_t fn)
725 it.duration = (unsigned long long) delta.tv64 >> 20; 724 it.duration = (unsigned long long) delta.tv64 >> 20;
726 printk("initcall %pF returned %d after %Ld msecs\n", fn, 725 printk("initcall %pF returned %d after %Ld msecs\n", fn,
727 it.result, it.duration); 726 it.result, it.duration);
728 trace_boot(&it); 727 trace_boot(&it, fn);
729 } 728 }
730 729
731 msgbuf[0] = 0; 730 msgbuf[0] = 0;
diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c
index 7c15f3e68ba3..b9dc2c0093ab 100644
--- a/kernel/trace/trace_boot.c
+++ b/kernel/trace/trace_boot.c
@@ -8,6 +8,7 @@
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/debugfs.h> 9#include <linux/debugfs.h>
10#include <linux/ftrace.h> 10#include <linux/ftrace.h>
11#include <linux/kallsyms.h>
11 12
12#include "trace.h" 13#include "trace.h"
13 14
@@ -56,17 +57,19 @@ static enum print_line_t initcall_print_line(struct trace_iterator *iter)
56 struct timespec rettime = ktime_to_timespec(it->rettime); 57 struct timespec rettime = ktime_to_timespec(it->rettime);
57 58
58 if (entry->type == TRACE_BOOT) { 59 if (entry->type == TRACE_BOOT) {
59 ret = trace_seq_printf(s, "[%5ld.%06ld] calling %pF @ %i\n", 60 ret = trace_seq_printf(s, "[%5ld.%06ld] calling %s @ %i\n",
60 calltime.tv_sec, 61 calltime.tv_sec,
61 calltime.tv_nsec, 62 calltime.tv_nsec,
62 it->func, it->caller); 63 it->func, it->caller);
63 if (!ret) 64 if (!ret)
64 return TRACE_TYPE_PARTIAL_LINE; 65 return TRACE_TYPE_PARTIAL_LINE;
65 ret = trace_seq_printf(s, "[%5ld.%06ld] initcall %pF " 66
67 ret = trace_seq_printf(s, "[%5ld.%06ld] initcall %s "
66 "returned %d after %lld msecs\n", 68 "returned %d after %lld msecs\n",
67 rettime.tv_sec, 69 rettime.tv_sec,
68 rettime.tv_nsec, 70 rettime.tv_nsec,
69 it->func, it->result, it->duration); 71 it->func, it->result, it->duration);
72
70 if (!ret) 73 if (!ret)
71 return TRACE_TYPE_PARTIAL_LINE; 74 return TRACE_TYPE_PARTIAL_LINE;
72 return TRACE_TYPE_HANDLED; 75 return TRACE_TYPE_HANDLED;
@@ -83,8 +86,7 @@ struct tracer boot_tracer __read_mostly =
83 .print_line = initcall_print_line, 86 .print_line = initcall_print_line,
84}; 87};
85 88
86 89void trace_boot(struct boot_trace *it, initcall_t fn)
87void trace_boot(struct boot_trace *it)
88{ 90{
89 struct ring_buffer_event *event; 91 struct ring_buffer_event *event;
90 struct trace_boot *entry; 92 struct trace_boot *entry;
@@ -95,6 +97,10 @@ void trace_boot(struct boot_trace *it)
95 if (!trace_boot_enabled) 97 if (!trace_boot_enabled)
96 return; 98 return;
97 99
100 /* Get its name now since this function could
101 * disappear because it is in the .init section.
102 */
103 sprint_symbol(it->func, (unsigned long)fn);
98 preempt_disable(); 104 preempt_disable();
99 data = tr->data[smp_processor_id()]; 105 data = tr->data[smp_processor_id()];
100 106