[PATCH 4.2.y-ckt 033/305] perf symbols: Fix dso lookup by long name and missing buildids

From: Kamal Mostafa
Date: Fri Jan 15 2016 - 20:28:31 EST

4.2.8-ckt2 -stable review patch. If anyone has any objections, please let me know.


From: Adrian Hunter <adrian.hunter@xxxxxxxxx>

commit e266a753bf51b2c3b46d0d230349662c35ac5629 upstream.

Commit 4598a0a6d22f ("perf symbols: Improve DSO long names lookup speed
with rbtree") Added a tree to lookup dsos by long name. That tree gets
corrupted whenever a dso long name is changed because the tree is not

One effect of that is buildid-list does not work with the 'with-hits'
option because dso lookup fails and results in two structs for the same
dso. The first has the buildid but no hits, the second has hits but no
buildid. e.g.


$ tools/perf/perf record ls
arch certs CREDITS Documentation firmware include
ipc Kconfig lib Makefile net REPORTING-BUGS
scripts sound usr block COPYING crypto
drivers fs init Kbuild kernel MAINTAINERS
mm README samples security tools virt
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.012 MB perf.data (11 samples) ]
$ tools/perf/perf buildid-list
574da826c66538a8d9060d393a8866289bd06005 [kernel.kallsyms]
30c94dc66a1fe95180c3d68d2b89e576d5ae213c /lib/x86_64-linux-gnu/libc-2.19.so
$ tools/perf/perf buildid-list -H
574da826c66538a8d9060d393a8866289bd06005 [kernel.kallsyms]
0000000000000000000000000000000000000000 /lib/x86_64-linux-gnu/libc-2.19.so


$ tools/perf/perf buildid-list -H
574da826c66538a8d9060d393a8866289bd06005 [kernel.kallsyms]
30c94dc66a1fe95180c3d68d2b89e576d5ae213c /lib/x86_64-linux-gnu/libc-2.19.so

The fix is to record the root of the tree on the dso so that
dso__set_long_name() can update the tree when the long name changes.

Signed-off-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>
Tested-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
Cc: Adrian Hunter <adrian.hunter@xxxxxxxxx>
Cc: Don Zickus <dzickus@xxxxxxxxxx>
Cc: Douglas Hatch <doug.hatch@xxxxxx>
Cc: Jiri Olsa <jolsa@xxxxxxxxxx>
Cc: Namhyung Kim <namhyung@xxxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Scott J Norton <scott.norton@xxxxxx>
Cc: Waiman Long <Waiman.Long@xxxxxx>
Fixes: 4598a0a6d22f ("perf symbols: Improve DSO long names lookup speed with rbtree")
Link: http://lkml.kernel.org/r/1447408112-1920-2-git-send-email-adrian.hunter@xxxxxxxxx
Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
Signed-off-by: Kamal Mostafa <kamal@xxxxxxxxxxxxx>
tools/perf/util/dso.c | 17 +++++++++++++++++
tools/perf/util/dso.h | 1 +
tools/perf/util/machine.c | 1 +
3 files changed, 19 insertions(+)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 7c0c083..425df5c 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,
/* Add new node and rebalance tree */
rb_link_node(&dso->rb_node, parent, p);
rb_insert_color(&dso->rb_node, root);
+ dso->root = root;
return NULL;
@@ -945,15 +946,30 @@ static inline struct dso *__dso__find_by_longname(struct rb_root *root,

void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
+ struct rb_root *root = dso->root;
if (name == NULL)

if (dso->long_name_allocated)
free((char *)dso->long_name);

+ if (root) {
+ rb_erase(&dso->rb_node, root);
+ /*
+ * __dso__findlink_by_longname() isn't guaranteed to add it
+ * back, so a clean removal is required here.
+ */
+ RB_CLEAR_NODE(&dso->rb_node);
+ dso->root = NULL;
+ }
dso->long_name = name;
dso->long_name_len = strlen(name);
dso->long_name_allocated = name_allocated;
+ if (root)
+ __dso__findlink_by_longname(root, dso, NULL);

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)
dso->kernel = DSO_TYPE_USER;
dso->needs_swap = DSO_SWAP__UNSET;
+ dso->root = NULL;
pthread_mutex_init(&dso->lock, NULL);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 2fe98bb..b9ec6d8 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -135,6 +135,7 @@ struct dso {
pthread_mutex_t lock;
struct list_head node;
struct rb_node rb_node; /* rbtree node sorted by long name */
+ struct rb_root *root; /* root of rbtree that rb_node is in */
struct rb_root symbols[MAP__NR_TYPES];
struct rb_root symbol_names[MAP__NR_TYPES];
void *a2l;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index f1a4c83..69c17dc 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -90,6 +90,7 @@ static void dsos__purge(struct dsos *dsos)

list_for_each_entry_safe(pos, n, &dsos->head, node) {
+ pos->root = NULL;