[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20100428204448.GE8591@Krystal>
Date: Wed, 28 Apr 2010 16:44:48 -0400
From: Mathieu Desnoyers <compudj@...stal.dyndns.org>
To: Steven Rostedt <rostedt@...dmis.org>
Cc: linux-kernel@...r.kernel.org, Ingo Molnar <mingo@...e.hu>,
Andrew Morton <akpm@...ux-foundation.org>,
Thomas Gleixner <tglx@...utronix.de>,
Peter Zijlstra <peterz@...radead.org>,
Frederic Weisbecker <fweisbec@...il.com>,
Arnaldo Carvalho de Melo <acme@...hat.com>,
Lai Jiangshan <laijs@...fujitsu.com>,
Li Zefan <lizf@...fujitsu.com>,
Masami Hiramatsu <mhiramat@...hat.com>,
Christoph Hellwig <hch@....de>
Subject: Re: [PATCH 04/10][RFC] tracing: Remove per event trace registering
* Steven Rostedt (rostedt@...dmis.org) wrote:
> From: Steven Rostedt <srostedt@...hat.com>
>
> This patch removes the register functions of TRACE_EVENT() to enable
> and disable tracepoints. The registering of a event is now down
> directly in the trace_events.c file. The tracepoint_probe_register()
> is now called directly.
>
> The prototypes are no longer type checked, but this should not be
> an issue since the tracepoints are created automatically by the
> macros. If a prototype is incorrect in the TRACE_EVENT() macro, then
> other macros will catch it.
>
> The trace_event_class structure now holds the probes to be called
> by the callbacks. This removes needing to have each event have
> a separate pointer for the probe.
>
> To handle kprobes and syscalls, since they register probes in a
> different manner, a "reg" field is added to the ftrace_event_class
> structure. If the "reg" field is assigned, then it will be called for
> enabling and disabling of the probe for either ftrace or perf. To let
> the reg function know what is happening, a new enum (trace_reg) is
> created that has the type of control that is needed.
>
> With this new rework, the 82 kernel events and 616 syscall events
> has their footprint dramatically lowered:
>
> text data bss dec hex filename
> 5788186 1337252 9351592 16477030 fb6b66 vmlinux.orig
> 5792282 1333796 9351592 16477670 fb6de6 vmlinux.class
> 5793448 1333780 9351592 16478820 fb7264 vmlinux.tracepoint
> 5796926 1337748 9351592 16486266 fb8f7a vmlinux.data
> 5774316 1306580 9351592 16432488 fabd68 vmlinux.regs
>
> The size went from 16477030 to 16432488, that's a total of 44K
> in savings. With tracepoints being continuously added, this is
> critical that the footprint becomes minimal.
Have you tried doing a BUILD_BUG_ON() on __typeof__() mismatch between
the type of the callback generated by TRACE_EVENT() and the expected
type ? This might help catching tricky preprocessor macro errors early.
Thanks,
Mathieu
>
> Signed-off-by: Steven Rostedt <rostedt@...dmis.org>
> ---
> include/linux/ftrace_event.h | 17 +++++--
> include/linux/syscalls.h | 29 ++---------
> include/linux/tracepoint.h | 12 ++++-
> include/trace/ftrace.h | 110 +++++----------------------------------
> kernel/trace/trace_event_perf.c | 15 ++++-
> kernel/trace/trace_events.c | 26 +++++++---
> kernel/trace/trace_kprobe.c | 34 +++++++++---
> kernel/trace/trace_syscalls.c | 56 +++++++++++++++++++-
> 8 files changed, 151 insertions(+), 148 deletions(-)
>
> diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
> index 496eea8..dd0051e 100644
> --- a/include/linux/ftrace_event.h
> +++ b/include/linux/ftrace_event.h
> @@ -113,8 +113,21 @@ void tracing_record_cmdline(struct task_struct *tsk);
>
> struct event_filter;
>
> +enum trace_reg {
> + TRACE_REG_REGISTER,
> + TRACE_REG_UNREGISTER,
> + TRACE_REG_PERF_REGISTER,
> + TRACE_REG_PERF_UNREGISTER,
> +};
> +
> +struct ftrace_event_call;
> +
> struct ftrace_event_class {
> char *system;
> + void *probe;
> + void *perf_probe;
> + int (*reg)(struct ftrace_event_call *event,
> + enum trace_reg type);
> };
>
> struct ftrace_event_call {
> @@ -124,8 +137,6 @@ struct ftrace_event_call {
> struct dentry *dir;
> struct trace_event *event;
> int enabled;
> - int (*regfunc)(struct ftrace_event_call *);
> - void (*unregfunc)(struct ftrace_event_call *);
> int id;
> const char *print_fmt;
> int (*raw_init)(struct ftrace_event_call *);
> @@ -137,8 +148,6 @@ struct ftrace_event_call {
> void *data;
>
> int perf_refcount;
> - int (*perf_event_enable)(struct ftrace_event_call *);
> - void (*perf_event_disable)(struct ftrace_event_call *);
> };
>
> #define PERF_MAX_TRACE_SIZE 2048
> diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
> index ac5791d..e3348c4 100644
> --- a/include/linux/syscalls.h
> +++ b/include/linux/syscalls.h
> @@ -103,22 +103,6 @@ struct perf_event_attr;
> #define __SC_TEST5(t5, a5, ...) __SC_TEST(t5); __SC_TEST4(__VA_ARGS__)
> #define __SC_TEST6(t6, a6, ...) __SC_TEST(t6); __SC_TEST5(__VA_ARGS__)
>
> -#ifdef CONFIG_PERF_EVENTS
> -
> -#define TRACE_SYS_ENTER_PERF_INIT(sname) \
> - .perf_event_enable = perf_sysenter_enable, \
> - .perf_event_disable = perf_sysenter_disable,
> -
> -#define TRACE_SYS_EXIT_PERF_INIT(sname) \
> - .perf_event_enable = perf_sysexit_enable, \
> - .perf_event_disable = perf_sysexit_disable,
> -#else
> -#define TRACE_SYS_ENTER_PERF(sname)
> -#define TRACE_SYS_ENTER_PERF_INIT(sname)
> -#define TRACE_SYS_EXIT_PERF(sname)
> -#define TRACE_SYS_EXIT_PERF_INIT(sname)
> -#endif /* CONFIG_PERF_EVENTS */
> -
> #ifdef CONFIG_FTRACE_SYSCALLS
> #define __SC_STR_ADECL1(t, a) #a
> #define __SC_STR_ADECL2(t, a, ...) #a, __SC_STR_ADECL1(__VA_ARGS__)
> @@ -134,7 +118,8 @@ struct perf_event_attr;
> #define __SC_STR_TDECL5(t, a, ...) #t, __SC_STR_TDECL4(__VA_ARGS__)
> #define __SC_STR_TDECL6(t, a, ...) #t, __SC_STR_TDECL5(__VA_ARGS__)
>
> -extern struct ftrace_event_class event_class_syscalls;
> +extern struct ftrace_event_class event_class_syscall_enter;
> +extern struct ftrace_event_class event_class_syscall_exit;
>
> #define SYSCALL_TRACE_ENTER_EVENT(sname) \
> static const struct syscall_metadata __syscall_meta_##sname; \
> @@ -148,14 +133,11 @@ extern struct ftrace_event_class event_class_syscalls;
> __attribute__((section("_ftrace_events"))) \
> event_enter_##sname = { \
> .name = "sys_enter"#sname, \
> - .class = &event_class_syscalls, \
> + .class = &event_class_syscall_enter, \
> .event = &enter_syscall_print_##sname, \
> .raw_init = init_syscall_trace, \
> .define_fields = syscall_enter_define_fields, \
> - .regfunc = reg_event_syscall_enter, \
> - .unregfunc = unreg_event_syscall_enter, \
> .data = (void *)&__syscall_meta_##sname,\
> - TRACE_SYS_ENTER_PERF_INIT(sname) \
> }
>
> #define SYSCALL_TRACE_EXIT_EVENT(sname) \
> @@ -170,14 +152,11 @@ extern struct ftrace_event_class event_class_syscalls;
> __attribute__((section("_ftrace_events"))) \
> event_exit_##sname = { \
> .name = "sys_exit"#sname, \
> - .class = &event_class_syscalls, \
> + .class = &event_class_syscall_exit, \
> .event = &exit_syscall_print_##sname, \
> .raw_init = init_syscall_trace, \
> .define_fields = syscall_exit_define_fields, \
> - .regfunc = reg_event_syscall_exit, \
> - .unregfunc = unreg_event_syscall_exit, \
> .data = (void *)&__syscall_meta_##sname,\
> - TRACE_SYS_EXIT_PERF_INIT(sname) \
> }
>
> #define SYSCALL_METADATA(sname, nb) \
> diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
> index c04988a..5876b77 100644
> --- a/include/linux/tracepoint.h
> +++ b/include/linux/tracepoint.h
> @@ -173,13 +173,21 @@ extern void tracepoint_update_probe_range(struct tracepoint *begin,
> { } \
> static inline void trace_##name(proto) \
> { } \
> + static inline int register_trace_##name(void (*probe)(proto)) \
> + { \
> + return -ENOSYS; \
> + } \
> + static inline int unregister_trace_##name(void (*probe)(proto)) \
> + { \
> + return -ENOSYS; \
> + } \
> static inline int \
> - register_trace_##name(void (*probe)(proto), void *data) \
> + register_trace_##name##_data(void (*probe)(proto), void *data) \
> { \
> return -ENOSYS; \
> } \
> static inline int \
> - unregister_trace_##name(void (*probe)(proto), void *data) \
> + unregister_trace_##name##_data(void (*probe)(proto), void *data) \
> { \
> return -ENOSYS; \
> }
> diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
> index 0921a8f..62fe622 100644
> --- a/include/trace/ftrace.h
> +++ b/include/trace/ftrace.h
> @@ -381,53 +381,6 @@ static inline notrace int ftrace_get_offsets_##call( \
>
> #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
>
> -#ifdef CONFIG_PERF_EVENTS
> -
> -/*
> - * Generate the functions needed for tracepoint perf_event support.
> - *
> - * NOTE: The insertion profile callback (ftrace_profile_<call>) is defined later
> - *
> - * static int ftrace_profile_enable_<call>(void)
> - * {
> - * return register_trace_<call>(ftrace_profile_<call>);
> - * }
> - *
> - * static void ftrace_profile_disable_<call>(void)
> - * {
> - * unregister_trace_<call>(ftrace_profile_<call>);
> - * }
> - *
> - */
> -
> -#undef DECLARE_EVENT_CLASS
> -#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print)
> -
> -#undef DEFINE_EVENT
> -#define DEFINE_EVENT(template, name, proto, args) \
> - \
> -static void perf_trace_##name(proto); \
> - \
> -static notrace int \
> -perf_trace_enable_##name(struct ftrace_event_call *unused) \
> -{ \
> - return register_trace_##name(perf_trace_##name); \
> -} \
> - \
> -static notrace void \
> -perf_trace_disable_##name(struct ftrace_event_call *unused) \
> -{ \
> - unregister_trace_##name(perf_trace_##name); \
> -}
> -
> -#undef DEFINE_EVENT_PRINT
> -#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
> - DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
> -
> -#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
> -
> -#endif /* CONFIG_PERF_EVENTS */
> -
> /*
> * Stage 4 of the trace events.
> *
> @@ -468,16 +421,6 @@ perf_trace_disable_##name(struct ftrace_event_call *unused) \
> * event, irq_flags, pc);
> * }
> *
> - * static int ftrace_raw_reg_event_<call>(struct ftrace_event_call *unused)
> - * {
> - * return register_trace_<call>(ftrace_raw_event_<call>);
> - * }
> - *
> - * static void ftrace_unreg_event_<call>(struct ftrace_event_call *unused)
> - * {
> - * unregister_trace_<call>(ftrace_raw_event_<call>);
> - * }
> - *
> * static struct trace_event ftrace_event_type_<call> = {
> * .trace = ftrace_raw_output_<call>, <-- stage 2
> * };
> @@ -504,11 +447,15 @@ perf_trace_disable_##name(struct ftrace_event_call *unused) \
>
> #ifdef CONFIG_PERF_EVENTS
>
> +#define _TRACE_PERF_PROTO(call, proto) \
> + static notrace void \
> + perf_trace_##call(proto, struct ftrace_event_call *event);
> +
> #define _TRACE_PERF_INIT(call) \
> - .perf_event_enable = perf_trace_enable_##call, \
> - .perf_event_disable = perf_trace_disable_##call,
> + .perf_probe = perf_trace_##call,
>
> #else
> +#define _TRACE_PERF_PROTO(call, proto)
> #define _TRACE_PERF_INIT(call)
> #endif /* CONFIG_PERF_EVENTS */
>
> @@ -542,8 +489,8 @@ perf_trace_disable_##name(struct ftrace_event_call *unused) \
> #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
> \
> static notrace void \
> -ftrace_raw_event_id_##call(struct ftrace_event_call *event_call, \
> - proto) \
> +ftrace_raw_event_##call(proto, \
> + struct ftrace_event_call *event_call) \
> { \
> struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
> struct ring_buffer_event *event; \
> @@ -578,23 +525,6 @@ ftrace_raw_event_id_##call(struct ftrace_event_call *event_call, \
> #undef DEFINE_EVENT
> #define DEFINE_EVENT(template, call, proto, args) \
> \
> -static notrace void ftrace_raw_event_##call(proto) \
> -{ \
> - ftrace_raw_event_id_##template(&event_##call, args); \
> -} \
> - \
> -static notrace int \
> -ftrace_raw_reg_event_##call(struct ftrace_event_call *unused) \
> -{ \
> - return register_trace_##call(ftrace_raw_event_##call); \
> -} \
> - \
> -static notrace void \
> -ftrace_raw_unreg_event_##call(struct ftrace_event_call *unused) \
> -{ \
> - unregister_trace_##call(ftrace_raw_event_##call); \
> -} \
> - \
> static struct trace_event ftrace_event_type_##call = { \
> .trace = ftrace_raw_output_##call, \
> };
> @@ -618,9 +548,12 @@ static struct trace_event ftrace_event_type_##call = { \
>
> #undef DECLARE_EVENT_CLASS
> #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
> +_TRACE_PERF_PROTO(call, PARAMS(proto)); \
> static const char print_fmt_##call[] = print; \
> static struct ftrace_event_class __used event_class_##call = { \
> - .system = __stringify(TRACE_SYSTEM) \
> + .system = __stringify(TRACE_SYSTEM), \
> + .probe = ftrace_raw_event_##call, \
> + _TRACE_PERF_INIT(call) \
> }
>
> #undef DEFINE_EVENT
> @@ -633,11 +566,8 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
> .class = &event_class_##template, \
> .event = &ftrace_event_type_##call, \
> .raw_init = trace_event_raw_init, \
> - .regfunc = ftrace_raw_reg_event_##call, \
> - .unregfunc = ftrace_raw_unreg_event_##call, \
> .print_fmt = print_fmt_##template, \
> .define_fields = ftrace_define_fields_##template, \
> - _TRACE_PERF_INIT(call) \
> }
>
> #undef DEFINE_EVENT_PRINT
> @@ -651,12 +581,7 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
> .name = #call, \
> .class = &event_class_##template, \
> .event = &ftrace_event_type_##call, \
> - .raw_init = trace_event_raw_init, \
> - .regfunc = ftrace_raw_reg_event_##call, \
> - .unregfunc = ftrace_raw_unreg_event_##call, \
> .print_fmt = print_fmt_##call, \
> - .define_fields = ftrace_define_fields_##template, \
> - _TRACE_PERF_INIT(call) \
> }
>
> #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
> @@ -756,8 +681,7 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
> #undef DECLARE_EVENT_CLASS
> #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
> static notrace void \
> -perf_trace_templ_##call(struct ftrace_event_call *event_call, \
> - proto) \
> +perf_trace_##call(proto, struct ftrace_event_call *event_call) \
> { \
> struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
> struct ftrace_raw_##call *entry; \
> @@ -792,13 +716,7 @@ perf_trace_templ_##call(struct ftrace_event_call *event_call, \
> }
>
> #undef DEFINE_EVENT
> -#define DEFINE_EVENT(template, call, proto, args) \
> -static notrace void perf_trace_##call(proto) \
> -{ \
> - struct ftrace_event_call *event_call = &event_##call; \
> - \
> - perf_trace_templ_##template(event_call, args); \
> -}
> +#define DEFINE_EVENT(template, call, proto, args)
>
> #undef DEFINE_EVENT_PRINT
> #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \
> diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
> index 81f691e..95df5a7 100644
> --- a/kernel/trace/trace_event_perf.c
> +++ b/kernel/trace/trace_event_perf.c
> @@ -44,7 +44,12 @@ static int perf_trace_event_enable(struct ftrace_event_call *event)
> rcu_assign_pointer(perf_trace_buf_nmi, buf);
> }
>
> - ret = event->perf_event_enable(event);
> + if (event->class->reg)
> + ret = event->class->reg(event, TRACE_REG_PERF_REGISTER);
> + else
> + ret = tracepoint_probe_register(event->name,
> + event->class->perf_probe,
> + event);
> if (!ret) {
> total_ref_count++;
> return 0;
> @@ -70,7 +75,8 @@ int perf_trace_enable(int event_id)
>
> mutex_lock(&event_mutex);
> list_for_each_entry(event, &ftrace_events, list) {
> - if (event->id == event_id && event->perf_event_enable &&
> + if (event->id == event_id &&
> + event->class && event->class->perf_probe &&
> try_module_get(event->mod)) {
> ret = perf_trace_event_enable(event);
> break;
> @@ -88,7 +94,10 @@ static void perf_trace_event_disable(struct ftrace_event_call *event)
> if (--event->perf_refcount > 0)
> return;
>
> - event->perf_event_disable(event);
> + if (event->class->reg)
> + event->class->reg(event, TRACE_REG_PERF_UNREGISTER);
> + else
> + tracepoint_probe_unregister(event->name, event->class->perf_probe, event);
>
> if (!--total_ref_count) {
> buf = perf_trace_buf;
> diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
> index f6893cc..f84cfcb 100644
> --- a/kernel/trace/trace_events.c
> +++ b/kernel/trace/trace_events.c
> @@ -126,13 +126,23 @@ static int ftrace_event_enable_disable(struct ftrace_event_call *call,
> if (call->enabled) {
> call->enabled = 0;
> tracing_stop_cmdline_record();
> - call->unregfunc(call);
> + if (call->class->reg)
> + call->class->reg(call, TRACE_REG_UNREGISTER);
> + else
> + tracepoint_probe_unregister(call->name,
> + call->class->probe,
> + call);
> }
> break;
> case 1:
> if (!call->enabled) {
> tracing_start_cmdline_record();
> - ret = call->regfunc(call);
> + if (call->class->reg)
> + ret = call->class->reg(call, TRACE_REG_REGISTER);
> + else
> + ret = tracepoint_probe_register(call->name,
> + call->class->probe,
> + call);
> if (ret) {
> tracing_stop_cmdline_record();
> pr_info("event trace: Could not enable event "
> @@ -170,7 +180,8 @@ static int __ftrace_set_clr_event(const char *match, const char *sub,
> mutex_lock(&event_mutex);
> list_for_each_entry(call, &ftrace_events, list) {
>
> - if (!call->name || !call->regfunc)
> + if (!call->name || !call->class ||
> + (!call->class->probe && !call->class->reg))
> continue;
>
> if (match &&
> @@ -296,7 +307,7 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
> * The ftrace subsystem is for showing formats only.
> * They can not be enabled or disabled via the event files.
> */
> - if (call->regfunc)
> + if (call->class && (call->class->probe || call->class->reg))
> return call;
> }
>
> @@ -449,7 +460,8 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
>
> mutex_lock(&event_mutex);
> list_for_each_entry(call, &ftrace_events, list) {
> - if (!call->name || !call->regfunc)
> + if (!call->name || !call->class ||
> + (!call->class->probe && !call->class->reg))
> continue;
>
> if (system && strcmp(call->class->system, system) != 0)
> @@ -934,11 +946,11 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
> return -1;
> }
>
> - if (call->regfunc)
> + if (call->class->probe || call->class->reg)
> trace_create_file("enable", 0644, call->dir, call,
> enable);
>
> - if (call->id && call->perf_event_enable)
> + if (call->id && (call->class->perf_probe || call->class->reg))
> trace_create_file("id", 0444, call->dir, call,
> id);
>
> diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
> index eda220b..f8af21a 100644
> --- a/kernel/trace/trace_kprobe.c
> +++ b/kernel/trace/trace_kprobe.c
> @@ -202,6 +202,7 @@ struct trace_probe {
> unsigned long nhit;
> unsigned int flags; /* For TP_FLAG_* */
> const char *symbol; /* symbol name */
> + struct ftrace_event_class class;
> struct ftrace_event_call call;
> struct trace_event event;
> unsigned int nr_args;
> @@ -323,6 +324,7 @@ static struct trace_probe *alloc_trace_probe(const char *group,
> goto error;
> }
>
> + tp->call.class = &tp->class;
> tp->call.name = kstrdup(event, GFP_KERNEL);
> if (!tp->call.name)
> goto error;
> @@ -332,8 +334,8 @@ static struct trace_probe *alloc_trace_probe(const char *group,
> goto error;
> }
>
> - tp->call.class->system = kstrdup(group, GFP_KERNEL);
> - if (!tp->call.class->system)
> + tp->class.system = kstrdup(group, GFP_KERNEL);
> + if (!tp->class.system)
> goto error;
>
> INIT_LIST_HEAD(&tp->list);
> @@ -1302,6 +1304,26 @@ static void probe_perf_disable(struct ftrace_event_call *call)
> }
> #endif /* CONFIG_PERF_EVENTS */
>
> +static __kprobes
> +int kprobe_register(struct ftrace_event_call *event, enum trace_reg type)
> +{
> + switch (type) {
> + case TRACE_REG_REGISTER:
> + return probe_event_enable(event);
> + case TRACE_REG_UNREGISTER:
> + probe_event_disable(event);
> + return 0;
> +
> +#ifdef CONFIG_PERF_EVENTS
> + case TRACE_REG_PERF_REGISTER:
> + return probe_perf_enable(event);
> + case TRACE_REG_PERF_UNREGISTER:
> + probe_perf_disable(event);
> + return 0;
> +#endif
> + }
> + return 0;
> +}
>
> static __kprobes
> int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs)
> @@ -1355,13 +1377,7 @@ static int register_probe_event(struct trace_probe *tp)
> return -ENODEV;
> }
> call->enabled = 0;
> - call->regfunc = probe_event_enable;
> - call->unregfunc = probe_event_disable;
> -
> -#ifdef CONFIG_PERF_EVENTS
> - call->perf_event_enable = probe_perf_enable;
> - call->perf_event_disable = probe_perf_disable;
> -#endif
> + call->class->reg = kprobe_register;
> call->data = tp;
> ret = trace_add_event_call(call);
> if (ret) {
> diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
> index 31fc95a..c92934d 100644
> --- a/kernel/trace/trace_syscalls.c
> +++ b/kernel/trace/trace_syscalls.c
> @@ -14,8 +14,19 @@ static int sys_refcount_exit;
> static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls);
> static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls);
>
> -struct ftrace_event_class event_class_syscalls = {
> - .system = "syscalls"
> +static int syscall_enter_register(struct ftrace_event_call *event,
> + enum trace_reg type);
> +static int syscall_exit_register(struct ftrace_event_call *event,
> + enum trace_reg type);
> +
> +struct ftrace_event_class event_class_syscall_enter = {
> + .system = "syscalls",
> + .reg = syscall_enter_register
> +};
> +
> +struct ftrace_event_class event_class_syscall_exit = {
> + .system = "syscalls",
> + .reg = syscall_exit_register
> };
>
> extern unsigned long __start_syscalls_metadata[];
> @@ -586,3 +597,44 @@ void perf_sysexit_disable(struct ftrace_event_call *call)
>
> #endif /* CONFIG_PERF_EVENTS */
>
> +static int syscall_enter_register(struct ftrace_event_call *event,
> + enum trace_reg type)
> +{
> + switch (type) {
> + case TRACE_REG_REGISTER:
> + return reg_event_syscall_enter(event);
> + case TRACE_REG_UNREGISTER:
> + unreg_event_syscall_enter(event);
> + return 0;
> +
> +#ifdef CONFIG_PERF_EVENTS
> + case TRACE_REG_PERF_REGISTER:
> + return perf_sysenter_enable(event);
> + case TRACE_REG_PERF_UNREGISTER:
> + perf_sysenter_disable(event);
> + return 0;
> +#endif
> + }
> + return 0;
> +}
> +
> +static int syscall_exit_register(struct ftrace_event_call *event,
> + enum trace_reg type)
> +{
> + switch (type) {
> + case TRACE_REG_REGISTER:
> + return reg_event_syscall_exit(event);
> + case TRACE_REG_UNREGISTER:
> + unreg_event_syscall_exit(event);
> + return 0;
> +
> +#ifdef CONFIG_PERF_EVENTS
> + case TRACE_REG_PERF_REGISTER:
> + return perf_sysexit_enable(event);
> + case TRACE_REG_PERF_UNREGISTER:
> + perf_sysexit_disable(event);
> + return 0;
> +#endif
> + }
> + return 0;
> +}
> --
> 1.7.0
>
>
--
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@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists