Skip to content

Commit

Permalink
Merge branch 'tracing-core-for-linus' of git://git.kernel.org/pub/scm…
Browse files Browse the repository at this point in the history
…/linux/kernel/git/tip/linux-2.6-tip

* 'tracing-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  tracing: Fix "integer as NULL pointer" warning.
  tracing: Fix tracepoint.h DECLARE_TRACE() to allow more than one header
  tracing: Make the documentation clear on trace_event boot option
  ring-buffer: Wrap open-coded WARN_ONCE
  tracing: Convert nop macros to static inlines
  tracing: Fix sleep time function profiling
  tracing: Show sample std dev in function profiling
  tracing: Add documentation for trace commands mod, traceon/traceoff
  ring-buffer: Make benchmark handle missed events
  ring-buffer: Make non-consuming read less expensive with lots of cpus.
  tracing: Add graph output support for irqsoff tracer
  tracing: Have graph flags passed in to ouput functions
  tracing: Add ftrace events for graph tracer
  tracing: Dump either the oops's cpu source or all cpus buffers
  tracing: Fix uninitialized variable of tracing/trace output
  • Loading branch information
Linus Torvalds committed May 18, 2010
2 parents b8ae30e + ad56b07 commit 752f114
Show file tree
Hide file tree
Showing 19 changed files with 723 additions and 210 deletions.
6 changes: 5 additions & 1 deletion Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -786,8 +786,12 @@ and is between 256 and 4096 characters. It is defined in the file
as early as possible in order to facilitate early
boot debugging.

ftrace_dump_on_oops
ftrace_dump_on_oops[=orig_cpu]
[FTRACE] will dump the trace buffers on oops.
If no parameter is passed, ftrace will dump
buffers of all CPUs, but if you pass orig_cpu, it will
dump only the buffer of the CPU that triggered the
oops.

ftrace_filter=[function-list]
[FTRACE] Limit the functions traced by the function
Expand Down
3 changes: 2 additions & 1 deletion Documentation/trace/events.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ In order to facilitate early boot debugging, use boot option:

trace_event=[event-list]

The format of this boot option is the same as described in section 2.1.
event-list is a comma separated list of events. See section 2.1 for event
format.

3. Defining an event-enabled tracepoint
=======================================
Expand Down
50 changes: 48 additions & 2 deletions Documentation/trace/ftrace.txt
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ of ftrace. Here is a list of some of the key files:
to be traced. Echoing names of functions into this file
will limit the trace to only those functions.

This interface also allows for commands to be used. See the
"Filter commands" section for more details.

set_ftrace_notrace:

This has an effect opposite to that of
Expand Down Expand Up @@ -1337,12 +1340,14 @@ ftrace_dump_on_oops must be set. To set ftrace_dump_on_oops, one
can either use the sysctl function or set it via the proc system
interface.

sysctl kernel.ftrace_dump_on_oops=1
sysctl kernel.ftrace_dump_on_oops=n

or

echo 1 > /proc/sys/kernel/ftrace_dump_on_oops
echo n > /proc/sys/kernel/ftrace_dump_on_oops

If n = 1, ftrace will dump buffers of all CPUs, if n = 2 ftrace will
only dump the buffer of the CPU that triggered the oops.

Here's an example of such a dump after a null pointer
dereference in a kernel module:
Expand Down Expand Up @@ -1822,6 +1827,47 @@ this special filter via:
echo > set_graph_function


Filter commands
---------------

A few commands are supported by the set_ftrace_filter interface.
Trace commands have the following format:

<function>:<command>:<parameter>

The following commands are supported:

- mod
This command enables function filtering per module. The
parameter defines the module. For example, if only the write*
functions in the ext3 module are desired, run:

echo 'write*:mod:ext3' > set_ftrace_filter

This command interacts with the filter in the same way as
filtering based on function names. Thus, adding more functions
in a different module is accomplished by appending (>>) to the
filter file. Remove specific module functions by prepending
'!':

