Following the same format as trace_instance, add a cmdline to configure a trace remote on registration:
trace_remote=<remote>^<opt1>^<opt2>,<evt1>,<evt2> Enabling events automatically turns on tracing. Signed-off-by: Vincent Donnefort <[email protected]> diff --git a/kernel/trace/trace_remote.c b/kernel/trace/trace_remote.c index 3164f327d4d8..0b44636b6eea 100644 --- a/kernel/trace/trace_remote.c +++ b/kernel/trace/trace_remote.c @@ -13,6 +13,8 @@ #include <linux/trace_seq.h> #include <linux/types.h> +#include <asm/setup.h> + #include "trace.h" #define TRACEFS_DIR "remotes" @@ -1057,6 +1059,124 @@ static int dump_on_oops_show(struct seq_file *s, void *unused) } DEFINE_SHOW_STORE_ATTRIBUTE(dump_on_oops); +static char trace_remote_cmdline[COMMAND_LINE_SIZE]; + +static int __init set_trace_remote_cmdline(char *str) +{ + static int idx; + + if (!str) + return 0; + + strscpy(trace_remote_cmdline + idx, str, COMMAND_LINE_SIZE - idx); + idx += strlen(str); + trace_remote_cmdline[idx++] = '\t'; + return 1; +} +__setup("trace_remote=", set_trace_remote_cmdline); + +static void trace_remote_apply_cmdline_opts(struct trace_remote *remote, char *cmdline) +{ + bool printk_on = false; + char *opt; + int ret; + + while ((opt = strsep(&cmdline, "^"))) { + if (!*opt) + continue; + + if (!strcmp(opt, "dump_on_oops")) { + remote->panic_on = true; + } else if (!strcmp(opt, "printk")) { + printk_on = true; + } else if (!strncmp(opt, "buf_size=", 9)) { + /* buf_size can only be applied if the buffer is unloaded */ + if (!WARN_ON(trace_remote_loaded(remote))) + remote->trace_buffer_size = memparse(opt + 9, NULL); + } else { + pr_warn("Unknown trace remote option '%s'\n", opt); + } + } + + if (printk_on) { + ret = trace_remote_enable_printk(remote, true); + if (ret) + pr_warn("Failed to enable trace remote printk (%d)\n", ret); + } +} + +static struct remote_event * +trace_remote_find_event_by_name(struct trace_remote *remote, const char *name); + +static int +trace_remote_enable_event(struct trace_remote *remote, struct remote_event *evt, bool enable); + +static void trace_remote_apply_cmdline_events(struct trace_remote *remote, char *cmdline) +{ + bool tracing_on = false; + char *token; + int ret; + + while ((token = strsep(&cmdline, ","))) { + struct remote_event *evt; + + if (!*token) + continue; + + evt = trace_remote_find_event_by_name(remote, token); + if (!evt) { + pr_warn("trace remote event '%s' not found\n", token); + continue; + } + + ret = trace_remote_enable_event(remote, evt, true); + if (ret) + pr_warn("Failed to enable trace remote event '%s' (%d)\n", token, ret); + else + tracing_on = true; + } + + if (tracing_on) { + ret = trace_remote_enable_tracing(remote); + if (ret) + pr_warn("Failed to enable trace remote tracing (%d)\n", ret); + } +} + +static void trace_remote_apply_cmdline(const char *name, struct trace_remote *remote) +{ + char *cmdline __free(kfree) = NULL; + char *events_cmdline = NULL; + char *opts_cmdline = NULL; + char *curr, *next; + + if (!trace_remote_cmdline[0]) + return; + + cmdline = kstrdup(trace_remote_cmdline, GFP_KERNEL); + if (!cmdline) + return; + + next = cmdline; + while ((curr = strsep(&next, "\t"))) { + char *token = strsep(&curr, ","); + char *rname = strsep(&token, "^"); + + if (strcmp(rname, name) == 0) { + opts_cmdline = token; + events_cmdline = curr; + break; + } + } + + guard(mutex)(&remote->lock); + + if (opts_cmdline) + trace_remote_apply_cmdline_opts(remote, opts_cmdline); + if (events_cmdline) + trace_remote_apply_cmdline_events(remote, events_cmdline); +} + static struct dentry *tracefs_root; static DEFINE_MUTEX(tracefs_lock); static u64 tracefs_root_count; @@ -1228,6 +1348,7 @@ int trace_remote_register(const char *name, struct trace_remote_callbacks *cbs, goto err_unregister_events; } + trace_remote_apply_cmdline(name, remote); no_free_ptr(remote); return 0; @@ -1708,3 +1829,15 @@ static struct remote_event *trace_remote_find_event(struct trace_remote *remote, return bsearch((const void *)(unsigned long)id, remote->events, remote->nr_events, sizeof(*remote->events), __cmp_events); } + +static struct remote_event * +trace_remote_find_event_by_name(struct trace_remote *remote, const char *name) +{ + int i; + + for (i = 0; i < remote->nr_events; i++) { + if (!strcmp(remote->events[i].name, name)) + return &remote->events[i]; + } + return NULL; +} -- 2.54.0.1032.g2f8565e1d1-goog
