[PATCH][RFC] tracing: Enable tracepoints via module parameters

From: Steven Rostedt
Date: Tue Mar 08 2011 - 17:18:12 EST


A few months ago it was suggested to have a way to enable tracepoints in
a module when it is loaded. I tried various methods, but this one seems
to be the least intrusive. In fact, it requires no modification to the
module code.

The trace event now adds its own MODULE_INFO() and kernel_param_ops that
and links the information about a tracepoint into the module's __param
section. A module can be loaded with a tracepoint active by adding
trace_<tracepoint>=1 as one of the parameters.

The following patch is in:

git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace.git

branch: rfc/trace


Steven Rostedt (1):
tracing: Enable tracepoints via module parameters

----
include/linux/ftrace_event.h | 4 +++
include/trace/ftrace.h | 22 ++++++++++++++++-
kernel/trace/trace_events.c | 52 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 76 insertions(+), 2 deletions(-)
---------------------------
commit b514aa1b59148994a47086cdd46db7f994b4789e
Author: Steven Rostedt <srostedt@xxxxxxxxxx>
Date: Tue Mar 8 17:06:14 2011 -0500

tracing: Enable tracepoints via module parameters

Add the tracepoints within the module to the module info section
and allow the tracepoints to be enabled when the module is loaded.

For example:

[root]# modinfo samples/trace_events/trace-events-sample.ko
filename: samples/trace_events/trace-events-sample.ko
license: GPL
description: trace-events-sample
author: Steven Rostedt
tracepoint: foo_bar
srcversion: F6AC4B8D911A5C5B9CCDD7B
depends:
vermagic: 2.6.38-rc5+ SMP preempt mod_unload

Notice that the trace-events-sample tracepoint "foo_bar" shows
up in the modinfo. When loading the module with:

# insmod trace-events-sample.ko trace_foo_bar=1

The tracepoint "foo_bar" will be enabled.

Cc: Yuanhan Liu <yuanhan.liu@xxxxxxxxxxxxxxx>
Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
Cc: Rusty Russell <rusty@xxxxxxxxxxxxxxxx>
Signed-off-by: Steven Rostedt <rostedt@xxxxxxxxxxx>

diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 47e3997..b672889 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -124,6 +124,8 @@ void tracing_record_cmdline(struct task_struct *tsk);

struct event_filter;

+extern struct kernel_param_ops ftrace_mod_ops;
+
enum trace_reg {
TRACE_REG_REGISTER,
TRACE_REG_UNREGISTER,
@@ -155,6 +157,7 @@ enum {
TRACE_EVENT_FL_FILTERED_BIT,
TRACE_EVENT_FL_RECORDED_CMD_BIT,
TRACE_EVENT_FL_CAP_ANY_BIT,
+ TRACE_EVENT_FL_MOD_ENABLE_BIT,
};

enum {
@@ -162,6 +165,7 @@ enum {
TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT),
TRACE_EVENT_FL_RECORDED_CMD = (1 << TRACE_EVENT_FL_RECORDED_CMD_BIT),
TRACE_EVENT_FL_CAP_ANY = (1 << TRACE_EVENT_FL_CAP_ANY_BIT),
+ TRACE_EVENT_FL_MOD_ENABLE = (1 << TRACE_EVENT_FL_MOD_ENABLE_BIT),
};

struct ftrace_event_call {
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 3e68366..3d4a6ee 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -561,6 +561,22 @@ static inline void ftrace_test_probe_##call(void) \
#undef __get_dynamic_array
#undef __get_str

+/*
+ * Add ftrace trace points in modules to be set by module
+ * parameters. This adds "trace_##call" as a module parameter.
+ * The user could enable trace points on module load with:
+ * trace_##call=1 as a module parameter.
+ */
+#undef ftrace_mod_params
+#ifdef MODULE
+#define ftrace_mod_params(call) \
+ module_param_cb(trace_##call, &ftrace_mod_ops, \
+ &event_##call, 0644); \
+ MODULE_INFO(tracepoint, #call)
+#else
+#define ftrace_mod_params(call)
+#endif
+
#undef TP_printk
#define TP_printk(fmt, args...) "\"" fmt "\", " __stringify(args)

@@ -588,7 +604,8 @@ static struct ftrace_event_call __used event_##call = { \
.print_fmt = print_fmt_##template, \
}; \
static struct ftrace_event_call __used \
-__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call
+__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call;\
+ftrace_mod_params(call)

#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, call, proto, args, print) \
@@ -602,7 +619,8 @@ static struct ftrace_event_call __used event_##call = { \
.print_fmt = print_fmt_##call, \
}; \
static struct ftrace_event_call __used \
-__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call
+__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call; \
+ftrace_mod_params(call)

#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)

diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 5f499e0..5223751 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -1285,6 +1285,7 @@ static void trace_module_add_events(struct module *mod)
{
struct ftrace_module_file_ops *file_ops = NULL;
struct ftrace_event_call **call, **start, **end;
+ int ret;

start = mod->trace_events;
end = mod->trace_events + mod->num_trace_events;
@@ -1300,6 +1301,14 @@ static void trace_module_add_events(struct module *mod)
__trace_add_event_call(*call, mod,
&file_ops->id, &file_ops->enable,
&file_ops->filter, &file_ops->format);
+ /* If the module tracepoint parameter was set */
+ if ((*call)->flags & TRACE_EVENT_FL_MOD_ENABLE) {
+ (*call)->flags = 0;
+ ret = ftrace_event_enable_disable(*call, 1);
+ if (ret < 0)
+ pr_warning("unable to enable tracepoint %s",
+ (*call)->name);
+ }
}
}

@@ -1457,6 +1466,49 @@ static __init int event_trace_init(void)
}
fs_initcall(event_trace_init);

+/* Allow modules to load with enabled trace points */
+int ftrace_mod_param_set(const char *val, const struct kernel_param *kp)
+{
+ struct ftrace_event_call *call = kp->arg;
+
+ /* This is set like param_set_bool() */
+
+ /* No equals means "set"... */
+ if (!val)
+ val = "1";
+
+ /* One of =[yYnN01] */
+ switch (val[0]) {
+ case 'y': case 'Y': case '1':
+ break;
+ case 'n': case 'N': case '0':
+ /* Do nothing */
+ return 0;
+ default:
+ return -EINVAL;
+ }
+
+ /* Set flag to tell ftrace to enable this event on init */
+ call->flags = TRACE_EVENT_FL_MOD_ENABLE;
+
+ return 0;
+}
+
+int ftrace_mod_param_get(char *buffer, const struct kernel_param *kp)
+{
+ struct ftrace_event_call *call = kp->arg;
+
+ return sprintf(buffer, "%d",
+ !!(call->flags &
+ (TRACE_EVENT_FL_MOD_ENABLE | TRACE_EVENT_FL_ENABLED)));
+}
+
+struct kernel_param_ops ftrace_mod_ops = {
+ .set = ftrace_mod_param_set,
+ .get = ftrace_mod_param_get,
+};
+EXPORT_SYMBOL(ftrace_mod_ops);
+
#ifdef CONFIG_FTRACE_STARTUP_TEST

static DEFINE_SPINLOCK(test_spinlock);


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/