echo '!writeback*:mod:ext3' >> set_ftrace_filter

- traceon/traceoff
These commands turn tracing on and off when the specified
functions are hit. The parameter determines how many times the
tracing system is turned on and off. If unspecified, there is
no limit. For example, to disable tracing when a schedule bug
is hit the first 5 times, run:

echo '__schedule_bug:traceoff:5' > set_ftrace_filter

These commands are cumulative whether or not they are appended
to set_ftrace_filter. To remove a command, prepend it by '!'
and drop the parameter:

echo '!__schedule_bug:traceoff' > set_ftrace_filter


trace_pipe
----------

Expand Down
2 changes: 1 addition & 1 deletion drivers/char/sysrq.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ static struct sysrq_key_op sysrq_showstate_blocked_op = {

static void sysrq_ftrace_dump(int key, struct tty_struct *tty)
{
ftrace_dump();
ftrace_dump(DUMP_ALL);
}
static struct sysrq_key_op sysrq_ftrace_dump_op = {
.handler = sysrq_ftrace_dump,
Expand Down
49 changes: 32 additions & 17 deletions include/linux/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,13 @@ void clear_ftrace_function(void);
extern void ftrace_stub(unsigned long a0, unsigned long a1);

#else /* !CONFIG_FUNCTION_TRACER */
# define register_ftrace_function(ops) do { } while (0)
# define unregister_ftrace_function(ops) do { } while (0)
# define clear_ftrace_function(ops) do { } while (0)
/*
* (un)register_ftrace_function must be a macro since the ops parameter
* must not be evaluated.
*/
#define register_ftrace_function(ops) ({ 0; })
#define unregister_ftrace_function(ops) ({ 0; })
static inline void clear_ftrace_function(void) { }
static inline void ftrace_kill(void) { }
static inline void ftrace_stop(void) { }
static inline void ftrace_start(void) { }
Expand Down Expand Up @@ -237,11 +241,13 @@ extern int skip_trace(unsigned long ip);
extern void ftrace_disable_daemon(void);
extern void ftrace_enable_daemon(void);
#else
# define skip_trace(ip) ({ 0; })
# define ftrace_force_update() ({ 0; })
# define ftrace_set_filter(buf, len, reset) do { } while (0)
# define ftrace_disable_daemon() do { } while (0)
# define ftrace_enable_daemon() do { } while (0)
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) {}
static inline int register_ftrace_command(struct ftrace_func_command *cmd)
{
Expand Down Expand Up @@ -314,16 +320,16 @@ static inline void __ftrace_enabled_restore(int enabled)
extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
extern void time_hardirqs_off(unsigned long a0, unsigned long a1);
#else
# define time_hardirqs_on(a0, a1) do { } while (0)
# define time_hardirqs_off(a0, a1) do { } while (0)
static inline void time_hardirqs_on(unsigned long a0, unsigned long a1) { }
static inline void time_hardirqs_off(unsigned long a0, unsigned long a1) { }
#endif

#ifdef CONFIG_PREEMPT_TRACER
extern void trace_preempt_on(unsigned long a0, unsigned long a1);
extern void trace_preempt_off(unsigned long a0, unsigned long a1);
#else
# define trace_preempt_on(a0, a1) do { } while (0)
# define trace_preempt_off(a0, a1) do { } while (0)
static inline void trace_preempt_on(unsigned long a0, unsigned long a1) { }
static inline void trace_preempt_off(unsigned long a0, unsigned long a1) { }
#endif

#ifdef CONFIG_FTRACE_MCOUNT_RECORD
Expand Down Expand Up @@ -352,6 +358,10 @@ struct ftrace_graph_ret {
int depth;
};

/* Type of the callback handlers for tracing function graph*/
typedef void (*trace_func_graph_ret_t)(struct ftrace_graph_ret *); /* return */
typedef int (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */

#ifdef CONFIG_FUNCTION_GRAPH_TRACER

/* for init task */
Expand Down Expand Up @@ -400,10 +410,6 @@ extern char __irqentry_text_end[];

#define FTRACE_RETFUNC_DEPTH 50
#define FTRACE_RETSTACK_ALLOC_SIZE 32
/* Type of the callback handlers for tracing function graph*/
typedef void (*trace_func_graph_ret_t)(struct ftrace_graph_ret *); /* return */
typedef int (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */

extern int register_ftrace_graph(trace_func_graph_ret_t retfunc,
trace_func_graph_ent_t entryfunc);

Expand Down Expand Up @@ -441,6 +447,13 @@ static inline void unpause_graph_tracing(void)
static inline void ftrace_graph_init_task(struct task_struct *t) { }
static inline void ftrace_graph_exit_task(struct task_struct *t) { }

static inline int register_ftrace_graph(trace_func_graph_ret_t retfunc,
trace_func_graph_ent_t entryfunc)
{
return -1;
}
static inline void unregister_ftrace_graph(void) { }

static inline int task_curr_ret_stack(struct task_struct *tsk)
{
return -1;
Expand Down Expand Up @@ -492,7 +505,9 @@ static inline int test_tsk_trace_graph(struct task_struct *tsk)
return tsk->trace & TSK_TRACE_FL_GRAPH;
}

extern int ftrace_dump_on_oops;
enum ftrace_dump_mode;

extern enum ftrace_dump_mode ftrace_dump_on_oops;

#ifdef CONFIG_PREEMPT
#define INIT_TRACE_RECURSION .trace_recursion = 0,
Expand Down
11 changes: 9 additions & 2 deletions include/linux/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,13 @@ static inline void tracing_off(void) { }
static inline void tracing_off_permanent(void) { }
static inline int tracing_is_on(void) { return 0; }
#endif

enum ftrace_dump_mode {
DUMP_NONE,
DUMP_ALL,
DUMP_ORIG,
};

#ifdef CONFIG_TRACING
extern void tracing_start(void);
extern void tracing_stop(void);
Expand Down Expand Up @@ -571,7 +578,7 @@ __ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap);
extern int
__ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap);

extern void ftrace_dump(void);
extern void ftrace_dump(enum ftrace_dump_mode oops_dump_mode);
#else
static inline void
ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) { }
Expand All @@ -592,7 +599,7 @@ ftrace_vprintk(const char *fmt, va_list ap)
{
return 0;
}
static inline void ftrace_dump(void) { }
static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
#endif /* CONFIG_TRACING */

/*
Expand Down
4 changes: 3 additions & 1 deletion include/linux/ring_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts,
unsigned long *lost_events);

struct ring_buffer_iter *
ring_buffer_read_start(struct ring_buffer *buffer, int cpu);
ring_buffer_read_prepare(struct ring_buffer *buffer, int cpu);
void ring_buffer_read_prepare_sync(void);
void ring_buffer_read_start(struct ring_buffer_iter *iter);
void ring_buffer_read_finish(struct ring_buffer_iter *iter);

struct ring_buffer_event *
Expand Down
114 changes: 59 additions & 55 deletions include/linux/tracepoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,65 @@ struct tracepoint {
* Keep in sync with vmlinux.lds.h.
*/

/*
* Connect a probe to a tracepoint.
* Internal API, should not be used directly.
*/
extern int tracepoint_probe_register(const char *name, void *probe);

/*
* Disconnect a probe from a tracepoint.
* Internal API, should not be used directly.
*/
extern int tracepoint_probe_unregister(const char *name, void *probe);

extern int tracepoint_probe_register_noupdate(const char *name, void *probe);
extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe);
extern void tracepoint_probe_update_all(void);

