diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-11-18 00:56:48 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-11-18 00:56:48 -0500 |
commit | e15bf88a44d1fcb685754b2868b1cd28927af3aa (patch) | |
tree | 9c4f25db4edd2a42a9372366f4e6230e4a7a4037 | |
parent | 2a49f02a7580d23802ea0e16ceb6d5523ab21aa8 (diff) | |
parent | 092b1f0b5f9f797812da0de927c3aa26acbe8762 (diff) |
Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/urgent fixes from Arnaldo Carvalho de Melo:
- Do not change the key of an object in a rbtree, this time it was
the one for DSOs lookup by its long_name, and the noticed symptom was
with 'perf buildid-list --with-hits' (Adrian Hunter)
- 'perf inject' is a pipe, events it doesn't touch should be passed
on, PERF_RECORD_LOST wasn't, fix it (Adrian Hunter)
- Make 'perf buildid-list' request event ordering, as it needs to
first get the mmap events to be able to mark wich DSOs had hits
(Adrian Hunter)
- Fix memory leaks on failure in 'perf probe' (Masami Hiramatsu, Wang Nan)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | tools/perf/builtin-inject.c | 1 | ||||
-rw-r--r-- | tools/perf/util/build-id.c | 1 | ||||
-rw-r--r-- | tools/perf/util/dso.c | 17 | ||||
-rw-r--r-- | tools/perf/util/dso.h | 1 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 1 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 24 |
6 files changed, 38 insertions, 7 deletions
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 0a945d2e8ca5..99d127fe9c35 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -675,6 +675,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
675 | .fork = perf_event__repipe, | 675 | .fork = perf_event__repipe, |
676 | .exit = perf_event__repipe, | 676 | .exit = perf_event__repipe, |
677 | .lost = perf_event__repipe, | 677 | .lost = perf_event__repipe, |
678 | .lost_samples = perf_event__repipe, | ||
678 | .aux = perf_event__repipe, | 679 | .aux = perf_event__repipe, |
679 | .itrace_start = perf_event__repipe, | 680 | .itrace_start = perf_event__repipe, |
680 | .context_switch = perf_event__repipe, | 681 | .context_switch = perf_event__repipe, |
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index d909459fb54c..217b5a60e2ab 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -76,6 +76,7 @@ struct perf_tool build_id__mark_dso_hit_ops = { | |||
76 | .exit = perf_event__exit_del_thread, | 76 | .exit = perf_event__exit_del_thread, |
77 | .attr = perf_event__process_attr, | 77 | .attr = perf_event__process_attr, |
78 | .build_id = perf_event__process_build_id, | 78 | .build_id = perf_event__process_build_id, |
79 | .ordered_events = true, | ||
79 | }; | 80 | }; |
80 | 81 | ||
81 | int build_id__sprintf(const u8 *build_id, int len, char *bf) | 82 | int build_id__sprintf(const u8 *build_id, int len, char *bf) |
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 7c0c08386a1d..425df5c86c9c 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c | |||
@@ -933,6 +933,7 @@ static struct dso *__dso__findlink_by_longname(struct rb_root *root, | |||
933 | /* Add new node and rebalance tree */ | 933 | /* Add new node and rebalance tree */ |
934 | rb_link_node(&dso->rb_node, parent, p); | 934 | rb_link_node(&dso->rb_node, parent, p); |
935 | rb_insert_color(&dso->rb_node, root); | 935 | rb_insert_color(&dso->rb_node, root); |
936 | dso->root = root; | ||
936 | } | 937 | } |
937 | return NULL; | 938 | return NULL; |
938 | } | 939 | } |
@@ -945,15 +946,30 @@ static inline struct dso *__dso__find_by_longname(struct rb_root *root, | |||
945 | 946 | ||
946 | void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) | 947 | void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) |
947 | { | 948 | { |
949 | struct rb_root *root = dso->root; | ||
950 | |||
948 | if (name == NULL) | 951 | if (name == NULL) |
949 | return; | 952 | return; |
950 | 953 | ||
951 | if (dso->long_name_allocated) | 954 | if (dso->long_name_allocated) |
952 | free((char *)dso->long_name); | 955 | free((char *)dso->long_name); |
953 | 956 | ||
957 | if (root) { | ||
958 | rb_erase(&dso->rb_node, root); | ||
959 | /* | ||
960 | * __dso__findlink_by_longname() isn't guaranteed to add it | ||
961 | * back, so a clean removal is required here. | ||
962 | */ | ||
963 | RB_CLEAR_NODE(&dso->rb_node); | ||
964 | dso->root = NULL; | ||
965 | } | ||
966 | |||
954 | dso->long_name = name; | 967 | dso->long_name = name; |
955 | dso->long_name_len = strlen(name); | 968 | dso->long_name_len = strlen(name); |
956 | dso->long_name_allocated = name_allocated; | 969 | dso->long_name_allocated = name_allocated; |
970 | |||
971 | if (root) | ||
972 | __dso__findlink_by_longname(root, dso, NULL); | ||
957 | } | 973 | } |
958 | 974 | ||
959 | void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated) | 975 | void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated) |
@@ -1046,6 +1062,7 @@ struct dso *dso__new(const char *name) | |||
1046 | dso->kernel = DSO_TYPE_USER; | 1062 | dso->kernel = DSO_TYPE_USER; |
1047 | dso->needs_swap = DSO_SWAP__UNSET; | 1063 | dso->needs_swap = DSO_SWAP__UNSET; |
1048 | RB_CLEAR_NODE(&dso->rb_node); | 1064 | RB_CLEAR_NODE(&dso->rb_node); |
1065 | dso->root = NULL; | ||
1049 | INIT_LIST_HEAD(&dso->node); | 1066 | INIT_LIST_HEAD(&dso->node); |
1050 | INIT_LIST_HEAD(&dso->data.open_entry); | 1067 | INIT_LIST_HEAD(&dso->data.open_entry); |
1051 | pthread_mutex_init(&dso->lock, NULL); | 1068 | pthread_mutex_init(&dso->lock, NULL); |
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index fc8db9c764ac..45ec4d0a50ed 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h | |||
@@ -135,6 +135,7 @@ struct dso { | |||
135 | pthread_mutex_t lock; | 135 | pthread_mutex_t lock; |
136 | struct list_head node; | 136 | struct list_head node; |
137 | struct rb_node rb_node; /* rbtree node sorted by long name */ | 137 | struct rb_node rb_node; /* rbtree node sorted by long name */ |
138 | struct rb_root *root; /* root of rbtree that rb_node is in */ | ||
138 | struct rb_root symbols[MAP__NR_TYPES]; | 139 | struct rb_root symbols[MAP__NR_TYPES]; |
139 | struct rb_root symbol_names[MAP__NR_TYPES]; | 140 | struct rb_root symbol_names[MAP__NR_TYPES]; |
140 | struct { | 141 | struct { |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 5ef90be2a249..8b303ff20289 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -91,6 +91,7 @@ static void dsos__purge(struct dsos *dsos) | |||
91 | 91 | ||
92 | list_for_each_entry_safe(pos, n, &dsos->head, node) { | 92 | list_for_each_entry_safe(pos, n, &dsos->head, node) { |
93 | RB_CLEAR_NODE(&pos->rb_node); | 93 | RB_CLEAR_NODE(&pos->rb_node); |
94 | pos->root = NULL; | ||
94 | list_del_init(&pos->node); | 95 | list_del_init(&pos->node); |
95 | dso__put(pos); | 96 | dso__put(pos); |
96 | } | 97 | } |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index bd8f03de5e40..05012bb178d7 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -1183,7 +1183,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1183 | container_of(pf, struct trace_event_finder, pf); | 1183 | container_of(pf, struct trace_event_finder, pf); |
1184 | struct perf_probe_point *pp = &pf->pev->point; | 1184 | struct perf_probe_point *pp = &pf->pev->point; |
1185 | struct probe_trace_event *tev; | 1185 | struct probe_trace_event *tev; |
1186 | struct perf_probe_arg *args; | 1186 | struct perf_probe_arg *args = NULL; |
1187 | int ret, i; | 1187 | int ret, i; |
1188 | 1188 | ||
1189 | /* Check number of tevs */ | 1189 | /* Check number of tevs */ |
@@ -1198,19 +1198,23 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1198 | ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr, | 1198 | ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr, |
1199 | pp->retprobe, pp->function, &tev->point); | 1199 | pp->retprobe, pp->function, &tev->point); |
1200 | if (ret < 0) | 1200 | if (ret < 0) |
1201 | return ret; | 1201 | goto end; |
1202 | 1202 | ||
1203 | tev->point.realname = strdup(dwarf_diename(sc_die)); | 1203 | tev->point.realname = strdup(dwarf_diename(sc_die)); |
1204 | if (!tev->point.realname) | 1204 | if (!tev->point.realname) { |
1205 | return -ENOMEM; | 1205 | ret = -ENOMEM; |
1206 | goto end; | ||
1207 | } | ||
1206 | 1208 | ||
1207 | pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, | 1209 | pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, |
1208 | tev->point.offset); | 1210 | tev->point.offset); |
1209 | 1211 | ||
1210 | /* Expand special probe argument if exist */ | 1212 | /* Expand special probe argument if exist */ |
1211 | args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS); | 1213 | args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS); |
1212 | if (args == NULL) | 1214 | if (args == NULL) { |
1213 | return -ENOMEM; | 1215 | ret = -ENOMEM; |
1216 | goto end; | ||
1217 | } | ||
1214 | 1218 | ||
1215 | ret = expand_probe_args(sc_die, pf, args); | 1219 | ret = expand_probe_args(sc_die, pf, args); |
1216 | if (ret < 0) | 1220 | if (ret < 0) |
@@ -1234,6 +1238,10 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1234 | } | 1238 | } |
1235 | 1239 | ||
1236 | end: | 1240 | end: |
1241 | if (ret) { | ||
1242 | clear_probe_trace_event(tev); | ||
1243 | tf->ntevs--; | ||
1244 | } | ||
1237 | free(args); | 1245 | free(args); |
1238 | return ret; | 1246 | return ret; |
1239 | } | 1247 | } |
@@ -1246,7 +1254,7 @@ int debuginfo__find_trace_events(struct debuginfo *dbg, | |||
1246 | struct trace_event_finder tf = { | 1254 | struct trace_event_finder tf = { |
1247 | .pf = {.pev = pev, .callback = add_probe_trace_event}, | 1255 | .pf = {.pev = pev, .callback = add_probe_trace_event}, |
1248 | .max_tevs = probe_conf.max_probes, .mod = dbg->mod}; | 1256 | .max_tevs = probe_conf.max_probes, .mod = dbg->mod}; |
1249 | int ret; | 1257 | int ret, i; |
1250 | 1258 | ||
1251 | /* Allocate result tevs array */ | 1259 | /* Allocate result tevs array */ |
1252 | *tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs); | 1260 | *tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs); |
@@ -1258,6 +1266,8 @@ int debuginfo__find_trace_events(struct debuginfo *dbg, | |||
1258 | 1266 | ||
1259 | ret = debuginfo__find_probes(dbg, &tf.pf); | 1267 | ret = debuginfo__find_probes(dbg, &tf.pf); |
1260 | if (ret < 0) { | 1268 | if (ret < 0) { |
1269 | for (i = 0; i < tf.ntevs; i++) | ||
1270 | clear_probe_trace_event(&tf.tevs[i]); | ||
1261 | zfree(tevs); | 1271 | zfree(tevs); |
1262 | return ret; | 1272 | return ret; |
1263 | } | 1273 | } |