tracing: Add show_event_triggers to expose active event triggers

To audit active event triggers, userspace currently must traverse the
events/ directory and read each individual trigger file. This is
cumbersome for system-wide auditing or debugging.

Introduce "show_event_triggers" at the trace root directory. This file
displays all events that currently have one or more triggers applied,
alongside the trigger configuration, in a consolidated
system:event [tab] trigger format.

The implementation leverages the existing trace_event_file iterators
and uses the trigger's own print() operation to ensure output
consistency with the per-event trigger files.

Link: https://patch.msgid.link/20260105142939.2655342-3-atomlin@atomlin.com
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
Aaron Tomlin 2026-01-05 09:29:39 -05:00 committed by Steven Rostedt (Google)
parent 729757b96a
commit 6a80838814
2 changed files with 72 additions and 0 deletions

View file

@ -692,6 +692,14 @@ of ftrace. Here is a list of some of the key files:
See events.rst for more information.
show_event_triggers:
A list of events that have triggers. This shows the
system/event pair along with the trigger that is attached to
the event.
See events.rst for more information.
available_events:
A list of events that can be enabled in tracing.

View file

@ -1688,6 +1688,38 @@ static int t_show_filters(struct seq_file *m, void *v)
return 0;
}
/**
* t_show_triggers - seq_file callback to display active event triggers
* @m: The seq_file interface for formatted output
* @v: The current trace_event_file being iterated
*
* Iterates through the trigger list of the current event file and prints
* each active trigger's configuration using its associated print
* operation.
*/
static int t_show_triggers(struct seq_file *m, void *v)
{
struct trace_event_file *file = v;
struct trace_event_call *call = file->event_call;
struct event_trigger_data *data;
/*
* The event_mutex is held by t_start(), protecting the
* file->triggers list traversal.
*/
if (list_empty(&file->triggers))
return 0;
list_for_each_entry_rcu(data, &file->triggers, list) {
seq_printf(m, "%s:%s\t", call->class->system,
trace_event_name(call));
data->cmd_ops->print(m, data);
}
return 0;
}
#ifdef CONFIG_MODULES
static int s_show(struct seq_file *m, void *v)
{
@ -2516,6 +2548,7 @@ ftrace_event_npid_write(struct file *filp, const char __user *ubuf,
static int ftrace_event_avail_open(struct inode *inode, struct file *file);
static int ftrace_event_set_open(struct inode *inode, struct file *file);
static int ftrace_event_show_filters_open(struct inode *inode, struct file *file);
static int ftrace_event_show_triggers_open(struct inode *inode, struct file *file);
static int ftrace_event_set_pid_open(struct inode *inode, struct file *file);
static int ftrace_event_set_npid_open(struct inode *inode, struct file *file);
static int ftrace_event_release(struct inode *inode, struct file *file);
@ -2541,6 +2574,13 @@ static const struct seq_operations show_show_event_filters_seq_ops = {
.stop = t_stop,
};
static const struct seq_operations show_show_event_triggers_seq_ops = {
.start = t_start,
.next = t_next,
.show = t_show_triggers,
.stop = t_stop,
};
static const struct seq_operations show_set_pid_seq_ops = {
.start = p_start,
.next = p_next,
@ -2577,6 +2617,13 @@ static const struct file_operations ftrace_show_event_filters_fops = {
.release = seq_release,
};
static const struct file_operations ftrace_show_event_triggers_fops = {
.open = ftrace_event_show_triggers_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static const struct file_operations ftrace_set_event_pid_fops = {
.open = ftrace_event_set_pid_open,
.read = seq_read,
@ -2735,6 +2782,20 @@ ftrace_event_show_filters_open(struct inode *inode, struct file *file)
return ftrace_event_open(inode, file, &show_show_event_filters_seq_ops);
}
/**
* ftrace_event_show_triggers_open - open interface for show_event_triggers
* @inode: The inode of the file
* @file: The file being opened
*
* Connects the show_event_triggers file to the sequence operations
* required to iterate over and display active event triggers.
*/
static int
ftrace_event_show_triggers_open(struct inode *inode, struct file *file)
{
return ftrace_event_open(inode, file, &show_show_event_triggers_seq_ops);
}
static int
ftrace_event_set_pid_open(struct inode *inode, struct file *file)
{
@ -4458,6 +4519,9 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
trace_create_file("show_event_filters", TRACE_MODE_READ, parent, tr,
&ftrace_show_event_filters_fops);
trace_create_file("show_event_triggers", TRACE_MODE_READ, parent, tr,
&ftrace_show_event_triggers_fops);
nr_entries = ARRAY_SIZE(events_entries);
e_events = eventfs_create_events_dir("events", parent, events_entries,