tracing: Add trace_trigger kernel command line option
Allow triggers to be enabled at kernel boot up. For example: trace_trigger="sched_switch.stacktrace if prev_state == 2" The above will enable the stacktrace trigger on top of the sched_switch event and only trigger if its prev_state is 2 (TASK_UNINTERRUPTIBLE). Then at boot up, a stacktrace will trigger and be recorded in the tracing ring buffer every time the sched_switch happens where the previous state is TASK_INTERRUPTIBLE. Another useful trigger would be "traceoff" which can stop tracing on an event if a field of the event matches a certain value defined by the filter ("if" statement). Link: https://lore.kernel.org/linux-trace-kernel/20221020210056.0d8d0a5b@gandalf.local.home Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
parent
8230f27b1c
commit
a01fdc897f
2 changed files with 89 additions and 2 deletions
|
@ -6257,6 +6257,25 @@
|
||||||
See also Documentation/trace/ftrace.rst "trace options"
|
See also Documentation/trace/ftrace.rst "trace options"
|
||||||
section.
|
section.
|
||||||
|
|
||||||
|
trace_trigger=[trigger-list]
|
||||||
|
[FTRACE] Add a event trigger on specific events.
|
||||||
|
Set a trigger on top of a specific event, with an optional
|
||||||
|
filter.
|
||||||
|
|
||||||
|
The format is is "trace_trigger=<event>.<trigger>[ if <filter>],..."
|
||||||
|
Where more than one trigger may be specified that are comma deliminated.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
trace_trigger="sched_switch.stacktrace if prev_state == 2"
|
||||||
|
|
||||||
|
The above will enable the "stacktrace" trigger on the "sched_switch"
|
||||||
|
event but only trigger it if the "prev_state" of the "sched_switch"
|
||||||
|
event is "2" (TASK_UNINTERUPTIBLE).
|
||||||
|
|
||||||
|
See also "Event triggers" in Documentation/trace/events.rst
|
||||||
|
|
||||||
|
|
||||||
traceoff_on_warning
|
traceoff_on_warning
|
||||||
[FTRACE] enable this option to disable tracing when a
|
[FTRACE] enable this option to disable tracing when a
|
||||||
warning is hit. This turns off "tracing_on". Tracing can
|
warning is hit. This turns off "tracing_on". Tracing can
|
||||||
|
|
|
@ -2796,6 +2796,44 @@ trace_create_new_event(struct trace_event_call *call,
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_HIST_TRIGGERS
|
||||||
|
#define MAX_BOOT_TRIGGERS 32
|
||||||
|
|
||||||
|
static struct boot_triggers {
|
||||||
|
const char *event;
|
||||||
|
char *trigger;
|
||||||
|
} bootup_triggers[MAX_BOOT_TRIGGERS];
|
||||||
|
|
||||||
|
static char bootup_trigger_buf[COMMAND_LINE_SIZE];
|
||||||
|
static int nr_boot_triggers;
|
||||||
|
|
||||||
|
static __init int setup_trace_triggers(char *str)
|
||||||
|
{
|
||||||
|
char *trigger;
|
||||||
|
char *buf;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
strlcpy(bootup_trigger_buf, str, COMMAND_LINE_SIZE);
|
||||||
|
ring_buffer_expanded = true;
|
||||||
|
disable_tracing_selftest("running event triggers");
|
||||||
|
|
||||||
|
buf = bootup_trigger_buf;
|
||||||
|
for (i = 0; i < MAX_BOOT_TRIGGERS; i++) {
|
||||||
|
trigger = strsep(&buf, ",");
|
||||||
|
if (!trigger)
|
||||||
|
break;
|
||||||
|
bootup_triggers[i].event = strsep(&trigger, ".");
|
||||||
|
bootup_triggers[i].trigger = strsep(&trigger, ".");
|
||||||
|
if (!bootup_triggers[i].trigger)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nr_boot_triggers = i;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
__setup("trace_trigger=", setup_trace_triggers);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Add an event to a trace directory */
|
/* Add an event to a trace directory */
|
||||||
static int
|
static int
|
||||||
__trace_add_new_event(struct trace_event_call *call, struct trace_array *tr)
|
__trace_add_new_event(struct trace_event_call *call, struct trace_array *tr)
|
||||||
|
@ -2812,6 +2850,28 @@ __trace_add_new_event(struct trace_event_call *call, struct trace_array *tr)
|
||||||
return event_define_fields(call);
|
return event_define_fields(call);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_HIST_TRIGGERS
|
||||||
|
static void trace_early_triggers(struct trace_event_file *file, const char *name)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < nr_boot_triggers; i++) {
|
||||||
|
if (strcmp(name, bootup_triggers[i].event))
|
||||||
|
continue;
|
||||||
|
mutex_lock(&event_mutex);
|
||||||
|
ret = trigger_process_regex(file, bootup_triggers[i].trigger);
|
||||||
|
mutex_unlock(&event_mutex);
|
||||||
|
if (ret)
|
||||||
|
pr_err("Failed to register trigger '%s' on event %s\n",
|
||||||
|
bootup_triggers[i].trigger,
|
||||||
|
bootup_triggers[i].event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline void trace_early_triggers(struct trace_event_file *file, const char *name) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Just create a descriptor for early init. A descriptor is required
|
* Just create a descriptor for early init. A descriptor is required
|
||||||
* for enabling events at boot. We want to enable events before
|
* for enabling events at boot. We want to enable events before
|
||||||
|
@ -2822,12 +2882,19 @@ __trace_early_add_new_event(struct trace_event_call *call,
|
||||||
struct trace_array *tr)
|
struct trace_array *tr)
|
||||||
{
|
{
|
||||||
struct trace_event_file *file;
|
struct trace_event_file *file;
|
||||||
|
int ret;
|
||||||
|
|
||||||
file = trace_create_new_event(call, tr);
|
file = trace_create_new_event(call, tr);
|
||||||
if (!file)
|
if (!file)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return event_define_fields(call);
|
ret = event_define_fields(call);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
trace_early_triggers(file, trace_event_name(call));
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ftrace_module_file_ops;
|
struct ftrace_module_file_ops;
|
||||||
|
@ -3735,6 +3802,8 @@ static __init int event_trace_enable(void)
|
||||||
list_add(&call->list, &ftrace_events);
|
list_add(&call->list, &ftrace_events);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
register_trigger_cmds();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need the top trace array to have a working set of trace
|
* We need the top trace array to have a working set of trace
|
||||||
* points at early init, before the debug files and directories
|
* points at early init, before the debug files and directories
|
||||||
|
@ -3749,7 +3818,6 @@ static __init int event_trace_enable(void)
|
||||||
|
|
||||||
register_event_cmds();
|
register_event_cmds();
|
||||||
|
|
||||||
register_trigger_cmds();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue