Re: [PATCH v5 3/4] tracing: Remove the backup instance automatically after read
From: Steven Rostedt <rostedt@goodmis.org>
Date: 2026-01-29 20:13:42
Also in:
lkml
On Wed, 28 Jan 2026 09:10:04 +0900 "Masami Hiramatsu (Google)" [off-list ref] wrote:
quoted hunk ↗ jump to hunk
From: Masami Hiramatsu (Google) <mhiramat@kernel.org> Since the backup instance is readonly, after reading all data via pipe, no data is left on the instance. Thus it can be removed safely after closing all files. This also removes it if user resets the ring buffer manually via 'trace' file. Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> --- Changes in v4: - Update description. --- kernel/trace/trace.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++- kernel/trace/trace.h | 6 +++++ 2 files changed, 69 insertions(+), 1 deletion(-)diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index d39f6509c12a..7d615a74f915 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c@@ -590,6 +590,55 @@ void trace_set_ring_buffer_expanded(struct trace_array *tr) tr->ring_buffer_expanded = true; } +static int __remove_instance(struct trace_array *tr); + +static void trace_array_autoremove(struct work_struct *work) +{ + struct trace_array *tr = container_of(work, struct trace_array, autoremove_work); + + guard(mutex)(&event_mutex); + guard(mutex)(&trace_types_lock); + + /* + * This can be fail if someone gets @tr before starting this + * function, but in that case, this will be kicked again when + * putting it. So we don't care the result.
"So we don't care about the result."
+ */
+ __remove_instance(tr);
+}
+
+static struct workqueue_struct *autoremove_wq;
+
+static void trace_array_init_autoremove(struct trace_array *tr)
+{
+ INIT_WORK(&tr->autoremove_work, trace_array_autoremove);
+}
+
+static void trace_array_kick_autoremove(struct trace_array *tr)
+{
+ if (!work_pending(&tr->autoremove_work) && autoremove_wq)
+ queue_work(autoremove_wq, &tr->autoremove_work);
+}
+
+static void trace_array_cancel_autoremove(struct trace_array *tr)
+{
+ if (work_pending(&tr->autoremove_work))
+ cancel_work(&tr->autoremove_work);
+}
+
+__init static int trace_array_init_autoremove_wq(void)
+{This isn't needed if there's no backup trace_array right? Instead of creating a work queue when its not needed, just exit out if there's no backup trace_array. Oh, and the above functions should always test autoremove_wq for NULL.
quoted hunk ↗ jump to hunk
+ autoremove_wq = alloc_workqueue("tr_autoremove_wq", + WQ_UNBOUND | WQ_HIGHPRI, 0); + if (!autoremove_wq) { + pr_err("Unable to allocate tr_autoremove_wq\n"); + return -ENOMEM; + } + return 0; +} + +late_initcall_sync(trace_array_init_autoremove_wq); + LIST_HEAD(ftrace_trace_arrays); int trace_array_get(struct trace_array *this_tr)@@ -598,7 +647,7 @@ int trace_array_get(struct trace_array *this_tr) guard(mutex)(&trace_types_lock); list_for_each_entry(tr, &ftrace_trace_arrays, list) { - if (tr == this_tr) { + if (tr == this_tr && !tr->free_on_close) { tr->ref++; return 0; }
Break the above into:
if (tr == this_tr) {
if (tr->free_on_close)
break;
tr->ref++;
return 0;
}
Why continue the loop if we found the trace_array but it's in the process
of closing?
-- Steve