Hi,
在 2026/2/26 08:27, Steven Rostedt 写道:
On Wed, 25 Feb 2026 13:46:39 +0800
[email protected] wrote:
From: Song Chen <[email protected]>
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 <[email protected]>
---
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);
Is the above safe? klp uses ftrace. That means klp_module_going() may
need to be called before ftrace_release_mod(). That said, I wonder if
klp_module_going() could be moved into ftrace_release_mod()?
I didn't test with klp, so i'm not sure if it's safe. But i consider klp
is the other part which should be decoupled after ftrace and klp should
introduce its own notifier.
If klp_module_going must be running before ftrace_release_mod, i can try
to use priority in notifier_block to ensure their order.
Let me see if there is any way to use notifier and remain below calling
sequence:
ftrace_module_enable
klp_module_coming
blocking_notifier_call_chain_robust(MODULE_STATE_COMING)
blocking_notifier_call_chain(MODULE_STATE_GOING)
klp_module_going
ftrace_release_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);
Have you tested the case for why this is called? It has to be called
before the module frees the kallsyms. It's for tracing the module's
init functions.
cd /sys/kernel/tracing
echo :mod:<module> > set_ftrace_filter
echo function > current_tracer
modprobe <module>
cat trace
You should see the init functions of the module loaded. If
ftrace_free_mem() is called after the module frees the kallsyms of the
module init functions, you'll just get garbage for the init function
names.
Yes, after applying this patch, i tested it with your above commands,
result is:
cat trace_pipe
<...>-4027 [004] ..... 103.171161: mem_blkdev_init
<-do_one_initcall
insmod-4027 [004] ..... 103.249854: mem_blkdev_queue_rq
<-blk_mq_dispatch_rq_list
insmod-4027 [004] ..... 103.249865: mem_blkdev_queue_rq
<-blk_mq_dispatch_rq_list
....
module init function can be seen when module is being loaded.
As far as my understanding, ftrace_free_mem is called right after
blocking_notifier_call_chain(MODULE_STATE_LIVE) originally in
do_init_module, after this patch, it's called by notifier, almost
nothing changed, so no impact to current calling sequence.
Correct me if I'm wrong.
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);
Same issue with ftrace and klp here.
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);
Now klp_module_going() may need to be called *after* the
MODULE_STATE_GOING callbacks and *before* ftrace_release_mod(). But
again, if that's moved into ftrace_release_mod() it may be fine.
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
-- Steve