Skip to content

Commit 7423907

Browse files
fweisbecIngo Molnar
authored andcommitted
tracing/fastboot: Use the ring-buffer timestamp for initcall entries
Impact: Split the boot tracer entries in two parts: call and return Now that we are using the sched tracer from the boot tracer, we want to use the same timestamp than the ring-buffer to have consistent time captures between sched events and initcall events. So we get rid of the old time capture by the boot tracer and split the initcall events in two parts: call and return. This way we have the ring buffer timestamp of both. An example trace: [ 27.904149584] calling net_ns_init+0x0/0x1c0 @ 1 [ 27.904429624] initcall net_ns_init+0x0/0x1c0 returned 0 after 0 msecs [ 27.904575926] calling reboot_init+0x0/0x20 @ 1 [ 27.904655399] initcall reboot_init+0x0/0x20 returned 0 after 0 msecs [ 27.904800228] calling sysctl_init+0x0/0x30 @ 1 [ 27.905142914] initcall sysctl_init+0x0/0x30 returned 0 after 0 msecs [ 27.905287211] calling ksysfs_init+0x0/0xb0 @ 1 ##### CPU 0 buffer started #### init-1 [000] 27.905395: 1:120:R + [001] 11:115:S ##### CPU 1 buffer started #### <idle>-0 [001] 27.905425: 0:140:R ==> [001] 11:115:R init-1 [000] 27.905426: 1:120:D ==> [000] 0:140:R <idle>-0 [000] 27.905431: 0:140:R + [000] 4:115:S <idle>-0 [000] 27.905451: 0:140:R ==> [000] 4:115:R ksoftirqd/0-4 [000] 27.905456: 4:115:S ==> [000] 0:140:R udevd-11 [001] 27.905458: 11:115:R + [001] 14:115:R <idle>-0 [000] 27.905459: 0:140:R + [000] 4:115:S <idle>-0 [000] 27.905462: 0:140:R ==> [000] 4:115:R udevd-11 [001] 27.905462: 11:115:R ==> [001] 14:115:R ksoftirqd/0-4 [000] 27.905467: 4:115:S ==> [000] 0:140:R <idle>-0 [000] 27.905470: 0:140:R + [000] 4:115:S <idle>-0 [000] 27.905473: 0:140:R ==> [000] 4:115:R ksoftirqd/0-4 [000] 27.905476: 4:115:S ==> [000] 0:140:R <idle>-0 [000] 27.905479: 0:140:R + [000] 4:115:S <idle>-0 [000] 27.905482: 0:140:R ==> [000] 4:115:R ksoftirqd/0-4 [000] 27.905486: 4:115:S ==> [000] 0:140:R udevd-14 [001] 27.905499: 14:120:X ==> [001] 11:115:R udevd-11 [001] 27.905506: 11:115:R + [000] 1:120:D <idle>-0 [000] 27.905515: 0:140:R ==> [000] 1:120:R udevd-11 [001] 27.905517: 11:115:S ==> [001] 0:140:R [ 27.905557107] initcall ksysfs_init+0x0/0xb0 returned 0 after 3906 msecs [ 27.905705736] calling init_jiffies_clocksource+0x0/0x10 @ 1 [ 27.905779239] initcall init_jiffies_clocksource+0x0/0x10 returned 0 after 0 msecs [ 27.906769814] calling pm_init+0x0/0x30 @ 1 [ 27.906853627] initcall pm_init+0x0/0x30 returned 0 after 0 msecs [ 27.906997803] calling pm_disk_init+0x0/0x20 @ 1 [ 27.907076946] initcall pm_disk_init+0x0/0x20 returned 0 after 0 msecs [ 27.907222556] calling swsusp_header_init+0x0/0x30 @ 1 [ 27.907294325] initcall swsusp_header_init+0x0/0x30 returned 0 after 0 msecs [ 27.907439620] calling stop_machine_init+0x0/0x50 @ 1 init-1 [000] 27.907485: 1:120:R + [000] 2:115:S init-1 [000] 27.907490: 1:120:D ==> [000] 2:115:R kthreadd-2 [000] 27.907507: 2:115:R + [001] 15:115:R <idle>-0 [001] 27.907517: 0:140:R ==> [001] 15:115:R kthreadd-2 [000] 27.907517: 2:115:D ==> [000] 0:140:R <idle>-0 [000] 27.907521: 0:140:R + [000] 4:115:S <idle>-0 [000] 27.907524: 0:140:R ==> [000] 4:115:R udevd-15 [001] 27.907527: 15:115:D + [000] 2:115:D ksoftirqd/0-4 [000] 27.907537: 4:115:S ==> [000] 2:115:R udevd-15 [001] 27.907537: 15:115:D ==> [001] 0:140:R kthreadd-2 [000] 27.907546: 2:115:R + [000] 1:120:D kthreadd-2 [000] 27.907550: 2:115:S ==> [000] 1:120:R init-1 [000] 27.907584: 1:120:R + [000] 15: 0:D init-1 [000] 27.907589: 1:120:R + [000] 2:115:S init-1 [000] 27.907593: 1:120:D ==> [000] 15: 0:R udevd-15 [000] 27.907601: 15: 0:S ==> [000] 2:115:R ##### CPU 0 buffer started #### kthreadd-2 [000] 27.907616: 2:115:R + [001] 16:115:R ##### CPU 1 buffer started #### <idle>-0 [001] 27.907620: 0:140:R ==> [001] 16:115:R kthreadd-2 [000] 27.907621: 2:115:D ==> [000] 0:140:R udevd-16 [001] 27.907625: 16:115:D + [000] 2:115:D <idle>-0 [000] 27.907628: 0:140:R + [000] 4:115:S udevd-16 [001] 27.907629: 16:115:D ==> [001] 0:140:R <idle>-0 [000] 27.907631: 0:140:R ==> [000] 4:115:R ksoftirqd/0-4 [000] 27.907636: 4:115:S ==> [000] 2:115:R kthreadd-2 [000] 27.907644: 2:115:R + [000] 1:120:D kthreadd-2 [000] 27.907647: 2:115:S ==> [000] 1:120:R init-1 [000] 27.907657: 1:120:R + [001] 16: 0:D <idle>-0 [001] 27.907666: 0:140:R ==> [001] 16: 0:R [ 27.907703862] initcall stop_machine_init+0x0/0x50 returned 0 after 0 msecs [ 27.907850704] calling filelock_init+0x0/0x30 @ 1 [ 27.907926573] initcall filelock_init+0x0/0x30 returned 0 after 0 msecs [ 27.908071327] calling init_script_binfmt+0x0/0x10 @ 1 [ 27.908165195] initcall init_script_binfmt+0x0/0x10 returned 0 after 0 msecs [ 27.908309461] calling init_elf_binfmt+0x0/0x10 @ 1 Signed-off-by: Frederic Weisbecker <[email protected]> Acked-by: Steven Rostedt <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
1 parent 3f5ec13 commit 7423907

