On Thu, 29 Jan 2026 15:13:52 -0500 Steven Rostedt <[email protected]> wrote:
> On Wed, 28 Jan 2026 09:10:04 +0900 > "Masami Hiramatsu (Google)" <[email protected]> wrote: > > > From: Masami Hiramatsu (Google) <[email protected]> > > > > 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) <[email protected]> > > --- > > 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." OK. > > > + */ > > + __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. Ah, right. OK, let me fix it. > > > + 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? Ah, indeed. OK, I'll fix it. Thank you! > > -- Steve > -- Masami Hiramatsu (Google) <[email protected]>
