* [PATCH v3 0/5] tracing/probes: Support tracepoint events on modules
@ 2024-08-18 10:42 Masami Hiramatsu (Google)
2024-08-18 10:42 ` [PATCH v3 1/5] tracepoint: Support iterating over tracepoints " Masami Hiramatsu (Google)
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Masami Hiramatsu (Google) @ 2024-08-18 10:42 UTC (permalink / raw)
To: Steven Rostedt
Cc: Mathieu Desnoyers, don, linux-kernel, linux-trace-kernel,
mhiramat
Hi,
This is the 3rd version of the raw tracepoint events on modules.
The previous version is here;
https://lore.kernel.org/all/fbfec8d9-d0ed-4384-bbd2-dd5c1e568ed1@efficios.com/
This version supports tracepoint event on unloaded modules according
to Mathies' suggestion ([2/5],[4/5] and part of [5/5]) .
The concern about blocking module unload by instrumentation is TBD.
Note, to support tracepoints in the unloaded modules, tracepoint event
can not check the given tracepoint is really defined or not. So unless
CONFIG_MODULES=n, it does not check the tracepoint existence. IOW,
user can specify any tracepoint name for tracepoint events. It will be
just ignored.
You can download this series from;
https://git.kernel.org/pub/scm/linux/kernel/git/mhiramat/linux.git topic/tprobe-on-module
Thank you,
---
Masami Hiramatsu (Google) (5):
tracepoint: Support iterating over tracepoints on modules
tracepoint: Support tterating tracepoints in a loading module
tracing/fprobe: Support raw tracepoint events on modules
tracing/fprobe: Support raw tracepoints on future loaded modules
sefltests/tracing: Add a test for tracepoint events on modules
include/linux/tracepoint.h | 20 ++
kernel/trace/trace_fprobe.c | 179 +++++++++++++++-----
kernel/tracepoint.c | 42 +++++
tools/testing/selftests/ftrace/config | 1
.../test.d/dynevent/add_remove_tprobe_module.tc | 61 +++++++
.../ftrace/test.d/dynevent/tprobe_syntax_errors.tc | 1
6 files changed, 254 insertions(+), 50 deletions(-)
create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/add_remove_tprobe_module.tc
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 1/5] tracepoint: Support iterating over tracepoints on modules
2024-08-18 10:42 [PATCH v3 0/5] tracing/probes: Support tracepoint events on modules Masami Hiramatsu (Google)
@ 2024-08-18 10:42 ` Masami Hiramatsu (Google)
2024-08-18 10:43 ` [PATCH v3 2/5] tracepoint: Support tterating tracepoints in a loading module Masami Hiramatsu (Google)
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Masami Hiramatsu (Google) @ 2024-08-18 10:42 UTC (permalink / raw)
To: Steven Rostedt
Cc: Mathieu Desnoyers, don, linux-kernel, linux-trace-kernel,
mhiramat
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Add for_each_module_tracepoint() for iterating over tracepoints
on modules. This is similar to the for_each_kernel_tracepoint()
but only for the tracepoints on modules (not including kernel
built-in tracepoints).
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v3:
- Add kerneldoc for for_each_module_tracepoint.
---
include/linux/tracepoint.h | 7 +++++++
kernel/tracepoint.c | 21 +++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 6be396bb4297..837fcf8ec0d5 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -64,6 +64,8 @@ struct tp_module {
bool trace_module_has_bad_taint(struct module *mod);
extern int register_tracepoint_module_notifier(struct notifier_block *nb);
extern int unregister_tracepoint_module_notifier(struct notifier_block *nb);
+void for_each_module_tracepoint(void (*fct)(struct tracepoint *, void *),
+ void *priv);
#else
static inline bool trace_module_has_bad_taint(struct module *mod)
{
@@ -79,6 +81,11 @@ int unregister_tracepoint_module_notifier(struct notifier_block *nb)
{
return 0;
}
+static inline
+void for_each_module_tracepoint(void (*fct)(struct tracepoint *, void *),
+ void *priv)
+{
+}
#endif /* CONFIG_MODULES */
/*
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 8d1507dd0724..bed4aad36d92 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -735,6 +735,27 @@ static __init int init_tracepoints(void)
return ret;
}
__initcall(init_tracepoints);
+
+/**
+ * for_each_module_tracepoint - iteration on all tracepoints in all modules
+ * @fct: callback
+ * @priv: private data
+ */
+void for_each_module_tracepoint(void (*fct)(struct tracepoint *tp, void *priv),
+ void *priv)
+{
+ struct tp_module *tp_mod;
+ struct module *mod;
+
+ mutex_lock(&tracepoint_module_list_mutex);
+ list_for_each_entry(tp_mod, &tracepoint_module_list, list) {
+ mod = tp_mod->mod;
+ for_each_tracepoint_range(mod->tracepoints_ptrs,
+ mod->tracepoints_ptrs + mod->num_tracepoints,
+ fct, priv);
+ }
+ mutex_unlock(&tracepoint_module_list_mutex);
+}
#endif /* CONFIG_MODULES */
/**
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 2/5] tracepoint: Support tterating tracepoints in a loading module
2024-08-18 10:42 [PATCH v3 0/5] tracing/probes: Support tracepoint events on modules Masami Hiramatsu (Google)
2024-08-18 10:42 ` [PATCH v3 1/5] tracepoint: Support iterating over tracepoints " Masami Hiramatsu (Google)
@ 2024-08-18 10:43 ` Masami Hiramatsu (Google)
2024-09-11 0:21 ` Masami Hiramatsu
2024-08-18 10:43 ` [PATCH v3 3/5] tracing/fprobe: Support raw tracepoint events on modules Masami Hiramatsu (Google)
` (2 subsequent siblings)
4 siblings, 1 reply; 7+ messages in thread
From: Masami Hiramatsu (Google) @ 2024-08-18 10:43 UTC (permalink / raw)
To: Steven Rostedt
Cc: Mathieu Desnoyers, don, linux-kernel, linux-trace-kernel,
mhiramat
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Add for_each_tracepoint_in_module() function to iterate tracepoints in
a module. This API is needed for handling tracepoints in a loading
module from tracepoint_module_notifier callback function.
This also update for_each_module_tracepoint() to pass the module to
callback function so that it can find module easily.
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v3:
- Newly added.
---
include/linux/tracepoint.h | 17 +++++++++++++++--
kernel/tracepoint.c | 37 +++++++++++++++++++++++++++++--------
2 files changed, 44 insertions(+), 10 deletions(-)
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 837fcf8ec0d5..93a9f3070b48 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -64,8 +64,13 @@ struct tp_module {
bool trace_module_has_bad_taint(struct module *mod);
extern int register_tracepoint_module_notifier(struct notifier_block *nb);
extern int unregister_tracepoint_module_notifier(struct notifier_block *nb);
-void for_each_module_tracepoint(void (*fct)(struct tracepoint *, void *),
+void for_each_module_tracepoint(void (*fct)(struct tracepoint *,
+ struct module *, void *),
void *priv);
+void for_each_tracepoint_in_module(struct module *,
+ void (*fct)(struct tracepoint *,
+ struct module *, void *),
+ void *priv);
#else
static inline bool trace_module_has_bad_taint(struct module *mod)
{
@@ -82,10 +87,18 @@ int unregister_tracepoint_module_notifier(struct notifier_block *nb)
return 0;
}
static inline
-void for_each_module_tracepoint(void (*fct)(struct tracepoint *, void *),
+void for_each_module_tracepoint(void (*fct)(struct tracepoint *,
+ struct module *, void *),
void *priv)
{
}
+static inline
+void for_each_tracepoint_in_module(struct module *mod,
+ void (*fct)(struct tracepoint *,
+ struct module *, void *),
+ void *priv)
+{
+}
#endif /* CONFIG_MODULES */
/*
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index bed4aad36d92..8879da16ef4d 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -736,24 +736,45 @@ static __init int init_tracepoints(void)
}
__initcall(init_tracepoints);
+/**
+ * for_each_tracepoint_in_module - iteration on all tracepoints in a module
+ * @mod: module
+ * @fct: callback
+ * @priv: private data
+ */
+void for_each_tracepoint_in_module(struct module *mod,
+ void (*fct)(struct tracepoint *tp,
+ struct module *mod, void *priv),
+ void *priv)
+{
+ tracepoint_ptr_t *begin, *end, *iter;
+
+ lockdep_assert_held(&tracepoint_module_list_mutex);
+
+ if (!mod)
+ return;
+
+ begin = mod->tracepoints_ptrs;
+ end = mod->tracepoints_ptrs + mod->num_tracepoints;
+
+ for (iter = begin; iter < end; iter++)
+ fct(tracepoint_ptr_deref(iter), mod, priv);
+}
+
/**
* for_each_module_tracepoint - iteration on all tracepoints in all modules
* @fct: callback
* @priv: private data
*/
-void for_each_module_tracepoint(void (*fct)(struct tracepoint *tp, void *priv),
+void for_each_module_tracepoint(void (*fct)(struct tracepoint *tp,
+ struct module *mod, void *priv),
void *priv)
{
struct tp_module *tp_mod;
- struct module *mod;
mutex_lock(&tracepoint_module_list_mutex);
- list_for_each_entry(tp_mod, &tracepoint_module_list, list) {
- mod = tp_mod->mod;
- for_each_tracepoint_range(mod->tracepoints_ptrs,
- mod->tracepoints_ptrs + mod->num_tracepoints,
- fct, priv);
- }
+ list_for_each_entry(tp_mod, &tracepoint_module_list, list)
+ for_each_tracepoint_in_module(tp_mod->mod, fct, priv);
mutex_unlock(&tracepoint_module_list_mutex);
}
#endif /* CONFIG_MODULES */
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 3/5] tracing/fprobe: Support raw tracepoint events on modules
2024-08-18 10:42 [PATCH v3 0/5] tracing/probes: Support tracepoint events on modules Masami Hiramatsu (Google)
2024-08-18 10:42 ` [PATCH v3 1/5] tracepoint: Support iterating over tracepoints " Masami Hiramatsu (Google)
2024-08-18 10:43 ` [PATCH v3 2/5] tracepoint: Support tterating tracepoints in a loading module Masami Hiramatsu (Google)
@ 2024-08-18 10:43 ` Masami Hiramatsu (Google)
2024-08-18 10:43 ` [PATCH v3 4/5] tracing/fprobe: Support raw tracepoints on future loaded modules Masami Hiramatsu (Google)
2024-08-18 10:43 ` [PATCH v3 5/5] sefltests/tracing: Add a test for tracepoint events on modules Masami Hiramatsu (Google)
4 siblings, 0 replies; 7+ messages in thread
From: Masami Hiramatsu (Google) @ 2024-08-18 10:43 UTC (permalink / raw)
To: Steven Rostedt
Cc: Mathieu Desnoyers, don, linux-kernel, linux-trace-kernel,
mhiramat
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Support raw tracepoint event on module by fprobe events.
Since it only uses for_each_kernel_tracepoint() to find a tracepoint,
the tracepoints on modules are not handled. Thus if user specified a
tracepoint on a module, it shows an error.
This adds new for_each_module_tracepoint() API to tracepoint subsystem,
and uses it to find tracepoints on modules.
Reported-by: don <zds100@gmail.com>
Closes: https://lore.kernel.org/all/20240530215718.aeec973a1d0bf058d39cb1e3@kernel.org/
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v2:
- Fix build errors with CONFIG_MODULES=y.
---
kernel/trace/trace_fprobe.c | 46 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 38 insertions(+), 8 deletions(-)
diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c
index 62e6a8f4aae9..8b1127e37da5 100644
--- a/kernel/trace/trace_fprobe.c
+++ b/kernel/trace/trace_fprobe.c
@@ -385,6 +385,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
const char *event,
const char *symbol,
struct tracepoint *tpoint,
+ struct module *mod,
int maxactive,
int nargs, bool is_return)
{
@@ -405,6 +406,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
tf->fp.entry_handler = fentry_dispatcher;
tf->tpoint = tpoint;
+ tf->mod = mod;
tf->fp.nr_maxactive = maxactive;
ret = trace_probe_init(&tf->tp, event, group, false, nargs);
@@ -895,8 +897,23 @@ static struct notifier_block tracepoint_module_nb = {
struct __find_tracepoint_cb_data {
const char *tp_name;
struct tracepoint *tpoint;
+ struct module *mod;
};
+static void __find_tracepoint_module_cb(struct tracepoint *tp, struct module *mod, void *priv)
+{
+ struct __find_tracepoint_cb_data *data = priv;
+
+ if (!data->tpoint && !strcmp(data->tp_name, tp->name)) {
+ data->tpoint = tp;
+ data->mod = mod;
+ if (!try_module_get(data->mod)) {
+ data->tpoint = NULL;
+ data->mod = NULL;
+ }
+ }
+}
+
static void __find_tracepoint_cb(struct tracepoint *tp, void *priv)
{
struct __find_tracepoint_cb_data *data = priv;
@@ -905,14 +922,28 @@ static void __find_tracepoint_cb(struct tracepoint *tp, void *priv)
data->tpoint = tp;
}
-static struct tracepoint *find_tracepoint(const char *tp_name)
+/*
+ * Find a tracepoint from kernel and module. If the tracepoint is in a module,
+ * this increments the module refcount to prevent unloading until the
+ * trace_fprobe is registered to the list. After registering the trace_fprobe
+ * on the trace_fprobe list, the module refcount is decremented because
+ * tracepoint_probe_module_cb will handle it.
+ */
+static struct tracepoint *find_tracepoint(const char *tp_name,
+ struct module **tp_mod)
{
struct __find_tracepoint_cb_data data = {
.tp_name = tp_name,
+ .mod = NULL,
};
for_each_kernel_tracepoint(__find_tracepoint_cb, &data);
+ if (!data.tpoint && IS_ENABLED(CONFIG_MODULES)) {
+ for_each_module_tracepoint(__find_tracepoint_module_cb, &data);
+ *tp_mod = data.mod;
+ }
+
return data.tpoint;
}
@@ -996,6 +1027,7 @@ static int __trace_fprobe_create(int argc, const char *argv[])
char abuf[MAX_BTF_ARGS_LEN];
char *dbuf = NULL;
bool is_tracepoint = false;
+ struct module *tp_mod = NULL;
struct tracepoint *tpoint = NULL;
struct traceprobe_parse_context ctx = {
.flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE,
@@ -1080,7 +1112,7 @@ static int __trace_fprobe_create(int argc, const char *argv[])
if (is_tracepoint) {
ctx.flags |= TPARG_FL_TPOINT;
- tpoint = find_tracepoint(symbol);
+ tpoint = find_tracepoint(symbol, &tp_mod);
if (!tpoint) {
trace_probe_log_set_index(1);
trace_probe_log_err(0, NO_TRACEPOINT);
@@ -1110,8 +1142,8 @@ static int __trace_fprobe_create(int argc, const char *argv[])
goto out;
/* setup a probe */
- tf = alloc_trace_fprobe(group, event, symbol, tpoint, maxactive,
- argc, is_return);
+ tf = alloc_trace_fprobe(group, event, symbol, tpoint, tp_mod,
+ maxactive, argc, is_return);
if (IS_ERR(tf)) {
ret = PTR_ERR(tf);
/* This must return -ENOMEM, else there is a bug */
@@ -1119,10 +1151,6 @@ static int __trace_fprobe_create(int argc, const char *argv[])
goto out; /* We know tf is not allocated */
}
- if (is_tracepoint)
- tf->mod = __module_text_address(
- (unsigned long)tf->tpoint->probestub);
-
/* parse arguments */
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
trace_probe_log_set_index(i + 2);
@@ -1155,6 +1183,8 @@ static int __trace_fprobe_create(int argc, const char *argv[])
}
out:
+ if (tp_mod)
+ module_put(tp_mod);
traceprobe_finish_parse(&ctx);
trace_probe_log_clear();
kfree(new_argv);
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 4/5] tracing/fprobe: Support raw tracepoints on future loaded modules
2024-08-18 10:42 [PATCH v3 0/5] tracing/probes: Support tracepoint events on modules Masami Hiramatsu (Google)
` (2 preceding siblings ...)
2024-08-18 10:43 ` [PATCH v3 3/5] tracing/fprobe: Support raw tracepoint events on modules Masami Hiramatsu (Google)
@ 2024-08-18 10:43 ` Masami Hiramatsu (Google)
2024-08-18 10:43 ` [PATCH v3 5/5] sefltests/tracing: Add a test for tracepoint events on modules Masami Hiramatsu (Google)
4 siblings, 0 replies; 7+ messages in thread
From: Masami Hiramatsu (Google) @ 2024-08-18 10:43 UTC (permalink / raw)
To: Steven Rostedt
Cc: Mathieu Desnoyers, don, linux-kernel, linux-trace-kernel,
mhiramat
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Support raw tracepoint events on future loaded (unloaded) modules.
This allows user to create raw tracepoint events which can be used from
module's __init functions.
Note: since the kernel does not have any information about the tracepoints
in the unloaded modules, fprobe events can not check whether the tracepoint
exists nor extend the BTF based arguments.
Suggested-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v3:
- Newly added.
---
kernel/trace/trace_fprobe.c | 151 +++++++++++++-------
.../ftrace/test.d/dynevent/tprobe_syntax_errors.tc | 1
2 files changed, 101 insertions(+), 51 deletions(-)
diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c
index 8b1127e37da5..a079abd8955b 100644
--- a/kernel/trace/trace_fprobe.c
+++ b/kernel/trace/trace_fprobe.c
@@ -21,6 +21,7 @@
#define FPROBE_EVENT_SYSTEM "fprobes"
#define TRACEPOINT_EVENT_SYSTEM "tracepoints"
#define RETHOOK_MAXACTIVE_MAX 4096
+#define TRACEPOINT_STUB ERR_PTR(-ENOENT)
static int trace_fprobe_create(const char *raw_command);
static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev);
@@ -674,6 +675,24 @@ static int unregister_fprobe_event(struct trace_fprobe *tf)
return trace_probe_unregister_event_call(&tf->tp);
}
+static int __regsiter_tracepoint_fprobe(struct trace_fprobe *tf)
+{
+ struct tracepoint *tpoint = tf->tpoint;
+ unsigned long ip = (unsigned long)tpoint->probestub;
+ int ret;
+
+ /*
+ * Here, we do 2 steps to enable fprobe on a tracepoint.
+ * At first, put __probestub_##TP function on the tracepoint
+ * and put a fprobe on the stub function.
+ */
+ ret = tracepoint_probe_register_prio_may_exist(tpoint,
+ tpoint->probestub, NULL, 0);
+ if (ret < 0)
+ return ret;
+ return register_fprobe_ips(&tf->fp, &ip, 1);
+}
+
/* Internal register function - just handle fprobe and flags */
static int __register_trace_fprobe(struct trace_fprobe *tf)
{
@@ -700,18 +719,12 @@ static int __register_trace_fprobe(struct trace_fprobe *tf)
tf->fp.flags |= FPROBE_FL_DISABLED;
if (trace_fprobe_is_tracepoint(tf)) {
- struct tracepoint *tpoint = tf->tpoint;
- unsigned long ip = (unsigned long)tpoint->probestub;
- /*
- * Here, we do 2 steps to enable fprobe on a tracepoint.
- * At first, put __probestub_##TP function on the tracepoint
- * and put a fprobe on the stub function.
- */
- ret = tracepoint_probe_register_prio_may_exist(tpoint,
- tpoint->probestub, NULL, 0);
- if (ret < 0)
- return ret;
- return register_fprobe_ips(&tf->fp, &ip, 1);
+
+ /* This tracepoint is not loaded yet */
+ if (tf->tpoint == TRACEPOINT_STUB)
+ return 0;
+
+ return __regsiter_tracepoint_fprobe(tf);
}
/* TODO: handle filter, nofilter or symbol list */
@@ -864,36 +877,6 @@ static int register_trace_fprobe(struct trace_fprobe *tf)
return ret;
}
-#ifdef CONFIG_MODULES
-static int __tracepoint_probe_module_cb(struct notifier_block *self,
- unsigned long val, void *data)
-{
- struct tp_module *tp_mod = data;
- struct trace_fprobe *tf;
- struct dyn_event *pos;
-
- if (val != MODULE_STATE_GOING)
- return NOTIFY_DONE;
-
- mutex_lock(&event_mutex);
- for_each_trace_fprobe(tf, pos) {
- if (tp_mod->mod == tf->mod) {
- tracepoint_probe_unregister(tf->tpoint,
- tf->tpoint->probestub, NULL);
- tf->tpoint = NULL;
- tf->mod = NULL;
- }
- }
- mutex_unlock(&event_mutex);
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block tracepoint_module_nb = {
- .notifier_call = __tracepoint_probe_module_cb,
-};
-#endif /* CONFIG_MODULES */
-
struct __find_tracepoint_cb_data {
const char *tp_name;
struct tracepoint *tpoint;
@@ -906,10 +889,12 @@ static void __find_tracepoint_module_cb(struct tracepoint *tp, struct module *mo
if (!data->tpoint && !strcmp(data->tp_name, tp->name)) {
data->tpoint = tp;
- data->mod = mod;
- if (!try_module_get(data->mod)) {
- data->tpoint = NULL;
- data->mod = NULL;
+ if (!data->mod) {
+ data->mod = mod;
+ if (!try_module_get(data->mod)) {
+ data->tpoint = NULL;
+ data->mod = NULL;
+ }
}
}
}
@@ -947,6 +932,67 @@ static struct tracepoint *find_tracepoint(const char *tp_name,
return data.tpoint;
}
+#ifdef CONFIG_MODULES
+static void reenable_trace_fprobe(struct trace_fprobe *tf)
+{
+ struct trace_probe *tp = &tf->tp;
+
+ list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) {
+ __enable_trace_fprobe(tf);
+ }
+}
+
+static struct tracepoint *find_tracepoint_in_module(struct module *mod,
+ const char *tp_name)
+{
+ struct __find_tracepoint_cb_data data = {
+ .tp_name = tp_name,
+ .mod = mod,
+ };
+
+ for_each_tracepoint_in_module(mod, __find_tracepoint_module_cb, &data);
+ return data.tpoint;
+}
+
+static int __tracepoint_probe_module_cb(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ struct tp_module *tp_mod = data;
+ struct tracepoint *tpoint;
+ struct trace_fprobe *tf;
+ struct dyn_event *pos;
+
+ if (val != MODULE_STATE_GOING && val != MODULE_STATE_COMING)
+ return NOTIFY_DONE;
+
+ mutex_lock(&event_mutex);
+ for_each_trace_fprobe(tf, pos) {
+ if (val == MODULE_STATE_COMING && tf->tpoint == TRACEPOINT_STUB) {
+ tpoint = find_tracepoint_in_module(tp_mod->mod, tf->symbol);
+ if (tpoint) {
+ tf->tpoint = tpoint;
+ tf->mod = tp_mod->mod;
+ if (!WARN_ON_ONCE(__regsiter_tracepoint_fprobe(tf)) &&
+ trace_probe_is_enabled(&tf->tp))
+ reenable_trace_fprobe(tf);
+ }
+ } else if (val == MODULE_STATE_GOING && tp_mod->mod == tf->mod) {
+ tracepoint_probe_unregister(tf->tpoint,
+ tf->tpoint->probestub, NULL);
+ tf->tpoint = NULL;
+ tf->mod = NULL;
+ }
+ }
+ mutex_unlock(&event_mutex);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block tracepoint_module_nb = {
+ .notifier_call = __tracepoint_probe_module_cb,
+};
+#endif /* CONFIG_MODULES */
+
static int parse_symbol_and_return(int argc, const char *argv[],
char **symbol, bool *is_return,
bool is_tracepoint)
@@ -1113,14 +1159,19 @@ static int __trace_fprobe_create(int argc, const char *argv[])
if (is_tracepoint) {
ctx.flags |= TPARG_FL_TPOINT;
tpoint = find_tracepoint(symbol, &tp_mod);
- if (!tpoint) {
+ if (tpoint) {
+ ctx.funcname = kallsyms_lookup(
+ (unsigned long)tpoint->probestub,
+ NULL, NULL, NULL, sbuf);
+ } else if (IS_ENABLED(CONFIG_MODULES)) {
+ /* This *may* be loaded afterwards */
+ tpoint = TRACEPOINT_STUB;
+ ctx.funcname = symbol;
+ } else {
trace_probe_log_set_index(1);
trace_probe_log_err(0, NO_TRACEPOINT);
goto parse_error;
}
- ctx.funcname = kallsyms_lookup(
- (unsigned long)tpoint->probestub,
- NULL, NULL, NULL, sbuf);
} else
ctx.funcname = symbol;
diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/tprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/dynevent/tprobe_syntax_errors.tc
index da117b8f1d12..ffe8ffef4027 100644
--- a/tools/testing/selftests/ftrace/test.d/dynevent/tprobe_syntax_errors.tc
+++ b/tools/testing/selftests/ftrace/test.d/dynevent/tprobe_syntax_errors.tc
@@ -9,7 +9,6 @@ check_error() { # command-with-error-pos-by-^
check_error 't^100 kfree' # BAD_MAXACT_TYPE
-check_error 't ^non_exist_tracepoint' # NO_TRACEPOINT
check_error 't:^/bar kfree' # NO_GROUP_NAME
check_error 't:^12345678901234567890123456789012345678901234567890123456789012345/bar kfree' # GROUP_TOO_LONG
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 5/5] sefltests/tracing: Add a test for tracepoint events on modules
2024-08-18 10:42 [PATCH v3 0/5] tracing/probes: Support tracepoint events on modules Masami Hiramatsu (Google)
` (3 preceding siblings ...)
2024-08-18 10:43 ` [PATCH v3 4/5] tracing/fprobe: Support raw tracepoints on future loaded modules Masami Hiramatsu (Google)
@ 2024-08-18 10:43 ` Masami Hiramatsu (Google)
4 siblings, 0 replies; 7+ messages in thread
From: Masami Hiramatsu (Google) @ 2024-08-18 10:43 UTC (permalink / raw)
To: Steven Rostedt
Cc: Mathieu Desnoyers, don, linux-kernel, linux-trace-kernel,
mhiramat
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Add a test case for tracepoint events on modules. This checks if it can add
and remove the events correctly.
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v3:
- Add not-loaded module test.
---
tools/testing/selftests/ftrace/config | 1
.../test.d/dynevent/add_remove_tprobe_module.tc | 61 ++++++++++++++++++++
2 files changed, 62 insertions(+)
create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/add_remove_tprobe_module.tc
diff --git a/tools/testing/selftests/ftrace/config b/tools/testing/selftests/ftrace/config
index 048a312abf40..544de0db5f58 100644
--- a/tools/testing/selftests/ftrace/config
+++ b/tools/testing/selftests/ftrace/config
@@ -20,6 +20,7 @@ CONFIG_PREEMPT_TRACER=y
CONFIG_PROBE_EVENTS_BTF_ARGS=y
CONFIG_SAMPLES=y
CONFIG_SAMPLE_FTRACE_DIRECT=m
+CONFIG_SAMPLE_TRACE_EVENTS=m
CONFIG_SAMPLE_TRACE_PRINTK=m
CONFIG_SCHED_TRACER=y
CONFIG_STACK_TRACER=y
diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_tprobe_module.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_tprobe_module.tc
new file mode 100644
index 000000000000..d319d5ed4226
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_tprobe_module.tc
@@ -0,0 +1,61 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: Generic dynamic event - add/remove tracepoint probe events on module
+# requires: dynamic_events "t[:[<group>/][<event>]] <tracepoint> [<args>]":README
+
+rmmod trace-events-sample ||:
+if ! modprobe trace-events-sample ; then
+ echo "No trace-events sample module - please make CONFIG_SAMPLE_TRACE_EVENTS=m"
+ exit_unresolved;
+fi
+trap "rmmod trace-events-sample" EXIT
+
+echo 0 > events/enable
+echo > dynamic_events
+
+TRACEPOINT1=foo_bar
+TRACEPOINT2=foo_bar_with_cond
+
+echo "t:myevent1 $TRACEPOINT1" >> dynamic_events
+echo "t:myevent2 $TRACEPOINT2" >> dynamic_events
+
+grep -q myevent1 dynamic_events
+grep -q myevent2 dynamic_events
+test -d events/tracepoints/myevent1
+test -d events/tracepoints/myevent2
+
+echo "-:myevent2" >> dynamic_events
+
+grep -q myevent1 dynamic_events
+! grep -q myevent2 dynamic_events
+
+echo > dynamic_events
+
+clear_trace
+
+:;: "Try to put a probe on a tracepoint in non-loaded module" ;:
+rmmod trace-events-sample
+
+echo "t:myevent1 $TRACEPOINT1" >> dynamic_events
+echo "t:myevent2 $TRACEPOINT2" >> dynamic_events
+
+grep -q myevent1 dynamic_events
+grep -q myevent2 dynamic_events
+test -d events/tracepoints/myevent1
+test -d events/tracepoints/myevent2
+
+echo 1 > events/tracepoints/enable
+
+modprobe trace-events-sample
+
+sleep 2
+
+grep -q "myevent1" trace
+grep -q "myevent2" trace
+
+rmmod trace-events-sample
+trap "" EXIT
+
+echo 0 > events/tracepoints/enable
+echo > dynamic_events
+clear_trace
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/5] tracepoint: Support tterating tracepoints in a loading module
2024-08-18 10:43 ` [PATCH v3 2/5] tracepoint: Support tterating tracepoints in a loading module Masami Hiramatsu (Google)
@ 2024-09-11 0:21 ` Masami Hiramatsu
0 siblings, 0 replies; 7+ messages in thread
From: Masami Hiramatsu @ 2024-09-11 0:21 UTC (permalink / raw)
To: Masami Hiramatsu (Google)
Cc: Steven Rostedt, Mathieu Desnoyers, don, linux-kernel,
linux-trace-kernel
The subject has a typo, "tterating" -> "iterating".
I'll fix it and import this to probes/for-next.
Thank you,
On Sun, 18 Aug 2024 19:43:07 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:
> From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
>
> Add for_each_tracepoint_in_module() function to iterate tracepoints in
> a module. This API is needed for handling tracepoints in a loading
> module from tracepoint_module_notifier callback function.
> This also update for_each_module_tracepoint() to pass the module to
> callback function so that it can find module easily.
>
> Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> ---
> Changes in v3:
> - Newly added.
> ---
> include/linux/tracepoint.h | 17 +++++++++++++++--
> kernel/tracepoint.c | 37 +++++++++++++++++++++++++++++--------
> 2 files changed, 44 insertions(+), 10 deletions(-)
>
> diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
> index 837fcf8ec0d5..93a9f3070b48 100644
> --- a/include/linux/tracepoint.h
> +++ b/include/linux/tracepoint.h
> @@ -64,8 +64,13 @@ struct tp_module {
> bool trace_module_has_bad_taint(struct module *mod);
> extern int register_tracepoint_module_notifier(struct notifier_block *nb);
> extern int unregister_tracepoint_module_notifier(struct notifier_block *nb);
> -void for_each_module_tracepoint(void (*fct)(struct tracepoint *, void *),
> +void for_each_module_tracepoint(void (*fct)(struct tracepoint *,
> + struct module *, void *),
> void *priv);
> +void for_each_tracepoint_in_module(struct module *,
> + void (*fct)(struct tracepoint *,
> + struct module *, void *),
> + void *priv);
> #else
> static inline bool trace_module_has_bad_taint(struct module *mod)
> {
> @@ -82,10 +87,18 @@ int unregister_tracepoint_module_notifier(struct notifier_block *nb)
> return 0;
> }
> static inline
> -void for_each_module_tracepoint(void (*fct)(struct tracepoint *, void *),
> +void for_each_module_tracepoint(void (*fct)(struct tracepoint *,
> + struct module *, void *),
> void *priv)
> {
> }
> +static inline
> +void for_each_tracepoint_in_module(struct module *mod,
> + void (*fct)(struct tracepoint *,
> + struct module *, void *),
> + void *priv)
> +{
> +}
> #endif /* CONFIG_MODULES */
>
> /*
> diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
> index bed4aad36d92..8879da16ef4d 100644
> --- a/kernel/tracepoint.c
> +++ b/kernel/tracepoint.c
> @@ -736,24 +736,45 @@ static __init int init_tracepoints(void)
> }
> __initcall(init_tracepoints);
>
> +/**
> + * for_each_tracepoint_in_module - iteration on all tracepoints in a module
> + * @mod: module
> + * @fct: callback
> + * @priv: private data
> + */
> +void for_each_tracepoint_in_module(struct module *mod,
> + void (*fct)(struct tracepoint *tp,
> + struct module *mod, void *priv),
> + void *priv)
> +{
> + tracepoint_ptr_t *begin, *end, *iter;
> +
> + lockdep_assert_held(&tracepoint_module_list_mutex);
> +
> + if (!mod)
> + return;
> +
> + begin = mod->tracepoints_ptrs;
> + end = mod->tracepoints_ptrs + mod->num_tracepoints;
> +
> + for (iter = begin; iter < end; iter++)
> + fct(tracepoint_ptr_deref(iter), mod, priv);
> +}
> +
> /**
> * for_each_module_tracepoint - iteration on all tracepoints in all modules
> * @fct: callback
> * @priv: private data
> */
> -void for_each_module_tracepoint(void (*fct)(struct tracepoint *tp, void *priv),
> +void for_each_module_tracepoint(void (*fct)(struct tracepoint *tp,
> + struct module *mod, void *priv),
> void *priv)
> {
> struct tp_module *tp_mod;
> - struct module *mod;
>
> mutex_lock(&tracepoint_module_list_mutex);
> - list_for_each_entry(tp_mod, &tracepoint_module_list, list) {
> - mod = tp_mod->mod;
> - for_each_tracepoint_range(mod->tracepoints_ptrs,
> - mod->tracepoints_ptrs + mod->num_tracepoints,
> - fct, priv);
> - }
> + list_for_each_entry(tp_mod, &tracepoint_module_list, list)
> + for_each_tracepoint_in_module(tp_mod->mod, fct, priv);
> mutex_unlock(&tracepoint_module_list_mutex);
> }
> #endif /* CONFIG_MODULES */
>
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-09-11 0:21 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-18 10:42 [PATCH v3 0/5] tracing/probes: Support tracepoint events on modules Masami Hiramatsu (Google)
2024-08-18 10:42 ` [PATCH v3 1/5] tracepoint: Support iterating over tracepoints " Masami Hiramatsu (Google)
2024-08-18 10:43 ` [PATCH v3 2/5] tracepoint: Support tterating tracepoints in a loading module Masami Hiramatsu (Google)
2024-09-11 0:21 ` Masami Hiramatsu
2024-08-18 10:43 ` [PATCH v3 3/5] tracing/fprobe: Support raw tracepoint events on modules Masami Hiramatsu (Google)
2024-08-18 10:43 ` [PATCH v3 4/5] tracing/fprobe: Support raw tracepoints on future loaded modules Masami Hiramatsu (Google)
2024-08-18 10:43 ` [PATCH v3 5/5] sefltests/tracing: Add a test for tracepoint events on modules Masami Hiramatsu (Google)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).