Merge branch 'perf' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 2a060be..45b7aec 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -2933,7 +2933,7 @@
 	 */
 
 	if (!local_dec_and_test(&data->nest))
-		return;
+		goto out;
 
 	/*
 	 * Publish the known good head. Rely on the full barrier implied
@@ -2954,6 +2954,7 @@
 	if (handle->wakeup != local_read(&data->wakeup))
 		perf_output_wakeup(handle);
 
+ out:
 	preempt_enable();
 }
 
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 0f60a39..70c5cf8 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -6,6 +6,8 @@
  * Copyright (C) 2009, 2010 Red Hat Inc.
  * Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
  */
+#include "util.h"
+#include <stdio.h>
 #include "build-id.h"
 #include "event.h"
 #include "symbol.h"
@@ -37,3 +39,23 @@
 	.mmap	= event__process_mmap,
 	.fork	= event__process_task,
 };
+
+char *dso__build_id_filename(struct dso *self, char *bf, size_t size)
+{
+	char build_id_hex[BUILD_ID_SIZE * 2 + 1];
+	const char *home;
+
+	if (!self->has_build_id)
+		return NULL;
+
+	build_id__sprintf(self->build_id, sizeof(self->build_id), build_id_hex);
+	home = getenv("HOME");
+	if (bf == NULL) {
+		if (asprintf(&bf, "%s/%s/.build-id/%.2s/%s", home,
+			     DEBUG_CACHE_DIR, build_id_hex, build_id_hex + 2) < 0)
+			return NULL;
+	} else
+		snprintf(bf, size, "%s/%s/.build-id/%.2s/%s", home,
+			 DEBUG_CACHE_DIR, build_id_hex, build_id_hex + 2);
+	return bf;
+}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 1d981d6..5dafb00 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -5,4 +5,6 @@
 
 extern struct perf_event_ops build_id__mark_dso_hit_ops;
 
+char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
+
 #endif
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 21a52e0..62b69ad 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -15,6 +15,7 @@
 #include <errno.h>
 #include <math.h>
 
+#include "util.h"
 #include "callchain.h"
 
 bool ip_callchain__valid(struct ip_callchain *chain, event_t *event)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 1cba1f5..1ca73e4 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -5,7 +5,6 @@
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include "event.h"
-#include "util.h"
 #include "symbol.h"
 
 enum chain_mode {
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 9a71c94..739c39f 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,3 +1,4 @@
+#include "build-id.h"
 #include "util.h"
 #include "hist.h"
 #include "session.h"
@@ -988,22 +989,35 @@
 	struct symbol *sym = self->ms.sym;
 	struct map *map = self->ms.map;
 	struct dso *dso = map->dso;
-	const char *filename = dso->long_name;
+	char *filename = dso__build_id_filename(dso, NULL, 0);
 	char command[PATH_MAX * 2];
 	FILE *file;
+	int err = -1;
 	u64 len;
 
-	if (!filename)
-		return -1;
+	if (filename == NULL) {
+		if (dso->has_build_id) {
+			pr_err("Can't annotate %s: not enough memory\n",
+			       sym->name);
+			return -1;
+		}
+		/*
+		 * If we don't have build-ids, well, lets hope that this
+		 * DSO is the same as when 'perf record' ran.
+		 */
+		filename = dso->long_name;
+	}
 
 	if (dso->origin == DSO__ORIG_KERNEL) {
-		if (dso->annotate_warned)
-			return 0;
+		if (dso->annotate_warned) {
+			err = 0;
+			goto out_free_filename;
+		}
 		dso->annotate_warned = 1;
 		pr_err("Can't annotate %s: No vmlinux file was found in the "
 		       "path:\n", sym->name);
 		vmlinux_path__fprintf(stderr);
-		return -1;
+		goto out_free_filename;
 	}
 
 	pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__,
@@ -1025,14 +1039,18 @@
 
 	file = popen(command, "r");
 	if (!file)
-		return -1;
+		goto out_free_filename;
 
 	while (!feof(file))
 		if (hist_entry__parse_objdump_line(self, file, head) < 0)
 			break;
 
 	pclose(file);
-	return 0;
+	err = 0;
+out_free_filename:
+	if (dso->has_build_id)
+		free(filename);
+	return err;
 }
 
 void hists__inc_nr_events(struct hists *self, u32 type)
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index 9d203c9..0b45658 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -383,6 +383,7 @@
 	newtFormAddHotKey(self->form, NEWT_KEY_DOWN);
 	newtFormAddHotKey(self->form, NEWT_KEY_PGUP);
 	newtFormAddHotKey(self->form, NEWT_KEY_PGDN);
+	newtFormAddHotKey(self->form, ' ');
 	newtFormAddHotKey(self->form, NEWT_KEY_HOME);
 	newtFormAddHotKey(self->form, NEWT_KEY_END);
 
@@ -419,6 +420,7 @@
 			}
 			break;
 		case NEWT_KEY_PGDN:
+		case ' ':
 			if (self->first_visible_entry_idx + self->height > self->nr_entries - 1)
 				break;
 
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 96bff0e..aaa51ba 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -11,6 +11,7 @@
 #include <sys/param.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include "build-id.h"
 #include "symbol.h"
 #include "strlist.h"
 
@@ -1293,7 +1294,6 @@
 	int size = PATH_MAX;
 	char *name;
 	u8 build_id[BUILD_ID_SIZE];
-	char build_id_hex[BUILD_ID_SIZE * 2 + 1];
 	int ret = -1;
 	int fd;
 	struct machine *machine;
@@ -1325,15 +1325,8 @@
 	}
 
 	self->origin = DSO__ORIG_BUILD_ID_CACHE;
-
-	if (self->has_build_id) {
-		build_id__sprintf(self->build_id, sizeof(self->build_id),
-				  build_id_hex);
-		snprintf(name, size, "%s/%s/.build-id/%.2s/%s",
-			 getenv("HOME"), DEBUG_CACHE_DIR,
-			 build_id_hex, build_id_hex + 2);
+	if (dso__build_id_filename(self, name, size) != NULL)
 		goto open_file;
-	}
 more:
 	do {
 		self->origin++;
@@ -1349,6 +1342,7 @@
 		case DSO__ORIG_BUILDID:
 			if (filename__read_build_id(self->long_name, build_id,
 						    sizeof(build_id))) {
+				char build_id_hex[BUILD_ID_SIZE * 2 + 1];
 				build_id__sprintf(build_id, sizeof(build_id),
 						  build_id_hex);
 				snprintf(name, size,