struct tracepoint_iter {
struct module *module;
struct tracepoint *tracepoint;
};

extern void tracepoint_iter_start(struct tracepoint_iter *iter);
extern void tracepoint_iter_next(struct tracepoint_iter *iter);
extern void tracepoint_iter_stop(struct tracepoint_iter *iter);
extern void tracepoint_iter_reset(struct tracepoint_iter *iter);
extern int tracepoint_get_iter_range(struct tracepoint **tracepoint,
struct tracepoint *begin, struct tracepoint *end);

/*
* tracepoint_synchronize_unregister must be called between the last tracepoint
* probe unregistration and the end of module exit to make sure there is no
* caller executing a probe when it is freed.
*/
static inline void tracepoint_synchronize_unregister(void)
{
synchronize_sched();
}

#define PARAMS(args...) args

#ifdef CONFIG_TRACEPOINTS
extern void tracepoint_update_probe_range(struct tracepoint *begin,
struct tracepoint *end);
#else
static inline void tracepoint_update_probe_range(struct tracepoint *begin,
struct tracepoint *end)
{ }
#endif /* CONFIG_TRACEPOINTS */

#endif /* _LINUX_TRACEPOINT_H */

/*
* Note: we keep the TRACE_EVENT and DECLARE_TRACE outside the include
* file ifdef protection.
* This is due to the way trace events work. If a file includes two
* trace event headers under one "CREATE_TRACE_POINTS" the first include
* will override the TRACE_EVENT and break the second include.
*/

