tracing: Add trigger file for trace_markers tracefs/ftrace/print

Allow writing to the trace_markers file initiate triggers defined in
tracefs/ftrace/print/trigger file. This will allow of user space to trigger
the same type of triggers (including histograms) that the trace events use.

Had to create a ftrace_event_register() function that will become the
trace_marker print event's reg() function. This is required because of how
triggers are enabled:

  event_trigger_write() {
    event_trigger_regex_write() {
      trigger_process_regex() {
        for p in trigger_commands {
          p->func(); /* trigger_snapshot_cmd->func */
            event_trigger_callback() {
              cmd_ops->reg() /* register_trigger() */ {
                trace_event_trigger_enable_disable() {
                  trace_event_enable_disable() {
                    call->class->reg();

Without the reg() function, the trigger code will call a NULL pointer and
crash the system.

Cc: Tom Zanussi <tom.zanussi@linux.intel.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Karim Yaghmour <karim.yaghmour@opersys.com>
Cc: Brendan Gregg <bgregg@netflix.com>
Suggested-by: default avatarJoel Fernandes <joelaf@google.com>
Reviewed-by: default avatarNamhyung Kim <namhyung@kernel.org>
Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
parent 5d948c86
...@@ -6074,6 +6074,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, ...@@ -6074,6 +6074,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
{ {
struct trace_array *tr = filp->private_data; struct trace_array *tr = filp->private_data;
struct ring_buffer_event *event; struct ring_buffer_event *event;
enum event_trigger_type tt = ETT_NONE;
struct ring_buffer *buffer; struct ring_buffer *buffer;
struct print_entry *entry; struct print_entry *entry;
unsigned long irq_flags; unsigned long irq_flags;
...@@ -6122,6 +6123,12 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, ...@@ -6122,6 +6123,12 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
written = cnt; written = cnt;
len = cnt; len = cnt;
if (tr->trace_marker_file && !list_empty(&tr->trace_marker_file->triggers)) {
/* do not add \n before testing triggers, but add \0 */
entry->buf[cnt] = '\0';
tt = event_triggers_call(tr->trace_marker_file, entry, event);
}
if (entry->buf[cnt - 1] != '\n') { if (entry->buf[cnt - 1] != '\n') {
entry->buf[cnt] = '\n'; entry->buf[cnt] = '\n';
entry->buf[cnt + 1] = '\0'; entry->buf[cnt + 1] = '\0';
...@@ -6130,6 +6137,9 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, ...@@ -6130,6 +6137,9 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
__buffer_unlock_commit(buffer, event); __buffer_unlock_commit(buffer, event);
if (tt)
event_triggers_post_call(tr->trace_marker_file, tt);
if (written > 0) if (written > 0)
*fpos += written; *fpos += written;
...@@ -7896,6 +7906,7 @@ static __init void create_trace_instances(struct dentry *d_tracer) ...@@ -7896,6 +7906,7 @@ static __init void create_trace_instances(struct dentry *d_tracer)
static void static void
init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
{ {
struct trace_event_file *file;
int cpu; int cpu;
trace_create_file("available_tracers", 0444, d_tracer, trace_create_file("available_tracers", 0444, d_tracer,
...@@ -7928,6 +7939,12 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) ...@@ -7928,6 +7939,12 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
trace_create_file("trace_marker", 0220, d_tracer, trace_create_file("trace_marker", 0220, d_tracer,
tr, &tracing_mark_fops); tr, &tracing_mark_fops);
file = __find_event_file(tr, "ftrace", "print");
if (file && file->dir)
trace_create_file("trigger", 0644, file->dir, file,
&event_trigger_fops);
tr->trace_marker_file = file;
trace_create_file("trace_marker_raw", 0220, d_tracer, trace_create_file("trace_marker_raw", 0220, d_tracer,
tr, &tracing_mark_raw_fops); tr, &tracing_mark_raw_fops);
......
...@@ -259,6 +259,7 @@ struct trace_array { ...@@ -259,6 +259,7 @@ struct trace_array {
struct trace_options *topts; struct trace_options *topts;
struct list_head systems; struct list_head systems;
struct list_head events; struct list_head events;
struct trace_event_file *trace_marker_file;
cpumask_var_t tracing_cpumask; /* only trace on set CPUs */ cpumask_var_t tracing_cpumask; /* only trace on set CPUs */
int ref; int ref;
#ifdef CONFIG_FUNCTION_TRACER #ifdef CONFIG_FUNCTION_TRACER
......
...@@ -230,7 +230,7 @@ FTRACE_ENTRY(bprint, bprint_entry, ...@@ -230,7 +230,7 @@ FTRACE_ENTRY(bprint, bprint_entry,
FILTER_OTHER FILTER_OTHER
); );
FTRACE_ENTRY(print, print_entry, FTRACE_ENTRY_REG(print, print_entry,
TRACE_PRINT, TRACE_PRINT,
...@@ -242,7 +242,9 @@ FTRACE_ENTRY(print, print_entry, ...@@ -242,7 +242,9 @@ FTRACE_ENTRY(print, print_entry,
F_printk("%ps: %s", F_printk("%ps: %s",
(void *)__entry->ip, __entry->buf), (void *)__entry->ip, __entry->buf),
FILTER_OTHER FILTER_OTHER,
ftrace_event_register
); );
FTRACE_ENTRY(raw_data, raw_data_entry, FTRACE_ENTRY(raw_data, raw_data_entry,
......
...@@ -14,6 +14,13 @@ ...@@ -14,6 +14,13 @@
#include "trace_output.h" #include "trace_output.h"
/* Stub function for events with triggers */
static int ftrace_event_register(struct trace_event_call *call,
enum trace_reg type, void *data)
{
return 0;
}
#undef TRACE_SYSTEM #undef TRACE_SYSTEM
#define TRACE_SYSTEM ftrace #define TRACE_SYSTEM ftrace
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment