diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/trace/Kconfig | 1 | ||||
| -rw-r--r-- | kernel/trace/trace.c | 5 | ||||
| -rw-r--r-- | kernel/trace/trace_selftest.c | 16 | ||||
| -rw-r--r-- | kernel/trace/trace_syscalls.c | 41 |
4 files changed, 34 insertions, 29 deletions
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 95a0ad191f19..b0a46f889659 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
| @@ -182,6 +182,7 @@ config FTRACE_SYSCALLS | |||
| 182 | bool "Trace syscalls" | 182 | bool "Trace syscalls" |
| 183 | depends on HAVE_FTRACE_SYSCALLS | 183 | depends on HAVE_FTRACE_SYSCALLS |
| 184 | select TRACING | 184 | select TRACING |
| 185 | select KALLSYMS | ||
| 185 | help | 186 | help |
| 186 | Basic tracer to catch the syscall entry and exit events. | 187 | Basic tracer to catch the syscall entry and exit events. |
| 187 | 188 | ||
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index efe3202c0209..ae32d3b99b4b 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -2494,7 +2494,7 @@ static int tracing_set_tracer(const char *buf) | |||
| 2494 | if (!ring_buffer_expanded) { | 2494 | if (!ring_buffer_expanded) { |
| 2495 | ret = tracing_resize_ring_buffer(trace_buf_size); | 2495 | ret = tracing_resize_ring_buffer(trace_buf_size); |
| 2496 | if (ret < 0) | 2496 | if (ret < 0) |
| 2497 | return ret; | 2497 | goto out; |
| 2498 | ret = 0; | 2498 | ret = 0; |
| 2499 | } | 2499 | } |
| 2500 | 2500 | ||
| @@ -4125,7 +4125,8 @@ __init static int tracer_alloc_buffers(void) | |||
| 4125 | &trace_panic_notifier); | 4125 | &trace_panic_notifier); |
| 4126 | 4126 | ||
| 4127 | register_die_notifier(&trace_die_notifier); | 4127 | register_die_notifier(&trace_die_notifier); |
| 4128 | ret = 0; | 4128 | |
| 4129 | return 0; | ||
| 4129 | 4130 | ||
| 4130 | out_free_cpumask: | 4131 | out_free_cpumask: |
| 4131 | free_cpumask_var(tracing_reader_cpumask); | 4132 | free_cpumask_var(tracing_reader_cpumask); |
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index f907a2b29028..a2ca6f0fef9b 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c | |||
| @@ -414,7 +414,7 @@ trace_selftest_startup_preemptirqsoff(struct tracer *trace, struct trace_array * | |||
| 414 | ret = tracer_init(trace, tr); | 414 | ret = tracer_init(trace, tr); |
| 415 | if (ret) { | 415 | if (ret) { |
| 416 | warn_failed_init_tracer(trace, ret); | 416 | warn_failed_init_tracer(trace, ret); |
| 417 | goto out; | 417 | goto out_no_start; |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | /* reset the max latency */ | 420 | /* reset the max latency */ |
| @@ -432,21 +432,16 @@ trace_selftest_startup_preemptirqsoff(struct tracer *trace, struct trace_array * | |||
| 432 | tracing_stop(); | 432 | tracing_stop(); |
| 433 | /* check both trace buffers */ | 433 | /* check both trace buffers */ |
| 434 | ret = trace_test_buffer(tr, NULL); | 434 | ret = trace_test_buffer(tr, NULL); |
| 435 | if (ret) { | 435 | if (ret) |
| 436 | tracing_start(); | ||
| 437 | goto out; | 436 | goto out; |
| 438 | } | ||
| 439 | 437 | ||
| 440 | ret = trace_test_buffer(&max_tr, &count); | 438 | ret = trace_test_buffer(&max_tr, &count); |
| 441 | if (ret) { | 439 | if (ret) |
| 442 | tracing_start(); | ||
| 443 | goto out; | 440 | goto out; |
| 444 | } | ||
| 445 | 441 | ||
| 446 | if (!ret && !count) { | 442 | if (!ret && !count) { |
| 447 | printk(KERN_CONT ".. no entries found .."); | 443 | printk(KERN_CONT ".. no entries found .."); |
| 448 | ret = -1; | 444 | ret = -1; |
| 449 | tracing_start(); | ||
| 450 | goto out; | 445 | goto out; |
| 451 | } | 446 | } |
| 452 | 447 | ||
| @@ -475,9 +470,10 @@ trace_selftest_startup_preemptirqsoff(struct tracer *trace, struct trace_array * | |||
| 475 | goto out; | 470 | goto out; |
| 476 | } | 471 | } |
| 477 | 472 | ||
| 478 | out: | 473 | out: |
| 479 | trace->reset(tr); | ||
| 480 | tracing_start(); | 474 | tracing_start(); |
| 475 | out_no_start: | ||
| 476 | trace->reset(tr); | ||
| 481 | tracing_max_latency = save_max; | 477 | tracing_max_latency = save_max; |
| 482 | 478 | ||
| 483 | return ret; | 479 | return ret; |
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index c72e599230ff..a2a3af29c943 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c | |||
| @@ -5,9 +5,13 @@ | |||
| 5 | #include "trace_output.h" | 5 | #include "trace_output.h" |
| 6 | #include "trace.h" | 6 | #include "trace.h" |
| 7 | 7 | ||
| 8 | static atomic_t refcount; | 8 | /* Keep a counter of the syscall tracing users */ |
| 9 | static int refcount; | ||
| 9 | 10 | ||
| 10 | /* Our two options */ | 11 | /* Prevent from races on thread flags toggling */ |
| 12 | static DEFINE_MUTEX(syscall_trace_lock); | ||
| 13 | |||
| 14 | /* Option to display the parameters types */ | ||
| 11 | enum { | 15 | enum { |
| 12 | TRACE_SYSCALLS_OPT_TYPES = 0x1, | 16 | TRACE_SYSCALLS_OPT_TYPES = 0x1, |
| 13 | }; | 17 | }; |
| @@ -18,7 +22,7 @@ static struct tracer_opt syscalls_opts[] = { | |||
| 18 | }; | 22 | }; |
| 19 | 23 | ||
| 20 | static struct tracer_flags syscalls_flags = { | 24 | static struct tracer_flags syscalls_flags = { |
| 21 | .val = 0, /* By default: no args types */ | 25 | .val = 0, /* By default: no parameters types */ |
| 22 | .opts = syscalls_opts | 26 | .opts = syscalls_opts |
| 23 | }; | 27 | }; |
| 24 | 28 | ||
| @@ -96,8 +100,11 @@ void start_ftrace_syscalls(void) | |||
| 96 | unsigned long flags; | 100 | unsigned long flags; |
| 97 | struct task_struct *g, *t; | 101 | struct task_struct *g, *t; |
| 98 | 102 | ||
| 99 | if (atomic_inc_return(&refcount) != 1) | 103 | mutex_lock(&syscall_trace_lock); |
| 100 | goto out; | 104 | |
| 105 | /* Don't enable the flag on the tasks twice */ | ||
| 106 | if (++refcount != 1) | ||
| 107 | goto unlock; | ||
| 101 | 108 | ||
| 102 | arch_init_ftrace_syscalls(); | 109 | arch_init_ftrace_syscalls(); |
| 103 | read_lock_irqsave(&tasklist_lock, flags); | 110 | read_lock_irqsave(&tasklist_lock, flags); |
| @@ -107,8 +114,9 @@ void start_ftrace_syscalls(void) | |||
| 107 | } while_each_thread(g, t); | 114 | } while_each_thread(g, t); |
| 108 | 115 | ||
| 109 | read_unlock_irqrestore(&tasklist_lock, flags); | 116 | read_unlock_irqrestore(&tasklist_lock, flags); |
| 110 | out: | 117 | |
| 111 | atomic_dec(&refcount); | 118 | unlock: |
| 119 | mutex_unlock(&syscall_trace_lock); | ||
| 112 | } | 120 | } |
| 113 | 121 | ||
| 114 | void stop_ftrace_syscalls(void) | 122 | void stop_ftrace_syscalls(void) |
| @@ -116,8 +124,11 @@ void stop_ftrace_syscalls(void) | |||
| 116 | unsigned long flags; | 124 | unsigned long flags; |
| 117 | struct task_struct *g, *t; | 125 | struct task_struct *g, *t; |
| 118 | 126 | ||
| 119 | if (atomic_dec_return(&refcount)) | 127 | mutex_lock(&syscall_trace_lock); |
| 120 | goto out; | 128 | |
| 129 | /* There are perhaps still some users */ | ||
| 130 | if (--refcount) | ||
| 131 | goto unlock; | ||
| 121 | 132 | ||
| 122 | read_lock_irqsave(&tasklist_lock, flags); | 133 | read_lock_irqsave(&tasklist_lock, flags); |
| 123 | 134 | ||
| @@ -126,8 +137,9 @@ void stop_ftrace_syscalls(void) | |||
| 126 | } while_each_thread(g, t); | 137 | } while_each_thread(g, t); |
| 127 | 138 | ||
| 128 | read_unlock_irqrestore(&tasklist_lock, flags); | 139 | read_unlock_irqrestore(&tasklist_lock, flags); |
| 129 | out: | 140 | |
| 130 | atomic_inc(&refcount); | 141 | unlock: |
| 142 | mutex_unlock(&syscall_trace_lock); | ||
| 131 | } | 143 | } |
| 132 | 144 | ||
| 133 | void ftrace_syscall_enter(struct pt_regs *regs) | 145 | void ftrace_syscall_enter(struct pt_regs *regs) |
| @@ -137,12 +149,9 @@ void ftrace_syscall_enter(struct pt_regs *regs) | |||
| 137 | struct ring_buffer_event *event; | 149 | struct ring_buffer_event *event; |
| 138 | int size; | 150 | int size; |
| 139 | int syscall_nr; | 151 | int syscall_nr; |
| 140 | int cpu; | ||
| 141 | 152 | ||
| 142 | syscall_nr = syscall_get_nr(current, regs); | 153 | syscall_nr = syscall_get_nr(current, regs); |
| 143 | 154 | ||
| 144 | cpu = raw_smp_processor_id(); | ||
| 145 | |||
| 146 | sys_data = syscall_nr_to_meta(syscall_nr); | 155 | sys_data = syscall_nr_to_meta(syscall_nr); |
| 147 | if (!sys_data) | 156 | if (!sys_data) |
| 148 | return; | 157 | return; |
| @@ -168,12 +177,9 @@ void ftrace_syscall_exit(struct pt_regs *regs) | |||
| 168 | struct syscall_metadata *sys_data; | 177 | struct syscall_metadata *sys_data; |
| 169 | struct ring_buffer_event *event; | 178 | struct ring_buffer_event *event; |
| 170 | int syscall_nr; | 179 | int syscall_nr; |
| 171 | int cpu; | ||
| 172 | 180 | ||
| 173 | syscall_nr = syscall_get_nr(current, regs); | 181 | syscall_nr = syscall_get_nr(current, regs); |
| 174 | 182 | ||
| 175 | cpu = raw_smp_processor_id(); | ||
| 176 | |||
| 177 | sys_data = syscall_nr_to_meta(syscall_nr); | 183 | sys_data = syscall_nr_to_meta(syscall_nr); |
| 178 | if (!sys_data) | 184 | if (!sys_data) |
| 179 | return; | 185 | return; |
| @@ -201,6 +207,7 @@ static int init_syscall_tracer(struct trace_array *tr) | |||
| 201 | static void reset_syscall_tracer(struct trace_array *tr) | 207 | static void reset_syscall_tracer(struct trace_array *tr) |
| 202 | { | 208 | { |
| 203 | stop_ftrace_syscalls(); | 209 | stop_ftrace_syscalls(); |
| 210 | tracing_reset_online_cpus(tr); | ||
| 204 | } | 211 | } |
| 205 | 212 | ||
| 206 | static struct trace_event syscall_enter_event = { | 213 | static struct trace_event syscall_enter_event = { |
