Commit 6a808388 authored by Aaron Tomlin's avatar Aaron Tomlin Committed by Steven Rostedt (Google)
Browse files

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: default avatarAaron Tomlin <atomlin@atomlin.com>
Signed-off-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
parent 729757b9
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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.
+64 −0
Original line number Diff line number Diff line
@@ -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,