diff options
author | Steven Rostedt <rostedt@goodmis.org> | 2025-03-05 11:45:47 -0500 |
---|---|---|
committer | Steven Rostedt (Google) <rostedt@goodmis.org> | 2025-03-28 08:39:27 -0400 |
commit | 5f3719f697c3fdfae5cd6805f10ac7a04b0f4e43 (patch) | |
tree | 44004eceb1738f5ba8359c8e9095d4228a57baaf | |
parent | 1bd25a6f7173c005844cd0076718b3c87bccd891 (diff) |
tracing: Update modules to persistent instances when loaded
When a module is loaded and a persistent buffer is actively tracing, add
it to the list of modules in the persistent memory.
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Link: https://lore.kernel.org/20250305164609.469844721@goodmis.org
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
-rw-r--r-- | kernel/trace/trace.c | 27 | ||||
-rw-r--r-- | kernel/trace/trace.h | 2 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 40 |
3 files changed, 57 insertions, 12 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index d22f8d34b18d..66c1683fa1dd 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -10087,6 +10087,32 @@ static void trace_module_remove_evals(struct module *mod) static inline void trace_module_remove_evals(struct module *mod) { } #endif /* CONFIG_TRACE_EVAL_MAP_FILE */ +static bool trace_array_active(struct trace_array *tr) +{ + if (tr->current_trace != &nop_trace) + return true; + + /* 0 is no events, 1 is all disabled */ + return trace_events_enabled(tr, NULL) > 1; +} + +static void trace_module_record(struct module *mod) +{ + struct trace_array *tr; + + list_for_each_entry(tr, &ftrace_trace_arrays, list) { + /* Update any persistent trace array that has already been started */ + if ((tr->flags & (TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT)) == + TRACE_ARRAY_FL_BOOT) { + /* Only update if the trace array is active */ + if (trace_array_active(tr)) { + guard(mutex)(&scratch_mutex); + save_mod(mod, tr); + } + } + } +} + static int trace_module_notify(struct notifier_block *self, unsigned long val, void *data) { @@ -10095,6 +10121,7 @@ static int trace_module_notify(struct notifier_block *self, switch (val) { case MODULE_STATE_COMING: trace_module_add_evals(mod); + trace_module_record(mod); break; case MODULE_STATE_GOING: trace_module_remove_evals(mod); diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 3a020fb82a34..90493220c362 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -786,6 +786,8 @@ extern void trace_find_cmdline(int pid, char comm[]); extern int trace_find_tgid(int pid); extern void trace_event_follow_fork(struct trace_array *tr, bool enable); +extern int trace_events_enabled(struct trace_array *tr, const char *system); + #ifdef CONFIG_DYNAMIC_FTRACE extern unsigned long ftrace_update_tot_cnt; extern unsigned long ftrace_number_of_pages; diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 513de9ceb80e..7b3ef1d26167 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1818,28 +1818,28 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, return cnt; } -static ssize_t -system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, - loff_t *ppos) +/* + * Returns: + * 0 : no events exist? + * 1 : all events are disabled + * 2 : all events are enabled + * 3 : some events are enabled and some are enabled + */ +int trace_events_enabled(struct trace_array *tr, const char *system) { - const char set_to_char[4] = { '?', '0', '1', 'X' }; - struct trace_subsystem_dir *dir = filp->private_data; - struct event_subsystem *system = dir->subsystem; struct trace_event_call *call; struct trace_event_file *file; - struct trace_array *tr = dir->tr; - char buf[2]; int set = 0; - int ret; - mutex_lock(&event_mutex); + guard(mutex)(&event_mutex); + list_for_each_entry(file, &tr->events, list) { call = file->event_call; if ((call->flags & TRACE_EVENT_FL_IGNORE_ENABLE) || !trace_event_name(call) || !call->class || !call->class->reg) continue; - if (system && strcmp(call->class->system, system->name) != 0) + if (system && strcmp(call->class->system, system) != 0) continue; /* @@ -1855,7 +1855,23 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, if (set == 3) break; } - mutex_unlock(&event_mutex); + + return set; +} + +static ssize_t +system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, + loff_t *ppos) +{ + const char set_to_char[4] = { '?', '0', '1', 'X' }; + struct trace_subsystem_dir *dir = filp->private_data; + struct event_subsystem *system = dir->subsystem; + struct trace_array *tr = dir->tr; + char buf[2]; + int set; + int ret; + + set = trace_events_enabled(tr, system ? system->name : NULL); buf[0] = set_to_char[set]; buf[1] = '\n'; |