#ifndef DECLARE_TRACE

#define TP_PROTO(args...) args
Expand Down Expand Up @@ -96,9 +155,6 @@ struct tracepoint {
#define EXPORT_TRACEPOINT_SYMBOL(name) \
EXPORT_SYMBOL(__tracepoint_##name)

extern void tracepoint_update_probe_range(struct tracepoint *begin,
struct tracepoint *end);

#else /* !CONFIG_TRACEPOINTS */
#define DECLARE_TRACE(name, proto, args) \
static inline void _do_trace_##name(struct tracepoint *tp, proto) \
Expand All @@ -119,61 +175,9 @@ extern void tracepoint_update_probe_range(struct tracepoint *begin,
#define EXPORT_TRACEPOINT_SYMBOL_GPL(name)
#define EXPORT_TRACEPOINT_SYMBOL(name)

static inline void tracepoint_update_probe_range(struct tracepoint *begin,
struct tracepoint *end)
{ }
#endif /* CONFIG_TRACEPOINTS */
#endif /* DECLARE_TRACE */

/*
* Connect a probe to a tracepoint.
* Internal API, should not be used directly.
*/
extern int tracepoint_probe_register(const char *name, void *probe);

/*
* Disconnect a probe from a tracepoint.
* Internal API, should not be used directly.
*/
extern int tracepoint_probe_unregister(const char *name, void *probe);

extern int tracepoint_probe_register_noupdate(const char *name, void *probe);
extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe);
extern void tracepoint_probe_update_all(void);

struct tracepoint_iter {
struct module *module;
struct tracepoint *tracepoint;
};

extern void tracepoint_iter_start(struct tracepoint_iter *iter);
extern void tracepoint_iter_next(struct tracepoint_iter *iter);
extern void tracepoint_iter_stop(struct tracepoint_iter *iter);
extern void tracepoint_iter_reset(struct tracepoint_iter *iter);
extern int tracepoint_get_iter_range(struct tracepoint **tracepoint,
struct tracepoint *begin, struct tracepoint *end);

/*
* tracepoint_synchronize_unregister must be called between the last tracepoint
* probe unregistration and the end of module exit to make sure there is no
* caller executing a probe when it is freed.
*/
static inline void tracepoint_synchronize_unregister(void)
{
synchronize_sched();
}

#define PARAMS(args...) args

#endif /* _LINUX_TRACEPOINT_H */

/*
* Note: we keep the TRACE_EVENT outside the include file ifdef protection.
* This is due to the way trace events work. If a file includes two
* trace event headers under one "CREATE_TRACE_POINTS" the first include
* will override the TRACE_EVENT and break the second include.
*/

#ifndef TRACE_EVENT
/*
* For use with the TRACE_EVENT macro:
Expand Down
Loading

0 comments on commit 752f114

Please sign in to comment.