[PATCH 1/2] tracing: Use a single array to represent tracer options files

From: Steven Rostedt

Date: Wed Sep 02 2026 - 17:34:02 EST


From: Steven Rostedt <rostedt@xxxxxxxxxxx>

An instance is represented by a trace_array descriptor that has an array
for options of each tracer. That array is a pointer to another array that
represents every option for a specific tracer. Instead of having two
arrays use just a single array for every tracer option within a
trace_array.

This not only simplifies the logic for representing the tracer option in
the callbacks, but also can be used to simplify a way to find the
trace_array descriptor from this one single array when needing to find
which trace_array the option is attached to in order to take its
reference.

Signed-off-by: Steven Rostedt <rostedt@xxxxxxxxxxx>
---
kernel/trace/trace.c | 47 ++++++++++++++++++--------------------------
kernel/trace/trace.h | 21 ++++++++------------
2 files changed, 27 insertions(+), 41 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 722d0ba2d233..f26244253a8b 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -7689,7 +7689,7 @@ static ssize_t
trace_options_read(struct file *filp, char __user *ubuf, size_t cnt,
loff_t *ppos)
{
- struct trace_option_dentry *topt = filp->private_data;
+ struct trace_options *topt = filp->private_data;
char *buf;

if (topt->flags->val & topt->opt->bit)
@@ -7704,7 +7704,7 @@ static ssize_t
trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt,
loff_t *ppos)
{
- struct trace_option_dentry *topt = filp->private_data;
+ struct trace_options *topt = filp->private_data;
unsigned long val;
int ret;

@@ -7730,7 +7730,7 @@ trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt,

static int tracing_open_options(struct inode *inode, struct file *filp)
{
- struct trace_option_dentry *topt = inode->i_private;
+ struct trace_options *topt = inode->i_private;
int ret;

ret = tracing_check_open_get_tr(topt->tr);
@@ -7743,7 +7743,7 @@ static int tracing_open_options(struct inode *inode, struct file *filp)

static int tracing_release_options(struct inode *inode, struct file *file)
{
- struct trace_option_dentry *topt = file->private_data;
+ struct trace_options *topt = file->private_data;

trace_array_put(topt->tr);
return 0;
@@ -7946,8 +7946,9 @@ static struct dentry *trace_options_init_dentry(struct trace_array *tr)

static void
create_trace_option_file(struct trace_array *tr,
- struct trace_option_dentry *topt,
+ struct trace_options *topt,
struct tracer_flags *flags,
+ struct tracer *tracer,
struct tracer_opt *opt)
{
struct dentry *t_options;
@@ -7959,6 +7960,7 @@ create_trace_option_file(struct trace_array *tr,
topt->flags = flags;
topt->opt = opt;
topt->tr = tr;
+ topt->tracer = tracer;

topt->entry = trace_create_file(opt->name, TRACE_MODE_WRITE,
t_options, topt, &trace_options_fops);
@@ -7968,10 +7970,9 @@ static int
create_trace_option_files(struct trace_array *tr, struct tracer *tracer,
struct tracer_flags *flags)
{
- struct trace_option_dentry *topts;
- struct trace_options *tr_topts;
+ struct trace_options *topts;
struct tracer_opt *opts;
- int cnt;
+ int i, cnt;

if (!flags || !flags->opts)
return 0;
@@ -7981,29 +7982,22 @@ create_trace_option_files(struct trace_array *tr, struct tracer *tracer,
for (cnt = 0; opts[cnt].name; cnt++)
;

- topts = kzalloc_objs(*topts, cnt + 1);
- if (!topts)
- return 0;
-
- tr_topts = krealloc_array(tr->topts, tr->nr_topts + 1, sizeof(*tr->topts),
+ topts = krealloc_array(tr->topts, tr->nr_topts + cnt, sizeof(*tr->topts),
GFP_KERNEL);
- if (!tr_topts) {
- kfree(topts);
+ if (!topts)
return -ENOMEM;
- }

- tr->topts = tr_topts;
- tr->topts[tr->nr_topts].tracer = tracer;
- tr->topts[tr->nr_topts].topts = topts;
- tr->nr_topts++;
+ tr->topts = topts;

- for (cnt = 0; opts[cnt].name; cnt++) {
- create_trace_option_file(tr, &topts[cnt], flags,
- &opts[cnt]);
- MEM_FAIL(topts[cnt].entry == NULL,
+ for (topts += tr->nr_topts, i = 0; i < cnt; topts++, i++) {
+ create_trace_option_file(tr, topts, flags, tracer,
+ &opts[i]);
+ MEM_FAIL(topts->entry == NULL,
"Failed to create trace option: %s",
- opts[cnt].name);
+ opts[i].name);
}
+
+ tr->nr_topts += cnt;
return 0;
}

@@ -8865,9 +8859,6 @@ static int __remove_instance(struct trace_array *tr)
if (tr->flags & TRACE_ARRAY_FL_VMALLOC)
vfree((void *)tr->range_addr_start);

- for (i = 0; i < tr->nr_topts; i++) {
- kfree(tr->topts[i].topts);
- }
kfree(tr->topts);

free_cpumask_var(tr->pipe_cpumask);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 3c111ca88e32..a07802be5673 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -224,11 +224,6 @@ struct array_buffer {

#define TRACE_FLAGS_MAX_SIZE 64

-struct trace_options {
- struct tracer *tracer;
- struct trace_option_dentry *topts;
-};
-
struct trace_pid_list *trace_pid_list_alloc(void);
void trace_pid_list_free(struct trace_pid_list *pid_list);
bool trace_pid_list_is_set(struct trace_pid_list *pid_list, unsigned int pid);
@@ -325,6 +320,14 @@ struct trace_module_delta {
long delta[];
};

+struct trace_options {
+ struct tracer_opt *opt;
+ struct tracer_flags *flags;
+ struct trace_array *tr;
+ struct tracer *tracer;
+ struct dentry *entry;
+};
+
/*
* The trace array - an array of per-CPU trace arrays. This is the
* highest level data structure that individual tracers deal with.
@@ -605,14 +608,6 @@ struct tracer_flags {
/* Makes more easy to define a tracer opt */
#define TRACER_OPT(s, b) .name = #s, .bit = b

-
-struct trace_option_dentry {
- struct tracer_opt *opt;
- struct tracer_flags *flags;
- struct trace_array *tr;
- struct dentry *entry;
-};
-
/**
* struct tracer - a specific tracer and its callbacks to interact with tracefs
* @name: the name chosen to select it on the available_tracers file
--
2.53.0