tracing: Add show_event_filters to expose active event filters

Currently, to audit active Ftrace event filters, userspace must
recursively traverse the events/ directory and read each individual
filter file. This is inefficient for monitoring tools and debugging.

Introduce "show_event_filters" at the trace root directory. This file
displays all events that currently have a filter applied, alongside the
actual filter string, in a consolidated system:event [tab] filter
format.

The implementation reuses the existing trace_event_file iterators to
ensure atomic traversal of the event list and utilises guard(rcu)() for
automatic, scope-based protection when accessing volatile filter
strings.

Link: https://patch.msgid.link/20260105142939.2655342-2-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:38 -05:00
committed by Steven Rostedt (Google)
parent e5136678b1
commit 729757b96a
2 changed files with 66 additions and 0 deletions

View File

@@ -684,6 +684,14 @@ of ftrace. Here is a list of some of the key files:
See events.rst for more information.
show_event_filters:
A list of events that have filters. This shows the
system/event pair along with the filter 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

@@ -1662,6 +1662,32 @@ static void t_stop(struct seq_file *m, void *p)
mutex_unlock(&event_mutex);
}
/**
* t_show_filters - seq_file callback to display active event filters
* @m: The seq_file interface for formatted output
* @v: The current trace_event_file being iterated
*
* Identifies and prints active filters for the current event file in the
* iteration. If a filter is applied to the current event and, if so,
* prints the system name, event name, and the filter string.
*/
static int t_show_filters(struct seq_file *m, void *v)
{
struct trace_event_file *file = v;
struct trace_event_call *call = file->event_call;
struct event_filter *filter;
guard(rcu)();
filter = rcu_dereference(file->filter);
if (!filter || !filter->filter_string)
return 0;
seq_printf(m, "%s:%s\t%s\n", call->class->system,
trace_event_name(call), filter->filter_string);
return 0;
}
#ifdef CONFIG_MODULES
static int s_show(struct seq_file *m, void *v)
{
@@ -2489,6 +2515,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_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);
@@ -2507,6 +2534,13 @@ static const struct seq_operations show_set_event_seq_ops = {
.stop = s_stop,
};
static const struct seq_operations show_show_event_filters_seq_ops = {
.start = t_start,
.next = t_next,
.show = t_show_filters,
.stop = t_stop,
};
static const struct seq_operations show_set_pid_seq_ops = {
.start = p_start,
.next = p_next,
@@ -2536,6 +2570,13 @@ static const struct file_operations ftrace_set_event_fops = {
.release = ftrace_event_release,
};
static const struct file_operations ftrace_show_event_filters_fops = {
.open = ftrace_event_show_filters_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,
@@ -2680,6 +2721,20 @@ ftrace_event_set_open(struct inode *inode, struct file *file)
return ret;
}
/**
* ftrace_event_show_filters_open - open interface for set_event_filters
* @inode: The inode of the file
* @file: The file being opened
*
* Connects the set_event_filters file to the sequence operations
* required to iterate over and display active event filters.
*/
static int
ftrace_event_show_filters_open(struct inode *inode, struct file *file)
{
return ftrace_event_open(inode, file, &show_show_event_filters_seq_ops);
}
static int
ftrace_event_set_pid_open(struct inode *inode, struct file *file)
{
@@ -4400,6 +4455,9 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
if (!entry)
return -ENOMEM;
trace_create_file("show_event_filters", TRACE_MODE_READ, parent, tr,
&ftrace_show_event_filters_fops);
nr_entries = ARRAY_SIZE(events_entries);
e_events = eventfs_create_events_dir("events", parent, events_entries,