diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/perf_event.c | 6 | ||||
| -rw-r--r-- | kernel/trace/ftrace.c | 4 | ||||
| -rw-r--r-- | kernel/trace/trace_event_perf.c | 3 | ||||
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 43 |
4 files changed, 34 insertions, 22 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 657555a5f30f..db5b56064687 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
| @@ -5761,15 +5761,15 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) | |||
| 5761 | { | 5761 | { |
| 5762 | unsigned int cpu = (long)hcpu; | 5762 | unsigned int cpu = (long)hcpu; |
| 5763 | 5763 | ||
| 5764 | switch (action) { | 5764 | switch (action & ~CPU_TASKS_FROZEN) { |
| 5765 | 5765 | ||
| 5766 | case CPU_UP_PREPARE: | 5766 | case CPU_UP_PREPARE: |
| 5767 | case CPU_UP_PREPARE_FROZEN: | 5767 | case CPU_DOWN_FAILED: |
| 5768 | perf_event_init_cpu(cpu); | 5768 | perf_event_init_cpu(cpu); |
| 5769 | break; | 5769 | break; |
| 5770 | 5770 | ||
| 5771 | case CPU_UP_CANCELED: | ||
| 5771 | case CPU_DOWN_PREPARE: | 5772 | case CPU_DOWN_PREPARE: |
| 5772 | case CPU_DOWN_PREPARE_FROZEN: | ||
| 5773 | perf_event_exit_cpu(cpu); | 5773 | perf_event_exit_cpu(cpu); |
| 5774 | break; | 5774 | break; |
| 5775 | 5775 | ||
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 7cb1f45a1de1..fa7ece649fe1 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -1510,6 +1510,8 @@ static void *t_start(struct seq_file *m, loff_t *pos) | |||
| 1510 | if (*pos > 0) | 1510 | if (*pos > 0) |
| 1511 | return t_hash_start(m, pos); | 1511 | return t_hash_start(m, pos); |
| 1512 | iter->flags |= FTRACE_ITER_PRINTALL; | 1512 | iter->flags |= FTRACE_ITER_PRINTALL; |
| 1513 | /* reset in case of seek/pread */ | ||
| 1514 | iter->flags &= ~FTRACE_ITER_HASH; | ||
| 1513 | return iter; | 1515 | return iter; |
| 1514 | } | 1516 | } |
| 1515 | 1517 | ||
| @@ -2416,7 +2418,7 @@ static const struct file_operations ftrace_filter_fops = { | |||
| 2416 | .open = ftrace_filter_open, | 2418 | .open = ftrace_filter_open, |
| 2417 | .read = seq_read, | 2419 | .read = seq_read, |
| 2418 | .write = ftrace_filter_write, | 2420 | .write = ftrace_filter_write, |
| 2419 | .llseek = ftrace_regex_lseek, | 2421 | .llseek = no_llseek, |
| 2420 | .release = ftrace_filter_release, | 2422 | .release = ftrace_filter_release, |
| 2421 | }; | 2423 | }; |
| 2422 | 2424 | ||
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 000e6e85b445..31cc4cb0dbf2 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c | |||
| @@ -91,6 +91,8 @@ int perf_trace_init(struct perf_event *p_event) | |||
| 91 | tp_event->class && tp_event->class->reg && | 91 | tp_event->class && tp_event->class->reg && |
| 92 | try_module_get(tp_event->mod)) { | 92 | try_module_get(tp_event->mod)) { |
| 93 | ret = perf_trace_event_init(tp_event, p_event); | 93 | ret = perf_trace_event_init(tp_event, p_event); |
| 94 | if (ret) | ||
| 95 | module_put(tp_event->mod); | ||
| 94 | break; | 96 | break; |
| 95 | } | 97 | } |
| 96 | } | 98 | } |
| @@ -146,6 +148,7 @@ void perf_trace_destroy(struct perf_event *p_event) | |||
| 146 | } | 148 | } |
| 147 | } | 149 | } |
| 148 | out: | 150 | out: |
| 151 | module_put(tp_event->mod); | ||
| 149 | mutex_unlock(&event_mutex); | 152 | mutex_unlock(&event_mutex); |
| 150 | } | 153 | } |
| 151 | 154 | ||
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 8b27c9849b42..544301d29dee 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -514,8 +514,8 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs); | |||
| 514 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, | 514 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, |
| 515 | struct pt_regs *regs); | 515 | struct pt_regs *regs); |
| 516 | 516 | ||
| 517 | /* Check the name is good for event/group */ | 517 | /* Check the name is good for event/group/fields */ |
| 518 | static int check_event_name(const char *name) | 518 | static int is_good_name(const char *name) |
| 519 | { | 519 | { |
| 520 | if (!isalpha(*name) && *name != '_') | 520 | if (!isalpha(*name) && *name != '_') |
| 521 | return 0; | 521 | return 0; |
| @@ -557,7 +557,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
| 557 | else | 557 | else |
| 558 | tp->rp.kp.pre_handler = kprobe_dispatcher; | 558 | tp->rp.kp.pre_handler = kprobe_dispatcher; |
| 559 | 559 | ||
| 560 | if (!event || !check_event_name(event)) { | 560 | if (!event || !is_good_name(event)) { |
| 561 | ret = -EINVAL; | 561 | ret = -EINVAL; |
| 562 | goto error; | 562 | goto error; |
| 563 | } | 563 | } |
| @@ -567,7 +567,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
| 567 | if (!tp->call.name) | 567 | if (!tp->call.name) |
| 568 | goto error; | 568 | goto error; |
| 569 | 569 | ||
| 570 | if (!group || !check_event_name(group)) { | 570 | if (!group || !is_good_name(group)) { |
| 571 | ret = -EINVAL; | 571 | ret = -EINVAL; |
| 572 | goto error; | 572 | goto error; |
| 573 | } | 573 | } |
| @@ -883,7 +883,7 @@ static int create_trace_probe(int argc, char **argv) | |||
| 883 | int i, ret = 0; | 883 | int i, ret = 0; |
| 884 | int is_return = 0, is_delete = 0; | 884 | int is_return = 0, is_delete = 0; |
| 885 | char *symbol = NULL, *event = NULL, *group = NULL; | 885 | char *symbol = NULL, *event = NULL, *group = NULL; |
| 886 | char *arg, *tmp; | 886 | char *arg; |
| 887 | unsigned long offset = 0; | 887 | unsigned long offset = 0; |
| 888 | void *addr = NULL; | 888 | void *addr = NULL; |
| 889 | char buf[MAX_EVENT_NAME_LEN]; | 889 | char buf[MAX_EVENT_NAME_LEN]; |
| @@ -992,26 +992,36 @@ static int create_trace_probe(int argc, char **argv) | |||
| 992 | /* parse arguments */ | 992 | /* parse arguments */ |
| 993 | ret = 0; | 993 | ret = 0; |
| 994 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { | 994 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { |
| 995 | /* Increment count for freeing args in error case */ | ||
| 996 | tp->nr_args++; | ||
| 997 | |||
| 995 | /* Parse argument name */ | 998 | /* Parse argument name */ |
| 996 | arg = strchr(argv[i], '='); | 999 | arg = strchr(argv[i], '='); |
| 997 | if (arg) | 1000 | if (arg) { |
| 998 | *arg++ = '\0'; | 1001 | *arg++ = '\0'; |
| 999 | else | 1002 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); |
| 1003 | } else { | ||
| 1000 | arg = argv[i]; | 1004 | arg = argv[i]; |
| 1005 | /* If argument name is omitted, set "argN" */ | ||
| 1006 | snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1); | ||
| 1007 | tp->args[i].name = kstrdup(buf, GFP_KERNEL); | ||
| 1008 | } | ||
| 1001 | 1009 | ||
| 1002 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); | ||
| 1003 | if (!tp->args[i].name) { | 1010 | if (!tp->args[i].name) { |
| 1004 | pr_info("Failed to allocate argument%d name '%s'.\n", | 1011 | pr_info("Failed to allocate argument[%d] name.\n", i); |
| 1005 | i, argv[i]); | ||
| 1006 | ret = -ENOMEM; | 1012 | ret = -ENOMEM; |
| 1007 | goto error; | 1013 | goto error; |
| 1008 | } | 1014 | } |
| 1009 | tmp = strchr(tp->args[i].name, ':'); | 1015 | |
| 1010 | if (tmp) | 1016 | if (!is_good_name(tp->args[i].name)) { |
| 1011 | *tmp = '_'; /* convert : to _ */ | 1017 | pr_info("Invalid argument[%d] name: %s\n", |
| 1018 | i, tp->args[i].name); | ||
| 1019 | ret = -EINVAL; | ||
| 1020 | goto error; | ||
| 1021 | } | ||
| 1012 | 1022 | ||
| 1013 | if (conflict_field_name(tp->args[i].name, tp->args, i)) { | 1023 | if (conflict_field_name(tp->args[i].name, tp->args, i)) { |
| 1014 | pr_info("Argument%d name '%s' conflicts with " | 1024 | pr_info("Argument[%d] name '%s' conflicts with " |
| 1015 | "another field.\n", i, argv[i]); | 1025 | "another field.\n", i, argv[i]); |
| 1016 | ret = -EINVAL; | 1026 | ret = -EINVAL; |
| 1017 | goto error; | 1027 | goto error; |
| @@ -1020,12 +1030,9 @@ static int create_trace_probe(int argc, char **argv) | |||
| 1020 | /* Parse fetch argument */ | 1030 | /* Parse fetch argument */ |
| 1021 | ret = parse_probe_arg(arg, tp, &tp->args[i], is_return); | 1031 | ret = parse_probe_arg(arg, tp, &tp->args[i], is_return); |
| 1022 | if (ret) { | 1032 | if (ret) { |
| 1023 | pr_info("Parse error at argument%d. (%d)\n", i, ret); | 1033 | pr_info("Parse error at argument[%d]. (%d)\n", i, ret); |
| 1024 | kfree(tp->args[i].name); | ||
| 1025 | goto error; | 1034 | goto error; |
| 1026 | } | 1035 | } |
| 1027 | |||
| 1028 | tp->nr_args++; | ||
| 1029 | } | 1036 | } |
| 1030 | 1037 | ||
| 1031 | ret = register_trace_probe(tp); | 1038 | ret = register_trace_probe(tp); |
