diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-19 12:48:42 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-19 12:48:42 -0500 |
commit | eca9dfcd0029c8a84b1094bb84a2fb53e4addf6c (patch) | |
tree | 2e5982fef1e737ce5f8936981c7dc7fb50fc655c /kernel | |
parent | 3981e152864fcc1dbbb564e1f4c0ae11a09639d2 (diff) | |
parent | b5b60fda1e462a849bc37dfbace2888191be82cc (diff) |
Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
perf session: Make events_stats u64 to avoid overflow on 32-bit arches
hw-breakpoints: Fix hardware breakpoints -> perf events dependency
perf events: Dont report side-band events on each cpu for per-task-per-cpu events
perf events, x86/stacktrace: Fix performance/softlockup by providing a special frame pointer-only stack walker
perf events, x86/stacktrace: Make stack walking optional
perf events: Remove unused perf_counter.h header file
perf probe: Check new event name
kprobe-tracer: Check new event/group name
perf probe: Check whether debugfs path is correct
perf probe: Fix libdwarf include path for Debian
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/perf_event.c | 32 | ||||
-rw-r--r-- | kernel/trace/trace_kprobe.c | 31 | ||||
-rw-r--r-- | kernel/trace/trace_sysprof.c | 1 |
3 files changed, 44 insertions, 20 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 97d1a3dd7a59..e0eb4a2fe183 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -1381,6 +1381,9 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx) | |||
1381 | if (event->state != PERF_EVENT_STATE_ACTIVE) | 1381 | if (event->state != PERF_EVENT_STATE_ACTIVE) |
1382 | continue; | 1382 | continue; |
1383 | 1383 | ||
1384 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | ||
1385 | continue; | ||
1386 | |||
1384 | hwc = &event->hw; | 1387 | hwc = &event->hw; |
1385 | 1388 | ||
1386 | interrupts = hwc->interrupts; | 1389 | interrupts = hwc->interrupts; |
@@ -3265,6 +3268,9 @@ static void perf_event_task_output(struct perf_event *event, | |||
3265 | 3268 | ||
3266 | static int perf_event_task_match(struct perf_event *event) | 3269 | static int perf_event_task_match(struct perf_event *event) |
3267 | { | 3270 | { |
3271 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | ||
3272 | return 0; | ||
3273 | |||
3268 | if (event->attr.comm || event->attr.mmap || event->attr.task) | 3274 | if (event->attr.comm || event->attr.mmap || event->attr.task) |
3269 | return 1; | 3275 | return 1; |
3270 | 3276 | ||
@@ -3290,12 +3296,11 @@ static void perf_event_task_event(struct perf_task_event *task_event) | |||
3290 | rcu_read_lock(); | 3296 | rcu_read_lock(); |
3291 | cpuctx = &get_cpu_var(perf_cpu_context); | 3297 | cpuctx = &get_cpu_var(perf_cpu_context); |
3292 | perf_event_task_ctx(&cpuctx->ctx, task_event); | 3298 | perf_event_task_ctx(&cpuctx->ctx, task_event); |
3293 | put_cpu_var(perf_cpu_context); | ||
3294 | |||
3295 | if (!ctx) | 3299 | if (!ctx) |
3296 | ctx = rcu_dereference(task_event->task->perf_event_ctxp); | 3300 | ctx = rcu_dereference(task_event->task->perf_event_ctxp); |
3297 | if (ctx) | 3301 | if (ctx) |
3298 | perf_event_task_ctx(ctx, task_event); | 3302 | perf_event_task_ctx(ctx, task_event); |
3303 | put_cpu_var(perf_cpu_context); | ||
3299 | rcu_read_unlock(); | 3304 | rcu_read_unlock(); |
3300 | } | 3305 | } |
3301 | 3306 | ||
@@ -3372,6 +3377,9 @@ static void perf_event_comm_output(struct perf_event *event, | |||
3372 | 3377 | ||
3373 | static int perf_event_comm_match(struct perf_event *event) | 3378 | static int perf_event_comm_match(struct perf_event *event) |
3374 | { | 3379 | { |
3380 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | ||
3381 | return 0; | ||
3382 | |||
3375 | if (event->attr.comm) | 3383 | if (event->attr.comm) |
3376 | return 1; | 3384 | return 1; |
3377 | 3385 | ||
@@ -3408,15 +3416,10 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) | |||
3408 | rcu_read_lock(); | 3416 | rcu_read_lock(); |
3409 | cpuctx = &get_cpu_var(perf_cpu_context); | 3417 | cpuctx = &get_cpu_var(perf_cpu_context); |
3410 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); | 3418 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); |
3411 | put_cpu_var(perf_cpu_context); | ||
3412 | |||
3413 | /* | ||
3414 | * doesn't really matter which of the child contexts the | ||
3415 | * events ends up in. | ||
3416 | */ | ||
3417 | ctx = rcu_dereference(current->perf_event_ctxp); | 3419 | ctx = rcu_dereference(current->perf_event_ctxp); |
3418 | if (ctx) | 3420 | if (ctx) |
3419 | perf_event_comm_ctx(ctx, comm_event); | 3421 | perf_event_comm_ctx(ctx, comm_event); |
3422 | put_cpu_var(perf_cpu_context); | ||
3420 | rcu_read_unlock(); | 3423 | rcu_read_unlock(); |
3421 | } | 3424 | } |
3422 | 3425 | ||
@@ -3491,6 +3494,9 @@ static void perf_event_mmap_output(struct perf_event *event, | |||
3491 | static int perf_event_mmap_match(struct perf_event *event, | 3494 | static int perf_event_mmap_match(struct perf_event *event, |
3492 | struct perf_mmap_event *mmap_event) | 3495 | struct perf_mmap_event *mmap_event) |
3493 | { | 3496 | { |
3497 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | ||
3498 | return 0; | ||
3499 | |||
3494 | if (event->attr.mmap) | 3500 | if (event->attr.mmap) |
3495 | return 1; | 3501 | return 1; |
3496 | 3502 | ||
@@ -3564,15 +3570,10 @@ got_name: | |||
3564 | rcu_read_lock(); | 3570 | rcu_read_lock(); |
3565 | cpuctx = &get_cpu_var(perf_cpu_context); | 3571 | cpuctx = &get_cpu_var(perf_cpu_context); |
3566 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event); | 3572 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event); |
3567 | put_cpu_var(perf_cpu_context); | ||
3568 | |||
3569 | /* | ||
3570 | * doesn't really matter which of the child contexts the | ||
3571 | * events ends up in. | ||
3572 | */ | ||
3573 | ctx = rcu_dereference(current->perf_event_ctxp); | 3573 | ctx = rcu_dereference(current->perf_event_ctxp); |
3574 | if (ctx) | 3574 | if (ctx) |
3575 | perf_event_mmap_ctx(ctx, mmap_event); | 3575 | perf_event_mmap_ctx(ctx, mmap_event); |
3576 | put_cpu_var(perf_cpu_context); | ||
3576 | rcu_read_unlock(); | 3577 | rcu_read_unlock(); |
3577 | 3578 | ||
3578 | kfree(buf); | 3579 | kfree(buf); |
@@ -3863,6 +3864,9 @@ static int perf_swevent_match(struct perf_event *event, | |||
3863 | struct perf_sample_data *data, | 3864 | struct perf_sample_data *data, |
3864 | struct pt_regs *regs) | 3865 | struct pt_regs *regs) |
3865 | { | 3866 | { |
3867 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | ||
3868 | return 0; | ||
3869 | |||
3866 | if (!perf_swevent_is_counting(event)) | 3870 | if (!perf_swevent_is_counting(event)) |
3867 | return 0; | 3871 | return 0; |
3868 | 3872 | ||
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 7ecab06547a5..375f81a568dc 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -282,6 +282,18 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs); | |||
282 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, | 282 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, |
283 | struct pt_regs *regs); | 283 | struct pt_regs *regs); |
284 | 284 | ||
285 | /* Check the name is good for event/group */ | ||
286 | static int check_event_name(const char *name) | ||
287 | { | ||
288 | if (!isalpha(*name) && *name != '_') | ||
289 | return 0; | ||
290 | while (*++name != '\0') { | ||
291 | if (!isalpha(*name) && !isdigit(*name) && *name != '_') | ||
292 | return 0; | ||
293 | } | ||
294 | return 1; | ||
295 | } | ||
296 | |||
285 | /* | 297 | /* |
286 | * Allocate new trace_probe and initialize it (including kprobes). | 298 | * Allocate new trace_probe and initialize it (including kprobes). |
287 | */ | 299 | */ |
@@ -293,10 +305,11 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
293 | int nargs, int is_return) | 305 | int nargs, int is_return) |
294 | { | 306 | { |
295 | struct trace_probe *tp; | 307 | struct trace_probe *tp; |
308 | int ret = -ENOMEM; | ||
296 | 309 | ||
297 | tp = kzalloc(SIZEOF_TRACE_PROBE(nargs), GFP_KERNEL); | 310 | tp = kzalloc(SIZEOF_TRACE_PROBE(nargs), GFP_KERNEL); |
298 | if (!tp) | 311 | if (!tp) |
299 | return ERR_PTR(-ENOMEM); | 312 | return ERR_PTR(ret); |
300 | 313 | ||
301 | if (symbol) { | 314 | if (symbol) { |
302 | tp->symbol = kstrdup(symbol, GFP_KERNEL); | 315 | tp->symbol = kstrdup(symbol, GFP_KERNEL); |
@@ -312,14 +325,20 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
312 | else | 325 | else |
313 | tp->rp.kp.pre_handler = kprobe_dispatcher; | 326 | tp->rp.kp.pre_handler = kprobe_dispatcher; |
314 | 327 | ||
315 | if (!event) | 328 | if (!event || !check_event_name(event)) { |
329 | ret = -EINVAL; | ||
316 | goto error; | 330 | goto error; |
331 | } | ||
332 | |||
317 | tp->call.name = kstrdup(event, GFP_KERNEL); | 333 | tp->call.name = kstrdup(event, GFP_KERNEL); |
318 | if (!tp->call.name) | 334 | if (!tp->call.name) |
319 | goto error; | 335 | goto error; |
320 | 336 | ||
321 | if (!group) | 337 | if (!group || !check_event_name(group)) { |
338 | ret = -EINVAL; | ||
322 | goto error; | 339 | goto error; |
340 | } | ||
341 | |||
323 | tp->call.system = kstrdup(group, GFP_KERNEL); | 342 | tp->call.system = kstrdup(group, GFP_KERNEL); |
324 | if (!tp->call.system) | 343 | if (!tp->call.system) |
325 | goto error; | 344 | goto error; |
@@ -330,7 +349,7 @@ error: | |||
330 | kfree(tp->call.name); | 349 | kfree(tp->call.name); |
331 | kfree(tp->symbol); | 350 | kfree(tp->symbol); |
332 | kfree(tp); | 351 | kfree(tp); |
333 | return ERR_PTR(-ENOMEM); | 352 | return ERR_PTR(ret); |
334 | } | 353 | } |
335 | 354 | ||
336 | static void free_probe_arg(struct probe_arg *arg) | 355 | static void free_probe_arg(struct probe_arg *arg) |
@@ -695,10 +714,10 @@ static int create_trace_probe(int argc, char **argv) | |||
695 | if (!event) { | 714 | if (!event) { |
696 | /* Make a new event name */ | 715 | /* Make a new event name */ |
697 | if (symbol) | 716 | if (symbol) |
698 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c@%s%+ld", | 717 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_%ld", |
699 | is_return ? 'r' : 'p', symbol, offset); | 718 | is_return ? 'r' : 'p', symbol, offset); |
700 | else | 719 | else |
701 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c@0x%p", | 720 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c_0x%p", |
702 | is_return ? 'r' : 'p', addr); | 721 | is_return ? 'r' : 'p', addr); |
703 | event = buf; | 722 | event = buf; |
704 | } | 723 | } |
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c index f6693969287d..a7974a552ca9 100644 --- a/kernel/trace/trace_sysprof.c +++ b/kernel/trace/trace_sysprof.c | |||
@@ -93,6 +93,7 @@ static const struct stacktrace_ops backtrace_ops = { | |||
93 | .warning_symbol = backtrace_warning_symbol, | 93 | .warning_symbol = backtrace_warning_symbol, |
94 | .stack = backtrace_stack, | 94 | .stack = backtrace_stack, |
95 | .address = backtrace_address, | 95 | .address = backtrace_address, |
96 | .walk_stack = print_context_stack, | ||
96 | }; | 97 | }; |
97 | 98 | ||
98 | static int | 99 | static int |