diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index cdc30111d2f8d0b1b16c832d4aeb481ea4e68e80..d16da3e53bc732710e7ea05e3e500d0f1784a94c 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h @@ -7,6 +7,7 @@ #include #include #include +#include struct trace_array; struct trace_buffer; @@ -232,6 +233,7 @@ enum { TRACE_EVENT_FL_IGNORE_ENABLE_BIT, TRACE_EVENT_FL_WAS_ENABLED_BIT, TRACE_EVENT_FL_USE_CALL_FILTER_BIT, + TRACE_EVENT_FL_TRACEPOINT_BIT, }; /* @@ -244,6 +246,7 @@ enum { * (used for module unloading, if a module event is enabled, * it is best to clear the buffers that used it). * USE_CALL_FILTER - For ftrace internal events, don't use file filter + * TRACEPOINT - Event is a tracepoint */ enum { TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT), @@ -252,12 +255,17 @@ enum { TRACE_EVENT_FL_IGNORE_ENABLE = (1 << TRACE_EVENT_FL_IGNORE_ENABLE_BIT), TRACE_EVENT_FL_WAS_ENABLED = (1 << TRACE_EVENT_FL_WAS_ENABLED_BIT), TRACE_EVENT_FL_USE_CALL_FILTER = (1 << TRACE_EVENT_FL_USE_CALL_FILTER_BIT), + TRACE_EVENT_FL_TRACEPOINT = (1 << TRACE_EVENT_FL_TRACEPOINT_BIT), }; struct ftrace_event_call { struct list_head list; struct ftrace_event_class *class; - char *name; + union { + char *name; + /* Set TRACE_EVENT_FL_TRACEPOINT flag when using "tp" */ + struct tracepoint *tp; + }; struct trace_event event; const char *print_fmt; struct event_filter *filter; @@ -271,6 +279,7 @@ struct ftrace_event_call { * bit 3: ftrace internal event (do not enable) * bit 4: Event was enabled by module * bit 5: use call filter rather than file filter + * bit 6: Event is a tracepoint */ int flags; /* static flags of different events */ @@ -283,6 +292,15 @@ struct ftrace_event_call { #endif }; +static inline const char * +ftrace_event_name(struct ftrace_event_call *call) +{ + if (call->flags & TRACE_EVENT_FL_TRACEPOINT) + return call->tp ? call->tp->name : NULL; + else + return call->name; +} + struct trace_array; struct ftrace_subsystem_dir; @@ -353,7 +371,7 @@ struct ftrace_event_file { #define __TRACE_EVENT_FLAGS(name, value) \ static int __init trace_init_flags_##name(void) \ { \ - event_##name.flags = value; \ + event_##name.flags |= value; \ return 0; \ } \ early_initcall(trace_init_flags_##name); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 697ceb70a9a9107689c1fc98f8599552314a9fd8..a4a0588c5397f5e0057a3565a45a60ed3d92c4d9 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -119,8 +119,10 @@ extern struct trace_event_functions exit_syscall_print_funcs; static struct syscall_metadata __syscall_meta_##sname; \ static struct ftrace_event_call __used \ event_enter_##sname = { \ - .name = "sys_enter"#sname, \ .class = &event_class_syscall_enter, \ + { \ + .name = "sys_enter"#sname, \ + }, \ .event.funcs = &enter_syscall_print_funcs, \ .data = (void *)&__syscall_meta_##sname,\ .flags = TRACE_EVENT_FL_CAP_ANY, \ @@ -133,8 +135,10 @@ extern struct trace_event_functions exit_syscall_print_funcs; static struct syscall_metadata __syscall_meta_##sname; \ static struct ftrace_event_call __used \ event_exit_##sname = { \ - .name = "sys_exit"#sname, \ .class = &event_class_syscall_exit, \ + { \ + .name = "sys_exit"#sname, \ + }, \ .event.funcs = &exit_syscall_print_funcs, \ .data = (void *)&__syscall_meta_##sname,\ .flags = TRACE_EVENT_FL_CAP_ANY, \ diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index 812b2553dfd84c78d4c4eab4e580b554e0edf2ab..9d30ee469c2aed19e9444de08ba37b0978bd1a27 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -6,7 +6,7 @@ * * See Documentation/trace/tracepoints.txt. * - * (C) Copyright 2008 Mathieu Desnoyers + * Copyright (C) 2008-2014 Mathieu Desnoyers * * Heavily inspired from the Linux Kernel Markers. * @@ -21,6 +21,7 @@ struct module; struct tracepoint; +struct notifier_block; struct tracepoint_func { void *func; @@ -35,31 +36,38 @@ struct tracepoint { struct tracepoint_func __rcu *funcs; }; -/* - * Connect a probe to a tracepoint. - * Internal API, should not be used directly. - */ -extern int tracepoint_probe_register(const char *name, void *probe, void *data); - -/* - * Disconnect a probe from a tracepoint. - * Internal API, should not be used directly. - */ extern int -tracepoint_probe_unregister(const char *name, void *probe, void *data); +tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data); +extern int +tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data); +extern void +for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv), + void *priv); #ifdef CONFIG_MODULES struct tp_module { struct list_head list; - unsigned int num_tracepoints; - struct tracepoint * const *tracepoints_ptrs; + struct module *mod; }; + 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); #else static inline bool trace_module_has_bad_taint(struct module *mod) { return false; } +static inline +int register_tracepoint_module_notifier(struct notifier_block *nb) +{ + return 0; +} +static inline +int unregister_tracepoint_module_notifier(struct notifier_block *nb) +{ + return 0; +} #endif /* CONFIG_MODULES */ /* @@ -72,6 +80,11 @@ static inline void tracepoint_synchronize_unregister(void) synchronize_sched(); } +#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS +extern void syscall_regfunc(void); +extern void syscall_unregfunc(void); +#endif /* CONFIG_HAVE_SYSCALL_TRACEPOINTS */ + #define PARAMS(args...) args #endif /* _LINUX_TRACEPOINT_H */ @@ -160,14 +173,14 @@ static inline void tracepoint_synchronize_unregister(void) static inline int \ register_trace_##name(void (*probe)(data_proto), void *data) \ { \ - return tracepoint_probe_register(#name, (void *)probe, \ - data); \ + return tracepoint_probe_register(&__tracepoint_##name, \ + (void *)probe, data); \ } \ static inline int \ unregister_trace_##name(void (*probe)(data_proto), void *data) \ { \ - return tracepoint_probe_unregister(#name, (void *)probe, \ - data); \ + return tracepoint_probe_unregister(&__tracepoint_##name,\ + (void *)probe, data); \ } \ static inline void \ check_trace_callback_type_##name(void (*cb)(data_proto)) \ diff --git a/include/trace/events/syscalls.h b/include/trace/events/syscalls.h index 5a4c04a75b3d369fc9665eca1deee12a2d442d61..14e49c7981359ccdac1e2d9d87a3c284e7c682f3 100644 --- a/include/trace/events/syscalls.h +++ b/include/trace/events/syscalls.h @@ -13,9 +13,6 @@ #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS -extern void syscall_regfunc(void); -extern void syscall_unregfunc(void); - TRACE_EVENT_FN(sys_enter, TP_PROTO(struct pt_regs *regs, long id), diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index 8765126b328ce4220d3c61af8c655f0226f29564..0a1a4f7caf095154c43aa901de0eca61be2b0208 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h @@ -470,10 +470,13 @@ static inline notrace int ftrace_get_offsets_##call( \ * }; * * static struct ftrace_event_call event_ = { - * .name = "", * .class = event_class_