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

From: Mathieu Desnoyers
Date: Tue Mar 08 2011 - 18:23:08 EST


* Steven Rostedt (rostedt@xxxxxxxxxxx) wrote:
> 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.

Hi Steven,

Can you walk me through the expected sequence someone wanting to enable a few
specific module tracepoints would have to go through ? I'm thinking here about
the context of a distro which has on-demand module loading. The scenario I am
thinking about is a distro specifying a basic set of tracepoints to enable in a
"standard catch-all tracing configuration", which includes some tracepoints in
yet-unloaded modules. I'm trying to figure out what the end user experience will
look like if we go for the solution you propose here.

Thanks,

Mathieu

>
> 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);
>
>

--
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
--
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/