diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-07-05 05:55:43 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-07-05 05:55:43 -0400 |
commit | 931da6137e8e8c622f59251e8b645467aea293f1 (patch) | |
tree | 2169cbd29d5d9a4cbc7104b2a744a95ba746c50d /kernel/trace | |
parent | 5d67be97f8903d05ce53597fb5f3bc25a45e8026 (diff) | |
parent | 1fd8df2c3970c9e7e4e262354154ee39e58bdd7c (diff) |
Merge branch 'tip/perf/core-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into perf/core
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/ftrace.c | 20 | ||||
-rw-r--r-- | kernel/trace/ring_buffer.c | 66 | ||||
-rw-r--r-- | kernel/trace/ring_buffer_benchmark.c | 2 | ||||
-rw-r--r-- | kernel/trace/trace.c | 242 | ||||
-rw-r--r-- | kernel/trace/trace.h | 10 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 26 | ||||
-rw-r--r-- | kernel/trace/trace_functions_graph.c | 223 | ||||
-rw-r--r-- | kernel/trace/trace_irqsoff.c | 4 | ||||
-rw-r--r-- | kernel/trace/trace_kprobe.c | 6 | ||||
-rw-r--r-- | kernel/trace/trace_sched_wakeup.c | 4 | ||||
-rw-r--r-- | kernel/trace/trace_stack.c | 13 |
11 files changed, 308 insertions, 308 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 908038f57440..c997f7371c65 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -32,7 +32,6 @@ | |||
32 | 32 | ||
33 | #include <trace/events/sched.h> | 33 | #include <trace/events/sched.h> |
34 | 34 | ||
35 | #include <asm/ftrace.h> | ||
36 | #include <asm/setup.h> | 35 | #include <asm/setup.h> |
37 | 36 | ||
38 | #include "trace_output.h" | 37 | #include "trace_output.h" |
@@ -82,8 +81,7 @@ static int ftrace_disabled __read_mostly; | |||
82 | 81 | ||
83 | static DEFINE_MUTEX(ftrace_lock); | 82 | static DEFINE_MUTEX(ftrace_lock); |
84 | 83 | ||
85 | static struct ftrace_ops ftrace_list_end __read_mostly = | 84 | static struct ftrace_ops ftrace_list_end __read_mostly = { |
86 | { | ||
87 | .func = ftrace_stub, | 85 | .func = ftrace_stub, |
88 | }; | 86 | }; |
89 | 87 | ||
@@ -785,8 +783,7 @@ static void unregister_ftrace_profiler(void) | |||
785 | unregister_ftrace_graph(); | 783 | unregister_ftrace_graph(); |
786 | } | 784 | } |
787 | #else | 785 | #else |
788 | static struct ftrace_ops ftrace_profile_ops __read_mostly = | 786 | static struct ftrace_ops ftrace_profile_ops __read_mostly = { |
789 | { | ||
790 | .func = function_profile_call, | 787 | .func = function_profile_call, |
791 | }; | 788 | }; |
792 | 789 | ||
@@ -806,19 +803,10 @@ ftrace_profile_write(struct file *filp, const char __user *ubuf, | |||
806 | size_t cnt, loff_t *ppos) | 803 | size_t cnt, loff_t *ppos) |
807 | { | 804 | { |
808 | unsigned long val; | 805 | unsigned long val; |
809 | char buf[64]; /* big enough to hold a number */ | ||
810 | int ret; | 806 | int ret; |
811 | 807 | ||
812 | if (cnt >= sizeof(buf)) | 808 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
813 | return -EINVAL; | 809 | if (ret) |
814 | |||
815 | if (copy_from_user(&buf, ubuf, cnt)) | ||
816 | return -EFAULT; | ||
817 | |||
818 | buf[cnt] = 0; | ||
819 | |||
820 | ret = strict_strtoul(buf, 10, &val); | ||
821 | if (ret < 0) | ||
822 | return ret; | 810 | return ret; |
823 | 811 | ||
824 | val = !!val; | 812 | val = !!val; |
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index b0c7aa407943..731201bf4acc 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -997,15 +997,21 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer, | |||
997 | unsigned nr_pages) | 997 | unsigned nr_pages) |
998 | { | 998 | { |
999 | struct buffer_page *bpage, *tmp; | 999 | struct buffer_page *bpage, *tmp; |
1000 | unsigned long addr; | ||
1001 | LIST_HEAD(pages); | 1000 | LIST_HEAD(pages); |
1002 | unsigned i; | 1001 | unsigned i; |
1003 | 1002 | ||
1004 | WARN_ON(!nr_pages); | 1003 | WARN_ON(!nr_pages); |
1005 | 1004 | ||
1006 | for (i = 0; i < nr_pages; i++) { | 1005 | for (i = 0; i < nr_pages; i++) { |
1006 | struct page *page; | ||
1007 | /* | ||
1008 | * __GFP_NORETRY flag makes sure that the allocation fails | ||
1009 | * gracefully without invoking oom-killer and the system is | ||
1010 | * not destabilized. | ||
1011 | */ | ||
1007 | bpage = kzalloc_node(ALIGN(sizeof(*bpage), cache_line_size()), | 1012 | bpage = kzalloc_node(ALIGN(sizeof(*bpage), cache_line_size()), |
1008 | GFP_KERNEL, cpu_to_node(cpu_buffer->cpu)); | 1013 | GFP_KERNEL | __GFP_NORETRY, |
1014 | cpu_to_node(cpu_buffer->cpu)); | ||
1009 | if (!bpage) | 1015 | if (!bpage) |
1010 | goto free_pages; | 1016 | goto free_pages; |
1011 | 1017 | ||
@@ -1013,10 +1019,11 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer, | |||
1013 | 1019 | ||
1014 | list_add(&bpage->list, &pages); | 1020 | list_add(&bpage->list, &pages); |
1015 | 1021 | ||
1016 | addr = __get_free_page(GFP_KERNEL); | 1022 | page = alloc_pages_node(cpu_to_node(cpu_buffer->cpu), |
1017 | if (!addr) | 1023 | GFP_KERNEL | __GFP_NORETRY, 0); |
1024 | if (!page) | ||
1018 | goto free_pages; | 1025 | goto free_pages; |
1019 | bpage->page = (void *)addr; | 1026 | bpage->page = page_address(page); |
1020 | rb_init_page(bpage->page); | 1027 | rb_init_page(bpage->page); |
1021 | } | 1028 | } |
1022 | 1029 | ||
@@ -1045,7 +1052,7 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) | |||
1045 | { | 1052 | { |
1046 | struct ring_buffer_per_cpu *cpu_buffer; | 1053 | struct ring_buffer_per_cpu *cpu_buffer; |
1047 | struct buffer_page *bpage; | 1054 | struct buffer_page *bpage; |
1048 | unsigned long addr; | 1055 | struct page *page; |
1049 | int ret; | 1056 | int ret; |
1050 | 1057 | ||
1051 | cpu_buffer = kzalloc_node(ALIGN(sizeof(*cpu_buffer), cache_line_size()), | 1058 | cpu_buffer = kzalloc_node(ALIGN(sizeof(*cpu_buffer), cache_line_size()), |
@@ -1067,10 +1074,10 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) | |||
1067 | rb_check_bpage(cpu_buffer, bpage); | 1074 | rb_check_bpage(cpu_buffer, bpage); |
1068 | 1075 | ||
1069 | cpu_buffer->reader_page = bpage; | 1076 | cpu_buffer->reader_page = bpage; |
1070 | addr = __get_free_page(GFP_KERNEL); | 1077 | page = alloc_pages_node(cpu_to_node(cpu), GFP_KERNEL, 0); |
1071 | if (!addr) | 1078 | if (!page) |
1072 | goto fail_free_reader; | 1079 | goto fail_free_reader; |
1073 | bpage->page = (void *)addr; | 1080 | bpage->page = page_address(page); |
1074 | rb_init_page(bpage->page); | 1081 | rb_init_page(bpage->page); |
1075 | 1082 | ||
1076 | INIT_LIST_HEAD(&cpu_buffer->reader_page->list); | 1083 | INIT_LIST_HEAD(&cpu_buffer->reader_page->list); |
@@ -1314,7 +1321,6 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size) | |||
1314 | unsigned nr_pages, rm_pages, new_pages; | 1321 | unsigned nr_pages, rm_pages, new_pages; |
1315 | struct buffer_page *bpage, *tmp; | 1322 | struct buffer_page *bpage, *tmp; |
1316 | unsigned long buffer_size; | 1323 | unsigned long buffer_size; |
1317 | unsigned long addr; | ||
1318 | LIST_HEAD(pages); | 1324 | LIST_HEAD(pages); |
1319 | int i, cpu; | 1325 | int i, cpu; |
1320 | 1326 | ||
@@ -1375,16 +1381,24 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size) | |||
1375 | 1381 | ||
1376 | for_each_buffer_cpu(buffer, cpu) { | 1382 | for_each_buffer_cpu(buffer, cpu) { |
1377 | for (i = 0; i < new_pages; i++) { | 1383 | for (i = 0; i < new_pages; i++) { |
1384 | struct page *page; | ||
1385 | /* | ||
1386 | * __GFP_NORETRY flag makes sure that the allocation | ||
1387 | * fails gracefully without invoking oom-killer and | ||
1388 | * the system is not destabilized. | ||
1389 | */ | ||
1378 | bpage = kzalloc_node(ALIGN(sizeof(*bpage), | 1390 | bpage = kzalloc_node(ALIGN(sizeof(*bpage), |
1379 | cache_line_size()), | 1391 | cache_line_size()), |
1380 | GFP_KERNEL, cpu_to_node(cpu)); | 1392 | GFP_KERNEL | __GFP_NORETRY, |
1393 | cpu_to_node(cpu)); | ||
1381 | if (!bpage) | 1394 | if (!bpage) |
1382 | goto free_pages; | 1395 | goto free_pages; |
1383 | list_add(&bpage->list, &pages); | 1396 | list_add(&bpage->list, &pages); |
1384 | addr = __get_free_page(GFP_KERNEL); | 1397 | page = alloc_pages_node(cpu_to_node(cpu), |
1385 | if (!addr) | 1398 | GFP_KERNEL | __GFP_NORETRY, 0); |
1399 | if (!page) | ||
1386 | goto free_pages; | 1400 | goto free_pages; |
1387 | bpage->page = (void *)addr; | 1401 | bpage->page = page_address(page); |
1388 | rb_init_page(bpage->page); | 1402 | rb_init_page(bpage->page); |
1389 | } | 1403 | } |
1390 | } | 1404 | } |
@@ -3730,16 +3744,17 @@ EXPORT_SYMBOL_GPL(ring_buffer_swap_cpu); | |||
3730 | * Returns: | 3744 | * Returns: |
3731 | * The page allocated, or NULL on error. | 3745 | * The page allocated, or NULL on error. |
3732 | */ | 3746 | */ |
3733 | void *ring_buffer_alloc_read_page(struct ring_buffer *buffer) | 3747 | void *ring_buffer_alloc_read_page(struct ring_buffer *buffer, int cpu) |
3734 | { | 3748 | { |
3735 | struct buffer_data_page *bpage; | 3749 | struct buffer_data_page *bpage; |
3736 | unsigned long addr; | 3750 | struct page *page; |
3737 | 3751 | ||
3738 | addr = __get_free_page(GFP_KERNEL); | 3752 | page = alloc_pages_node(cpu_to_node(cpu), |
3739 | if (!addr) | 3753 | GFP_KERNEL | __GFP_NORETRY, 0); |
3754 | if (!page) | ||
3740 | return NULL; | 3755 | return NULL; |
3741 | 3756 | ||
3742 | bpage = (void *)addr; | 3757 | bpage = page_address(page); |
3743 | 3758 | ||
3744 | rb_init_page(bpage); | 3759 | rb_init_page(bpage); |
3745 | 3760 | ||
@@ -3978,20 +3993,11 @@ rb_simple_write(struct file *filp, const char __user *ubuf, | |||
3978 | size_t cnt, loff_t *ppos) | 3993 | size_t cnt, loff_t *ppos) |
3979 | { | 3994 | { |
3980 | unsigned long *p = filp->private_data; | 3995 | unsigned long *p = filp->private_data; |
3981 | char buf[64]; | ||
3982 | unsigned long val; | 3996 | unsigned long val; |
3983 | int ret; | 3997 | int ret; |
3984 | 3998 | ||
3985 | if (cnt >= sizeof(buf)) | 3999 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
3986 | return -EINVAL; | 4000 | if (ret) |
3987 | |||
3988 | if (copy_from_user(&buf, ubuf, cnt)) | ||
3989 | return -EFAULT; | ||
3990 | |||
3991 | buf[cnt] = 0; | ||
3992 | |||
3993 | ret = strict_strtoul(buf, 10, &val); | ||
3994 | if (ret < 0) | ||
3995 | return ret; | 4001 | return ret; |
3996 | 4002 | ||
3997 | if (val) | 4003 | if (val) |
diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c index 302f8a614635..a5457d577b98 100644 --- a/kernel/trace/ring_buffer_benchmark.c +++ b/kernel/trace/ring_buffer_benchmark.c | |||
@@ -106,7 +106,7 @@ static enum event_status read_page(int cpu) | |||
106 | int inc; | 106 | int inc; |
107 | int i; | 107 | int i; |
108 | 108 | ||
109 | bpage = ring_buffer_alloc_read_page(buffer); | 109 | bpage = ring_buffer_alloc_read_page(buffer, cpu); |
110 | if (!bpage) | 110 | if (!bpage) |
111 | return EVENT_DROPPED; | 111 | return EVENT_DROPPED; |
112 | 112 | ||
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index ee9c921d7f21..d9c16123f6e2 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -343,26 +343,27 @@ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK | | |||
343 | static int trace_stop_count; | 343 | static int trace_stop_count; |
344 | static DEFINE_SPINLOCK(tracing_start_lock); | 344 | static DEFINE_SPINLOCK(tracing_start_lock); |
345 | 345 | ||
346 | static void wakeup_work_handler(struct work_struct *work) | ||
347 | { | ||
348 | wake_up(&trace_wait); | ||
349 | } | ||
350 | |||
351 | static DECLARE_DELAYED_WORK(wakeup_work, wakeup_work_handler); | ||
352 | |||
346 | /** | 353 | /** |
347 | * trace_wake_up - wake up tasks waiting for trace input | 354 | * trace_wake_up - wake up tasks waiting for trace input |
348 | * | 355 | * |
349 | * Simply wakes up any task that is blocked on the trace_wait | 356 | * Schedules a delayed work to wake up any task that is blocked on the |
350 | * queue. These is used with trace_poll for tasks polling the trace. | 357 | * trace_wait queue. These is used with trace_poll for tasks polling the |
358 | * trace. | ||
351 | */ | 359 | */ |
352 | void trace_wake_up(void) | 360 | void trace_wake_up(void) |
353 | { | 361 | { |
354 | int cpu; | 362 | const unsigned long delay = msecs_to_jiffies(2); |
355 | 363 | ||
356 | if (trace_flags & TRACE_ITER_BLOCK) | 364 | if (trace_flags & TRACE_ITER_BLOCK) |
357 | return; | 365 | return; |
358 | /* | 366 | schedule_delayed_work(&wakeup_work, delay); |
359 | * The runqueue_is_locked() can fail, but this is the best we | ||
360 | * have for now: | ||
361 | */ | ||
362 | cpu = get_cpu(); | ||
363 | if (!runqueue_is_locked(cpu)) | ||
364 | wake_up(&trace_wait); | ||
365 | put_cpu(); | ||
366 | } | 367 | } |
367 | 368 | ||
368 | static int __init set_buf_size(char *str) | 369 | static int __init set_buf_size(char *str) |
@@ -424,6 +425,7 @@ static const char *trace_options[] = { | |||
424 | "graph-time", | 425 | "graph-time", |
425 | "record-cmd", | 426 | "record-cmd", |
426 | "overwrite", | 427 | "overwrite", |
428 | "disable_on_free", | ||
427 | NULL | 429 | NULL |
428 | }; | 430 | }; |
429 | 431 | ||
@@ -1191,6 +1193,18 @@ void trace_nowake_buffer_unlock_commit(struct ring_buffer *buffer, | |||
1191 | } | 1193 | } |
1192 | EXPORT_SYMBOL_GPL(trace_nowake_buffer_unlock_commit); | 1194 | EXPORT_SYMBOL_GPL(trace_nowake_buffer_unlock_commit); |
1193 | 1195 | ||
1196 | void trace_nowake_buffer_unlock_commit_regs(struct ring_buffer *buffer, | ||
1197 | struct ring_buffer_event *event, | ||
1198 | unsigned long flags, int pc, | ||
1199 | struct pt_regs *regs) | ||
1200 | { | ||
1201 | ring_buffer_unlock_commit(buffer, event); | ||
1202 | |||
1203 | ftrace_trace_stack_regs(buffer, flags, 0, pc, regs); | ||
1204 | ftrace_trace_userstack(buffer, flags, pc); | ||
1205 | } | ||
1206 | EXPORT_SYMBOL_GPL(trace_nowake_buffer_unlock_commit_regs); | ||
1207 | |||
1194 | void trace_current_buffer_discard_commit(struct ring_buffer *buffer, | 1208 | void trace_current_buffer_discard_commit(struct ring_buffer *buffer, |
1195 | struct ring_buffer_event *event) | 1209 | struct ring_buffer_event *event) |
1196 | { | 1210 | { |
@@ -1236,7 +1250,7 @@ ftrace(struct trace_array *tr, struct trace_array_cpu *data, | |||
1236 | #ifdef CONFIG_STACKTRACE | 1250 | #ifdef CONFIG_STACKTRACE |
1237 | static void __ftrace_trace_stack(struct ring_buffer *buffer, | 1251 | static void __ftrace_trace_stack(struct ring_buffer *buffer, |
1238 | unsigned long flags, | 1252 | unsigned long flags, |
1239 | int skip, int pc) | 1253 | int skip, int pc, struct pt_regs *regs) |
1240 | { | 1254 | { |
1241 | struct ftrace_event_call *call = &event_kernel_stack; | 1255 | struct ftrace_event_call *call = &event_kernel_stack; |
1242 | struct ring_buffer_event *event; | 1256 | struct ring_buffer_event *event; |
@@ -1255,24 +1269,36 @@ static void __ftrace_trace_stack(struct ring_buffer *buffer, | |||
1255 | trace.skip = skip; | 1269 | trace.skip = skip; |
1256 | trace.entries = entry->caller; | 1270 | trace.entries = entry->caller; |
1257 | 1271 | ||
1258 | save_stack_trace(&trace); | 1272 | if (regs) |
1273 | save_stack_trace_regs(regs, &trace); | ||
1274 | else | ||
1275 | save_stack_trace(&trace); | ||
1259 | if (!filter_check_discard(call, entry, buffer, event)) | 1276 | if (!filter_check_discard(call, entry, buffer, event)) |
1260 | ring_buffer_unlock_commit(buffer, event); | 1277 | ring_buffer_unlock_commit(buffer, event); |
1261 | } | 1278 | } |
1262 | 1279 | ||
1280 | void ftrace_trace_stack_regs(struct ring_buffer *buffer, unsigned long flags, | ||
1281 | int skip, int pc, struct pt_regs *regs) | ||
1282 | { | ||
1283 | if (!(trace_flags & TRACE_ITER_STACKTRACE)) | ||
1284 | return; | ||
1285 | |||
1286 | __ftrace_trace_stack(buffer, flags, skip, pc, regs); | ||
1287 | } | ||
1288 | |||
1263 | void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags, | 1289 | void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags, |
1264 | int skip, int pc) | 1290 | int skip, int pc) |
1265 | { | 1291 | { |
1266 | if (!(trace_flags & TRACE_ITER_STACKTRACE)) | 1292 | if (!(trace_flags & TRACE_ITER_STACKTRACE)) |
1267 | return; | 1293 | return; |
1268 | 1294 | ||
1269 | __ftrace_trace_stack(buffer, flags, skip, pc); | 1295 | __ftrace_trace_stack(buffer, flags, skip, pc, NULL); |
1270 | } | 1296 | } |
1271 | 1297 | ||
1272 | void __trace_stack(struct trace_array *tr, unsigned long flags, int skip, | 1298 | void __trace_stack(struct trace_array *tr, unsigned long flags, int skip, |
1273 | int pc) | 1299 | int pc) |
1274 | { | 1300 | { |
1275 | __ftrace_trace_stack(tr->buffer, flags, skip, pc); | 1301 | __ftrace_trace_stack(tr->buffer, flags, skip, pc, NULL); |
1276 | } | 1302 | } |
1277 | 1303 | ||
1278 | /** | 1304 | /** |
@@ -1288,7 +1314,7 @@ void trace_dump_stack(void) | |||
1288 | local_save_flags(flags); | 1314 | local_save_flags(flags); |
1289 | 1315 | ||
1290 | /* skipping 3 traces, seems to get us at the caller of this function */ | 1316 | /* skipping 3 traces, seems to get us at the caller of this function */ |
1291 | __ftrace_trace_stack(global_trace.buffer, flags, 3, preempt_count()); | 1317 | __ftrace_trace_stack(global_trace.buffer, flags, 3, preempt_count(), NULL); |
1292 | } | 1318 | } |
1293 | 1319 | ||
1294 | static DEFINE_PER_CPU(int, user_stack_count); | 1320 | static DEFINE_PER_CPU(int, user_stack_count); |
@@ -2051,6 +2077,9 @@ void trace_default_header(struct seq_file *m) | |||
2051 | { | 2077 | { |
2052 | struct trace_iterator *iter = m->private; | 2078 | struct trace_iterator *iter = m->private; |
2053 | 2079 | ||
2080 | if (!(trace_flags & TRACE_ITER_CONTEXT_INFO)) | ||
2081 | return; | ||
2082 | |||
2054 | if (iter->iter_flags & TRACE_FILE_LAT_FMT) { | 2083 | if (iter->iter_flags & TRACE_FILE_LAT_FMT) { |
2055 | /* print nothing if the buffers are empty */ | 2084 | /* print nothing if the buffers are empty */ |
2056 | if (trace_empty(iter)) | 2085 | if (trace_empty(iter)) |
@@ -2701,20 +2730,11 @@ tracing_ctrl_write(struct file *filp, const char __user *ubuf, | |||
2701 | size_t cnt, loff_t *ppos) | 2730 | size_t cnt, loff_t *ppos) |
2702 | { | 2731 | { |
2703 | struct trace_array *tr = filp->private_data; | 2732 | struct trace_array *tr = filp->private_data; |
2704 | char buf[64]; | ||
2705 | unsigned long val; | 2733 | unsigned long val; |
2706 | int ret; | 2734 | int ret; |
2707 | 2735 | ||
2708 | if (cnt >= sizeof(buf)) | 2736 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
2709 | return -EINVAL; | 2737 | if (ret) |
2710 | |||
2711 | if (copy_from_user(&buf, ubuf, cnt)) | ||
2712 | return -EFAULT; | ||
2713 | |||
2714 | buf[cnt] = 0; | ||
2715 | |||
2716 | ret = strict_strtoul(buf, 10, &val); | ||
2717 | if (ret < 0) | ||
2718 | return ret; | 2738 | return ret; |
2719 | 2739 | ||
2720 | val = !!val; | 2740 | val = !!val; |
@@ -2767,7 +2787,7 @@ int tracer_init(struct tracer *t, struct trace_array *tr) | |||
2767 | return t->init(tr); | 2787 | return t->init(tr); |
2768 | } | 2788 | } |
2769 | 2789 | ||
2770 | static int tracing_resize_ring_buffer(unsigned long size) | 2790 | static int __tracing_resize_ring_buffer(unsigned long size) |
2771 | { | 2791 | { |
2772 | int ret; | 2792 | int ret; |
2773 | 2793 | ||
@@ -2819,6 +2839,41 @@ static int tracing_resize_ring_buffer(unsigned long size) | |||
2819 | return ret; | 2839 | return ret; |
2820 | } | 2840 | } |
2821 | 2841 | ||
2842 | static ssize_t tracing_resize_ring_buffer(unsigned long size) | ||
2843 | { | ||
2844 | int cpu, ret = size; | ||
2845 | |||
2846 | mutex_lock(&trace_types_lock); | ||
2847 | |||
2848 | tracing_stop(); | ||
2849 | |||
2850 | /* disable all cpu buffers */ | ||
2851 | for_each_tracing_cpu(cpu) { | ||
2852 | if (global_trace.data[cpu]) | ||
2853 | atomic_inc(&global_trace.data[cpu]->disabled); | ||
2854 | if (max_tr.data[cpu]) | ||
2855 | atomic_inc(&max_tr.data[cpu]->disabled); | ||
2856 | } | ||
2857 | |||
2858 | if (size != global_trace.entries) | ||
2859 | ret = __tracing_resize_ring_buffer(size); | ||
2860 | |||
2861 | if (ret < 0) | ||
2862 | ret = -ENOMEM; | ||
2863 | |||
2864 | for_each_tracing_cpu(cpu) { | ||
2865 | if (global_trace.data[cpu]) | ||
2866 | atomic_dec(&global_trace.data[cpu]->disabled); | ||
2867 | if (max_tr.data[cpu]) | ||
2868 | atomic_dec(&max_tr.data[cpu]->disabled); | ||
2869 | } | ||
2870 | |||
2871 | tracing_start(); | ||
2872 | mutex_unlock(&trace_types_lock); | ||
2873 | |||
2874 | return ret; | ||
2875 | } | ||
2876 | |||
2822 | 2877 | ||
2823 | /** | 2878 | /** |
2824 | * tracing_update_buffers - used by tracing facility to expand ring buffers | 2879 | * tracing_update_buffers - used by tracing facility to expand ring buffers |
@@ -2836,7 +2891,7 @@ int tracing_update_buffers(void) | |||
2836 | 2891 | ||
2837 | mutex_lock(&trace_types_lock); | 2892 | mutex_lock(&trace_types_lock); |
2838 | if (!ring_buffer_expanded) | 2893 | if (!ring_buffer_expanded) |
2839 | ret = tracing_resize_ring_buffer(trace_buf_size); | 2894 | ret = __tracing_resize_ring_buffer(trace_buf_size); |
2840 | mutex_unlock(&trace_types_lock); | 2895 | mutex_unlock(&trace_types_lock); |
2841 | 2896 | ||
2842 | return ret; | 2897 | return ret; |
@@ -2860,7 +2915,7 @@ static int tracing_set_tracer(const char *buf) | |||
2860 | mutex_lock(&trace_types_lock); | 2915 | mutex_lock(&trace_types_lock); |
2861 | 2916 | ||
2862 | if (!ring_buffer_expanded) { | 2917 | if (!ring_buffer_expanded) { |
2863 | ret = tracing_resize_ring_buffer(trace_buf_size); | 2918 | ret = __tracing_resize_ring_buffer(trace_buf_size); |
2864 | if (ret < 0) | 2919 | if (ret < 0) |
2865 | goto out; | 2920 | goto out; |
2866 | ret = 0; | 2921 | ret = 0; |
@@ -2966,20 +3021,11 @@ tracing_max_lat_write(struct file *filp, const char __user *ubuf, | |||
2966 | size_t cnt, loff_t *ppos) | 3021 | size_t cnt, loff_t *ppos) |
2967 | { | 3022 | { |
2968 | unsigned long *ptr = filp->private_data; | 3023 | unsigned long *ptr = filp->private_data; |
2969 | char buf[64]; | ||
2970 | unsigned long val; | 3024 | unsigned long val; |
2971 | int ret; | 3025 | int ret; |
2972 | 3026 | ||
2973 | if (cnt >= sizeof(buf)) | 3027 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
2974 | return -EINVAL; | 3028 | if (ret) |
2975 | |||
2976 | if (copy_from_user(&buf, ubuf, cnt)) | ||
2977 | return -EFAULT; | ||
2978 | |||
2979 | buf[cnt] = 0; | ||
2980 | |||
2981 | ret = strict_strtoul(buf, 10, &val); | ||
2982 | if (ret < 0) | ||
2983 | return ret; | 3029 | return ret; |
2984 | 3030 | ||
2985 | *ptr = val * 1000; | 3031 | *ptr = val * 1000; |
@@ -3434,67 +3480,54 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
3434 | size_t cnt, loff_t *ppos) | 3480 | size_t cnt, loff_t *ppos) |
3435 | { | 3481 | { |
3436 | unsigned long val; | 3482 | unsigned long val; |
3437 | char buf[64]; | 3483 | int ret; |
3438 | int ret, cpu; | ||
3439 | |||
3440 | if (cnt >= sizeof(buf)) | ||
3441 | return -EINVAL; | ||
3442 | |||
3443 | if (copy_from_user(&buf, ubuf, cnt)) | ||
3444 | return -EFAULT; | ||
3445 | |||
3446 | buf[cnt] = 0; | ||
3447 | 3484 | ||
3448 | ret = strict_strtoul(buf, 10, &val); | 3485 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
3449 | if (ret < 0) | 3486 | if (ret) |
3450 | return ret; | 3487 | return ret; |
3451 | 3488 | ||
3452 | /* must have at least 1 entry */ | 3489 | /* must have at least 1 entry */ |
3453 | if (!val) | 3490 | if (!val) |
3454 | return -EINVAL; | 3491 | return -EINVAL; |
3455 | 3492 | ||
3456 | mutex_lock(&trace_types_lock); | ||
3457 | |||
3458 | tracing_stop(); | ||
3459 | |||
3460 | /* disable all cpu buffers */ | ||
3461 | for_each_tracing_cpu(cpu) { | ||
3462 | if (global_trace.data[cpu]) | ||
3463 | atomic_inc(&global_trace.data[cpu]->disabled); | ||
3464 | if (max_tr.data[cpu]) | ||
3465 | atomic_inc(&max_tr.data[cpu]->disabled); | ||
3466 | } | ||
3467 | |||
3468 | /* value is in KB */ | 3493 | /* value is in KB */ |
3469 | val <<= 10; | 3494 | val <<= 10; |
3470 | 3495 | ||
3471 | if (val != global_trace.entries) { | 3496 | ret = tracing_resize_ring_buffer(val); |
3472 | ret = tracing_resize_ring_buffer(val); | 3497 | if (ret < 0) |
3473 | if (ret < 0) { | 3498 | return ret; |
3474 | cnt = ret; | ||
3475 | goto out; | ||
3476 | } | ||
3477 | } | ||
3478 | 3499 | ||
3479 | *ppos += cnt; | 3500 | *ppos += cnt; |
3480 | 3501 | ||
3481 | /* If check pages failed, return ENOMEM */ | 3502 | return cnt; |
3482 | if (tracing_disabled) | 3503 | } |
3483 | cnt = -ENOMEM; | ||
3484 | out: | ||
3485 | for_each_tracing_cpu(cpu) { | ||
3486 | if (global_trace.data[cpu]) | ||
3487 | atomic_dec(&global_trace.data[cpu]->disabled); | ||
3488 | if (max_tr.data[cpu]) | ||
3489 | atomic_dec(&max_tr.data[cpu]->disabled); | ||
3490 | } | ||
3491 | 3504 | ||
3492 | tracing_start(); | 3505 | static ssize_t |
3493 | mutex_unlock(&trace_types_lock); | 3506 | tracing_free_buffer_write(struct file *filp, const char __user *ubuf, |
3507 | size_t cnt, loff_t *ppos) | ||
3508 | { | ||
3509 | /* | ||
3510 | * There is no need to read what the user has written, this function | ||
3511 | * is just to make sure that there is no error when "echo" is used | ||
3512 | */ | ||
3513 | |||
3514 | *ppos += cnt; | ||
3494 | 3515 | ||
3495 | return cnt; | 3516 | return cnt; |
3496 | } | 3517 | } |
3497 | 3518 | ||
3519 | static int | ||
3520 | tracing_free_buffer_release(struct inode *inode, struct file *filp) | ||
3521 | { | ||
3522 | /* disable tracing ? */ | ||
3523 | if (trace_flags & TRACE_ITER_STOP_ON_FREE) | ||
3524 | tracing_off(); | ||
3525 | /* resize the ring buffer to 0 */ | ||
3526 | tracing_resize_ring_buffer(0); | ||
3527 | |||
3528 | return 0; | ||
3529 | } | ||
3530 | |||
3498 | static int mark_printk(const char *fmt, ...) | 3531 | static int mark_printk(const char *fmt, ...) |
3499 | { | 3532 | { |
3500 | int ret; | 3533 | int ret; |
@@ -3640,6 +3673,11 @@ static const struct file_operations tracing_entries_fops = { | |||
3640 | .llseek = generic_file_llseek, | 3673 | .llseek = generic_file_llseek, |
3641 | }; | 3674 | }; |
3642 | 3675 | ||
3676 | static const struct file_operations tracing_free_buffer_fops = { | ||
3677 | .write = tracing_free_buffer_write, | ||
3678 | .release = tracing_free_buffer_release, | ||
3679 | }; | ||
3680 | |||
3643 | static const struct file_operations tracing_mark_fops = { | 3681 | static const struct file_operations tracing_mark_fops = { |
3644 | .open = tracing_open_generic, | 3682 | .open = tracing_open_generic, |
3645 | .write = tracing_mark_write, | 3683 | .write = tracing_mark_write, |
@@ -3696,7 +3734,7 @@ tracing_buffers_read(struct file *filp, char __user *ubuf, | |||
3696 | return 0; | 3734 | return 0; |
3697 | 3735 | ||
3698 | if (!info->spare) | 3736 | if (!info->spare) |
3699 | info->spare = ring_buffer_alloc_read_page(info->tr->buffer); | 3737 | info->spare = ring_buffer_alloc_read_page(info->tr->buffer, info->cpu); |
3700 | if (!info->spare) | 3738 | if (!info->spare) |
3701 | return -ENOMEM; | 3739 | return -ENOMEM; |
3702 | 3740 | ||
@@ -3853,7 +3891,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
3853 | 3891 | ||
3854 | ref->ref = 1; | 3892 | ref->ref = 1; |
3855 | ref->buffer = info->tr->buffer; | 3893 | ref->buffer = info->tr->buffer; |
3856 | ref->page = ring_buffer_alloc_read_page(ref->buffer); | 3894 | ref->page = ring_buffer_alloc_read_page(ref->buffer, info->cpu); |
3857 | if (!ref->page) { | 3895 | if (!ref->page) { |
3858 | kfree(ref); | 3896 | kfree(ref); |
3859 | break; | 3897 | break; |
@@ -3862,8 +3900,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
3862 | r = ring_buffer_read_page(ref->buffer, &ref->page, | 3900 | r = ring_buffer_read_page(ref->buffer, &ref->page, |
3863 | len, info->cpu, 1); | 3901 | len, info->cpu, 1); |
3864 | if (r < 0) { | 3902 | if (r < 0) { |
3865 | ring_buffer_free_read_page(ref->buffer, | 3903 | ring_buffer_free_read_page(ref->buffer, ref->page); |
3866 | ref->page); | ||
3867 | kfree(ref); | 3904 | kfree(ref); |
3868 | break; | 3905 | break; |
3869 | } | 3906 | } |
@@ -4099,19 +4136,10 @@ trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
4099 | { | 4136 | { |
4100 | struct trace_option_dentry *topt = filp->private_data; | 4137 | struct trace_option_dentry *topt = filp->private_data; |
4101 | unsigned long val; | 4138 | unsigned long val; |
4102 | char buf[64]; | ||
4103 | int ret; | 4139 | int ret; |
4104 | 4140 | ||
4105 | if (cnt >= sizeof(buf)) | 4141 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
4106 | return -EINVAL; | 4142 | if (ret) |
4107 | |||
4108 | if (copy_from_user(&buf, ubuf, cnt)) | ||
4109 | return -EFAULT; | ||
4110 | |||
4111 | buf[cnt] = 0; | ||
4112 | |||
4113 | ret = strict_strtoul(buf, 10, &val); | ||
4114 | if (ret < 0) | ||
4115 | return ret; | 4143 | return ret; |
4116 | 4144 | ||
4117 | if (val != 0 && val != 1) | 4145 | if (val != 0 && val != 1) |
@@ -4159,20 +4187,11 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
4159 | loff_t *ppos) | 4187 | loff_t *ppos) |
4160 | { | 4188 | { |
4161 | long index = (long)filp->private_data; | 4189 | long index = (long)filp->private_data; |
4162 | char buf[64]; | ||
4163 | unsigned long val; | 4190 | unsigned long val; |
4164 | int ret; | 4191 | int ret; |
4165 | 4192 | ||
4166 | if (cnt >= sizeof(buf)) | 4193 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
4167 | return -EINVAL; | 4194 | if (ret) |
4168 | |||
4169 | if (copy_from_user(&buf, ubuf, cnt)) | ||
4170 | return -EFAULT; | ||
4171 | |||
4172 | buf[cnt] = 0; | ||
4173 | |||
4174 | ret = strict_strtoul(buf, 10, &val); | ||
4175 | if (ret < 0) | ||
4176 | return ret; | 4195 | return ret; |
4177 | 4196 | ||
4178 | if (val != 0 && val != 1) | 4197 | if (val != 0 && val != 1) |
@@ -4365,6 +4384,9 @@ static __init int tracer_init_debugfs(void) | |||
4365 | trace_create_file("buffer_size_kb", 0644, d_tracer, | 4384 | trace_create_file("buffer_size_kb", 0644, d_tracer, |
4366 | &global_trace, &tracing_entries_fops); | 4385 | &global_trace, &tracing_entries_fops); |
4367 | 4386 | ||
4387 | trace_create_file("free_buffer", 0644, d_tracer, | ||
4388 | &global_trace, &tracing_free_buffer_fops); | ||
4389 | |||
4368 | trace_create_file("trace_marker", 0220, d_tracer, | 4390 | trace_create_file("trace_marker", 0220, d_tracer, |
4369 | NULL, &tracing_mark_fops); | 4391 | NULL, &tracing_mark_fops); |
4370 | 4392 | ||
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 229f8591f61d..a3e2db708072 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -389,6 +389,9 @@ void update_max_tr_single(struct trace_array *tr, | |||
389 | void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags, | 389 | void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags, |
390 | int skip, int pc); | 390 | int skip, int pc); |
391 | 391 | ||
392 | void ftrace_trace_stack_regs(struct ring_buffer *buffer, unsigned long flags, | ||
393 | int skip, int pc, struct pt_regs *regs); | ||
394 | |||
392 | void ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, | 395 | void ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, |
393 | int pc); | 396 | int pc); |
394 | 397 | ||
@@ -400,6 +403,12 @@ static inline void ftrace_trace_stack(struct ring_buffer *buffer, | |||
400 | { | 403 | { |
401 | } | 404 | } |
402 | 405 | ||
406 | static inline void ftrace_trace_stack_regs(struct ring_buffer *buffer, | ||
407 | unsigned long flags, int skip, | ||
408 | int pc, struct pt_regs *regs) | ||
409 | { | ||
410 | } | ||
411 | |||
403 | static inline void ftrace_trace_userstack(struct ring_buffer *buffer, | 412 | static inline void ftrace_trace_userstack(struct ring_buffer *buffer, |
404 | unsigned long flags, int pc) | 413 | unsigned long flags, int pc) |
405 | { | 414 | { |
@@ -609,6 +618,7 @@ enum trace_iterator_flags { | |||
609 | TRACE_ITER_GRAPH_TIME = 0x80000, | 618 | TRACE_ITER_GRAPH_TIME = 0x80000, |
610 | TRACE_ITER_RECORD_CMD = 0x100000, | 619 | TRACE_ITER_RECORD_CMD = 0x100000, |
611 | TRACE_ITER_OVERWRITE = 0x200000, | 620 | TRACE_ITER_OVERWRITE = 0x200000, |
621 | TRACE_ITER_STOP_ON_FREE = 0x400000, | ||
612 | }; | 622 | }; |
613 | 623 | ||
614 | /* | 624 | /* |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 686ec399f2a8..4d7e1498ae91 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -486,20 +486,11 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
486 | loff_t *ppos) | 486 | loff_t *ppos) |
487 | { | 487 | { |
488 | struct ftrace_event_call *call = filp->private_data; | 488 | struct ftrace_event_call *call = filp->private_data; |
489 | char buf[64]; | ||
490 | unsigned long val; | 489 | unsigned long val; |
491 | int ret; | 490 | int ret; |
492 | 491 | ||
493 | if (cnt >= sizeof(buf)) | 492 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
494 | return -EINVAL; | 493 | if (ret) |
495 | |||
496 | if (copy_from_user(&buf, ubuf, cnt)) | ||
497 | return -EFAULT; | ||
498 | |||
499 | buf[cnt] = 0; | ||
500 | |||
501 | ret = strict_strtoul(buf, 10, &val); | ||
502 | if (ret < 0) | ||
503 | return ret; | 494 | return ret; |
504 | 495 | ||
505 | ret = tracing_update_buffers(); | 496 | ret = tracing_update_buffers(); |
@@ -571,19 +562,10 @@ system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
571 | { | 562 | { |
572 | const char *system = filp->private_data; | 563 | const char *system = filp->private_data; |
573 | unsigned long val; | 564 | unsigned long val; |
574 | char buf[64]; | ||
575 | ssize_t ret; | 565 | ssize_t ret; |
576 | 566 | ||
577 | if (cnt >= sizeof(buf)) | 567 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
578 | return -EINVAL; | 568 | if (ret) |
579 | |||
580 | if (copy_from_user(&buf, ubuf, cnt)) | ||
581 | return -EFAULT; | ||
582 | |||
583 | buf[cnt] = 0; | ||
584 | |||
585 | ret = strict_strtoul(buf, 10, &val); | ||
586 | if (ret < 0) | ||
587 | return ret; | 569 | return ret; |
588 | 570 | ||
589 | ret = tracing_update_buffers(); | 571 | ret = tracing_update_buffers(); |
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 962cdb24ed81..e8d6bb55d719 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c | |||
@@ -74,6 +74,20 @@ static struct tracer_flags tracer_flags = { | |||
74 | 74 | ||
75 | static struct trace_array *graph_array; | 75 | static struct trace_array *graph_array; |
76 | 76 | ||
77 | /* | ||
78 | * DURATION column is being also used to display IRQ signs, | ||
79 | * following values are used by print_graph_irq and others | ||
80 | * to fill in space into DURATION column. | ||
81 | */ | ||
82 | enum { | ||
83 | DURATION_FILL_FULL = -1, | ||
84 | DURATION_FILL_START = -2, | ||
85 | DURATION_FILL_END = -3, | ||
86 | }; | ||
87 | |||
88 | static enum print_line_t | ||
89 | print_graph_duration(unsigned long long duration, struct trace_seq *s, | ||
90 | u32 flags); | ||
77 | 91 | ||
78 | /* Add a function return address to the trace stack on thread info.*/ | 92 | /* Add a function return address to the trace stack on thread info.*/ |
79 | int | 93 | int |
@@ -577,32 +591,6 @@ get_return_for_leaf(struct trace_iterator *iter, | |||
577 | return next; | 591 | return next; |
578 | } | 592 | } |
579 | 593 | ||
580 | /* Signal a overhead of time execution to the output */ | ||
581 | static int | ||
582 | print_graph_overhead(unsigned long long duration, struct trace_seq *s, | ||
583 | u32 flags) | ||
584 | { | ||
585 | /* If duration disappear, we don't need anything */ | ||
586 | if (!(flags & TRACE_GRAPH_PRINT_DURATION)) | ||
587 | return 1; | ||
588 | |||
589 | /* Non nested entry or return */ | ||
590 | if (duration == -1) | ||
591 | return trace_seq_printf(s, " "); | ||
592 | |||
593 | if (flags & TRACE_GRAPH_PRINT_OVERHEAD) { | ||
594 | /* Duration exceeded 100 msecs */ | ||
595 | if (duration > 100000ULL) | ||
596 | return trace_seq_printf(s, "! "); | ||
597 | |||
598 | /* Duration exceeded 10 msecs */ | ||
599 | if (duration > 10000ULL) | ||
600 | return trace_seq_printf(s, "+ "); | ||
601 | } | ||
602 | |||
603 | return trace_seq_printf(s, " "); | ||
604 | } | ||
605 | |||
606 | static int print_graph_abs_time(u64 t, struct trace_seq *s) | 594 | static int print_graph_abs_time(u64 t, struct trace_seq *s) |
607 | { | 595 | { |
608 | unsigned long usecs_rem; | 596 | unsigned long usecs_rem; |
@@ -625,34 +613,36 @@ print_graph_irq(struct trace_iterator *iter, unsigned long addr, | |||
625 | addr >= (unsigned long)__irqentry_text_end) | 613 | addr >= (unsigned long)__irqentry_text_end) |
626 | return TRACE_TYPE_UNHANDLED; | 614 | return TRACE_TYPE_UNHANDLED; |
627 | 615 | ||
628 | /* Absolute time */ | 616 | if (trace_flags & TRACE_ITER_CONTEXT_INFO) { |
629 | if (flags & TRACE_GRAPH_PRINT_ABS_TIME) { | 617 | /* Absolute time */ |
630 | ret = print_graph_abs_time(iter->ts, s); | 618 | if (flags & TRACE_GRAPH_PRINT_ABS_TIME) { |
631 | if (!ret) | 619 | ret = print_graph_abs_time(iter->ts, s); |
632 | return TRACE_TYPE_PARTIAL_LINE; | 620 | if (!ret) |
633 | } | 621 | return TRACE_TYPE_PARTIAL_LINE; |
622 | } | ||
634 | 623 | ||
635 | /* Cpu */ | 624 | /* Cpu */ |
636 | if (flags & TRACE_GRAPH_PRINT_CPU) { | 625 | if (flags & TRACE_GRAPH_PRINT_CPU) { |
637 | ret = print_graph_cpu(s, cpu); | 626 | ret = print_graph_cpu(s, cpu); |
638 | if (ret == TRACE_TYPE_PARTIAL_LINE) | 627 | if (ret == TRACE_TYPE_PARTIAL_LINE) |
639 | return TRACE_TYPE_PARTIAL_LINE; | 628 | return TRACE_TYPE_PARTIAL_LINE; |
640 | } | 629 | } |
641 | 630 | ||
642 | /* Proc */ | 631 | /* Proc */ |
643 | if (flags & TRACE_GRAPH_PRINT_PROC) { | 632 | if (flags & TRACE_GRAPH_PRINT_PROC) { |
644 | ret = print_graph_proc(s, pid); | 633 | ret = print_graph_proc(s, pid); |
645 | if (ret == TRACE_TYPE_PARTIAL_LINE) | 634 | if (ret == TRACE_TYPE_PARTIAL_LINE) |
646 | return TRACE_TYPE_PARTIAL_LINE; | 635 | return TRACE_TYPE_PARTIAL_LINE; |
647 | ret = trace_seq_printf(s, " | "); | 636 | ret = trace_seq_printf(s, " | "); |
648 | if (!ret) | 637 | if (!ret) |
649 | return TRACE_TYPE_PARTIAL_LINE; | 638 | return TRACE_TYPE_PARTIAL_LINE; |
639 | } | ||
650 | } | 640 | } |
651 | 641 | ||
652 | /* No overhead */ | 642 | /* No overhead */ |
653 | ret = print_graph_overhead(-1, s, flags); | 643 | ret = print_graph_duration(DURATION_FILL_START, s, flags); |
654 | if (!ret) | 644 | if (ret != TRACE_TYPE_HANDLED) |
655 | return TRACE_TYPE_PARTIAL_LINE; | 645 | return ret; |
656 | 646 | ||
657 | if (type == TRACE_GRAPH_ENT) | 647 | if (type == TRACE_GRAPH_ENT) |
658 | ret = trace_seq_printf(s, "==========>"); | 648 | ret = trace_seq_printf(s, "==========>"); |
@@ -662,9 +652,10 @@ print_graph_irq(struct trace_iterator *iter, unsigned long addr, | |||
662 | if (!ret) | 652 | if (!ret) |
663 | return TRACE_TYPE_PARTIAL_LINE; | 653 | return TRACE_TYPE_PARTIAL_LINE; |
664 | 654 | ||
665 | /* Don't close the duration column if haven't one */ | 655 | ret = print_graph_duration(DURATION_FILL_END, s, flags); |
666 | if (flags & TRACE_GRAPH_PRINT_DURATION) | 656 | if (ret != TRACE_TYPE_HANDLED) |
667 | trace_seq_printf(s, " |"); | 657 | return ret; |
658 | |||
668 | ret = trace_seq_printf(s, "\n"); | 659 | ret = trace_seq_printf(s, "\n"); |
669 | 660 | ||
670 | if (!ret) | 661 | if (!ret) |
@@ -716,9 +707,49 @@ trace_print_graph_duration(unsigned long long duration, struct trace_seq *s) | |||
716 | } | 707 | } |
717 | 708 | ||
718 | static enum print_line_t | 709 | static enum print_line_t |
719 | print_graph_duration(unsigned long long duration, struct trace_seq *s) | 710 | print_graph_duration(unsigned long long duration, struct trace_seq *s, |
711 | u32 flags) | ||
720 | { | 712 | { |
721 | int ret; | 713 | int ret = -1; |
714 | |||
715 | if (!(flags & TRACE_GRAPH_PRINT_DURATION) || | ||
716 | !(trace_flags & TRACE_ITER_CONTEXT_INFO)) | ||
717 | return TRACE_TYPE_HANDLED; | ||
718 | |||
719 | /* No real adata, just filling the column with spaces */ | ||
720 | switch (duration) { | ||
721 | case DURATION_FILL_FULL: | ||
722 | ret = trace_seq_printf(s, " | "); | ||
723 | return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE; | ||
724 | case DURATION_FILL_START: | ||
725 | ret = trace_seq_printf(s, " "); | ||
726 | return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE; | ||
727 | case DURATION_FILL_END: | ||
728 | ret = trace_seq_printf(s, " |"); | ||
729 | return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE; | ||
730 | } | ||
731 | |||
732 | /* Signal a overhead of time execution to the output */ | ||
733 | if (flags & TRACE_GRAPH_PRINT_OVERHEAD) { | ||
734 | /* Duration exceeded 100 msecs */ | ||
735 | if (duration > 100000ULL) | ||
736 | ret = trace_seq_printf(s, "! "); | ||
737 | /* Duration exceeded 10 msecs */ | ||
738 | else if (duration > 10000ULL) | ||
739 | ret = trace_seq_printf(s, "+ "); | ||
740 | } | ||
741 | |||
742 | /* | ||
743 | * The -1 means we either did not exceed the duration tresholds | ||
744 | * or we dont want to print out the overhead. Either way we need | ||
745 | * to fill out the space. | ||
746 | */ | ||
747 | if (ret == -1) | ||
748 | ret = trace_seq_printf(s, " "); | ||
749 | |||
750 | /* Catching here any failure happenned above */ | ||
751 | if (!ret) | ||
752 | return TRACE_TYPE_PARTIAL_LINE; | ||
722 | 753 | ||
723 | ret = trace_print_graph_duration(duration, s); | 754 | ret = trace_print_graph_duration(duration, s); |
724 | if (ret != TRACE_TYPE_HANDLED) | 755 | if (ret != TRACE_TYPE_HANDLED) |
@@ -767,18 +798,11 @@ print_graph_entry_leaf(struct trace_iterator *iter, | |||
767 | cpu_data->enter_funcs[call->depth] = 0; | 798 | cpu_data->enter_funcs[call->depth] = 0; |
768 | } | 799 | } |
769 | 800 | ||
770 | /* Overhead */ | 801 | /* Overhead and duration */ |
771 | ret = print_graph_overhead(duration, s, flags); | 802 | ret = print_graph_duration(duration, s, flags); |
772 | if (!ret) | 803 | if (ret == TRACE_TYPE_PARTIAL_LINE) |
773 | return TRACE_TYPE_PARTIAL_LINE; | 804 | return TRACE_TYPE_PARTIAL_LINE; |
774 | 805 | ||
775 | /* Duration */ | ||
776 | if (flags & TRACE_GRAPH_PRINT_DURATION) { | ||
777 | ret = print_graph_duration(duration, s); | ||
778 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
779 | return TRACE_TYPE_PARTIAL_LINE; | ||
780 | } | ||
781 | |||
782 | /* Function */ | 806 | /* Function */ |
783 | for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) { | 807 | for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) { |
784 | ret = trace_seq_printf(s, " "); | 808 | ret = trace_seq_printf(s, " "); |
@@ -815,17 +839,10 @@ print_graph_entry_nested(struct trace_iterator *iter, | |||
815 | cpu_data->enter_funcs[call->depth] = call->func; | 839 | cpu_data->enter_funcs[call->depth] = call->func; |
816 | } | 840 | } |
817 | 841 | ||
818 | /* No overhead */ | ||
819 | ret = print_graph_overhead(-1, s, flags); | ||
820 | if (!ret) | ||
821 | return TRACE_TYPE_PARTIAL_LINE; | ||
822 | |||
823 | /* No time */ | 842 | /* No time */ |
824 | if (flags & TRACE_GRAPH_PRINT_DURATION) { | 843 | ret = print_graph_duration(DURATION_FILL_FULL, s, flags); |
825 | ret = trace_seq_printf(s, " | "); | 844 | if (ret != TRACE_TYPE_HANDLED) |
826 | if (!ret) | 845 | return ret; |
827 | return TRACE_TYPE_PARTIAL_LINE; | ||
828 | } | ||
829 | 846 | ||
830 | /* Function */ | 847 | /* Function */ |
831 | for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) { | 848 | for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) { |
@@ -865,6 +882,9 @@ print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s, | |||
865 | return TRACE_TYPE_PARTIAL_LINE; | 882 | return TRACE_TYPE_PARTIAL_LINE; |
866 | } | 883 | } |
867 | 884 | ||
885 | if (!(trace_flags & TRACE_ITER_CONTEXT_INFO)) | ||
886 | return 0; | ||
887 | |||
868 | /* Absolute time */ | 888 | /* Absolute time */ |
869 | if (flags & TRACE_GRAPH_PRINT_ABS_TIME) { | 889 | if (flags & TRACE_GRAPH_PRINT_ABS_TIME) { |
870 | ret = print_graph_abs_time(iter->ts, s); | 890 | ret = print_graph_abs_time(iter->ts, s); |
@@ -1078,18 +1098,11 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, | |||
1078 | if (print_graph_prologue(iter, s, 0, 0, flags)) | 1098 | if (print_graph_prologue(iter, s, 0, 0, flags)) |
1079 | return TRACE_TYPE_PARTIAL_LINE; | 1099 | return TRACE_TYPE_PARTIAL_LINE; |
1080 | 1100 | ||
1081 | /* Overhead */ | 1101 | /* Overhead and duration */ |
1082 | ret = print_graph_overhead(duration, s, flags); | 1102 | ret = print_graph_duration(duration, s, flags); |
1083 | if (!ret) | 1103 | if (ret == TRACE_TYPE_PARTIAL_LINE) |
1084 | return TRACE_TYPE_PARTIAL_LINE; | 1104 | return TRACE_TYPE_PARTIAL_LINE; |
1085 | 1105 | ||
1086 | /* Duration */ | ||
1087 | if (flags & TRACE_GRAPH_PRINT_DURATION) { | ||
1088 | ret = print_graph_duration(duration, s); | ||
1089 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
1090 | return TRACE_TYPE_PARTIAL_LINE; | ||
1091 | } | ||
1092 | |||
1093 | /* Closing brace */ | 1106 | /* Closing brace */ |
1094 | for (i = 0; i < trace->depth * TRACE_GRAPH_INDENT; i++) { | 1107 | for (i = 0; i < trace->depth * TRACE_GRAPH_INDENT; i++) { |
1095 | ret = trace_seq_printf(s, " "); | 1108 | ret = trace_seq_printf(s, " "); |
@@ -1146,17 +1159,10 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent, | |||
1146 | if (print_graph_prologue(iter, s, 0, 0, flags)) | 1159 | if (print_graph_prologue(iter, s, 0, 0, flags)) |
1147 | return TRACE_TYPE_PARTIAL_LINE; | 1160 | return TRACE_TYPE_PARTIAL_LINE; |
1148 | 1161 | ||
1149 | /* No overhead */ | ||
1150 | ret = print_graph_overhead(-1, s, flags); | ||
1151 | if (!ret) | ||
1152 | return TRACE_TYPE_PARTIAL_LINE; | ||
1153 | |||
1154 | /* No time */ | 1162 | /* No time */ |
1155 | if (flags & TRACE_GRAPH_PRINT_DURATION) { | 1163 | ret = print_graph_duration(DURATION_FILL_FULL, s, flags); |
1156 | ret = trace_seq_printf(s, " | "); | 1164 | if (ret != TRACE_TYPE_HANDLED) |
1157 | if (!ret) | 1165 | return ret; |
1158 | return TRACE_TYPE_PARTIAL_LINE; | ||
1159 | } | ||
1160 | 1166 | ||
1161 | /* Indentation */ | 1167 | /* Indentation */ |
1162 | if (depth > 0) | 1168 | if (depth > 0) |
@@ -1207,7 +1213,7 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent, | |||
1207 | 1213 | ||
1208 | 1214 | ||
1209 | enum print_line_t | 1215 | enum print_line_t |
1210 | __print_graph_function_flags(struct trace_iterator *iter, u32 flags) | 1216 | print_graph_function_flags(struct trace_iterator *iter, u32 flags) |
1211 | { | 1217 | { |
1212 | struct ftrace_graph_ent_entry *field; | 1218 | struct ftrace_graph_ent_entry *field; |
1213 | struct fgraph_data *data = iter->private; | 1219 | struct fgraph_data *data = iter->private; |
@@ -1270,18 +1276,7 @@ __print_graph_function_flags(struct trace_iterator *iter, u32 flags) | |||
1270 | static enum print_line_t | 1276 | static enum print_line_t |
1271 | print_graph_function(struct trace_iterator *iter) | 1277 | print_graph_function(struct trace_iterator *iter) |
1272 | { | 1278 | { |
1273 | return __print_graph_function_flags(iter, tracer_flags.val); | 1279 | return print_graph_function_flags(iter, tracer_flags.val); |
1274 | } | ||
1275 | |||
1276 | enum print_line_t print_graph_function_flags(struct trace_iterator *iter, | ||
1277 | u32 flags) | ||
1278 | { | ||
1279 | if (trace_flags & TRACE_ITER_LATENCY_FMT) | ||
1280 | flags |= TRACE_GRAPH_PRINT_DURATION; | ||
1281 | else | ||
1282 | flags |= TRACE_GRAPH_PRINT_ABS_TIME; | ||
1283 | |||
1284 | return __print_graph_function_flags(iter, flags); | ||
1285 | } | 1280 | } |
1286 | 1281 | ||
1287 | static enum print_line_t | 1282 | static enum print_line_t |
@@ -1309,8 +1304,7 @@ static void print_lat_header(struct seq_file *s, u32 flags) | |||
1309 | seq_printf(s, "#%.*s / _----=> need-resched \n", size, spaces); | 1304 | seq_printf(s, "#%.*s / _----=> need-resched \n", size, spaces); |
1310 | seq_printf(s, "#%.*s| / _---=> hardirq/softirq \n", size, spaces); | 1305 | seq_printf(s, "#%.*s| / _---=> hardirq/softirq \n", size, spaces); |
1311 | seq_printf(s, "#%.*s|| / _--=> preempt-depth \n", size, spaces); | 1306 | seq_printf(s, "#%.*s|| / _--=> preempt-depth \n", size, spaces); |
1312 | seq_printf(s, "#%.*s||| / _-=> lock-depth \n", size, spaces); | 1307 | seq_printf(s, "#%.*s||| / \n", size, spaces); |
1313 | seq_printf(s, "#%.*s|||| / \n", size, spaces); | ||
1314 | } | 1308 | } |
1315 | 1309 | ||
1316 | static void __print_graph_headers_flags(struct seq_file *s, u32 flags) | 1310 | static void __print_graph_headers_flags(struct seq_file *s, u32 flags) |
@@ -1329,7 +1323,7 @@ static void __print_graph_headers_flags(struct seq_file *s, u32 flags) | |||
1329 | if (flags & TRACE_GRAPH_PRINT_PROC) | 1323 | if (flags & TRACE_GRAPH_PRINT_PROC) |
1330 | seq_printf(s, " TASK/PID "); | 1324 | seq_printf(s, " TASK/PID "); |
1331 | if (lat) | 1325 | if (lat) |
1332 | seq_printf(s, "|||||"); | 1326 | seq_printf(s, "||||"); |
1333 | if (flags & TRACE_GRAPH_PRINT_DURATION) | 1327 | if (flags & TRACE_GRAPH_PRINT_DURATION) |
1334 | seq_printf(s, " DURATION "); | 1328 | seq_printf(s, " DURATION "); |
1335 | seq_printf(s, " FUNCTION CALLS\n"); | 1329 | seq_printf(s, " FUNCTION CALLS\n"); |
@@ -1343,7 +1337,7 @@ static void __print_graph_headers_flags(struct seq_file *s, u32 flags) | |||
1343 | if (flags & TRACE_GRAPH_PRINT_PROC) | 1337 | if (flags & TRACE_GRAPH_PRINT_PROC) |
1344 | seq_printf(s, " | | "); | 1338 | seq_printf(s, " | | "); |
1345 | if (lat) | 1339 | if (lat) |
1346 | seq_printf(s, "|||||"); | 1340 | seq_printf(s, "||||"); |
1347 | if (flags & TRACE_GRAPH_PRINT_DURATION) | 1341 | if (flags & TRACE_GRAPH_PRINT_DURATION) |
1348 | seq_printf(s, " | | "); | 1342 | seq_printf(s, " | | "); |
1349 | seq_printf(s, " | | | |\n"); | 1343 | seq_printf(s, " | | | |\n"); |
@@ -1358,15 +1352,16 @@ void print_graph_headers_flags(struct seq_file *s, u32 flags) | |||
1358 | { | 1352 | { |
1359 | struct trace_iterator *iter = s->private; | 1353 | struct trace_iterator *iter = s->private; |
1360 | 1354 | ||
1355 | if (!(trace_flags & TRACE_ITER_CONTEXT_INFO)) | ||
1356 | return; | ||
1357 | |||
1361 | if (trace_flags & TRACE_ITER_LATENCY_FMT) { | 1358 | if (trace_flags & TRACE_ITER_LATENCY_FMT) { |
1362 | /* print nothing if the buffers are empty */ | 1359 | /* print nothing if the buffers are empty */ |
1363 | if (trace_empty(iter)) | 1360 | if (trace_empty(iter)) |
1364 | return; | 1361 | return; |
1365 | 1362 | ||
1366 | print_trace_header(s, iter); | 1363 | print_trace_header(s, iter); |
1367 | flags |= TRACE_GRAPH_PRINT_DURATION; | 1364 | } |
1368 | } else | ||
1369 | flags |= TRACE_GRAPH_PRINT_ABS_TIME; | ||
1370 | 1365 | ||
1371 | __print_graph_headers_flags(s, flags); | 1366 | __print_graph_headers_flags(s, flags); |
1372 | } | 1367 | } |
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index c77424be284d..667aa8cc0cfc 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c | |||
@@ -226,7 +226,9 @@ static void irqsoff_trace_close(struct trace_iterator *iter) | |||
226 | } | 226 | } |
227 | 227 | ||
228 | #define GRAPH_TRACER_FLAGS (TRACE_GRAPH_PRINT_CPU | \ | 228 | #define GRAPH_TRACER_FLAGS (TRACE_GRAPH_PRINT_CPU | \ |
229 | TRACE_GRAPH_PRINT_PROC) | 229 | TRACE_GRAPH_PRINT_PROC | \ |
230 | TRACE_GRAPH_PRINT_ABS_TIME | \ | ||
231 | TRACE_GRAPH_PRINT_DURATION) | ||
230 | 232 | ||
231 | static enum print_line_t irqsoff_print_line(struct trace_iterator *iter) | 233 | static enum print_line_t irqsoff_print_line(struct trace_iterator *iter) |
232 | { | 234 | { |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 27d13b36b8be..7db7b68c6c37 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -1397,7 +1397,8 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
1397 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); | 1397 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
1398 | 1398 | ||
1399 | if (!filter_current_check_discard(buffer, call, entry, event)) | 1399 | if (!filter_current_check_discard(buffer, call, entry, event)) |
1400 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); | 1400 | trace_nowake_buffer_unlock_commit_regs(buffer, event, |
1401 | irq_flags, pc, regs); | ||
1401 | } | 1402 | } |
1402 | 1403 | ||
1403 | /* Kretprobe handler */ | 1404 | /* Kretprobe handler */ |
@@ -1429,7 +1430,8 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
1429 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); | 1430 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
1430 | 1431 | ||
1431 | if (!filter_current_check_discard(buffer, call, entry, event)) | 1432 | if (!filter_current_check_discard(buffer, call, entry, event)) |
1432 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); | 1433 | trace_nowake_buffer_unlock_commit_regs(buffer, event, |
1434 | irq_flags, pc, regs); | ||
1433 | } | 1435 | } |
1434 | 1436 | ||
1435 | /* Event entry printers */ | 1437 | /* Event entry printers */ |
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c index f029dd4fd2ca..e4a70c0c71b6 100644 --- a/kernel/trace/trace_sched_wakeup.c +++ b/kernel/trace/trace_sched_wakeup.c | |||
@@ -227,7 +227,9 @@ static void wakeup_trace_close(struct trace_iterator *iter) | |||
227 | graph_trace_close(iter); | 227 | graph_trace_close(iter); |
228 | } | 228 | } |
229 | 229 | ||
230 | #define GRAPH_TRACER_FLAGS (TRACE_GRAPH_PRINT_PROC) | 230 | #define GRAPH_TRACER_FLAGS (TRACE_GRAPH_PRINT_PROC | \ |
231 | TRACE_GRAPH_PRINT_ABS_TIME | \ | ||
232 | TRACE_GRAPH_PRINT_DURATION) | ||
231 | 233 | ||
232 | static enum print_line_t wakeup_print_line(struct trace_iterator *iter) | 234 | static enum print_line_t wakeup_print_line(struct trace_iterator *iter) |
233 | { | 235 | { |
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c index b0b53b8e4c25..77575b386d97 100644 --- a/kernel/trace/trace_stack.c +++ b/kernel/trace/trace_stack.c | |||
@@ -156,20 +156,11 @@ stack_max_size_write(struct file *filp, const char __user *ubuf, | |||
156 | { | 156 | { |
157 | long *ptr = filp->private_data; | 157 | long *ptr = filp->private_data; |
158 | unsigned long val, flags; | 158 | unsigned long val, flags; |
159 | char buf[64]; | ||
160 | int ret; | 159 | int ret; |
161 | int cpu; | 160 | int cpu; |
162 | 161 | ||
163 | if (count >= sizeof(buf)) | 162 | ret = kstrtoul_from_user(ubuf, count, 10, &val); |
164 | return -EINVAL; | 163 | if (ret) |
165 | |||
166 | if (copy_from_user(&buf, ubuf, count)) | ||
167 | return -EFAULT; | ||
168 | |||
169 | buf[count] = 0; | ||
170 | |||
171 | ret = strict_strtoul(buf, 10, &val); | ||
172 | if (ret < 0) | ||
173 | return ret; | 164 | return ret; |
174 | 165 | ||
175 | local_irq_save(flags); | 166 | local_irq_save(flags); |