File tree

4 files changed

+144
-59
lines changed

4 files changed

+144
-59
lines changed

include/trace/boot.h

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,30 @@
22
#define _LINUX_TRACE_BOOT_H
33

44
/*
5-
* Structure which defines the trace of an initcall.
5+
* Structure which defines the trace of an initcall
6+
* while it is called.
67
* You don't have to fill the func field since it is
78
* only used internally by the tracer.
89
*/
9-
struct boot_trace {
10+
struct boot_trace_call {
1011
pid_t caller;
1112
char func[KSYM_NAME_LEN];
12-
int result;
13-
unsigned long long duration; /* usecs */
14-
ktime_t calltime;
15-
ktime_t rettime;
13+
};
14+
15+
/*
16+
* Structure which defines the trace of an initcall
17+
* while it returns.
18+
*/
19+
struct boot_trace_ret {
20+
char func[KSYM_NAME_LEN];
21+
int result;
22+
unsigned long long duration; /* nsecs */
1623
};
1724

1825
#ifdef CONFIG_BOOT_TRACER
19-
/* Append the trace on the ring-buffer */
20-
extern void trace_boot(struct boot_trace *it, initcall_t fn);
26+
/* Append the traces on the ring-buffer */
27+
extern void trace_boot_call(struct boot_trace_call *bt, initcall_t fn);
28+
extern void trace_boot_ret(struct boot_trace_ret *bt, initcall_t fn);
2129

2230
/* Tells the tracer that smp_pre_initcall is finished.
2331
* So we can start the tracing
@@ -34,7 +42,12 @@ extern void enable_boot_trace(void);
3442
*/
3543
extern void disable_boot_trace(void);
3644
#else
37-
static inline void trace_boot(struct boot_trace *it, initcall_t fn) { }
45+
static inline
46+
void trace_boot_call(struct boot_trace_call *bt, initcall_t fn) { }
47+
48+
static inline
49+
void trace_boot_ret(struct boot_trace_ret *bt, initcall_t fn) { }
50+
3851
static inline void start_boot_trace(void) { }
3952
static inline void enable_boot_trace(void) { }
4053
static inline void disable_boot_trace(void) { }

init/main.c

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -704,33 +704,35 @@ core_param(initcall_debug, initcall_debug, bool, 0644);
704704
int do_one_initcall(initcall_t fn)
705705
{
706706
int count = preempt_count();
707-
ktime_t delta;
707+
ktime_t calltime, delta, rettime;
708708
char msgbuf[64];
709-
struct boot_trace it;
709+
struct boot_trace_call call;
710+
struct boot_trace_ret ret;
710711

711712
if (initcall_debug) {
712-
it.caller = task_pid_nr(current);
713-
printk("calling %pF @ %i\n", fn, it.caller);
714-
it.calltime = ktime_get();
713+
call.caller = task_pid_nr(current);
714+
printk("calling %pF @ %i\n", fn, call.caller);
715+
calltime = ktime_get();
716+
trace_boot_call(&call, fn);
715717
enable_boot_trace();
716718
}
717719

718-
it.result = fn();
720+
ret.result = fn();
719721

720722
if (initcall_debug) {
721-
it.rettime = ktime_get();
722-
delta = ktime_sub(it.rettime, it.calltime);
723-
it.duration = (unsigned long long) delta.tv64 >> 10;
724-
printk("initcall %pF returned %d after %Ld usecs\n", fn,
725-
it.result, it.duration);
726-
trace_boot(&it, fn);
727723
disable_boot_trace();
724+
rettime = ktime_get();
725+
delta = ktime_sub(rettime, calltime);
726+
ret.duration = (unsigned long long) delta.tv64 >> 10;
727+
trace_boot_ret(&ret, fn);
728+
printk("initcall %pF returned %d after %Ld usecs\n", fn,
729+
ret.result, ret.duration);
728730
}
729731

730732
msgbuf[0] = 0;
731733

732-
if (it.result && it.result != -ENODEV && initcall_debug)
733-
sprintf(msgbuf, "error code %d ", it.result);
734+
if (ret.result && ret.result != -ENODEV && initcall_debug)
735+
sprintf(msgbuf, "error code %d ", ret.result);
734736

735737
if (preempt_count() != count) {
736738
strlcat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
@@ -744,7 +746,7 @@ int do_one_initcall(initcall_t fn)
744746
printk("initcall %pF returned with %s\n", fn, msgbuf);
745747
}
746748

747-
return it.result;
749+
return ret.result;
748750
}
749751

750752

kernel/trace/trace.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ enum trace_type {
2222
TRACE_SPECIAL,
2323
TRACE_MMIO_RW,
2424
TRACE_MMIO_MAP,
25-
TRACE_BOOT,
25+
TRACE_BOOT_CALL,
26+
TRACE_BOOT_RET,
2627
TRACE_FN_RET,
2728

2829
__TRACE_LAST_TYPE
@@ -123,9 +124,14 @@ struct trace_mmiotrace_map {
123124
struct mmiotrace_map map;
124125
};
125126

126-
struct trace_boot {
127+
struct trace_boot_call {
127128
struct trace_entry ent;
128-
struct boot_trace initcall;
129+
struct boot_trace_call boot_call;
130+
};
131+
132+
struct trace_boot_ret {
133+
struct trace_entry ent;
134+
struct boot_trace_ret boot_ret;
129135
};
130136

131137
/*
@@ -228,8 +234,9 @@ extern void __ftrace_bad_type(void);
228234
TRACE_MMIO_RW); \
229235
IF_ASSIGN(var, ent, struct trace_mmiotrace_map, \
230236
TRACE_MMIO_MAP); \
231-
IF_ASSIGN(var, ent, struct trace_boot, TRACE_BOOT); \
232-
IF_ASSIGN(var, ent, struct ftrace_ret_entry, TRACE_FN_RET); \
237+
IF_ASSIGN(var, ent, struct trace_boot_call, TRACE_BOOT_CALL);\
238+
IF_ASSIGN(var, ent, struct trace_boot_ret, TRACE_BOOT_RET);\
239+
IF_ASSIGN(var, ent, struct ftrace_ret_entry, TRACE_FN_RET);\
233240
__ftrace_bad_type(); \
234241
} while (0)
235242

kernel/trace/trace_boot.c

Lines changed: 93 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -58,35 +58,71 @@ static void boot_trace_init(struct trace_array *tr)
5858
tracing_sched_switch_assign_trace(tr);
5959
}
6060

61-
static enum print_line_t initcall_print_line(struct trace_iterator *iter)
61+
static enum print_line_t
62+
initcall_call_print_line(struct trace_iterator *iter)
6263
{
64+
struct trace_entry *entry = iter->ent;
65+
struct trace_seq *s = &iter->seq;
66+
struct trace_boot_call *field;
67+
struct boot_trace_call *call;
68+
u64 ts;
69+
unsigned long nsec_rem;
6370
int ret;
71+
72+
trace_assign_type(field, entry);
73+
call = &field->boot_call;
74+
ts = iter->ts;
75+
nsec_rem = do_div(ts, 1000000000);
76+
77+
ret = trace_seq_printf(s, "[%5ld.%09ld] calling %s @ %i\n",
78+
(unsigned long)ts, nsec_rem, call->func, call->caller);
79+
80+
if (!ret)
81+
return TRACE_TYPE_PARTIAL_LINE;
82+
else
83+
return TRACE_TYPE_HANDLED;
84+
}
85+
86+
static enum print_line_t
87+
initcall_ret_print_line(struct trace_iterator *iter)
88+
{
6489
struct trace_entry *entry = iter->ent;
65-
struct trace_boot *field = (struct trace_boot *)entry;
66-
struct boot_trace *it = &field->initcall;
6790
struct trace_seq *s = &iter->seq;
68-
struct timespec calltime = ktime_to_timespec(it->calltime);
69-
struct timespec rettime = ktime_to_timespec(it->rettime);
70-
71-
if (entry->type == TRACE_BOOT) {
72-
ret = trace_seq_printf(s, "[%5ld.%09ld] calling %s @ %i\n",
73-
calltime.tv_sec,
74-
calltime.tv_nsec,
75-
it->func, it->caller);
76-
if (!ret)
77-
return TRACE_TYPE_PARTIAL_LINE;
78-
79-
ret = trace_seq_printf(s, "[%5ld.%09ld] initcall %s "
80-
"returned %d after %lld msecs\n",
81-
rettime.tv_sec,
82-
rettime.tv_nsec,
83-
it->func, it->result, it->duration);
84-
85-
if (!ret)
86-
return TRACE_TYPE_PARTIAL_LINE;
91+
struct trace_boot_ret *field;
92+
struct boot_trace_ret *init_ret;
93+
u64 ts;
94+
unsigned long nsec_rem;
95+
int ret;
96+
97+
trace_assign_type(field, entry);
98+
init_ret = &field->boot_ret;
99+
ts = iter->ts;
100+
nsec_rem = do_div(ts, 1000000000);
101+
102+
ret = trace_seq_printf(s, "[%5ld.%09ld] initcall %s "
103+
"returned %d after %llu msecs\n",
104+
(unsigned long) ts,
105+
nsec_rem,
106+
init_ret->func, init_ret->result, init_ret->duration);
107+
108+
if (!ret)
109+
return TRACE_TYPE_PARTIAL_LINE;
110+
else
87111
return TRACE_TYPE_HANDLED;
112+
}
113+
114+
static enum print_line_t initcall_print_line(struct trace_iterator *iter)
115+
{
116+
struct trace_entry *entry = iter->ent;
117+
118+
switch (entry->type) {
119+
case TRACE_BOOT_CALL:
120+
return initcall_call_print_line(iter);
121+
case TRACE_BOOT_RET:
122+
return initcall_ret_print_line(iter);
123+
default:
124+
return TRACE_TYPE_UNHANDLED;
88125
}
89-
return TRACE_TYPE_UNHANDLED;
90126
}
91127

92128
struct tracer boot_tracer __read_mostly =
@@ -97,11 +133,10 @@ struct tracer boot_tracer __read_mostly =
97133
.print_line = initcall_print_line,
98134
};
99135

100-
void trace_boot(struct boot_trace *it, initcall_t fn)
136+
void trace_boot_call(struct boot_trace_call *bt, initcall_t fn)
101137
{
102138
struct ring_buffer_event *event;
103-
struct trace_boot *entry;
104-
struct trace_array_cpu *data;
139+
struct trace_boot_call *entry;
105140
unsigned long irq_flags;
106141
struct trace_array *tr = boot_trace;
107142

@@ -111,18 +146,46 @@ void trace_boot(struct boot_trace *it, initcall_t fn)
111146
/* Get its name now since this function could
112147
* disappear because it is in the .init section.
113148
*/
114-
sprint_symbol(it->func, (unsigned long)fn);
149+
sprint_symbol(bt->func, (unsigned long)fn);
150+
preempt_disable();
151+
152+
event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
153+
&irq_flags);
154+
if (!event)
155+
goto out;
156+
entry = ring_buffer_event_data(event);
157+
tracing_generic_entry_update(&entry->ent, 0, 0);
158+
entry->ent.type = TRACE_BOOT_CALL;
159+
entry->boot_call = *bt;
160+
ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
161+
162+
trace_wake_up();
163+
164+
out:
165+
preempt_enable();
166+
}
167+
168+
void trace_boot_ret(struct boot_trace_ret *bt, initcall_t fn)
169+
{
170+
struct ring_buffer_event *event;
171+
struct trace_boot_ret *entry;
172+
unsigned long irq_flags;
173+
struct trace_array *tr = boot_trace;
174+
175+
if (!pre_initcalls_finished)
176+
return;
177+
178+
sprint_symbol(bt->func, (unsigned long)fn);
115179
preempt_disable();
116-
data = tr->data[smp_processor_id()];
117180

118181
event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
119182
&irq_flags);
120183
if (!event)
121184
goto out;
122185
entry = ring_buffer_event_data(event);
123186
tracing_generic_entry_update(&entry->ent, 0, 0);
124-
entry->ent.type = TRACE_BOOT;
125-
entry->initcall = *it;
187+
entry->ent.type = TRACE_BOOT_RET;
188+
entry->boot_ret = *bt;
126189
ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
127190

128191
trace_wake_up();

0 commit comments

Comments
 (0)