Skip to content

Commit

Permalink
tracing/fgraph: Add max_graph_depth to limit function_graph depth
Browse files Browse the repository at this point in the history
Add the file max_graph_depth to the debug tracing directory that lets
the user define the depth of the function graph.

A very useful operation is to set the depth to 1. Then it traces only
the first function that is called when entering the kernel. This can
be used to determine what system operations interrupt a process.

For example, to work on NOHZ processes (single tasks running without
a timer tick), if any interrupt goes off and preempts that task, this
code will show it happening.

  # cd /sys/kernel/debug/tracing
  # echo 1 > max_graph_depth
  # echo function_graph > current_tracer
  # cat per_cpu/cpu/<cpu-of-process>/trace

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
  • Loading branch information
Steven Rostedt authored and Steven Rostedt committed Jan 21, 2013
1 parent 0f1ac8f commit 8741db5
Showing 1 changed file with 58 additions and 2 deletions.
60 changes: 58 additions & 2 deletions kernel/trace/trace_functions_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ struct fgraph_data {
#define TRACE_GRAPH_PRINT_ABS_TIME 0x20
#define TRACE_GRAPH_PRINT_IRQS 0x40

static unsigned int max_depth;

static struct tracer_opt trace_opts[] = {
/* Display overruns? (for self-debug purpose) */
{ TRACER_OPT(funcgraph-overrun, TRACE_GRAPH_PRINT_OVERRUN) },
Expand Down Expand Up @@ -250,8 +252,9 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
return 0;

/* trace it when it is-nested-in or is a function enabled. */
if (!(trace->depth || ftrace_graph_addr(trace->func)) ||
ftrace_graph_ignore_irqs())
if ((!(trace->depth || ftrace_graph_addr(trace->func)) ||
ftrace_graph_ignore_irqs()) ||
(max_depth && trace->depth >= max_depth))
return 0;

local_irq_save(flags);
Expand Down Expand Up @@ -1457,6 +1460,59 @@ static struct tracer graph_trace __read_mostly = {
#endif
};


static ssize_t
graph_depth_write(struct file *filp, const char __user *ubuf, size_t cnt,
loff_t *ppos)
{
unsigned long val;
int ret;

ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
if (ret)
return ret;

max_depth = val;

*ppos += cnt;

return cnt;
}

static ssize_t
graph_depth_read(struct file *filp, char __user *ubuf, size_t cnt,
loff_t *ppos)
{
char buf[15]; /* More than enough to hold UINT_MAX + "\n"*/
int n;

n = sprintf(buf, "%d\n", max_depth);

return simple_read_from_buffer(ubuf, cnt, ppos, buf, n);
}

static const struct file_operations graph_depth_fops = {
.open = tracing_open_generic,
.write = graph_depth_write,
.read = graph_depth_read,
.llseek = generic_file_llseek,
};

static __init int init_graph_debugfs(void)
{
struct dentry *d_tracer;

d_tracer = tracing_init_dentry();
if (!d_tracer)
return 0;

trace_create_file("max_graph_depth", 0644, d_tracer,
NULL, &graph_depth_fops);

return 0;
}
fs_initcall(init_graph_debugfs);

static __init int init_graph_trace(void)
{
max_bytes_for_cpu = snprintf(NULL, 0, "%d", nr_cpu_ids - 1);
Expand Down

0 comments on commit 8741db5

Please sign in to comment.