2009-04-13 19:20:49 +04:00
|
|
|
#ifndef _LINUX_FTRACE_EVENT_H
|
|
|
|
#define _LINUX_FTRACE_EVENT_H
|
|
|
|
|
|
|
|
#include <linux/ring_buffer.h>
|
2009-09-13 03:04:54 +04:00
|
|
|
#include <linux/trace_seq.h>
|
2009-05-26 22:25:22 +04:00
|
|
|
#include <linux/percpu.h>
|
2009-09-18 08:10:28 +04:00
|
|
|
#include <linux/hardirq.h>
|
2010-01-28 04:32:29 +03:00
|
|
|
#include <linux/perf_event.h>
|
2009-04-13 19:20:49 +04:00
|
|
|
|
|
|
|
struct trace_array;
|
|
|
|
struct tracer;
|
2009-04-10 22:53:50 +04:00
|
|
|
struct dentry;
|
2009-04-13 19:20:49 +04:00
|
|
|
|
2009-05-26 22:25:22 +04:00
|
|
|
struct trace_print_flags {
|
|
|
|
unsigned long mask;
|
|
|
|
const char *name;
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *ftrace_print_flags_seq(struct trace_seq *p, const char *delim,
|
|
|
|
unsigned long flags,
|
|
|
|
const struct trace_print_flags *flag_array);
|
|
|
|
|
2009-05-21 03:21:47 +04:00
|
|
|
const char *ftrace_print_symbols_seq(struct trace_seq *p, unsigned long val,
|
|
|
|
const struct trace_print_flags *symbol_array);
|
|
|
|
|
2010-04-01 15:40:58 +04:00
|
|
|
const char *ftrace_print_hex_seq(struct trace_seq *p,
|
|
|
|
const unsigned char *buf, int len);
|
|
|
|
|
2009-04-13 19:20:49 +04:00
|
|
|
/*
|
|
|
|
* The trace entry - the most basic unit of tracing. This is what
|
|
|
|
* is printed in the end as a single line in the trace output, such as:
|
|
|
|
*
|
|
|
|
* bash-15816 [01] 235.197585: idle_cpu <- irq_enter
|
|
|
|
*/
|
|
|
|
struct trace_entry {
|
2009-03-26 18:03:29 +03:00
|
|
|
unsigned short type;
|
2009-04-13 19:20:49 +04:00
|
|
|
unsigned char flags;
|
|
|
|
unsigned char preempt_count;
|
|
|
|
int pid;
|
2009-09-11 21:55:35 +04:00
|
|
|
int lock_depth;
|
2009-04-13 19:20:49 +04:00
|
|
|
};
|
|
|
|
|
2009-03-26 18:03:29 +03:00
|
|
|
#define FTRACE_MAX_EVENT \
|
|
|
|
((1 << (sizeof(((struct trace_entry *)0)->type) * 8)) - 1)
|
|
|
|
|
2009-04-13 19:20:49 +04:00
|
|
|
/*
|
|
|
|
* Trace iterator - used by printout routines who present trace
|
|
|
|
* results to users and which routines might sleep, etc:
|
|
|
|
*/
|
|
|
|
struct trace_iterator {
|
|
|
|
struct trace_array *tr;
|
|
|
|
struct tracer *trace;
|
|
|
|
void *private;
|
|
|
|
int cpu_file;
|
|
|
|
struct mutex mutex;
|
|
|
|
struct ring_buffer_iter *buffer_iter[NR_CPUS];
|
2009-06-01 23:16:05 +04:00
|
|
|
unsigned long iter_flags;
|
2009-04-13 19:20:49 +04:00
|
|
|
|
2010-06-03 14:26:24 +04:00
|
|
|
/* trace_seq for __print_flags() and __print_symbolic() etc. */
|
|
|
|
struct trace_seq tmp_seq;
|
|
|
|
|
2009-04-13 19:20:49 +04:00
|
|
|
/* The below is zeroed out in pipe_read */
|
|
|
|
struct trace_seq seq;
|
|
|
|
struct trace_entry *ent;
|
2010-04-01 03:49:26 +04:00
|
|
|
unsigned long lost_events;
|
2009-12-07 17:11:39 +03:00
|
|
|
int leftover;
|
2009-04-13 19:20:49 +04:00
|
|
|
int cpu;
|
|
|
|
u64 ts;
|
|
|
|
|
|
|
|
loff_t pos;
|
|
|
|
long idx;
|
|
|
|
|
|
|
|
cpumask_var_t started;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-04-23 02:46:14 +04:00
|
|
|
struct trace_event;
|
|
|
|
|
2009-04-13 19:20:49 +04:00
|
|
|
typedef enum print_line_t (*trace_print_func)(struct trace_iterator *iter,
|
2010-04-23 02:46:14 +04:00
|
|
|
int flags, struct trace_event *event);
|
|
|
|
|
|
|
|
struct trace_event_functions {
|
2009-04-13 19:20:49 +04:00
|
|
|
trace_print_func trace;
|
|
|
|
trace_print_func raw;
|
|
|
|
trace_print_func hex;
|
|
|
|
trace_print_func binary;
|
|
|
|
};
|
|
|
|
|
2010-04-23 02:46:14 +04:00
|
|
|
struct trace_event {
|
|
|
|
struct hlist_node node;
|
|
|
|
struct list_head list;
|
|
|
|
int type;
|
|
|
|
struct trace_event_functions *funcs;
|
|
|
|
};
|
|
|
|
|
2009-04-13 19:20:49 +04:00
|
|
|
extern int register_ftrace_event(struct trace_event *event);
|
|
|
|
extern int unregister_ftrace_event(struct trace_event *event);
|
|
|
|
|
|
|
|
/* Return values for print_line callback */
|
|
|
|
enum print_line_t {
|
|
|
|
TRACE_TYPE_PARTIAL_LINE = 0, /* Retry after flushing the seq */
|
|
|
|
TRACE_TYPE_HANDLED = 1,
|
|
|
|
TRACE_TYPE_UNHANDLED = 2, /* Relay to other output functions */
|
|
|
|
TRACE_TYPE_NO_CONSUME = 3 /* Handled but ask to not consume */
|
|
|
|
};
|
|
|
|
|
2009-08-07 03:25:54 +04:00
|
|
|
void tracing_generic_entry_update(struct trace_entry *entry,
|
|
|
|
unsigned long flags,
|
|
|
|
int pc);
|
2009-04-13 19:20:49 +04:00
|
|
|
struct ring_buffer_event *
|
2009-09-02 22:17:06 +04:00
|
|
|
trace_current_buffer_lock_reserve(struct ring_buffer **current_buffer,
|
|
|
|
int type, unsigned long len,
|
2009-04-13 19:20:49 +04:00
|
|
|
unsigned long flags, int pc);
|
2009-09-02 22:17:06 +04:00
|
|
|
void trace_current_buffer_unlock_commit(struct ring_buffer *buffer,
|
|
|
|
struct ring_buffer_event *event,
|
2009-04-13 19:20:49 +04:00
|
|
|
unsigned long flags, int pc);
|
2009-09-02 22:17:06 +04:00
|
|
|
void trace_nowake_buffer_unlock_commit(struct ring_buffer *buffer,
|
|
|
|
struct ring_buffer_event *event,
|
2009-04-13 19:20:49 +04:00
|
|
|
unsigned long flags, int pc);
|
2009-09-02 22:17:06 +04:00
|
|
|
void trace_current_buffer_discard_commit(struct ring_buffer *buffer,
|
|
|
|
struct ring_buffer_event *event);
|
2009-04-13 19:20:49 +04:00
|
|
|
|
|
|
|
void tracing_record_cmdline(struct task_struct *tsk);
|
|
|
|
|
2009-07-20 06:20:53 +04:00
|
|
|
struct event_filter;
|
|
|
|
|
2010-04-21 20:27:06 +04:00
|
|
|
enum trace_reg {
|
|
|
|
TRACE_REG_REGISTER,
|
|
|
|
TRACE_REG_UNREGISTER,
|
|
|
|
TRACE_REG_PERF_REGISTER,
|
|
|
|
TRACE_REG_PERF_UNREGISTER,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ftrace_event_call;
|
|
|
|
|
2010-04-20 18:47:33 +04:00
|
|
|
struct ftrace_event_class {
|
|
|
|
char *system;
|
2010-04-21 20:27:06 +04:00
|
|
|
void *probe;
|
|
|
|
#ifdef CONFIG_PERF_EVENTS
|
|
|
|
void *perf_probe;
|
|
|
|
#endif
|
|
|
|
int (*reg)(struct ftrace_event_call *event,
|
|
|
|
enum trace_reg type);
|
2010-04-22 18:35:55 +04:00
|
|
|
int (*define_fields)(struct ftrace_event_call *);
|
|
|
|
struct list_head *(*get_fields)(struct ftrace_event_call *);
|
|
|
|
struct list_head fields;
|
2010-04-22 19:46:44 +04:00
|
|
|
int (*raw_init)(struct ftrace_event_call *);
|
2010-04-20 18:47:33 +04:00
|
|
|
};
|
|
|
|
|
2010-06-08 19:22:06 +04:00
|
|
|
extern int ftrace_event_reg(struct ftrace_event_call *event,
|
|
|
|
enum trace_reg type);
|
|
|
|
|
2010-04-23 19:12:36 +04:00
|
|
|
enum {
|
|
|
|
TRACE_EVENT_FL_ENABLED_BIT,
|
|
|
|
TRACE_EVENT_FL_FILTERED_BIT,
|
2010-07-02 07:07:32 +04:00
|
|
|
TRACE_EVENT_FL_RECORDED_CMD_BIT,
|
2010-04-23 19:12:36 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
2010-07-02 07:07:32 +04:00
|
|
|
TRACE_EVENT_FL_ENABLED = (1 << TRACE_EVENT_FL_ENABLED_BIT),
|
|
|
|
TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT),
|
|
|
|
TRACE_EVENT_FL_RECORDED_CMD = (1 << TRACE_EVENT_FL_RECORDED_CMD_BIT),
|
2010-04-23 19:12:36 +04:00
|
|
|
};
|
|
|
|
|
2009-04-13 19:20:49 +04:00
|
|
|
struct ftrace_event_call {
|
2009-04-10 21:52:20 +04:00
|
|
|
struct list_head list;
|
2010-04-20 18:47:33 +04:00
|
|
|
struct ftrace_event_class *class;
|
2009-04-13 19:20:49 +04:00
|
|
|
char *name;
|
|
|
|
struct dentry *dir;
|
2010-04-23 18:00:22 +04:00
|
|
|
struct trace_event event;
|
2009-12-15 10:39:42 +03:00
|
|
|
const char *print_fmt;
|
2009-07-20 06:20:53 +04:00
|
|
|
struct event_filter *filter;
|
2009-04-10 22:53:50 +04:00
|
|
|
void *mod;
|
2009-08-11 00:52:44 +04:00
|
|
|
void *data;
|
2009-04-13 19:20:49 +04:00
|
|
|
|
2010-04-23 19:12:36 +04:00
|
|
|
/*
|
|
|
|
* 32 bit flags:
|
|
|
|
* bit 1: enabled
|
|
|
|
* bit 2: filter_active
|
2010-07-02 07:07:32 +04:00
|
|
|
* bit 3: enabled cmd record
|
2010-04-23 19:12:36 +04:00
|
|
|
*
|
2010-05-14 18:19:13 +04:00
|
|
|
* Changes to flags must hold the event_mutex.
|
|
|
|
*
|
|
|
|
* Note: Reads of flags do not hold the event_mutex since
|
|
|
|
* they occur in critical sections. But the way flags
|
|
|
|
* is currently used, these changes do no affect the code
|
|
|
|
* except that when a change is made, it may have a slight
|
|
|
|
* delay in propagating the changes to other CPUs due to
|
|
|
|
* caching and such.
|
2010-04-23 19:12:36 +04:00
|
|
|
*/
|
|
|
|
unsigned int flags;
|
|
|
|
|
2010-05-21 19:49:57 +04:00
|
|
|
#ifdef CONFIG_PERF_EVENTS
|
2010-03-05 07:35:37 +03:00
|
|
|
int perf_refcount;
|
2010-05-19 16:02:22 +04:00
|
|
|
struct hlist_head *perf_events;
|
2010-05-21 19:49:57 +04:00
|
|
|
#endif
|
2009-04-13 19:20:49 +04:00
|
|
|
};
|
|
|
|
|
2010-03-05 07:35:37 +03:00
|
|
|
#define PERF_MAX_TRACE_SIZE 2048
|
2009-09-18 08:10:28 +04:00
|
|
|
|
tracing/filters: a better event parser
Replace the current event parser hack with a better one. Filters are
no longer specified predicate by predicate, but all at once and can
use parens and any of the following operators:
numeric fields:
==, !=, <, <=, >, >=
string fields:
==, !=
predicates can be combined with the logical operators:
&&, ||
examples:
"common_preempt_count > 4" > filter
"((sig >= 10 && sig < 15) || sig == 17) && comm != bash" > filter
If there was an error, the erroneous string along with an error
message can be seen by looking at the filter e.g.:
((sig >= 10 && sig < 15) || dsig == 17) && comm != bash
^
parse_error: Field not found
Currently the caret for an error always appears at the beginning of
the filter; a real position should be used, but the error message
should be useful even without it.
To clear a filter, '0' can be written to the filter file.
Filters can also be set or cleared for a complete subsystem by writing
the same filter as would be written to an individual event to the
filter file at the root of the subsytem. Note however, that if any
event in the subsystem lacks a field specified in the filter being
set, the set will fail and all filters in the subsytem are
automatically cleared. This change from the previous version was made
because using only the fields that happen to exist for a given event
would most likely result in a meaningless filter.
Because the logical operators are now implemented as predicates, the
maximum number of predicates in a filter was increased from 8 to 16.
[ Impact: add new, extended trace-filter implementation ]
Signed-off-by: Tom Zanussi <tzanussi@gmail.com>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Cc: fweisbec@gmail.com
Cc: Li Zefan <lizf@cn.fujitsu.com>
LKML-Reference: <1240905899.6416.121.camel@tropicana>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-04-28 12:04:59 +04:00
|
|
|
#define MAX_FILTER_PRED 32
|
2009-09-13 03:04:54 +04:00
|
|
|
#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */
|
2009-04-13 19:20:49 +04:00
|
|
|
|
2009-05-06 06:33:04 +04:00
|
|
|
extern void destroy_preds(struct ftrace_event_call *call);
|
2009-10-15 07:21:42 +04:00
|
|
|
extern int filter_match_preds(struct event_filter *filter, void *rec);
|
2009-09-02 22:17:06 +04:00
|
|
|
extern int filter_current_check_discard(struct ring_buffer *buffer,
|
|
|
|
struct ftrace_event_call *call,
|
2009-04-13 19:20:49 +04:00
|
|
|
void *rec,
|
|
|
|
struct ring_buffer_event *event);
|
|
|
|
|
2009-08-07 06:33:22 +04:00
|
|
|
enum {
|
|
|
|
FILTER_OTHER = 0,
|
|
|
|
FILTER_STATIC_STRING,
|
|
|
|
FILTER_DYN_STRING,
|
2009-08-07 06:33:43 +04:00
|
|
|
FILTER_PTR_STRING,
|
2009-08-07 06:33:22 +04:00
|
|
|
};
|
|
|
|
|
2009-12-08 06:14:20 +03:00
|
|
|
extern int trace_event_raw_init(struct ftrace_event_call *call);
|
2009-08-27 07:09:51 +04:00
|
|
|
extern int trace_define_field(struct ftrace_event_call *call, const char *type,
|
|
|
|
const char *name, int offset, int size,
|
|
|
|
int is_signed, int filter_type);
|
2009-08-14 00:34:53 +04:00
|
|
|
extern int trace_add_event_call(struct ftrace_event_call *call);
|
|
|
|
extern void trace_remove_event_call(struct ftrace_event_call *call);
|
2009-04-13 19:20:49 +04:00
|
|
|
|
2009-04-28 12:04:53 +04:00
|
|
|
#define is_signed_type(type) (((type)(-1)) < 0)
|
2009-04-13 19:20:49 +04:00
|
|
|
|
2009-05-09 00:27:41 +04:00
|
|
|
int trace_set_clr_event(const char *system, const char *event, int set);
|
|
|
|
|
2009-04-13 19:20:49 +04:00
|
|
|
/*
|
|
|
|
* The double __builtin_constant_p is because gcc will give us an error
|
|
|
|
* if we try to allocate the static variable to fmt if it is not a
|
|
|
|
* constant. Even with the outer if statement optimizing out.
|
|
|
|
*/
|
|
|
|
#define event_trace_printk(ip, fmt, args...) \
|
|
|
|
do { \
|
|
|
|
__trace_printk_check_format(fmt, ##args); \
|
|
|
|
tracing_record_cmdline(current); \
|
|
|
|
if (__builtin_constant_p(fmt)) { \
|
|
|
|
static const char *trace_printk_fmt \
|
|
|
|
__attribute__((section("__trace_printk_fmt"))) = \
|
|
|
|
__builtin_constant_p(fmt) ? fmt : NULL; \
|
|
|
|
\
|
|
|
|
__trace_bprintk(ip, trace_printk_fmt, ##args); \
|
|
|
|
} else \
|
|
|
|
__trace_printk(ip, fmt, ##args); \
|
|
|
|
} while (0)
|
|
|
|
|
2009-12-21 09:27:35 +03:00
|
|
|
#ifdef CONFIG_PERF_EVENTS
|
2009-10-15 07:21:42 +04:00
|
|
|
struct perf_event;
|
2010-03-03 09:16:16 +03:00
|
|
|
|
|
|
|
DECLARE_PER_CPU(struct pt_regs, perf_trace_regs);
|
|
|
|
|
2010-05-19 16:02:22 +04:00
|
|
|
extern int perf_trace_init(struct perf_event *event);
|
|
|
|
extern void perf_trace_destroy(struct perf_event *event);
|
|
|
|
extern int perf_trace_enable(struct perf_event *event);
|
|
|
|
extern void perf_trace_disable(struct perf_event *event);
|
|
|
|
extern int ftrace_profile_set_filter(struct perf_event *event, int event_id,
|
2009-10-15 07:21:42 +04:00
|
|
|
char *filter_str);
|
|
|
|
extern void ftrace_profile_free_filter(struct perf_event *event);
|
2010-05-19 12:52:27 +04:00
|
|
|
extern void *perf_trace_buf_prepare(int size, unsigned short type,
|
|
|
|
struct pt_regs *regs, int *rctxp);
|
2010-01-28 04:32:29 +03:00
|
|
|
|
|
|
|
static inline void
|
2010-03-05 07:35:37 +03:00
|
|
|
perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr,
|
2010-05-19 16:02:22 +04:00
|
|
|
u64 count, struct pt_regs *regs, void *head)
|
2010-01-28 04:32:29 +03:00
|
|
|
{
|
2010-05-21 17:11:34 +04:00
|
|
|
perf_tp_event(addr, count, raw_data, size, regs, head, rctx);
|
2010-01-28 04:32:29 +03:00
|
|
|
}
|
2009-10-15 07:21:42 +04:00
|
|
|
#endif
|
|
|
|
|
2009-04-13 19:20:49 +04:00
|
|
|
#endif /* _LINUX_FTRACE_EVENT_H */
|