public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] kernel/trace/ftrace: introduce ftrace module notifier
@ 2026-02-25  5:46 chensong_2000
  2026-02-26  0:27 ` Steven Rostedt
  0 siblings, 1 reply; 7+ messages in thread
From: chensong_2000 @ 2026-02-25  5:46 UTC (permalink / raw)
  To: mcgrof, petr.pavlu, da.gomez, samitolvanen, atomlin, rostedt,
	mhiramat, mark.rutland, mathieu.desnoyers
  Cc: linux-modules, linux-kernel, linux-trace-kernel, Song Chen

From: Song Chen <chensong_2000@189.cn>

Like kprobe, fprobe and btf, this patch attempts to introduce
a notifier_block for ftrace to decouple its initialization from
load_module.

Below is the table of ftrace fucntions calls in different
module state:

	MODULE_STATE_UNFORMED	ftrace_module_init
	MODULE_STATE_COMING	ftrace_module_enable
	MODULE_STATE_LIVE	ftrace_free_mem
	MODULE_STATE_GOING	ftrace_release_mod

Unlike others, ftrace module notifier must take care of state
MODULE_STATE_UNFORMED to ensure calling ftrace_module_init
before complete_formation which changes module's text property.

That pretty much remains same logic with its original design,
the only thing that changes is blocking_notifier_call_chain
(MODULE_STATE_GOING) has to be moved from coming_cleanup to
ddebug_cleanup in function load_module to ensure
ftrace_release_mod is invoked in case complete_formation fails.

Signed-off-by: Song Chen <chensong_2000@189.cn>
---
 kernel/module/main.c  | 14 ++++----------
 kernel/trace/ftrace.c | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/kernel/module/main.c b/kernel/module/main.c
index 710ee30b3bea..5dc0a980e9bd 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -45,7 +45,6 @@
 #include <linux/license.h>
 #include <asm/sections.h>
 #include <linux/tracepoint.h>
-#include <linux/ftrace.h>
 #include <linux/livepatch.h>
 #include <linux/async.h>
 #include <linux/percpu.h>
@@ -836,7 +835,6 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
 	blocking_notifier_call_chain(&module_notify_list,
 				     MODULE_STATE_GOING, mod);
 	klp_module_going(mod);
-	ftrace_release_mod(mod);
 
 	async_synchronize_full();
 
@@ -3067,8 +3065,6 @@ static noinline int do_init_module(struct module *mod)
 	if (!mod->async_probe_requested)
 		async_synchronize_full();
 
-	ftrace_free_mem(mod, mod->mem[MOD_INIT_TEXT].base,
-			mod->mem[MOD_INIT_TEXT].base + mod->mem[MOD_INIT_TEXT].size);
 	mutex_lock(&module_mutex);
 	/* Drop initial reference. */
 	module_put(mod);
@@ -3131,7 +3127,6 @@ static noinline int do_init_module(struct module *mod)
 	blocking_notifier_call_chain(&module_notify_list,
 				     MODULE_STATE_GOING, mod);
 	klp_module_going(mod);
-	ftrace_release_mod(mod);
 	free_module(mod);
 	wake_up_all(&module_wq);
 
@@ -3278,7 +3273,6 @@ static int prepare_coming_module(struct module *mod)
 {
 	int err;
 
-	ftrace_module_enable(mod);
 	err = klp_module_coming(mod);
 	if (err)
 		return err;
@@ -3461,7 +3455,8 @@ static int load_module(struct load_info *info, const char __user *uargs,
 	init_build_id(mod, info);
 
 	/* Ftrace init must be called in the MODULE_STATE_UNFORMED state */
-	ftrace_module_init(mod);
+	blocking_notifier_call_chain(&module_notify_list,
+				MODULE_STATE_UNFORMED, mod);
 
 	/* Finally it's fully formed, ready to start executing. */
 	err = complete_formation(mod, info);
@@ -3513,8 +3508,6 @@ static int load_module(struct load_info *info, const char __user *uargs,
  coming_cleanup:
 	mod->state = MODULE_STATE_GOING;
 	destroy_params(mod->kp, mod->num_kp);
-	blocking_notifier_call_chain(&module_notify_list,
-				     MODULE_STATE_GOING, mod);
 	klp_module_going(mod);
  bug_cleanup:
 	mod->state = MODULE_STATE_GOING;
@@ -3524,7 +3517,8 @@ static int load_module(struct load_info *info, const char __user *uargs,
 	mutex_unlock(&module_mutex);
 
  ddebug_cleanup:
-	ftrace_release_mod(mod);
+	blocking_notifier_call_chain(&module_notify_list,
+				     MODULE_STATE_GOING, mod);
 	synchronize_rcu();
 	kfree(mod->args);
  free_arch_cleanup:
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 3ec2033c0774..47c74d4a2425 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -5223,6 +5223,43 @@ static int __init ftrace_mod_cmd_init(void)
 }
 core_initcall(ftrace_mod_cmd_init);
 
+static int ftrace_module_callback(struct notifier_block *nb, unsigned long op,
+			void *module)
+{
+	struct module *mod = module;
+
+	switch (op) {
+	case MODULE_STATE_UNFORMED:
+		ftrace_module_init(mod);
+		break;
+	case MODULE_STATE_COMING:
+		ftrace_module_enable(mod);
+		break;
+	case MODULE_STATE_LIVE:
+		ftrace_free_mem(mod, mod->mem[MOD_INIT_TEXT].base,
+				mod->mem[MOD_INIT_TEXT].base + mod->mem[MOD_INIT_TEXT].size);
+		break;
+	case MODULE_STATE_GOING:
+		ftrace_release_mod(mod);
+		break;
+	default:
+		break;
+	}
+
+	return notifier_from_errno(0);
+}
+
+static struct notifier_block ftrace_module_nb = {
+	.notifier_call = ftrace_module_callback,
+	.priority = 0
+};
+
+static int __init ftrace_register_module_notifier(void)
+{
+	return register_module_notifier(&ftrace_module_nb);
+}
+core_initcall(ftrace_register_module_notifier);
+
 static void function_trace_probe_call(unsigned long ip, unsigned long parent_ip,
 				      struct ftrace_ops *op, struct ftrace_regs *fregs)
 {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-03-06  9:57 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-25  5:46 [PATCH] kernel/trace/ftrace: introduce ftrace module notifier chensong_2000
2026-02-26  0:27 ` Steven Rostedt
2026-02-26 10:12   ` Song Chen
2026-02-26 10:51     ` Miroslav Benes
2026-02-26 17:30       ` Steven Rostedt
2026-02-27  1:34         ` Song Chen
2026-03-06  9:57           ` Petr Mladek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox