diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 23:47:30 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 23:47:30 -0500 |
| commit | 6f696eb17be741668810fe1f798135c7cf6733e2 (patch) | |
| tree | f9bcfe5831dfcaaad50ca68d7f04d80d8236fa56 /kernel/trace | |
| parent | c4e194e3b71ff4fed01d727c32ee1071921d28a3 (diff) | |
| parent | 125580380f418000b1a06d9a54700f1191b6e561 (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: (57 commits)
x86, perf events: Check if we have APIC enabled
perf_event: Fix variable initialization in other codepaths
perf kmem: Fix unused argument build warning
perf symbols: perf_header__read_build_ids() offset'n'size should be u64
perf symbols: dsos__read_build_ids() should read both user and kernel buildids
perf tools: Align long options which have no short forms
perf kmem: Show usage if no option is specified
sched: Mark sched_clock() as notrace
perf sched: Add max delay time snapshot
perf tools: Correct size given to memset
perf_event: Fix perf_swevent_hrtimer() variable initialization
perf sched: Fix for getting task's execution time
tracing/kprobes: Fix field creation's bad error handling
perf_event: Cleanup for cpu_clock_perf_event_update()
perf_event: Allocate children's perf_event_ctxp at the right time
perf_event: Clean up __perf_event_init_context()
hw-breakpoints: Modify breakpoints without unregistering them
perf probe: Update perf-probe document
perf probe: Support --del option
trace-kprobe: Support delete probe syntax
...
Diffstat (limited to 'kernel/trace')
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 41 | ||||
| -rw-r--r-- | kernel/trace/trace_ksym.c | 5 |
2 files changed, 33 insertions, 13 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index aff5f80b59b8..b52d397e57eb 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -606,23 +606,22 @@ static int create_trace_probe(int argc, char **argv) | |||
| 606 | */ | 606 | */ |
| 607 | struct trace_probe *tp; | 607 | struct trace_probe *tp; |
| 608 | int i, ret = 0; | 608 | int i, ret = 0; |
| 609 | int is_return = 0; | 609 | int is_return = 0, is_delete = 0; |
| 610 | char *symbol = NULL, *event = NULL, *arg = NULL, *group = NULL; | 610 | char *symbol = NULL, *event = NULL, *arg = NULL, *group = NULL; |
| 611 | unsigned long offset = 0; | 611 | unsigned long offset = 0; |
| 612 | void *addr = NULL; | 612 | void *addr = NULL; |
| 613 | char buf[MAX_EVENT_NAME_LEN]; | 613 | char buf[MAX_EVENT_NAME_LEN]; |
| 614 | 614 | ||
| 615 | if (argc < 2) { | 615 | /* argc must be >= 1 */ |
| 616 | pr_info("Probe point is not specified.\n"); | ||
| 617 | return -EINVAL; | ||
| 618 | } | ||
| 619 | |||
| 620 | if (argv[0][0] == 'p') | 616 | if (argv[0][0] == 'p') |
| 621 | is_return = 0; | 617 | is_return = 0; |
| 622 | else if (argv[0][0] == 'r') | 618 | else if (argv[0][0] == 'r') |
| 623 | is_return = 1; | 619 | is_return = 1; |
| 620 | else if (argv[0][0] == '-') | ||
| 621 | is_delete = 1; | ||
| 624 | else { | 622 | else { |
| 625 | pr_info("Probe definition must be started with 'p' or 'r'.\n"); | 623 | pr_info("Probe definition must be started with 'p', 'r' or" |
| 624 | " '-'.\n"); | ||
| 626 | return -EINVAL; | 625 | return -EINVAL; |
| 627 | } | 626 | } |
| 628 | 627 | ||
| @@ -642,7 +641,29 @@ static int create_trace_probe(int argc, char **argv) | |||
| 642 | return -EINVAL; | 641 | return -EINVAL; |
| 643 | } | 642 | } |
| 644 | } | 643 | } |
| 644 | if (!group) | ||
| 645 | group = KPROBE_EVENT_SYSTEM; | ||
| 645 | 646 | ||
| 647 | if (is_delete) { | ||
| 648 | if (!event) { | ||
| 649 | pr_info("Delete command needs an event name.\n"); | ||
| 650 | return -EINVAL; | ||
| 651 | } | ||
| 652 | tp = find_probe_event(event, group); | ||
| 653 | if (!tp) { | ||
| 654 | pr_info("Event %s/%s doesn't exist.\n", group, event); | ||
| 655 | return -ENOENT; | ||
| 656 | } | ||
| 657 | /* delete an event */ | ||
| 658 | unregister_trace_probe(tp); | ||
| 659 | free_trace_probe(tp); | ||
| 660 | return 0; | ||
| 661 | } | ||
| 662 | |||
| 663 | if (argc < 2) { | ||
| 664 | pr_info("Probe point is not specified.\n"); | ||
| 665 | return -EINVAL; | ||
| 666 | } | ||
| 646 | if (isdigit(argv[1][0])) { | 667 | if (isdigit(argv[1][0])) { |
| 647 | if (is_return) { | 668 | if (is_return) { |
| 648 | pr_info("Return probe point must be a symbol.\n"); | 669 | pr_info("Return probe point must be a symbol.\n"); |
| @@ -671,8 +692,6 @@ static int create_trace_probe(int argc, char **argv) | |||
| 671 | argc -= 2; argv += 2; | 692 | argc -= 2; argv += 2; |
| 672 | 693 | ||
| 673 | /* setup a probe */ | 694 | /* setup a probe */ |
| 674 | if (!group) | ||
| 675 | group = KPROBE_EVENT_SYSTEM; | ||
| 676 | if (!event) { | 695 | if (!event) { |
| 677 | /* Make a new event name */ | 696 | /* Make a new event name */ |
| 678 | if (symbol) | 697 | if (symbol) |
| @@ -1114,7 +1133,7 @@ static int kprobe_event_define_fields(struct ftrace_event_call *event_call) | |||
| 1114 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 1133 | struct trace_probe *tp = (struct trace_probe *)event_call->data; |
| 1115 | 1134 | ||
| 1116 | ret = trace_define_common_fields(event_call); | 1135 | ret = trace_define_common_fields(event_call); |
| 1117 | if (!ret) | 1136 | if (ret) |
| 1118 | return ret; | 1137 | return ret; |
| 1119 | 1138 | ||
| 1120 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); | 1139 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); |
| @@ -1132,7 +1151,7 @@ static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) | |||
| 1132 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 1151 | struct trace_probe *tp = (struct trace_probe *)event_call->data; |
| 1133 | 1152 | ||
| 1134 | ret = trace_define_common_fields(event_call); | 1153 | ret = trace_define_common_fields(event_call); |
| 1135 | if (!ret) | 1154 | if (ret) |
| 1136 | return ret; | 1155 | return ret; |
| 1137 | 1156 | ||
| 1138 | DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); | 1157 | DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); |
diff --git a/kernel/trace/trace_ksym.c b/kernel/trace/trace_ksym.c index ddfa0fd43bc0..acb87d4a4ac1 100644 --- a/kernel/trace/trace_ksym.c +++ b/kernel/trace/trace_ksym.c | |||
| @@ -79,11 +79,12 @@ void ksym_collect_stats(unsigned long hbp_hit_addr) | |||
| 79 | } | 79 | } |
| 80 | #endif /* CONFIG_PROFILE_KSYM_TRACER */ | 80 | #endif /* CONFIG_PROFILE_KSYM_TRACER */ |
| 81 | 81 | ||
| 82 | void ksym_hbp_handler(struct perf_event *hbp, void *data) | 82 | void ksym_hbp_handler(struct perf_event *hbp, int nmi, |
| 83 | struct perf_sample_data *data, | ||
| 84 | struct pt_regs *regs) | ||
| 83 | { | 85 | { |
| 84 | struct ring_buffer_event *event; | 86 | struct ring_buffer_event *event; |
| 85 | struct ksym_trace_entry *entry; | 87 | struct ksym_trace_entry *entry; |
| 86 | struct pt_regs *regs = data; | ||
| 87 | struct ring_buffer *buffer; | 88 | struct ring_buffer *buffer; |
| 88 | int pc; | 89 | int pc; |
| 89 | 90 | ||
