perf/tracing: fixes and add function trace to perf
Subsystems (3)
Steven Rostedt
maintainerIngo,
Please pull the latest tip/perf/core tree, which can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
tip/perf/core
Head SHA1: 5500fa51199aee770ce53718853732600543619e
Andrey Vagin (1):
tracing: Don't print an extra separator of flags
Jiri Olsa (7):
ftrace: Add enable/disable ftrace_ops control interface ftrace, perf: Add open/close tracepoint perf registration actions ftrace, perf: Add add/del tracepoint perf registration actions
ftrace: Add FTRACE_ENTRY_REG macro to allow event registration ftrace, perf: Add support to use function tracepoint in perf
ftrace: Allow to specify filter field type for ftrace events ftrace, perf: Add filter support for function trace event
Steven Rostedt (1):
tracing: Don't use p->len field to determine output in __print_*() functions
----
include/linux/ftrace.h | 73 ++++++++++++- include/linux/ftrace_event.h | 9 ++- include/linux/perf_event.h | 3 + kernel/trace/ftrace.c | 117 +++++++++++++++++++-- kernel/trace/trace.h | 38 +++++-- kernel/trace/trace_entries.h | 54 +++++++--- kernel/trace/trace_event_perf.c | 208 ++++++++++++++++++++++++++++------- kernel/trace/trace_events.c | 12 ++- kernel/trace/trace_events_filter.c | 168 ++++++++++++++++++++++++++++- kernel/trace/trace_export.c | 64 ++++++++---- kernel/trace/trace_kprobe.c | 8 ++- kernel/trace/trace_output.c | 12 ++- kernel/trace/trace_syscalls.c | 18 +++- 13 files changed, 667 insertions(+), 117 deletions(-)
Steven Rostedt
maintainerPATCH 1/9 tracing: Dont print an extra separator of flags
From: Andrey Vagin <[email protected]>
If __print_flags() is used after another __print_*() function, the temp seq_file buffer will not be empty on entry, and the delimiter will be printed even though there's just one field. We get something like:
|S
instead of just:
S
This is because the length of the temp seq buffer is used to determine if the delimiter is printed or not. But this algorithm fails when the seq buffer is not empty on entry, and the delimiter will be printed because it thinks that a previous field was already printed.
--- kernel/trace/trace_output.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
kernel/trace/trace_output.c +4 -2
@@ -300,7 +300,7 @@ ftrace_print_flags_seq(struct trace_seq *p, const char *delim,unsigned long mask;const char *str;const char *ret = p->buffer + p->len; -int i; +int i, first =1 ;for (i =0 ; flag_array[i].name && flags; i++) {
@@ -310,8 +310,10 @@ ftrace_print_flags_seq(struct trace_seq *p, const char *delim, str = flag_array[i].name; flags &= ~mask; -if (p->len && delim) +if (!first && delim)trace_seq_puts (p, delim); +else + first =0 ;trace_seq_puts (p, str); }
Signature · 1 line
1.7.8.3
Steven Rostedt
maintainerPATCH 2/9 tracing: Dont use p->len field to determine output in __print_*() functions
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
If more than one __print_*() function is used in a tracepoint (__print_flags(), __print_symbols(), etc), then the temp seq buffer will not be zero on entry. Using the temp seq buffer's length to know if data has been printed or not in the current function is incorrect and may produce incorrect results.
Currently, no in-tree tracepoint causes this bug, but new ones may be created.
--- kernel/trace/trace_output.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
kernel/trace/trace_output.c +3 -3
@@ -319,7 +319,7 @@ ftrace_print_flags_seq(struct trace_seq *p, const char *delim,/* check for left over flags */ if (flags) { -if (p->len && delim) +if (!first && delim)trace_seq_puts (p, delim);trace_seq_printf (p,"0x%lx" , flags); }
@@ -346,7 +346,7 @@ ftrace_print_symbols_seq(struct trace_seq *p, unsigned long val,break ; } -if (!p->len) +if (ret == (const char *)(p->buffer + p->len))trace_seq_printf (p,"0x%lx" , val);trace_seq_putc (p,0 );
@@ -372,7 +372,7 @@ ftrace_print_symbols_seq_u64(struct trace_seq *p, unsigned long long val,break ; } -if (!p->len) +if (ret == (const char *)(p->buffer + p->len))trace_seq_printf (p,"0x%llx" , val);trace_seq_putc (p,0 );
Signature · 1 line
1.7.8.3
Steven Rostedt
maintainerPATCH 3/9 ftrace: Add enable/disable ftrace_ops control interface
In reply to Steven RostedtFrom: Jiri Olsa <[email protected]>
Adding a way to temporarily enable/disable ftrace_ops. The change follows the same way as 'global' ftrace_ops are done.
Introducing 2 global ftrace_ops - control_ops and ftrace_control_list which take over all ftrace_ops registered with FTRACE_OPS_FL_CONTROL flag. In addition new per cpu flag called 'disabled' is also added to ftrace_ops to provide the control information for each cpu.
When ftrace_ops with FTRACE_OPS_FL_CONTROL is registered, it is set as disabled for all cpus.
The ftrace_control_list contains all the registered 'control' ftrace_ops. The control_ops provides function which iterates ftrace_control_list and does the check for 'disabled' flag on current cpu.
Adding 3 inline functions:
ftrace_function_local_disable/ftrace_function_local_enable
- enable/disable the ftrace_ops on current cpu ftrace_function_local_disabled
- get disabled ftrace_ops::disabled value for current cpu
--- include/linux/ftrace.h | 66 ++++++++++++++++++++++++++++ kernel/trace/ftrace.c | 111 +++++++++++++++++++++++++++++++++++++++++++++--- kernel/trace/trace.h | 2 + 3 files changed, 172 insertions(+), 7 deletions(-)
include/linux/ftrace.h +66 -0
@@ -31,16 +31,33 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,typedef void (*ftrace_func_t )(unsigned long ip,unsigned long parent_ip); +/* +* FTRACE_OPS_FL_* bits denote the state of ftrace_ops struct and are +* set in the flags member. +* +* ENABLED - set/unset when ftrace_ops is registered/unregistered +* GLOBAL - set manualy by ftrace_ops user to denote the ftrace_ops +* is part of the global tracers sharing the same filter +* via set_ftrace_* debugfs files. +* DYNAMIC - set when ftrace_ops is registered to denote dynamically +* allocated ftrace_ops which need special care +* CONTROL - set manualy by ftrace_ops user to denote the ftrace_ops +* could be controled by following calls: +* ftrace_function_local_enable +* ftrace_function_local_disable +*/ enum {FTRACE_OPS_FL_ENABLED =1 <<0 ,FTRACE_OPS_FL_GLOBAL =1 <<1 ,FTRACE_OPS_FL_DYNAMIC =1 <<2 , +FTRACE_OPS_FL_CONTROL =1 <<3 , };struct ftrace_ops {ftrace_func_t func;struct ftrace_ops *next;unsigned long flags; +int __percpu *disabled;#ifdef CONFIG_DYNAMIC_FTRACE struct ftrace_hash *notrace_hash;struct ftrace_hash *filter_hash;
@@ -97,6 +114,55 @@ int register_ftrace_function(struct ftrace_ops *ops);int unregister_ftrace_function (struct ftrace_ops *ops);void clear_ftrace_function (void ); +/** +* ftrace_function_local_enable - enable controlled ftrace_ops on current cpu +* +* This function enables tracing on current cpu by decreasing +* the per cpu control variable. +* It must be called with preemption disabled and only on ftrace_ops +* registered with FTRACE_OPS_FL_CONTROL. If called without preemption +* disabled, this_cpu_ptr will complain when CONFIG_DEBUG_PREEMPT is enabled. +*/ +static inline void ftrace_function_local_enable (struct ftrace_ops *ops) +{ +if (WARN_ON_ONCE (!(ops->flags &FTRACE_OPS_FL_CONTROL ))) +return ; + + (*this_cpu_ptr (ops->disabled))--; +} + +/** +* ftrace_function_local_disable - enable controlled ftrace_ops on current cpu +* +* This function enables tracing on current cpu by decreasing +* the per cpu control variable. +* It must be called with preemption disabled and only on ftrace_ops +* registered with FTRACE_OPS_FL_CONTROL. If called without preemption +* disabled, this_cpu_ptr will complain when CONFIG_DEBUG_PREEMPT is enabled. +*/ +static inline void ftrace_function_local_disable (struct ftrace_ops *ops) +{ +if (WARN_ON_ONCE (!(ops->flags &FTRACE_OPS_FL_CONTROL ))) +return ; + + (*this_cpu_ptr (ops->disabled))++; +} + +/** +* ftrace_function_local_disabled - returns ftrace_ops disabled value +* on current cpu +* +* This function returns value of ftrace_ops::disabled on current cpu. +* It must be called with preemption disabled and only on ftrace_ops +* registered with FTRACE_OPS_FL_CONTROL. If called without preemption +* disabled, this_cpu_ptr will complain when CONFIG_DEBUG_PREEMPT is enabled. +*/ +static inline int ftrace_function_local_disabled (struct ftrace_ops *ops) +{ +WARN_ON_ONCE (!(ops->flags &FTRACE_OPS_FL_CONTROL )); +return *this_cpu_ptr (ops->disabled); +} +extern void ftrace_stub (unsigned long a0,unsigned long a1);#else /* !CONFIG_FUNCTION_TRACER */
kernel/trace/ftrace.c +104 -7
166 lines not on this page · raw message
kernel/trace/trace.h +2 -0
@@ -288,6 +288,8 @@ struct tracer {/* for function tracing recursion */ #define TRACE_INTERNAL_BIT (1<<11)#define TRACE_GLOBAL_BIT (1<<12) +#define TRACE_CONTROL_BIT (1<<13) +/* * Abuse of the trace_recursion. * As we need a way to maintain state if we are tracing the function
Signature · 1 line
1.7.8.3
Steven Rostedt
maintainerPATCH 4/9 ftrace, perf: Add open/close tracepoint perf registration actions
In reply to Steven RostedtFrom: Jiri Olsa <[email protected]>
Adding TRACE_REG_PERF_OPEN and TRACE_REG_PERF_CLOSE to differentiate register/unregister from open/close actions.
The register/unregister actions are invoked for the first/last tracepoint user when opening/closing the event.
The open/close actions are invoked for each tracepoint user when opening/closing the event.
--- include/linux/ftrace_event.h | 6 +- kernel/trace/trace_event_perf.c | 116 +++++++++++++++++++++++++-------------- kernel/trace/trace_events.c | 10 ++- kernel/trace/trace_kprobe.c | 6 ++- kernel/trace/trace_syscalls.c | 14 +++- 5 files changed, 101 insertions(+), 51 deletions(-)
include/linux/ftrace_event.h +4 -2
@@ -146,6 +146,8 @@ enum trace_reg {TRACE_REG_UNREGISTER ,TRACE_REG_PERF_REGISTER ,TRACE_REG_PERF_UNREGISTER , +TRACE_REG_PERF_OPEN , + TRACE_REG_PERF_CLOSE, };struct ftrace_event_call ;
@@ -157,7 +159,7 @@ struct ftrace_event_class {void *perf_probe;#endif int (*reg)(struct ftrace_event_call *event, -enum trace_reg type); +enum trace_reg type,void *data);int (*define_fields)(struct ftrace_event_call *);struct list_head *(*get_fields)(struct ftrace_event_call *);struct list_head fields;
@@ -165,7 +167,7 @@ struct ftrace_event_class { };extern int ftrace_event_reg (struct ftrace_event_call *event, -enum trace_reg type); +enum trace_reg type,void *data);enum {TRACE_EVENT_FL_ENABLED_BIT ,
kernel/trace/trace_event_perf.c +75 -41
154 lines not on this page · raw message
kernel/trace/trace_events.c +7 -3
@@ -147,7 +147,8 @@ int trace_event_raw_init(struct ftrace_event_call *call) }EXPORT_SYMBOL_GPL (trace_event_raw_init); -int ftrace_event_reg (struct ftrace_event_call *call,enum trace_reg type) +int ftrace_event_reg (struct ftrace_event_call *call, +enum trace_reg type,void *data) {switch (type) {case TRACE_REG_REGISTER :
@@ -170,6 +171,9 @@ int ftrace_event_reg(struct ftrace_event_call *call, enum trace_reg type) call->class->perf_probe, call);return 0 ; +case TRACE_REG_PERF_OPEN : +case TRACE_REG_PERF_CLOSE : +return 0 ;#endif }return 0 ;
@@ -209,7 +213,7 @@ static int ftrace_event_enable_disable(struct ftrace_event_call *call,tracing_stop_cmdline_record (); call->flags &= ~TRACE_EVENT_FL_RECORDED_CMD ; } - call->class->reg (call,TRACE_REG_UNREGISTER ); + call->class->reg (call,TRACE_REG_UNREGISTER ,NULL ); }break ;case 1 :
@@ -218,7 +222,7 @@ static int ftrace_event_enable_disable(struct ftrace_event_call *call,tracing_start_cmdline_record (); call->flags |=TRACE_EVENT_FL_RECORDED_CMD ; } - ret = call->class->reg (call,TRACE_REG_REGISTER ); + ret = call->class->reg (call,TRACE_REG_REGISTER ,NULL );if (ret) {tracing_stop_cmdline_record (); pr_info("event trace: Could not enable event "
kernel/trace/trace_kprobe.c +5 -1
@@ -1892,7 +1892,8 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri,#endif /* CONFIG_PERF_EVENTS */ static __kprobes -int kprobe_register (struct ftrace_event_call *event,enum trace_reg type) +int kprobe_register (struct ftrace_event_call *event, +enum trace_reg type,void *data) {struct trace_probe *tp = (struct trace_probe *)event->data;
@@ -1909,6 +1910,9 @@ int kprobe_register(struct ftrace_event_call *event, enum trace_reg type)case TRACE_REG_PERF_UNREGISTER :disable_trace_probe (tp,TP_FLAG_PROFILE );return 0 ; +case TRACE_REG_PERF_OPEN : +case TRACE_REG_PERF_CLOSE : +return 0 ;#endif }return 0 ;
kernel/trace/trace_syscalls.c +10 -4
@@ -17,9 +17,9 @@ static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls); static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls);static int syscall_enter_register (struct ftrace_event_call *event, -enum trace_reg type); +enum trace_reg type,void *data);static int syscall_exit_register (struct ftrace_event_call *event, -enum trace_reg type); +enum trace_reg type,void *data);static int syscall_enter_define_fields (struct ftrace_event_call *call);static int syscall_exit_define_fields (struct ftrace_event_call *call);
@@ -649,7 +649,7 @@ 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) +enum trace_reg type,void *data) {switch (type) {case TRACE_REG_REGISTER :
@@ -664,13 +664,16 @@ static int syscall_enter_register(struct ftrace_event_call *event,case TRACE_REG_PERF_UNREGISTER :perf_sysenter_disable (event);return 0 ; +case TRACE_REG_PERF_OPEN : +case TRACE_REG_PERF_CLOSE : +return 0 ;#endif }return 0 ; }static int syscall_exit_register (struct ftrace_event_call *event, -enum trace_reg type) +enum trace_reg type,void *data) {switch (type) {case TRACE_REG_REGISTER :
@@ -685,6 +688,9 @@ static int syscall_exit_register(struct ftrace_event_call *event,case TRACE_REG_PERF_UNREGISTER :perf_sysexit_disable (event);return 0 ; +case TRACE_REG_PERF_OPEN : +case TRACE_REG_PERF_CLOSE : +return 0 ;#endif }return 0 ;
Signature · 1 line
1.7.8.3
Steven Rostedt
maintainerPATCH 5/9 ftrace, perf: Add add/del tracepoint perf registration actions
In reply to Steven RostedtFrom: Jiri Olsa <[email protected]>
Adding TRACE_REG_PERF_ADD and TRACE_REG_PERF_DEL to handle perf event schedule in/out actions.
The add action is invoked for when the perf event is scheduled in, while the del action is invoked when the event is scheduled out.
--- include/linux/ftrace_event.h | 2 ++ kernel/trace/trace_event_perf.c | 4 +++- kernel/trace/trace_events.c | 2 ++ kernel/trace/trace_kprobe.c | 2 ++ kernel/trace/trace_syscalls.c | 4 ++++ 5 files changed, 13 insertions(+), 1 deletions(-)
include/linux/ftrace_event.h +2 -0
@@ -148,6 +148,8 @@ enum trace_reg {TRACE_REG_PERF_UNREGISTER ,TRACE_REG_PERF_OPEN ,TRACE_REG_PERF_CLOSE , +TRACE_REG_PERF_ADD , + TRACE_REG_PERF_DEL, };struct ftrace_event_call ;
kernel/trace/trace_event_perf.c +3 -1
@@ -211,12 +211,14 @@ int perf_trace_add(struct perf_event *p_event, int flags) list =this_cpu_ptr (pcpu_list);hlist_add_head_rcu (&p_event->hlist_entry, list); -return 0 ; +return tp_event->class->reg (tp_event,TRACE_REG_PERF_ADD , p_event); }void perf_trace_del (struct perf_event *p_event,int flags) { +struct ftrace_event_call *tp_event = p_event->tp_event;hlist_del_rcu (&p_event->hlist_entry); + tp_event->class->reg (tp_event,TRACE_REG_PERF_DEL , p_event); } __kprobes void *perf_trace_buf_prepare(int size, unsigned short type,
kernel/trace/trace_events.c +2 -0
@@ -173,6 +173,8 @@ int ftrace_event_reg(struct ftrace_event_call *call,return 0 ;case TRACE_REG_PERF_OPEN :case TRACE_REG_PERF_CLOSE : +case TRACE_REG_PERF_ADD : +case TRACE_REG_PERF_DEL :return 0 ;#endif }
kernel/trace/trace_kprobe.c +2 -0
@@ -1912,6 +1912,8 @@ int kprobe_register(struct ftrace_event_call *event,return 0 ;case TRACE_REG_PERF_OPEN :case TRACE_REG_PERF_CLOSE : +case TRACE_REG_PERF_ADD : +case TRACE_REG_PERF_DEL :return 0 ;#endif }
kernel/trace/trace_syscalls.c +4 -0
@@ -666,6 +666,8 @@ static int syscall_enter_register(struct ftrace_event_call *event,return 0 ;case TRACE_REG_PERF_OPEN :case TRACE_REG_PERF_CLOSE : +case TRACE_REG_PERF_ADD : +case TRACE_REG_PERF_DEL :return 0 ;#endif }
@@ -690,6 +692,8 @@ static int syscall_exit_register(struct ftrace_event_call *event,return 0 ;case TRACE_REG_PERF_OPEN :case TRACE_REG_PERF_CLOSE : +case TRACE_REG_PERF_ADD : +case TRACE_REG_PERF_DEL :return 0 ;#endif }
Signature · 1 line
1.7.8.3
Steven Rostedt
maintainerPATCH 6/9 ftrace: Add FTRACE_ENTRY_REG macro to allow event registration
In reply to Steven RostedtFrom: Jiri Olsa <[email protected]>
Adding FTRACE_ENTRY_REG macro so particular ftrace entries could specify registration function and thus become accesible via perf.
This will be used in upcomming patch for function trace.
--- kernel/trace/trace.h | 4 ++++ kernel/trace/trace_export.c | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-)
kernel/trace/trace.h +4 -0
@@ -68,6 +68,10 @@ enum trace_type {#undef FTRACE_ENTRY_DUP#define FTRACE_ENTRY_DUP (name, name_struct, id, tstruct, printk) +#undef FTRACE_ENTRY_REG +#define FTRACE_ENTRY_REG (name, struct_name, id, tstruct, print, regfn) \ + FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print)) +#include "trace_entries.h" /*
kernel/trace/trace_export.c +16 -2
@@ -18,6 +18,14 @@#undef TRACE_SYSTEM#define TRACE_SYSTEM ftrace +/* +* The FTRACE_ENTRY_REG macro allows ftrace entry to define register +* function and thus become accesible via perf. +*/ +#undef FTRACE_ENTRY_REG +#define FTRACE_ENTRY_REG (name, struct_name, id, tstruct, print, regfn) \ + FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print)) +/* not needed for this file */ #undef __field_struct#define __field_struct (type, item)
@@ -152,13 +160,14 @@ ftrace_define_fields_##name(struct ftrace_event_call *event_call) \#undef F_printk #define F_printk(fmt, args...) #fmt ", " __stringify(args) -#undef FTRACE_ENTRY -#define FTRACE_ENTRY (call, struct_name, etype, tstruct, print) \ +#undef FTRACE_ENTRY_REG +#define FTRACE_ENTRY_REG (call, struct_name, etype, tstruct, print, regfn)\ \ struct ftrace_event_class event_class_ftrace_##call = { \ .system = __stringify(TRACE_SYSTEM), \ .define_fields = ftrace_define_fields_##call, \ .fields = LIST_HEAD_INIT(event_class_ftrace_##call.fields),\ + .reg = regfn, \ }; \ \ struct ftrace_event_call __used event_##call = { \
@@ -170,4 +179,9 @@ struct ftrace_event_call __used event_##call = { \ struct ftrace_event_call __used \ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call; +#undef FTRACE_ENTRY +#define FTRACE_ENTRY (call, struct_name, etype, tstruct, print) \ + FTRACE_ENTRY_REG(call, struct_name, etype, \ + PARAMS(tstruct), PARAMS(print), NULL) +#include "trace_entries.h"
Signature · 1 line
1.7.8.3
Steven Rostedt
maintainerPATCH 7/9 ftrace, perf: Add support to use function tracepoint in perf
In reply to Steven RostedtFrom: Jiri Olsa <[email protected]>
Adding perf registration support for the ftrace function event, so it is now possible to register it via perf interface.
The perf_event struct statically contains ftrace_ops as a handle for function tracer. The function tracer is registered/unregistered in open/close actions.
To be efficient, we enable/disable ftrace_ops each time the traced process is scheduled in/out (via TRACE_REG_PERF_(ADD|DELL) handlers). This way tracing is enabled only when the process is running. Intentionally using this way instead of the event's hw state PERF_HES_STOPPED, which would not disable the ftrace_ops.
It is now possible to use function trace within perf commands like:
perf record -e ftrace:function ls
perf stat -e ftrace:function ls
Allowed only for root.
--- include/linux/perf_event.h | 3 + kernel/trace/trace.h | 11 +++++ kernel/trace/trace_entries.h | 6 ++- kernel/trace/trace_event_perf.c | 86 +++++++++++++++++++++++++++++++++++++++ kernel/trace/trace_export.c | 5 ++ 5 files changed, 109 insertions(+), 2 deletions(-)
include/linux/perf_event.h +3 -0
@@ -859,6 +859,9 @@ struct perf_event {#ifdef CONFIG_EVENT_TRACING struct ftrace_event_call *tp_event;struct event_filter *filter; +#ifdef CONFIG_FUNCTION_TRACER +struct ftrace_ops ftrace_ops; +#endif #endif #ifdef CONFIG_CGROUP_PERF
kernel/trace/trace.h +11 -0
@@ -595,6 +595,8 @@ static inline int ftrace_trace_task(struct task_struct *task)static inline int ftrace_is_dead (void ) {return 0 ; }#endif +int ftrace_event_is_function (struct ftrace_event_call *call); +/* * struct trace_parser - servers for reading the user input separated by spaces * @cont: set if the input is not complete - no final space char was found
@@ -832,4 +834,13 @@ extern const char *__stop___trace_bprintk_fmt[]; FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print))#include "trace_entries.h" +#ifdef CONFIG_PERF_EVENTS +#ifdef CONFIG_FUNCTION_TRACER +int perf_ftrace_event_register (struct ftrace_event_call *call, +enum trace_reg type,void *data); +#else +#define perf_ftrace_event_register NULL +#endif /* CONFIG_FUNCTION_TRACER */ +#endif /* CONFIG_PERF_EVENTS */ +#endif /* _LINUX_KERNEL_TRACE_H */
kernel/trace/trace_entries.h +4 -2
@@ -55,7 +55,7 @@/* * Function trace entry - function address and parent function address: */ -FTRACE_ENTRY(function, ftrace_entry, +FTRACE_ENTRY_REG(function, ftrace_entry, TRACE_FN,
@@ -64,7 +64,9 @@ FTRACE_ENTRY(function, ftrace_entry, __field( unsigned long, parent_ip ) ), - F_printk(" %lx <-- %lx", __entry->ip, __entry->parent_ip) + F_printk(" %lx <-- %lx", __entry->ip, __entry->parent_ip), + +perf_ftrace_event_register );/* Function call entry */
kernel/trace/trace_event_perf.c +86 -0
95 lines not on this page · raw message
kernel/trace/trace_export.c +5 -0
@@ -184,4 +184,9 @@ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call;FTRACE_ENTRY_REG (call, struct_name, etype, \ PARAMS(tstruct), PARAMS(print), NULL) +int ftrace_event_is_function (struct ftrace_event_call *call) +{ +return call == &event_function; +} +#include "trace_entries.h"
Signature · 1 line
1.7.8.3
Steven Rostedt
maintainerPATCH 8/9 ftrace: Allow to specify filter field type for ftrace events
In reply to Steven RostedtFrom: Jiri Olsa <[email protected]>
Adding FILTER_TRACE_FN event field type for function tracepoint event, so it can be properly recognized within filtering code.
Currently all fields of ftrace subsystem events share the common field type FILTER_OTHER. Since the function trace fields need special care within the filtering code we need to recognize it properly, hence adding the FILTER_TRACE_FN event type.
Adding filter parameter to the FTRACE_ENTRY macro, to specify the filter field type for the event.
--- include/linux/ftrace_event.h | 1 + kernel/trace/trace.h | 23 +++++++++------- kernel/trace/trace_entries.h | 48 ++++++++++++++++++++++++--------- kernel/trace/trace_events_filter.c | 7 ++++- kernel/trace/trace_export.c | 51 +++++++++++++++++++---------------- 5 files changed, 83 insertions(+), 47 deletions(-)
include/linux/ftrace_event.h +1 -0
@@ -245,6 +245,7 @@ enum {FILTER_STATIC_STRING ,FILTER_DYN_STRING ,FILTER_PTR_STRING , + FILTER_TRACE_FN, };#define EVENT_STORAGE_SIZE 128
kernel/trace/trace.h +13 -10
@@ -56,21 +56,23 @@ enum trace_type { #define F_STRUCT(args...) args#undef FTRACE_ENTRY -#define FTRACE_ENTRY (name, struct_name, id, tstruct, print) \ - struct struct_name { \ - struct trace_entry ent; \ - tstruct \ +#define FTRACE_ENTRY (name, struct_name, id, tstruct, print, filter) \ + struct struct_name { \ + struct trace_entry ent; \ + tstruct \ }#undef TP_ARGS #define TP_ARGS(args...) args#undef FTRACE_ENTRY_DUP -#define FTRACE_ENTRY_DUP (name, name_struct, id, tstruct, printk) +#define FTRACE_ENTRY_DUP (name, name_struct, id, tstruct, printk, filter)#undef FTRACE_ENTRY_REG -#define FTRACE_ENTRY_REG (name, struct_name, id, tstruct, print, regfn) \ - FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print)) +#define FTRACE_ENTRY_REG (name, struct_name, id, tstruct, print, \ + filter, regfn) \ + FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print), \ + filter)#include "trace_entries.h"
@@ -826,12 +828,13 @@ extern const char *__start___trace_bprintk_fmt[];extern const char *__stop___trace_bprintk_fmt[];#undef FTRACE_ENTRY -#define FTRACE_ENTRY (call, struct_name, id, tstruct, print) \ +#define FTRACE_ENTRY (call, struct_name, id, tstruct, print, filter) \ extern struct ftrace_event_call \ __attribute__((__aligned__(4))) event_##call;#undef FTRACE_ENTRY_DUP -#define FTRACE_ENTRY_DUP (call, struct_name, id, tstruct, print) \ - FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print)) +#define FTRACE_ENTRY_DUP (call, struct_name, id, tstruct, print, filter) \ + FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print), \ + filter)#include "trace_entries.h" #ifdef CONFIG_PERF_EVENTS
kernel/trace/trace_entries.h +35 -13
119 lines not on this page · raw message
kernel/trace/trace_events_filter.c +6 -1
@@ -899,6 +899,11 @@ int filter_assign_type(const char *type)return FILTER_OTHER ; } +static bool is_function_field (struct ftrace_event_field *field) +{ +return field->filter_type ==FILTER_TRACE_FN ; +} +static bool is_string_field (struct ftrace_event_field *field) { return field->filter_type == FILTER_DYN_STRING ||
@@ -986,7 +991,7 @@ static int init_pred(struct filter_parse_state *ps, fn = filter_pred_strloc; else fn = filter_pred_pchar; - }else { + }else if (!is_function_field (field)) {if (field->is_signed) ret =strict_strtoll (pred->regex.pattern,0 , &val);else
kernel/trace/trace_export.c +28 -23
118 lines not on this page · raw message
Signature · 1 line
1.7.8.3
Steven Rostedt
maintainerPATCH 9/9 ftrace, perf: Add filter support for function trace event
In reply to Steven RostedtFrom: Jiri Olsa <[email protected]>
Adding support to filter function trace event via perf interface. It is now possible to use filter interface in the perf tool like:
perf record -e ftrace:function --filter="(ip == mm_*)" ls
The filter syntax is restricted to the the 'ip' field only, and following operators are accepted '==' '!=' '||', ending up with the filter strings like:
ip == f1[, ]f2 ... || ip != f3[, ]f4 ...
with comma ',' or space ' ' as a function separator. If the space ' ' is used as a separator, the right side of the assignment needs to be enclosed in double quotes '"', e.g.:
perf record -e ftrace:function --filter '(ip == do_execve,sys_*,ext*)' ls perf record -e ftrace:function --filter '(ip == "do_execve,sys_*,ext*")' ls perf record -e ftrace:function --filter '(ip == "do_execve sys_* ext*")' ls
The '==' operator adds trace filter with same effect as would be added via set_ftrace_filter file.
The '!=' operator adds trace filter with same effect as would be added via set_ftrace_notrace file.
The right side of the '!=', '==' operators is list of functions or regexp. to be added to filter separated by space.
The '||' operator is used for connecting multiple filter definitions together. It is possible to have more than one '==' and '!=' operators within one filter string.
--- include/linux/ftrace.h | 7 +- kernel/trace/ftrace.c | 6 ++ kernel/trace/trace.h | 2 - kernel/trace/trace_event_perf.c | 4 +- kernel/trace/trace_events_filter.c | 165 ++++++++++++++++++++++++++++++++++-- 5 files changed, 172 insertions(+), 12 deletions(-)
include/linux/ftrace.h +4 -3
@@ -250,6 +250,7 @@ int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf, int len, int reset);void ftrace_set_global_filter (unsigned char *buf,int len,int reset);void ftrace_set_global_notrace (unsigned char *buf,int len,int reset); +void ftrace_free_filter (struct ftrace_ops *ops);int register_ftrace_command (struct ftrace_func_command *cmd);int unregister_ftrace_command (struct ftrace_func_command *cmd);
@@ -380,9 +381,6 @@ extern void ftrace_enable_daemon(void);#else static inline int skip_trace (unsigned long ip) {return 0 ; }static inline int ftrace_force_update (void ) {return 0 ; } -static inline void ftrace_set_filter (unsigned char *buf,int len,int reset) -{ -}static inline void ftrace_disable_daemon (void ) { }static inline void ftrace_enable_daemon (void ) { }static inline void ftrace_release_mod (struct module *mod) {}
@@ -406,6 +404,9 @@ static inline int ftrace_text_reserved(void *start, void *end)*/ #define ftrace_regex_open (ops, flag, inod, file) ({ -ENODEV; })#define ftrace_set_early_filter (ops, buf, enable) do { } while (0) +#define ftrace_set_filter (ops, buf, len, reset) ({ -ENODEV; }) +#define ftrace_set_notrace (ops, buf, len, reset) ({ -ENODEV; }) +#define ftrace_free_filter (ops) do { } while (0)static inline ssize_t ftrace_filter_write (struct file *file,const char __user *ubuf,size_t cnt,loff_t *ppos) {return -ENODEV ; }
kernel/trace/ftrace.c +6 -0
@@ -1186,6 +1186,12 @@ static void free_ftrace_hash_rcu(struct ftrace_hash *hash)call_rcu_sched (&hash->rcu, __free_ftrace_hash_rcu); } +void ftrace_free_filter (struct ftrace_ops *ops) +{ +free_ftrace_hash (ops->filter_hash); +free_ftrace_hash (ops->notrace_hash); +} +static struct ftrace_hash *alloc_ftrace_hash (int size_bits) {struct ftrace_hash *hash;
kernel/trace/trace.h +0 -2
@@ -776,9 +776,7 @@ struct filter_pred {u64 val;struct regex regex;unsigned short *ops; -#ifdef CONFIG_FTRACE_STARTUP_TEST struct ftrace_event_field *field; -#endif int offset;int not;int op;
kernel/trace/trace_event_perf.c +3 -1
@@ -298,7 +298,9 @@ static int perf_ftrace_function_register(struct perf_event *event)static int perf_ftrace_function_unregister (struct perf_event *event) {struct ftrace_ops *ops = &event->ftrace_ops; -return unregister_ftrace_function (ops); +int ret =unregister_ftrace_function (ops); +ftrace_free_filter (ops); +return ret; }static void perf_ftrace_function_enable (struct perf_event *event)
kernel/trace/trace_events_filter.c +159 -6
203 lines not on this page · raw message
Signature · 1 line
1.7.8.3