Commit b355247d authored by Steven Rostedt's avatar Steven Rostedt Committed by Steven Rostedt (Google)
Browse files

tracing: Cache ":mod:" events for modules not loaded yet

When the :mod: command is written into /sys/kernel/tracing/set_event (or
that file within an instance), if the module specified after the ":mod:"
is not yet loaded, it will store that string internally. When the module
is loaded, it will enable the events as if the module was loaded when the
string was written into the set_event file.

This can also be useful to enable events that are in the init section of
the module, as the events are enabled before the init section is executed.

This also works on the kernel command line:

 trace_event=:mod:<module>

Will enable the events for <module> when it is loaded.

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/20250116143533.514730995@goodmis.org


Signed-off-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
parent 4c86bc53
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -6858,6 +6858,14 @@
			comma-separated list of trace events to enable. See
			also Documentation/trace/events.rst

			To enable modules, use :mod: keyword:

			trace_event=:mod:<module>

			The value before :mod: will only enable specific events
			that are part of the module. See the above mentioned
			document for more information.

	trace_instance=[instance-info]
			[FTRACE] Create a ring buffer instance early in boot up.
			This will be listed in:
+3 −1
Original line number Diff line number Diff line
@@ -60,7 +60,9 @@ a specific module::

	# echo ':mod:<module>' > /sys/kernel/tracing/set_event

Will enable all events in the module ``<module>``.
Will enable all events in the module ``<module>``.  If the module is not yet
loaded, the string will be saved and when a module is that matches ``<module>``
is loaded, then it will apply the enabling of events then.

The text before ``:mod:`` will be parsed to specify specific events that the
module creates::
+0 −17
Original line number Diff line number Diff line
@@ -4930,23 +4930,6 @@ static int ftrace_hash_move_and_update_ops(struct ftrace_ops *ops,
	return __ftrace_hash_move_and_update_ops(ops, orig_hash, hash, enable);
}

static bool module_exists(const char *module)
{
	/* All modules have the symbol __this_module */
	static const char this_mod[] = "__this_module";
	char modname[MAX_PARAM_PREFIX_LEN + sizeof(this_mod) + 2];
	unsigned long val;
	int n;

	n = snprintf(modname, sizeof(modname), "%s:%s", module, this_mod);

	if (n > sizeof(modname) - 1)
		return false;

	val = module_kallsyms_lookup_name(modname);
	return val != 0;
}

static int cache_mod(struct trace_array *tr,
		     const char *func, char *module, int enable)
{
+26 −0
Original line number Diff line number Diff line
@@ -9407,6 +9407,10 @@ trace_array_create_systems(const char *name, const char *systems,
	INIT_LIST_HEAD(&tr->hist_vars);
	INIT_LIST_HEAD(&tr->err_log);

#ifdef CONFIG_MODULES
	INIT_LIST_HEAD(&tr->mod_events);
#endif

	if (allocate_trace_buffers(tr, trace_buf_size) < 0)
		goto out_free_tr;

@@ -9823,6 +9827,24 @@ late_initcall_sync(trace_eval_sync);


#ifdef CONFIG_MODULES

bool module_exists(const char *module)
{
	/* All modules have the symbol __this_module */
	static const char this_mod[] = "__this_module";
	char modname[MAX_PARAM_PREFIX_LEN + sizeof(this_mod) + 2];
	unsigned long val;
	int n;

	n = snprintf(modname, sizeof(modname), "%s:%s", module, this_mod);

	if (n > sizeof(modname) - 1)
		return false;

	val = module_kallsyms_lookup_name(modname);
	return val != 0;
}

static void trace_module_add_evals(struct module *mod)
{
	if (!mod->num_trace_evals)
@@ -10535,6 +10557,10 @@ __init static int tracer_alloc_buffers(void)
#endif
	ftrace_init_global_array_ops(&global_trace);

#ifdef CONFIG_MODULES
	INIT_LIST_HEAD(&global_trace.mod_events);
#endif

	init_trace_flags_index(&global_trace);

	register_tracer(&nop_trace);
+12 −0
Original line number Diff line number Diff line
@@ -400,6 +400,9 @@ struct trace_array {
	cpumask_var_t		pipe_cpumask;
	int			ref;
	int			trace_ref;
#ifdef CONFIG_MODULES
	struct list_head	mod_events;
#endif
#ifdef CONFIG_FUNCTION_TRACER
	struct ftrace_ops	*ops;
	struct trace_pid_list	__rcu *function_pids;
@@ -434,6 +437,15 @@ enum {
	TRACE_ARRAY_FL_BOOT	= BIT(1),
};

#ifdef CONFIG_MODULES
bool module_exists(const char *module);
#else
static inline bool module_exists(const char *module)
{
	return false;
}
#endif

extern struct list_head ftrace_trace_arrays;

extern struct mutex trace_types_lock;
Loading