diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-08 16:52:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-08 16:52:59 -0500 |
commit | 3ab6d1ebd54bc377e9cd6c1792aaffa0a1fd11f8 (patch) | |
tree | 97b0d3b90783950f36964203d48fcf36749974b9 | |
parent | ea83ae2fb30cd134d0220221bcf81efb579f8d73 (diff) | |
parent | 12ca6ad2e3a896256f086497a7c7406a547ee373 (diff) |
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar:
"Two core subsystem fixes, plus a handful of tooling fixes"
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf: Fix race in swevent hash
perf: Fix race in perf_event_exec()
perf list: Robustify event printing routine
perf list: Add support for PERF_COUNT_SW_BPF_OUT
perf hists browser: Fix segfault if use symbol filter in cmdline
perf hists browser: Reset selection when refresh
perf hists browser: Add NULL pointer check to prevent crash
perf buildid-list: Fix return value of perf buildid-list -k
perf buildid-list: Show running kernel build id fix
-rw-r--r-- | kernel/events/core.c | 35 | ||||
-rw-r--r-- | tools/perf/builtin-buildid-list.c | 2 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 8 | ||||
-rw-r--r-- | tools/perf/util/build-id.c | 2 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 6 |
5 files changed, 21 insertions, 32 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index ef2d6ea10736..cfc227ccfceb 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -3154,15 +3154,16 @@ static int event_enable_on_exec(struct perf_event *event, | |||
3154 | * Enable all of a task's events that have been marked enable-on-exec. | 3154 | * Enable all of a task's events that have been marked enable-on-exec. |
3155 | * This expects task == current. | 3155 | * This expects task == current. |
3156 | */ | 3156 | */ |
3157 | static void perf_event_enable_on_exec(struct perf_event_context *ctx) | 3157 | static void perf_event_enable_on_exec(int ctxn) |
3158 | { | 3158 | { |
3159 | struct perf_event_context *clone_ctx = NULL; | 3159 | struct perf_event_context *ctx, *clone_ctx = NULL; |
3160 | struct perf_event *event; | 3160 | struct perf_event *event; |
3161 | unsigned long flags; | 3161 | unsigned long flags; |
3162 | int enabled = 0; | 3162 | int enabled = 0; |
3163 | int ret; | 3163 | int ret; |
3164 | 3164 | ||
3165 | local_irq_save(flags); | 3165 | local_irq_save(flags); |
3166 | ctx = current->perf_event_ctxp[ctxn]; | ||
3166 | if (!ctx || !ctx->nr_events) | 3167 | if (!ctx || !ctx->nr_events) |
3167 | goto out; | 3168 | goto out; |
3168 | 3169 | ||
@@ -3205,17 +3206,11 @@ out: | |||
3205 | 3206 | ||
3206 | void perf_event_exec(void) | 3207 | void perf_event_exec(void) |
3207 | { | 3208 | { |
3208 | struct perf_event_context *ctx; | ||
3209 | int ctxn; | 3209 | int ctxn; |
3210 | 3210 | ||
3211 | rcu_read_lock(); | 3211 | rcu_read_lock(); |
3212 | for_each_task_context_nr(ctxn) { | 3212 | for_each_task_context_nr(ctxn) |
3213 | ctx = current->perf_event_ctxp[ctxn]; | 3213 | perf_event_enable_on_exec(ctxn); |
3214 | if (!ctx) | ||
3215 | continue; | ||
3216 | |||
3217 | perf_event_enable_on_exec(ctx); | ||
3218 | } | ||
3219 | rcu_read_unlock(); | 3214 | rcu_read_unlock(); |
3220 | } | 3215 | } |
3221 | 3216 | ||
@@ -6493,9 +6488,6 @@ struct swevent_htable { | |||
6493 | 6488 | ||
6494 | /* Recursion avoidance in each contexts */ | 6489 | /* Recursion avoidance in each contexts */ |
6495 | int recursion[PERF_NR_CONTEXTS]; | 6490 | int recursion[PERF_NR_CONTEXTS]; |
6496 | |||
6497 | /* Keeps track of cpu being initialized/exited */ | ||
6498 | bool online; | ||
6499 | }; | 6491 | }; |
6500 | 6492 | ||
6501 | static DEFINE_PER_CPU(struct swevent_htable, swevent_htable); | 6493 | static DEFINE_PER_CPU(struct swevent_htable, swevent_htable); |
@@ -6753,14 +6745,8 @@ static int perf_swevent_add(struct perf_event *event, int flags) | |||
6753 | hwc->state = !(flags & PERF_EF_START); | 6745 | hwc->state = !(flags & PERF_EF_START); |
6754 | 6746 | ||
6755 | head = find_swevent_head(swhash, event); | 6747 | head = find_swevent_head(swhash, event); |
6756 | if (!head) { | 6748 | if (WARN_ON_ONCE(!head)) |
6757 | /* | ||
6758 | * We can race with cpu hotplug code. Do not | ||
6759 | * WARN if the cpu just got unplugged. | ||
6760 | */ | ||
6761 | WARN_ON_ONCE(swhash->online); | ||
6762 | return -EINVAL; | 6749 | return -EINVAL; |
6763 | } | ||
6764 | 6750 | ||
6765 | hlist_add_head_rcu(&event->hlist_entry, head); | 6751 | hlist_add_head_rcu(&event->hlist_entry, head); |
6766 | perf_event_update_userpage(event); | 6752 | perf_event_update_userpage(event); |
@@ -6828,7 +6814,6 @@ static int swevent_hlist_get_cpu(struct perf_event *event, int cpu) | |||
6828 | int err = 0; | 6814 | int err = 0; |
6829 | 6815 | ||
6830 | mutex_lock(&swhash->hlist_mutex); | 6816 | mutex_lock(&swhash->hlist_mutex); |
6831 | |||
6832 | if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) { | 6817 | if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) { |
6833 | struct swevent_hlist *hlist; | 6818 | struct swevent_hlist *hlist; |
6834 | 6819 | ||
@@ -9291,7 +9276,6 @@ static void perf_event_init_cpu(int cpu) | |||
9291 | struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); | 9276 | struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); |
9292 | 9277 | ||
9293 | mutex_lock(&swhash->hlist_mutex); | 9278 | mutex_lock(&swhash->hlist_mutex); |
9294 | swhash->online = true; | ||
9295 | if (swhash->hlist_refcount > 0) { | 9279 | if (swhash->hlist_refcount > 0) { |
9296 | struct swevent_hlist *hlist; | 9280 | struct swevent_hlist *hlist; |
9297 | 9281 | ||
@@ -9333,14 +9317,7 @@ static void perf_event_exit_cpu_context(int cpu) | |||
9333 | 9317 | ||
9334 | static void perf_event_exit_cpu(int cpu) | 9318 | static void perf_event_exit_cpu(int cpu) |
9335 | { | 9319 | { |
9336 | struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); | ||
9337 | |||
9338 | perf_event_exit_cpu_context(cpu); | 9320 | perf_event_exit_cpu_context(cpu); |
9339 | |||
9340 | mutex_lock(&swhash->hlist_mutex); | ||
9341 | swhash->online = false; | ||
9342 | swevent_hlist_release(swhash); | ||
9343 | mutex_unlock(&swhash->hlist_mutex); | ||
9344 | } | 9321 | } |
9345 | #else | 9322 | #else |
9346 | static inline void perf_event_exit_cpu(int cpu) { } | 9323 | static inline void perf_event_exit_cpu(int cpu) { } |
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index 918b4de29de4..6419f57b0850 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c | |||
@@ -110,7 +110,7 @@ int cmd_buildid_list(int argc, const char **argv, | |||
110 | setup_pager(); | 110 | setup_pager(); |
111 | 111 | ||
112 | if (show_kernel) | 112 | if (show_kernel) |
113 | return sysfs__fprintf_build_id(stdout); | 113 | return !(sysfs__fprintf_build_id(stdout) > 0); |
114 | 114 | ||
115 | return perf_session__list_build_ids(force, with_hits); | 115 | return perf_session__list_build_ids(force, with_hits); |
116 | } | 116 | } |
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index fa9eb92c9e24..81def6c3f24b 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -298,6 +298,9 @@ static bool hist_browser__toggle_fold(struct hist_browser *browser) | |||
298 | struct callchain_list *cl = container_of(ms, struct callchain_list, ms); | 298 | struct callchain_list *cl = container_of(ms, struct callchain_list, ms); |
299 | bool has_children; | 299 | bool has_children; |
300 | 300 | ||
301 | if (!he || !ms) | ||
302 | return false; | ||
303 | |||
301 | if (ms == &he->ms) | 304 | if (ms == &he->ms) |
302 | has_children = hist_entry__toggle_fold(he); | 305 | has_children = hist_entry__toggle_fold(he); |
303 | else | 306 | else |
@@ -928,6 +931,8 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser) | |||
928 | } | 931 | } |
929 | 932 | ||
930 | ui_browser__hists_init_top(browser); | 933 | ui_browser__hists_init_top(browser); |
934 | hb->he_selection = NULL; | ||
935 | hb->selection = NULL; | ||
931 | 936 | ||
932 | for (nd = browser->top; nd; nd = rb_next(nd)) { | 937 | for (nd = browser->top; nd; nd = rb_next(nd)) { |
933 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); | 938 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); |
@@ -1033,6 +1038,9 @@ static void ui_browser__hists_seek(struct ui_browser *browser, | |||
1033 | * and stop when we printed enough lines to fill the screen. | 1038 | * and stop when we printed enough lines to fill the screen. |
1034 | */ | 1039 | */ |
1035 | do_offset: | 1040 | do_offset: |
1041 | if (!nd) | ||
1042 | return; | ||
1043 | |||
1036 | if (offset > 0) { | 1044 | if (offset > 0) { |
1037 | do { | 1045 | do { |
1038 | h = rb_entry(nd, struct hist_entry, rb_node); | 1046 | h = rb_entry(nd, struct hist_entry, rb_node); |
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 217b5a60e2ab..6a7e273a514a 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -91,7 +91,7 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf) | |||
91 | bid += 2; | 91 | bid += 2; |
92 | } | 92 | } |
93 | 93 | ||
94 | return raw - build_id; | 94 | return (bid - bf) + 1; |
95 | } | 95 | } |
96 | 96 | ||
97 | int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id) | 97 | int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id) |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index e48d9da75707..6fc8cd753e1a 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -124,6 +124,10 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { | |||
124 | .symbol = "dummy", | 124 | .symbol = "dummy", |
125 | .alias = "", | 125 | .alias = "", |
126 | }, | 126 | }, |
127 | [PERF_COUNT_SW_BPF_OUTPUT] = { | ||
128 | .symbol = "bpf-output", | ||
129 | .alias = "", | ||
130 | }, | ||
127 | }; | 131 | }; |
128 | 132 | ||
129 | #define __PERF_EVENT_FIELD(config, name) \ | 133 | #define __PERF_EVENT_FIELD(config, name) \ |
@@ -1879,7 +1883,7 @@ restart: | |||
1879 | 1883 | ||
1880 | for (i = 0; i < max; i++, syms++) { | 1884 | for (i = 0; i < max; i++, syms++) { |
1881 | 1885 | ||
1882 | if (event_glob != NULL && | 1886 | if (event_glob != NULL && syms->symbol != NULL && |
1883 | !(strglobmatch(syms->symbol, event_glob) || | 1887 | !(strglobmatch(syms->symbol, event_glob) || |
1884 | (syms->alias && strglobmatch(syms->alias, event_glob)))) | 1888 | (syms->alias && strglobmatch(syms->alias, event_glob)))) |
1885 | continue; | 1889 | continue; |