diff options
Diffstat (limited to 'kernel/trace/trace_functions_graph.c')
| -rw-r--r-- | kernel/trace/trace_functions_graph.c | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 4edb4b74eb7e..7008d2e13cf2 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c | |||
| @@ -47,6 +47,8 @@ struct fgraph_data { | |||
| 47 | #define TRACE_GRAPH_PRINT_ABS_TIME 0x20 | 47 | #define TRACE_GRAPH_PRINT_ABS_TIME 0x20 |
| 48 | #define TRACE_GRAPH_PRINT_IRQS 0x40 | 48 | #define TRACE_GRAPH_PRINT_IRQS 0x40 |
| 49 | 49 | ||
| 50 | static unsigned int max_depth; | ||
| 51 | |||
| 50 | static struct tracer_opt trace_opts[] = { | 52 | static struct tracer_opt trace_opts[] = { |
| 51 | /* Display overruns? (for self-debug purpose) */ | 53 | /* Display overruns? (for self-debug purpose) */ |
| 52 | { TRACER_OPT(funcgraph-overrun, TRACE_GRAPH_PRINT_OVERRUN) }, | 54 | { TRACER_OPT(funcgraph-overrun, TRACE_GRAPH_PRINT_OVERRUN) }, |
| @@ -250,8 +252,9 @@ int trace_graph_entry(struct ftrace_graph_ent *trace) | |||
| 250 | return 0; | 252 | return 0; |
| 251 | 253 | ||
| 252 | /* trace it when it is-nested-in or is a function enabled. */ | 254 | /* trace it when it is-nested-in or is a function enabled. */ |
| 253 | if (!(trace->depth || ftrace_graph_addr(trace->func)) || | 255 | if ((!(trace->depth || ftrace_graph_addr(trace->func)) || |
| 254 | ftrace_graph_ignore_irqs()) | 256 | ftrace_graph_ignore_irqs()) || |
| 257 | (max_depth && trace->depth >= max_depth)) | ||
| 255 | return 0; | 258 | return 0; |
| 256 | 259 | ||
| 257 | local_irq_save(flags); | 260 | local_irq_save(flags); |
| @@ -1457,6 +1460,59 @@ static struct tracer graph_trace __read_mostly = { | |||
| 1457 | #endif | 1460 | #endif |
| 1458 | }; | 1461 | }; |
| 1459 | 1462 | ||
| 1463 | |||
| 1464 | static ssize_t | ||
| 1465 | graph_depth_write(struct file *filp, const char __user *ubuf, size_t cnt, | ||
| 1466 | loff_t *ppos) | ||
| 1467 | { | ||
| 1468 | unsigned long val; | ||
| 1469 | int ret; | ||
| 1470 | |||
| 1471 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); | ||
| 1472 | if (ret) | ||
| 1473 | return ret; | ||
| 1474 | |||
| 1475 | max_depth = val; | ||
| 1476 | |||
| 1477 | *ppos += cnt; | ||
| 1478 | |||
| 1479 | return cnt; | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | static ssize_t | ||
| 1483 | graph_depth_read(struct file *filp, char __user *ubuf, size_t cnt, | ||
| 1484 | loff_t *ppos) | ||
| 1485 | { | ||
| 1486 | char buf[15]; /* More than enough to hold UINT_MAX + "\n"*/ | ||
| 1487 | int n; | ||
| 1488 | |||
| 1489 | n = sprintf(buf, "%d\n", max_depth); | ||
| 1490 | |||
| 1491 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, n); | ||
| 1492 | } | ||
| 1493 | |||
| 1494 | static const struct file_operations graph_depth_fops = { | ||
| 1495 | .open = tracing_open_generic, | ||
| 1496 | .write = graph_depth_write, | ||
| 1497 | .read = graph_depth_read, | ||
| 1498 | .llseek = generic_file_llseek, | ||
| 1499 | }; | ||
| 1500 | |||
| 1501 | static __init int init_graph_debugfs(void) | ||
| 1502 | { | ||
| 1503 | struct dentry *d_tracer; | ||
| 1504 | |||
| 1505 | d_tracer = tracing_init_dentry(); | ||
| 1506 | if (!d_tracer) | ||
| 1507 | return 0; | ||
| 1508 | |||
| 1509 | trace_create_file("max_graph_depth", 0644, d_tracer, | ||
| 1510 | NULL, &graph_depth_fops); | ||
| 1511 | |||
| 1512 | return 0; | ||
| 1513 | } | ||
| 1514 | fs_initcall(init_graph_debugfs); | ||
| 1515 | |||
| 1460 | static __init int init_graph_trace(void) | 1516 | static __init int init_graph_trace(void) |
| 1461 | { | 1517 | { |
| 1462 | max_bytes_for_cpu = snprintf(NULL, 0, "%d", nr_cpu_ids - 1); | 1518 | max_bytes_for_cpu = snprintf(NULL, 0, "%d", nr_cpu_ids - 1); |
