Skip to content

Commit 9c1c251

Browse files
committed
tracing: Allow boot instances to have snapshot buffers
Add to ftrace_boot_snapshot, "=<instance>" name, where the instance will get a snapshot buffer, and will take a snapshot at the end of boot (which will save the boot traces). Link: https://lkml.kernel.org/r/[email protected] Cc: Masami Hiramatsu <[email protected]> Cc: Andrew Morton <[email protected]> Reviewed-by: Ross Zwisler <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent d503b8f commit 9c1c251

File tree

2 files changed

+81
-7
lines changed

2 files changed

+81
-7
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,6 +1532,15 @@
15321532
boot up that is likely to be overridden by user space
15331533
start up functionality.
15341534

1535+
Optionally, the snapshot can also be defined for a tracing
1536+
instance that was created by the trace_instance= command
1537+
line parameter.
1538+
1539+
trace_instance=foo,sched_switch ftrace_boot_snapshot=foo
1540+
1541+
The above will cause the "foo" tracing instance to trigger
1542+
a snapshot at the end of boot up.
1543+
15351544
ftrace_dump_on_oops[=orig_cpu]
15361545
[FTRACE] will dump the trace buffers on oops.
15371546
If no parameter is passed, ftrace will dump

kernel/trace/trace.c

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ static bool snapshot_at_boot;
191191
static char boot_instance_info[COMMAND_LINE_SIZE] __initdata;
192192
static int boot_instance_index;
193193

194+
static char boot_snapshot_info[COMMAND_LINE_SIZE] __initdata;
195+
static int boot_snapshot_index;
196+
194197
static int __init set_cmdline_ftrace(char *str)
195198
{
196199
strlcpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
@@ -227,9 +230,22 @@ __setup("traceoff_on_warning", stop_trace_on_warning);
227230

228231
static int __init boot_alloc_snapshot(char *str)
229232
{
230-
allocate_snapshot = true;
231-
/* We also need the main ring buffer expanded */
232-
ring_buffer_expanded = true;
233+
char *slot = boot_snapshot_info + boot_snapshot_index;
234+
int left = sizeof(boot_snapshot_info) - boot_snapshot_index;
235+
int ret;
236+
237+
if (str[0] == '=') {
238+
str++;
239+
if (strlen(str) >= left)
240+
return -1;
241+
242+
ret = snprintf(slot, left, "%s\t", str);
243+
boot_snapshot_index += ret;
244+
} else {
245+
allocate_snapshot = true;
246+
/* We also need the main ring buffer expanded */
247+
ring_buffer_expanded = true;
248+
}
233249
return 1;
234250
}
235251
__setup("alloc_snapshot", boot_alloc_snapshot);
@@ -9254,10 +9270,6 @@ static int allocate_trace_buffers(struct trace_array *tr, int size)
92549270
}
92559271
tr->allocated_snapshot = allocate_snapshot;
92569272

9257-
/*
9258-
* Only the top level trace array gets its snapshot allocated
9259-
* from the kernel command line.
9260-
*/
92619273
allocate_snapshot = false;
92629274
#endif
92639275

@@ -10173,6 +10185,47 @@ ssize_t trace_parse_run_command(struct file *file, const char __user *buffer,
1017310185
return ret;
1017410186
}
1017510187

10188+
#ifdef CONFIG_TRACER_MAX_TRACE
10189+
__init static bool tr_needs_alloc_snapshot(const char *name)
10190+
{
10191+
char *test;
10192+
int len = strlen(name);
10193+
bool ret;
10194+
10195+
if (!boot_snapshot_index)
10196+
return false;
10197+
10198+
if (strncmp(name, boot_snapshot_info, len) == 0 &&
10199+
boot_snapshot_info[len] == '\t')
10200+
return true;
10201+
10202+
test = kmalloc(strlen(name) + 3, GFP_KERNEL);
10203+
if (!test)
10204+
return false;
10205+
10206+
sprintf(test, "\t%s\t", name);
10207+
ret = strstr(boot_snapshot_info, test) == NULL;
10208+
kfree(test);
10209+
return ret;
10210+
}
10211+
10212+
__init static void do_allocate_snapshot(const char *name)
10213+
{
10214+
if (!tr_needs_alloc_snapshot(name))
10215+
return;
10216+
10217+
/*
10218+
* When allocate_snapshot is set, the next call to
10219+
* allocate_trace_buffers() (called by trace_array_get_by_name())
10220+
* will allocate the snapshot buffer. That will alse clear
10221+
* this flag.
10222+
*/
10223+
allocate_snapshot = true;
10224+
}
10225+
#else
10226+
static inline void do_allocate_snapshot(const char *name) { }
10227+
#endif
10228+
1017610229
__init static void enable_instances(void)
1017710230
{
1017810231
struct trace_array *tr;
@@ -10188,6 +10241,9 @@ __init static void enable_instances(void)
1018810241

1018910242
tok = strsep(&curr_str, ",");
1019010243

10244+
if (IS_ENABLED(CONFIG_TRACER_MAX_TRACE))
10245+
do_allocate_snapshot(tok);
10246+
1019110247
tr = trace_array_get_by_name(tok);
1019210248
if (!tr) {
1019310249
pr_warn("Failed to create instance buffer %s\n", curr_str);
@@ -10335,10 +10391,19 @@ __init static int tracer_alloc_buffers(void)
1033510391

1033610392
void __init ftrace_boot_snapshot(void)
1033710393
{
10394+
struct trace_array *tr;
10395+
1033810396
if (snapshot_at_boot) {
1033910397
tracing_snapshot();
1034010398
internal_trace_puts("** Boot snapshot taken **\n");
1034110399
}
10400+
10401+
list_for_each_entry(tr, &ftrace_trace_arrays, list) {
10402+
if (tr == &global_trace)
10403+
continue;
10404+
trace_array_puts(tr, "** Boot snapshot taken **\n");
10405+
tracing_snapshot_instance(tr);
10406+
}
1034210407
}
1034310408

1034410409
void __init early_trace_init(void)

0 commit comments

Comments
 (0)