diff options
author | Steven Rostedt <srostedt@redhat.com> | 2008-12-03 15:36:57 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-04 03:09:34 -0500 |
commit | ea4e2bc4d9f7370e57a343ccb5e7c0ad3222ec3c (patch) | |
tree | 64a4a1d9d7d3de0695cb2e8c7161886ab660e311 /include | |
parent | b29144c317fb748dae6d72c0f88eda9d43165b8d (diff) |
ftrace: graph of a single function
This patch adds the file:
/debugfs/tracing/set_graph_function
which can be used along with the function graph tracer.
When this file is empty, the function graph tracer will act as
usual. When the file has a function in it, the function graph
tracer will only trace that function.
For example:
# echo blk_unplug > /debugfs/tracing/set_graph_function
# cat /debugfs/tracing/trace
[...]
------------------------------------------
| 2) make-19003 => kjournald-2219
------------------------------------------
2) | blk_unplug() {
2) | dm_unplug_all() {
2) | dm_get_table() {
2) 1.381 us | _read_lock();
2) 0.911 us | dm_table_get();
2) 1. 76 us | _read_unlock();
2) + 12.912 us | }
2) | dm_table_unplug_all() {
2) | blk_unplug() {
2) 0.778 us | generic_unplug_device();
2) 2.409 us | }
2) 5.992 us | }
2) 0.813 us | dm_table_put();
2) + 29. 90 us | }
2) + 34.532 us | }
You can add up to 32 functions into this file. Currently we limit it
to 32, but this may change with later improvements.
To add another function, use the append '>>':
# echo sys_read >> /debugfs/tracing/set_graph_function
# cat /debugfs/tracing/set_graph_function
blk_unplug
sys_read
Using the '>' will clear out the function and write anew:
# echo sys_write > /debug/tracing/set_graph_function
# cat /debug/tracing/set_graph_function
sys_write
Note, if you have function graph running while doing this, the small
time between clearing it and updating it will cause the graph to
record all functions. This should not be an issue because after
it sets the filter, only those functions will be recorded from then on.
If you need to only record a particular function then set this
file first before starting the function graph tracer. In the future
this side effect may be corrected.
The set_graph_function file is similar to the set_ftrace_filter but
it does not take wild cards nor does it allow for more than one
function to be set with a single write. There is no technical reason why
this is the case, I just do not have the time yet to implement that.
Note, dynamic ftrace must be enabled for this to appear because it
uses the dynamic ftrace records to match the name to the mcount
call sites.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/ftrace.h | 46 | ||||
-rw-r--r-- | include/linux/sched.h | 4 |
2 files changed, 50 insertions, 0 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 469ceb3e85ba..b295d3106bfe 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/types.h> | 8 | #include <linux/types.h> |
9 | #include <linux/kallsyms.h> | 9 | #include <linux/kallsyms.h> |
10 | #include <linux/bitops.h> | ||
10 | 11 | ||
11 | #ifdef CONFIG_FUNCTION_TRACER | 12 | #ifdef CONFIG_FUNCTION_TRACER |
12 | 13 | ||
@@ -391,4 +392,49 @@ static inline void ftrace_graph_init_task(struct task_struct *t) { } | |||
391 | static inline void ftrace_graph_exit_task(struct task_struct *t) { } | 392 | static inline void ftrace_graph_exit_task(struct task_struct *t) { } |
392 | #endif | 393 | #endif |
393 | 394 | ||
395 | #ifdef CONFIG_TRACING | ||
396 | #include <linux/sched.h> | ||
397 | |||
398 | /* flags for current->trace */ | ||
399 | enum { | ||
400 | TSK_TRACE_FL_TRACE_BIT = 0, | ||
401 | TSK_TRACE_FL_GRAPH_BIT = 1, | ||
402 | }; | ||
403 | enum { | ||
404 | TSK_TRACE_FL_TRACE = 1 << TSK_TRACE_FL_TRACE_BIT, | ||
405 | TSK_TRACE_FL_GRAPH = 1 << TSK_TRACE_FL_GRAPH_BIT, | ||
406 | }; | ||
407 | |||
408 | static inline void set_tsk_trace_trace(struct task_struct *tsk) | ||
409 | { | ||
410 | set_bit(TSK_TRACE_FL_TRACE_BIT, &tsk->trace); | ||
411 | } | ||
412 | |||
413 | static inline void clear_tsk_trace_trace(struct task_struct *tsk) | ||
414 | { | ||
415 | clear_bit(TSK_TRACE_FL_TRACE_BIT, &tsk->trace); | ||
416 | } | ||
417 | |||
418 | static inline int test_tsk_trace_trace(struct task_struct *tsk) | ||
419 | { | ||
420 | return tsk->trace & TSK_TRACE_FL_TRACE; | ||
421 | } | ||
422 | |||
423 | static inline void set_tsk_trace_graph(struct task_struct *tsk) | ||
424 | { | ||
425 | set_bit(TSK_TRACE_FL_GRAPH_BIT, &tsk->trace); | ||
426 | } | ||
427 | |||
428 | static inline void clear_tsk_trace_graph(struct task_struct *tsk) | ||
429 | { | ||
430 | clear_bit(TSK_TRACE_FL_GRAPH_BIT, &tsk->trace); | ||
431 | } | ||
432 | |||
433 | static inline int test_tsk_trace_graph(struct task_struct *tsk) | ||
434 | { | ||
435 | return tsk->trace & TSK_TRACE_FL_GRAPH; | ||
436 | } | ||
437 | |||
438 | #endif /* CONFIG_TRACING */ | ||
439 | |||
394 | #endif /* _LINUX_FTRACE_H */ | 440 | #endif /* _LINUX_FTRACE_H */ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 2d0a93c31228..4c152e0acc9e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1380,6 +1380,10 @@ struct task_struct { | |||
1380 | */ | 1380 | */ |
1381 | atomic_t trace_overrun; | 1381 | atomic_t trace_overrun; |
1382 | #endif | 1382 | #endif |
1383 | #ifdef CONFIG_TRACING | ||
1384 | /* state flags for use by tracers */ | ||
1385 | unsigned long trace; | ||
1386 | #endif | ||
1383 | }; | 1387 | }; |
1384 | 1388 | ||
1385 | /* | 1389 | /* |