All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] perf: add new PERF_RECORD_MMAP2 record type
@ 2013-08-21 10:10 Stephane Eranian
  2013-08-21 10:10 ` [PATCH v2 1/2] perf: add attr->mmap2 attribute to an event Stephane Eranian
  2013-08-21 10:10 ` [PATCH v2 2/2] perf tools: add attr->mmap2 support Stephane Eranian
  0 siblings, 2 replies; 24+ messages in thread
From: Stephane Eranian @ 2013-08-21 10:10 UTC (permalink / raw)
  To: linux-kernel; +Cc: peterz, mingo, ak, acme, jolsa, namhyung.kim, dsahern

This patch series introduces a new record type for mmaps. This
new record is called PERF_RECORD_MMAP2. It provides more information
than the existing PERF_RECORD_MMAP. For each file-backed or
shared memory segment mapping, the device major, minor and the
inode numbers are recorded. This triplet may be used to
disambiguate virtual file-backed mappings between processes.

The triplet could not be fitted into the existing PERF_RECORD_MMAP
record without breaking backward compatibility. This is why we
introduce this new record type.

To activate this new record type, the mmap2 bit must be set
in perf_event_attr struct. It supersedes the mmap bit, but is
distinct from mmap_data. For mmap2 data records, both mmap2 and
mmap_data must be set. For code, only mmap2 must be set.

The series also provides the perf tool support for this new
MMAP2 record type. Perf record activates this mode by default.
The maj, min, ino are not yet exploited by perf report but
will be in subsequent perf tools.

In V2, we added a new field to the MMAP2 record: i_generation.
It captures the generation number of the inode. It can help
further disambiguate mappings. The inode generation is not
avail for MMAP2 records synthesized from /proc/PID/maps.

We also updated the header for the MMAP2 record layout to
show the sample_id struct which is appended if
attr->sample_id_all is set.

Patch is relative to tip.git

Signed-off-by: Stephane Eranian <eranian@google.com>

Stephane Eranian (2):
  perf: add attr->mmap2 attribute to an event
  perf tools: add attr->mmap2 support

 include/uapi/linux/perf_event.h |   24 ++++++++++++++++-
 kernel/events/core.c            |   46 +++++++++++++++++++++++++++++---
 tools/perf/builtin-annotate.c   |    1 +
 tools/perf/builtin-inject.c     |   15 +++++++++++
 tools/perf/builtin-mem.c        |    1 +
 tools/perf/builtin-report.c     |    1 +
 tools/perf/builtin-script.c     |    1 +
 tools/perf/util/build-id.c      |    1 +
 tools/perf/util/event.c         |   56 ++++++++++++++++++++++++++++++---------
 tools/perf/util/event.h         |   19 +++++++++++++
 tools/perf/util/evsel.c         |    5 ++--
 tools/perf/util/header.c        |    3 +++
 tools/perf/util/machine.c       |   52 +++++++++++++++++++++++++++++++++++-
 tools/perf/util/machine.h       |    1 +
 tools/perf/util/map.c           |    8 +++++-
 tools/perf/util/map.h           |    8 ++++--
 tools/perf/util/session.c       |   25 ++++++++++++++++-
 tools/perf/util/tool.h          |    1 +
 18 files changed, 244 insertions(+), 24 deletions(-)

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v2 1/2] perf: add attr->mmap2 attribute to an event
  2013-08-21 10:10 [PATCH v2 0/2] perf: add new PERF_RECORD_MMAP2 record type Stephane Eranian
@ 2013-08-21 10:10 ` Stephane Eranian
  2013-08-22 15:57   ` Arnaldo Carvalho de Melo
  2013-09-02  7:41   ` [tip:perf/core] perf: Add " tip-bot for Stephane Eranian
  2013-08-21 10:10 ` [PATCH v2 2/2] perf tools: add attr->mmap2 support Stephane Eranian
  1 sibling, 2 replies; 24+ messages in thread
From: Stephane Eranian @ 2013-08-21 10:10 UTC (permalink / raw)
  To: linux-kernel; +Cc: peterz, mingo, ak, acme, jolsa, namhyung.kim, dsahern

Adds a new PERF_RECORD_MMAP2 record type.

Used to request mmap records with more information about
the mapping, including device major, minor and the inode
number and generation for mappings associated with files
or shared memory segments. Works for code and data
(with attr->mmap_data set).

Existing PERF_RECORD_MMAP record is unmodified by this patch.

Signed-off-by: Stephane Eranian <eranian@google.com>
---
 include/uapi/linux/perf_event.h |   24 +++++++++++++++++++-
 kernel/events/core.c            |   46 +++++++++++++++++++++++++++++++++++----
 2 files changed, 65 insertions(+), 5 deletions(-)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 62c25a2..5268f78 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -275,8 +275,9 @@ struct perf_event_attr {
 
 				exclude_callchain_kernel : 1, /* exclude kernel callchains */
 				exclude_callchain_user   : 1, /* exclude user callchains */
+				mmap2          :  1, /* include mmap with inode data     */
 
-				__reserved_1   : 41;
+				__reserved_1   : 40;
 
 	union {
 		__u32		wakeup_events;	  /* wakeup every n events */
@@ -638,6 +639,27 @@ enum perf_event_type {
 	 */
 	PERF_RECORD_SAMPLE			= 9,
 
+	/*
+	 * The MMAP2 records are an augmented version of MMAP, they add
+	 * maj, min, ino numbers to be used to uniquely identify each mapping
+	 *
+	 * struct {
+	 *	struct perf_event_header	header;
+	 *
+	 *	u32				pid, tid;
+	 *	u64				addr;
+	 *	u64				len;
+	 *	u64				pgoff;
+	 *	u32				maj;
+	 *	u32				min;
+	 *	u64				ino;
+	 *	u64				ino_generation;
+	 *	char				filename[];
+	 * 	struct sample_id		sample_id;
+	 * };
+	 */
+	PERF_RECORD_MMAP2			= 10,
+
 	PERF_RECORD_MAX,			/* non-ABI */
 };
 
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 928fae7..60a5bbd 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4767,7 +4767,7 @@ next:
 /*
  * task tracking -- fork/exit
  *
- * enabled by: attr.comm | attr.mmap | attr.mmap_data | attr.task
+ * enabled by: attr.comm | attr.mmap | attr.mmap2 | attr.mmap_data | attr.task
  */
 
 struct perf_task_event {
@@ -4787,8 +4787,9 @@ struct perf_task_event {
 
 static int perf_event_task_match(struct perf_event *event)
 {
-	return event->attr.comm || event->attr.mmap ||
-	       event->attr.mmap_data || event->attr.task;
+	return event->attr.comm  || event->attr.mmap ||
+	       event->attr.mmap2 || event->attr.mmap_data ||
+	       event->attr.task;
 }
 
 static void perf_event_task_output(struct perf_event *event,
@@ -4983,6 +4984,9 @@ struct perf_mmap_event {
 
 	const char		*file_name;
 	int			file_size;
+	int			maj, min;
+	u64			ino;
+	u64			ino_generation;
 
 	struct {
 		struct perf_event_header	header;
@@ -5003,7 +5007,7 @@ static int perf_event_mmap_match(struct perf_event *event,
 	int executable = vma->vm_flags & VM_EXEC;
 
 	return (!executable && event->attr.mmap_data) ||
-	       (executable && event->attr.mmap);
+	       (executable && (event->attr.mmap || event->attr.mmap2));
 }
 
 static void perf_event_mmap_output(struct perf_event *event,
@@ -5018,6 +5022,13 @@ static void perf_event_mmap_output(struct perf_event *event,
 	if (!perf_event_mmap_match(event, data))
 		return;
 
+	if (event->attr.mmap2) {
+		mmap_event->event_id.header.type = PERF_RECORD_MMAP2;
+		mmap_event->event_id.header.size += sizeof(mmap_event->maj);
+		mmap_event->event_id.header.size += sizeof(mmap_event->min);
+		mmap_event->event_id.header.size += sizeof(mmap_event->ino);
+	}
+
 	perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
 	ret = perf_output_begin(&handle, event,
 				mmap_event->event_id.header.size);
@@ -5028,6 +5039,14 @@ static void perf_event_mmap_output(struct perf_event *event,
 	mmap_event->event_id.tid = perf_event_tid(event, current);
 
 	perf_output_put(&handle, mmap_event->event_id);
+
+	if (event->attr.mmap2) {
+		perf_output_put(&handle, mmap_event->maj);
+		perf_output_put(&handle, mmap_event->min);
+		perf_output_put(&handle, mmap_event->ino);
+		perf_output_put(&handle, mmap_event->ino_generation);
+	}
+
 	__output_copy(&handle, mmap_event->file_name,
 				   mmap_event->file_size);
 
@@ -5042,6 +5061,8 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 {
 	struct vm_area_struct *vma = mmap_event->vma;
 	struct file *file = vma->vm_file;
+	int maj = 0, min = 0;
+	u64 ino = 0, gen = 0;
 	unsigned int size;
 	char tmp[16];
 	char *buf = NULL;
@@ -5050,6 +5071,8 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 	memset(tmp, 0, sizeof(tmp));
 
 	if (file) {
+		struct inode *inode;
+		dev_t dev;
 		/*
 		 * d_path works from the end of the rb backwards, so we
 		 * need to add enough zero bytes after the string to handle
@@ -5065,6 +5088,13 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 			name = strncpy(tmp, "//toolong", sizeof(tmp));
 			goto got_name;
 		}
+		inode = file_inode(vma->vm_file);
+		dev = inode->i_sb->s_dev;
+		ino = inode->i_ino;
+		gen = inode->i_generation;
+		maj = MAJOR(dev);
+		min = MINOR(dev);
+
 	} else {
 		if (arch_vma_name(mmap_event->vma)) {
 			name = strncpy(tmp, arch_vma_name(mmap_event->vma),
@@ -5095,6 +5125,10 @@ got_name:
 
 	mmap_event->file_name = name;
 	mmap_event->file_size = size;
+	mmap_event->maj = maj;
+	mmap_event->min = min;
+	mmap_event->ino = ino;
+	mmap_event->ino_generation = gen;
 
 	if (!(vma->vm_flags & VM_EXEC))
 		mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_DATA;
@@ -5131,6 +5165,10 @@ void perf_event_mmap(struct vm_area_struct *vma)
 			.len    = vma->vm_end - vma->vm_start,
 			.pgoff  = (u64)vma->vm_pgoff << PAGE_SHIFT,
 		},
+		/* .maj (attr_mmap2 only) */
+		/* .min (attr_mmap2 only) */
+		/* .ino (attr_mmap2 only) */
+		/* .ino_generation (attr_mmap2 only) */
 	};
 
 	perf_event_mmap_event(&mmap_event);
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-08-21 10:10 [PATCH v2 0/2] perf: add new PERF_RECORD_MMAP2 record type Stephane Eranian
  2013-08-21 10:10 ` [PATCH v2 1/2] perf: add attr->mmap2 attribute to an event Stephane Eranian
@ 2013-08-21 10:10 ` Stephane Eranian
  2013-08-22 10:51   ` Peter Zijlstra
                     ` (2 more replies)
  1 sibling, 3 replies; 24+ messages in thread
From: Stephane Eranian @ 2013-08-21 10:10 UTC (permalink / raw)
  To: linux-kernel; +Cc: peterz, mingo, ak, acme, jolsa, namhyung.kim, dsahern

This patch adds support for the new PERF_RECORD_MMAP2
record type exposed by the kernel. This is an extended
PERF_RECORD_MMAP record. It adds for each file-backed
mapping the device major, minor number and the inode
number and generation. This triplet uniquely identifies
the source of a file-backed mapping. It can be used to
detect identical virtual mappings between processes, for
instance.

The patch will prefer MMAP2 over MMAP.

Signed-off-by: Stephane Eranian <eranian@google.com>
---
 tools/perf/builtin-annotate.c |    1 +
 tools/perf/builtin-inject.c   |   15 +++++++++++
 tools/perf/builtin-mem.c      |    1 +
 tools/perf/builtin-report.c   |    1 +
 tools/perf/builtin-script.c   |    1 +
 tools/perf/util/build-id.c    |    1 +
 tools/perf/util/event.c       |   56 ++++++++++++++++++++++++++++++++---------
 tools/perf/util/event.h       |   19 ++++++++++++++
 tools/perf/util/evsel.c       |    5 ++--
 tools/perf/util/header.c      |    3 +++
 tools/perf/util/machine.c     |   52 +++++++++++++++++++++++++++++++++++++-
 tools/perf/util/machine.h     |    1 +
 tools/perf/util/map.c         |    8 +++++-
 tools/perf/util/map.h         |    8 ++++--
 tools/perf/util/session.c     |   25 +++++++++++++++++-
 tools/perf/util/tool.h        |    1 +
 16 files changed, 179 insertions(+), 19 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index f988d38..5ebd0c3 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -277,6 +277,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
 		.tool = {
 			.sample	= process_sample_event,
 			.mmap	= perf_event__process_mmap,
+			.mmap2	= perf_event__process_mmap2,
 			.comm	= perf_event__process_comm,
 			.exit	= perf_event__process_exit,
 			.fork	= perf_event__process_fork,
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 1d8de2e..8695f35 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -123,6 +123,19 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,
 	return err;
 }
 
+static int perf_event__repipe_mmap2(struct perf_tool *tool,
+				   union perf_event *event,
+				   struct perf_sample *sample,
+				   struct machine *machine)
+{
+	int err;
+
+	err = perf_event__process_mmap2(tool, event, sample, machine);
+	perf_event__repipe(tool, event, sample, machine);
+
+	return err;
+}
+
 static int perf_event__repipe_fork(struct perf_tool *tool,
 				   union perf_event *event,
 				   struct perf_sample *sample,
@@ -337,6 +350,7 @@ static int __cmd_inject(struct perf_inject *inject)
 
 	if (inject->build_ids || inject->sched_stat) {
 		inject->tool.mmap	  = perf_event__repipe_mmap;
+		inject->tool.mmap2	  = perf_event__repipe_mmap2;
 		inject->tool.fork	  = perf_event__repipe_fork;
 		inject->tool.tracing_data = perf_event__repipe_tracing_data;
 	}
@@ -388,6 +402,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
 		.tool = {
 			.sample		= perf_event__repipe_sample,
 			.mmap		= perf_event__repipe,
+			.mmap2		= perf_event__repipe,
 			.comm		= perf_event__repipe,
 			.fork		= perf_event__repipe,
 			.exit		= perf_event__repipe,
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 706a1fa..ebf500e 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -190,6 +190,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
 		.tool = {
 			.sample		= process_sample_event,
 			.mmap		= perf_event__process_mmap,
+			.mmap2		= perf_event__process_mmap2,
 			.comm		= perf_event__process_comm,
 			.lost		= perf_event__process_lost,
 			.fork		= perf_event__process_fork,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 958a56a..96625a79 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -744,6 +744,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 		.tool = {
 			.sample		 = process_sample_event,
 			.mmap		 = perf_event__process_mmap,
+			.mmap2		 = perf_event__process_mmap2,
 			.comm		 = perf_event__process_comm,
 			.exit		 = perf_event__process_exit,
 			.fork		 = perf_event__process_fork,
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 2ad9d5b..eed7f77 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -541,6 +541,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 static struct perf_tool perf_script = {
 	.sample		 = process_sample_event,
 	.mmap		 = perf_event__process_mmap,
+	.mmap2		 = perf_event__process_mmap2,
 	.comm		 = perf_event__process_comm,
 	.exit		 = perf_event__process_exit,
 	.fork		 = perf_event__process_fork,
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 5295625..d8dd29a 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -64,6 +64,7 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
 struct perf_tool build_id__mark_dso_hit_ops = {
 	.sample	= build_id__mark_dso_hit,
 	.mmap	= perf_event__process_mmap,
+	.mmap2	= perf_event__process_mmap2,
 	.fork	= perf_event__process_fork,
 	.exit	= perf_event__exit_del_thread,
 	.attr		 = perf_event__process_attr,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 49713ae..3b7134c 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -11,6 +11,7 @@
 static const char *perf_event__names[] = {
 	[0]					= "TOTAL",
 	[PERF_RECORD_MMAP]			= "MMAP",
+	[PERF_RECORD_MMAP2]			= "MMAP2",
 	[PERF_RECORD_LOST]			= "LOST",
 	[PERF_RECORD_COMM]			= "COMM",
 	[PERF_RECORD_EXIT]			= "EXIT",
@@ -186,7 +187,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		return -1;
 	}
 
-	event->header.type = PERF_RECORD_MMAP;
+	event->header.type = PERF_RECORD_MMAP2;
 	/*
 	 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
 	 */
@@ -197,7 +198,9 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		char prot[5];
 		char execname[PATH_MAX];
 		char anonstr[] = "//anon";
+		unsigned int ino;
 		size_t size;
+		ssize_t n;
 
 		if (fgets(bf, sizeof(bf), fp) == NULL)
 			break;
@@ -206,9 +209,16 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		strcpy(execname, "");
 
 		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
-		sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n",
-		       &event->mmap.start, &event->mmap.len, prot,
-		       &event->mmap.pgoff, execname);
+		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
+		       &event->mmap2.start, &event->mmap2.len, prot,
+		       &event->mmap2.pgoff, &event->mmap2.maj,
+		       &event->mmap2.min,
+		       &ino, execname);
+
+		event->mmap2.ino = (u64)ino;
+
+		if (n != 8)
+			continue;
 
 		if (prot[2] != 'x')
 			continue;
@@ -217,15 +227,15 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 			strcpy(execname, anonstr);
 
 		size = strlen(execname) + 1;
-		memcpy(event->mmap.filename, execname, size);
+		memcpy(event->mmap2.filename, execname, size);
 		size = PERF_ALIGN(size, sizeof(u64));
-		event->mmap.len -= event->mmap.start;
-		event->mmap.header.size = (sizeof(event->mmap) -
-					   (sizeof(event->mmap.filename) - size));
-		memset(event->mmap.filename + size, 0, machine->id_hdr_size);
-		event->mmap.header.size += machine->id_hdr_size;
-		event->mmap.pid = tgid;
-		event->mmap.tid = pid;
+		event->mmap2.len -= event->mmap.start;
+		event->mmap2.header.size = (sizeof(event->mmap2) -
+					(sizeof(event->mmap2.filename) - size));
+		memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
+		event->mmap2.header.size += machine->id_hdr_size;
+		event->mmap2.pid = tgid;
+		event->mmap2.tid = pid;
 
 		if (process(tool, event, &synth_sample, machine) != 0) {
 			rc = -1;
@@ -527,6 +537,17 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
 		       event->mmap.len, event->mmap.pgoff, event->mmap.filename);
 }
 
+size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
+{
+	return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
+			   " %02x:%02x %"PRIu64" %"PRIu64"]: %s\n",
+		       event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
+		       event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
+		       event->mmap2.min, event->mmap2.ino,
+		       event->mmap2.ino_generation,
+		       event->mmap2.filename);
+}
+
 int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
 			     struct perf_sample *sample __maybe_unused,
@@ -535,6 +556,14 @@ int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
 	return machine__process_mmap_event(machine, event);
 }
 
+int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
+			     union perf_event *event,
+			     struct perf_sample *sample __maybe_unused,
+			     struct machine *machine)
+{
+	return machine__process_mmap2_event(machine, event);
+}
+
 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
 {
 	return fprintf(fp, "(%d:%d):(%d:%d)\n",
@@ -574,6 +603,9 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
 	case PERF_RECORD_MMAP:
 		ret += perf_event__fprintf_mmap(event, fp);
 		break;
+	case PERF_RECORD_MMAP2:
+		ret += perf_event__fprintf_mmap2(event, fp);
+		break;
 	default:
 		ret += fprintf(fp, "\n");
 	}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 15db071..23b3879 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -27,6 +27,19 @@ struct mmap_event {
 	char filename[PATH_MAX];
 };
 
+struct mmap2_event {
+	struct perf_event_header header;
+	u32 pid, tid;
+	u64 start;
+	u64 len;
+	u64 pgoff;
+	u32 maj;
+	u32 min;
+	u64 ino;
+	u64 ino_generation;
+	char filename[PATH_MAX];
+};
+
 struct comm_event {
 	struct perf_event_header header;
 	u32 pid, tid;
@@ -168,6 +181,7 @@ union perf_event {
 	struct perf_event_header	header;
 	struct ip_event			ip;
 	struct mmap_event		mmap;
+	struct mmap2_event		mmap2;
 	struct comm_event		comm;
 	struct fork_event		fork;
 	struct lost_event		lost;
@@ -217,6 +231,10 @@ int perf_event__process_mmap(struct perf_tool *tool,
 			     union perf_event *event,
 			     struct perf_sample *sample,
 			     struct machine *machine);
+int perf_event__process_mmap2(struct perf_tool *tool,
+			     union perf_event *event,
+			     struct perf_sample *sample,
+			     struct machine *machine);
 int perf_event__process_fork(struct perf_tool *tool,
 			     union perf_event *event,
 			     struct perf_sample *sample,
@@ -244,6 +262,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
 
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf(union perf_event *event, FILE *fp);
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 960394e..2bc0e4d 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -598,8 +598,9 @@ void perf_evsel__config(struct perf_evsel *evsel,
 	if (opts->sample_weight)
 		attr->sample_type	|= PERF_SAMPLE_WEIGHT;
 
-	attr->mmap = track;
-	attr->comm = track;
+	attr->mmap  = track;
+	attr->mmap2 = track;
+	attr->comm  = track;
 
 	/*
 	 * XXX see the function comment above
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a33197a..26441d0 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1351,6 +1351,9 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
 
 		fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
 
+		fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2);
+		fprintf(fp, ", attr_mmap  = %d", evsel->attr.mmap);
+		fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data);
 		if (evsel->ids) {
 			fprintf(fp, ", id = {");
 			for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 4514e7e..1412e17 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -987,6 +987,53 @@ out_problem:
 	return -1;
 }
 
+int machine__process_mmap2_event(struct machine *machine,
+				 union perf_event *event)
+{
+	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+	struct thread *thread;
+	struct map *map;
+	enum map_type type;
+	int ret = 0;
+
+	if (dump_trace)
+		perf_event__fprintf_mmap2(event, stdout);
+
+	if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
+	    cpumode == PERF_RECORD_MISC_KERNEL) {
+		ret = machine__process_kernel_mmap_event(machine, event);
+		if (ret < 0)
+			goto out_problem;
+		return 0;
+	}
+
+	thread = machine__findnew_thread(machine, event->mmap2.pid);
+	if (thread == NULL)
+		goto out_problem;
+
+	if (event->header.misc & PERF_RECORD_MISC_MMAP_DATA)
+		type = MAP__VARIABLE;
+	else
+		type = MAP__FUNCTION;
+
+	map = map__new(&machine->user_dsos, event->mmap2.start,
+			event->mmap2.len, event->mmap2.pgoff,
+			event->mmap2.pid, event->mmap2.maj,
+			event->mmap2.min, event->mmap2.ino,
+			event->mmap2.ino_generation,
+			event->mmap2.filename, type);
+
+	if (map == NULL)
+		goto out_problem;
+
+	thread__insert_map(thread, map);
+	return 0;
+
+out_problem:
+	dump_printf("problem processing PERF_RECORD_MMAP2, skipping event.\n");
+	return 0;
+}
+
 int machine__process_mmap_event(struct machine *machine, union perf_event *event)
 {
 	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
@@ -1017,7 +1064,8 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
 
 	map = map__new(&machine->user_dsos, event->mmap.start,
 			event->mmap.len, event->mmap.pgoff,
-			event->mmap.pid, event->mmap.filename,
+			event->mmap.pid, 0, 0, 0, 0,
+			event->mmap.filename,
 			type);
 
 	if (map == NULL)
@@ -1081,6 +1129,8 @@ int machine__process_event(struct machine *machine, union perf_event *event)
 		ret = machine__process_comm_event(machine, event); break;
 	case PERF_RECORD_MMAP:
 		ret = machine__process_mmap_event(machine, event); break;
+	case PERF_RECORD_MMAP2:
+		ret = machine__process_mmap2_event(machine, event); break;
 	case PERF_RECORD_FORK:
 		ret = machine__process_fork_event(machine, event); break;
 	case PERF_RECORD_EXIT:
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 603ffba..2593147 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -45,6 +45,7 @@ int machine__process_exit_event(struct machine *machine, union perf_event *event
 int machine__process_fork_event(struct machine *machine, union perf_event *event);
 int machine__process_lost_event(struct machine *machine, union perf_event *event);
 int machine__process_mmap_event(struct machine *machine, union perf_event *event);
+int machine__process_mmap2_event(struct machine *machine, union perf_event *event);
 int machine__process_event(struct machine *machine, union perf_event *event);
 
 typedef void (*machine__process_t)(struct machine *machine, void *data);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 9e8304c..4f6680d 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -48,7 +48,8 @@ void map__init(struct map *map, enum map_type type,
 }
 
 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
-		     u64 pgoff, u32 pid, char *filename,
+		     u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
+		     u64 ino_gen, char *filename,
 		     enum map_type type)
 {
 	struct map *map = malloc(sizeof(*map));
@@ -62,6 +63,11 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
 		vdso = is_vdso_map(filename);
 		no_dso = is_no_dso_memory(filename);
 
+		map->maj = d_maj;
+		map->min = d_min;
+		map->ino = ino;
+		map->ino_generation = ino_gen;
+
 		if (anon) {
 			snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
 			filename = newfilename;
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 2cc93cb..4886ca2 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -36,6 +36,9 @@ struct map {
 	bool			erange_warned;
 	u32			priv;
 	u64			pgoff;
+	u32			maj, min; /* only valid for MMAP2 record */
+	u64			ino;      /* only valid for MMAP2 record */
+	u64			ino_generation;/* only valid for MMAP2 record */
 
 	/* ip -> dso rip */
 	u64			(*map_ip)(struct map *, u64);
@@ -88,8 +91,9 @@ typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
 void map__init(struct map *map, enum map_type type,
 	       u64 start, u64 end, u64 pgoff, struct dso *dso);
 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
-		     u64 pgoff, u32 pid, char *filename,
-		     enum map_type type);
+		     u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
+		     u64 ino_gen,
+		     char *filename, enum map_type type);
 struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
 void map__delete(struct map *map);
 struct map *map__clone(struct map *map);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index de16a77..99e60f9 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -351,6 +351,25 @@ static void perf_event__mmap_swap(union perf_event *event,
 	}
 }
 
+static void perf_event__mmap2_swap(union perf_event *event,
+				  bool sample_id_all)
+{
+	event->mmap2.pid   = bswap_32(event->mmap2.pid);
+	event->mmap2.tid   = bswap_32(event->mmap2.tid);
+	event->mmap2.start = bswap_64(event->mmap2.start);
+	event->mmap2.len   = bswap_64(event->mmap2.len);
+	event->mmap2.pgoff = bswap_64(event->mmap2.pgoff);
+	event->mmap2.maj   = bswap_32(event->mmap2.maj);
+	event->mmap2.min   = bswap_32(event->mmap2.min);
+	event->mmap2.ino   = bswap_64(event->mmap2.ino);
+
+	if (sample_id_all) {
+		void *data = &event->mmap2.filename;
+
+		data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
+		swap_sample_id_all(event, data);
+	}
+}
 static void perf_event__task_swap(union perf_event *event, bool sample_id_all)
 {
 	event->fork.pid	 = bswap_32(event->fork.pid);
@@ -455,6 +474,7 @@ typedef void (*perf_event__swap_op)(union perf_event *event,
 
 static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_MMAP]		  = perf_event__mmap_swap,
+	[PERF_RECORD_MMAP2]		  = perf_event__mmap2_swap,
 	[PERF_RECORD_COMM]		  = perf_event__comm_swap,
 	[PERF_RECORD_FORK]		  = perf_event__task_swap,
 	[PERF_RECORD_EXIT]		  = perf_event__task_swap,
@@ -849,7 +869,8 @@ static struct machine *
 	     (cpumode == PERF_RECORD_MISC_GUEST_USER))) {
 		u32 pid;
 
-		if (event->header.type == PERF_RECORD_MMAP)
+		if (event->header.type == PERF_RECORD_MMAP
+		    || event->header.type == PERF_RECORD_MMAP2)
 			pid = event->mmap.pid;
 		else
 			pid = event->ip.pid;
@@ -975,6 +996,8 @@ static int perf_session_deliver_event(struct perf_session *session,
 						    sample, evsel, machine);
 	case PERF_RECORD_MMAP:
 		return tool->mmap(tool, event, sample, machine);
+	case PERF_RECORD_MMAP2:
+		return tool->mmap2(tool, event, sample, machine);
 	case PERF_RECORD_COMM:
 		return tool->comm(tool, event, sample, machine);
 	case PERF_RECORD_FORK:
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 62b16b6..4385816 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -29,6 +29,7 @@ struct perf_tool {
 	event_sample	sample,
 			read;
 	event_op	mmap,
+			mmap2,
 			comm,
 			fork,
 			exit,
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-08-21 10:10 ` [PATCH v2 2/2] perf tools: add attr->mmap2 support Stephane Eranian
@ 2013-08-22 10:51   ` Peter Zijlstra
  2013-08-30 14:03     ` Stephane Eranian
  2013-09-09 19:47   ` Arnaldo Carvalho de Melo
  2013-09-12 11:10   ` [tip:perf/urgent] perf tools: Add " tip-bot for Stephane Eranian
  2 siblings, 1 reply; 24+ messages in thread
From: Peter Zijlstra @ 2013-08-22 10:51 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: linux-kernel, mingo, ak, acme, jolsa, namhyung.kim, dsahern

On Wed, Aug 21, 2013 at 12:10:25PM +0200, Stephane Eranian wrote:
> This patch adds support for the new PERF_RECORD_MMAP2
> record type exposed by the kernel. This is an extended
> PERF_RECORD_MMAP record. It adds for each file-backed
> mapping the device major, minor number and the inode
> number and generation. This triplet uniquely identifies
> the source of a file-backed mapping. It can be used to
> detect identical virtual mappings between processes, for
> instance.
> 
> The patch will prefer MMAP2 over MMAP.
> 
> Signed-off-by: Stephane Eranian <eranian@google.com>

Acme, ACK?

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 1/2] perf: add attr->mmap2 attribute to an event
  2013-08-21 10:10 ` [PATCH v2 1/2] perf: add attr->mmap2 attribute to an event Stephane Eranian
@ 2013-08-22 15:57   ` Arnaldo Carvalho de Melo
  2013-09-02  7:41   ` [tip:perf/core] perf: Add " tip-bot for Stephane Eranian
  1 sibling, 0 replies; 24+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-08-22 15:57 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: linux-kernel, peterz, mingo, ak, jolsa, namhyung.kim, dsahern

Em Wed, Aug 21, 2013 at 12:10:24PM +0200, Stephane Eranian escreveu:
> Adds a new PERF_RECORD_MMAP2 record type.
> 
> Used to request mmap records with more information about
> the mapping, including device major, minor and the inode
> number and generation for mappings associated with files
> or shared memory segments. Works for code and data
> (with attr->mmap_data set).
> 
> Existing PERF_RECORD_MMAP record is unmodified by this patch.

So this is exactly what we get from PERF_RECORD_MMAP + a few other
fields, right?

I think we should take the opportunity and remove the fields that are
in PERF_RECORD_MMAP but can be selectively asked for using
->sample_id_all, i.e. we use sample_type to ask for:

	PERF_SAMPLE_CPU
	PERF_SAMPLE_STREAM_ID
	PERF_SAMPLE_ID
	PERF_SAMPLE_TIME
	PERF_SAMPLE_TID

That should not be present in the PERF_RECORD_MMAP2 fixed payload.

This way we take the opportunity to compress the event by using an
existing facility: attr.sample_id_all and attr.sample_type.

But then this is "just" for the 8 bytes used for pid/tid, selectable via
PERF_SAMPLE_TID, so up to peterz, if you think its not worth the
complexity, Acked.

- Arnaldo
 
> Signed-off-by: Stephane Eranian <eranian@google.com>
> ---
>  include/uapi/linux/perf_event.h |   24 +++++++++++++++++++-
>  kernel/events/core.c            |   46 +++++++++++++++++++++++++++++++++++----
>  2 files changed, 65 insertions(+), 5 deletions(-)
> 
> diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
> index 62c25a2..5268f78 100644
> --- a/include/uapi/linux/perf_event.h
> +++ b/include/uapi/linux/perf_event.h
> @@ -275,8 +275,9 @@ struct perf_event_attr {
>  
>  				exclude_callchain_kernel : 1, /* exclude kernel callchains */
>  				exclude_callchain_user   : 1, /* exclude user callchains */
> +				mmap2          :  1, /* include mmap with inode data     */
>  
> -				__reserved_1   : 41;
> +				__reserved_1   : 40;
>  
>  	union {
>  		__u32		wakeup_events;	  /* wakeup every n events */
> @@ -638,6 +639,27 @@ enum perf_event_type {
>  	 */
>  	PERF_RECORD_SAMPLE			= 9,
>  
> +	/*
> +	 * The MMAP2 records are an augmented version of MMAP, they add
> +	 * maj, min, ino numbers to be used to uniquely identify each mapping
> +	 *
> +	 * struct {
> +	 *	struct perf_event_header	header;
> +	 *
> +	 *	u32				pid, tid;
> +	 *	u64				addr;
> +	 *	u64				len;
> +	 *	u64				pgoff;
> +	 *	u32				maj;
> +	 *	u32				min;
> +	 *	u64				ino;
> +	 *	u64				ino_generation;
> +	 *	char				filename[];
> +	 * 	struct sample_id		sample_id;
> +	 * };
> +	 */
> +	PERF_RECORD_MMAP2			= 10,
> +
>  	PERF_RECORD_MAX,			/* non-ABI */
>  };
>  
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 928fae7..60a5bbd 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -4767,7 +4767,7 @@ next:
>  /*
>   * task tracking -- fork/exit
>   *
> - * enabled by: attr.comm | attr.mmap | attr.mmap_data | attr.task
> + * enabled by: attr.comm | attr.mmap | attr.mmap2 | attr.mmap_data | attr.task
>   */
>  
>  struct perf_task_event {
> @@ -4787,8 +4787,9 @@ struct perf_task_event {
>  
>  static int perf_event_task_match(struct perf_event *event)
>  {
> -	return event->attr.comm || event->attr.mmap ||
> -	       event->attr.mmap_data || event->attr.task;
> +	return event->attr.comm  || event->attr.mmap ||
> +	       event->attr.mmap2 || event->attr.mmap_data ||
> +	       event->attr.task;
>  }
>  
>  static void perf_event_task_output(struct perf_event *event,
> @@ -4983,6 +4984,9 @@ struct perf_mmap_event {
>  
>  	const char		*file_name;
>  	int			file_size;
> +	int			maj, min;
> +	u64			ino;
> +	u64			ino_generation;
>  
>  	struct {
>  		struct perf_event_header	header;
> @@ -5003,7 +5007,7 @@ static int perf_event_mmap_match(struct perf_event *event,
>  	int executable = vma->vm_flags & VM_EXEC;
>  
>  	return (!executable && event->attr.mmap_data) ||
> -	       (executable && event->attr.mmap);
> +	       (executable && (event->attr.mmap || event->attr.mmap2));
>  }
>  
>  static void perf_event_mmap_output(struct perf_event *event,
> @@ -5018,6 +5022,13 @@ static void perf_event_mmap_output(struct perf_event *event,
>  	if (!perf_event_mmap_match(event, data))
>  		return;
>  
> +	if (event->attr.mmap2) {
> +		mmap_event->event_id.header.type = PERF_RECORD_MMAP2;
> +		mmap_event->event_id.header.size += sizeof(mmap_event->maj);
> +		mmap_event->event_id.header.size += sizeof(mmap_event->min);
> +		mmap_event->event_id.header.size += sizeof(mmap_event->ino);
> +	}
> +
>  	perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
>  	ret = perf_output_begin(&handle, event,
>  				mmap_event->event_id.header.size);
> @@ -5028,6 +5039,14 @@ static void perf_event_mmap_output(struct perf_event *event,
>  	mmap_event->event_id.tid = perf_event_tid(event, current);
>  
>  	perf_output_put(&handle, mmap_event->event_id);
> +
> +	if (event->attr.mmap2) {
> +		perf_output_put(&handle, mmap_event->maj);
> +		perf_output_put(&handle, mmap_event->min);
> +		perf_output_put(&handle, mmap_event->ino);
> +		perf_output_put(&handle, mmap_event->ino_generation);
> +	}
> +
>  	__output_copy(&handle, mmap_event->file_name,
>  				   mmap_event->file_size);
>  
> @@ -5042,6 +5061,8 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
>  {
>  	struct vm_area_struct *vma = mmap_event->vma;
>  	struct file *file = vma->vm_file;
> +	int maj = 0, min = 0;
> +	u64 ino = 0, gen = 0;
>  	unsigned int size;
>  	char tmp[16];
>  	char *buf = NULL;
> @@ -5050,6 +5071,8 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
>  	memset(tmp, 0, sizeof(tmp));
>  
>  	if (file) {
> +		struct inode *inode;
> +		dev_t dev;
>  		/*
>  		 * d_path works from the end of the rb backwards, so we
>  		 * need to add enough zero bytes after the string to handle
> @@ -5065,6 +5088,13 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
>  			name = strncpy(tmp, "//toolong", sizeof(tmp));
>  			goto got_name;
>  		}
> +		inode = file_inode(vma->vm_file);
> +		dev = inode->i_sb->s_dev;
> +		ino = inode->i_ino;
> +		gen = inode->i_generation;
> +		maj = MAJOR(dev);
> +		min = MINOR(dev);
> +
>  	} else {
>  		if (arch_vma_name(mmap_event->vma)) {
>  			name = strncpy(tmp, arch_vma_name(mmap_event->vma),
> @@ -5095,6 +5125,10 @@ got_name:
>  
>  	mmap_event->file_name = name;
>  	mmap_event->file_size = size;
> +	mmap_event->maj = maj;
> +	mmap_event->min = min;
> +	mmap_event->ino = ino;
> +	mmap_event->ino_generation = gen;
>  
>  	if (!(vma->vm_flags & VM_EXEC))
>  		mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_DATA;
> @@ -5131,6 +5165,10 @@ void perf_event_mmap(struct vm_area_struct *vma)
>  			.len    = vma->vm_end - vma->vm_start,
>  			.pgoff  = (u64)vma->vm_pgoff << PAGE_SHIFT,
>  		},
> +		/* .maj (attr_mmap2 only) */
> +		/* .min (attr_mmap2 only) */
> +		/* .ino (attr_mmap2 only) */
> +		/* .ino_generation (attr_mmap2 only) */
>  	};
>  
>  	perf_event_mmap_event(&mmap_event);
> -- 
> 1.7.10.4

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-08-22 10:51   ` Peter Zijlstra
@ 2013-08-30 14:03     ` Stephane Eranian
  2013-08-30 14:08       ` Peter Zijlstra
  0 siblings, 1 reply; 24+ messages in thread
From: Stephane Eranian @ 2013-08-30 14:03 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: LKML, mingo, ak, Arnaldo Carvalho de Melo, Jiri Olsa,
	Namhyung Kim, David Ahern

Hi,

I realized I have forgotten to patch builtin-inject.c to repipe mmap2 records.
Will resubmit V3.


On Thu, Aug 22, 2013 at 12:51 PM, Peter Zijlstra <peterz@infradead.org> wrote:
> On Wed, Aug 21, 2013 at 12:10:25PM +0200, Stephane Eranian wrote:
>> This patch adds support for the new PERF_RECORD_MMAP2
>> record type exposed by the kernel. This is an extended
>> PERF_RECORD_MMAP record. It adds for each file-backed
>> mapping the device major, minor number and the inode
>> number and generation. This triplet uniquely identifies
>> the source of a file-backed mapping. It can be used to
>> detect identical virtual mappings between processes, for
>> instance.
>>
>> The patch will prefer MMAP2 over MMAP.
>>
>> Signed-off-by: Stephane Eranian <eranian@google.com>
>
> Acme, ACK?

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-08-30 14:03     ` Stephane Eranian
@ 2013-08-30 14:08       ` Peter Zijlstra
  2013-08-30 14:15         ` Stephane Eranian
  0 siblings, 1 reply; 24+ messages in thread
From: Peter Zijlstra @ 2013-08-30 14:08 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: LKML, mingo, ak, Arnaldo Carvalho de Melo, Jiri Olsa,
	Namhyung Kim, David Ahern

On Fri, Aug 30, 2013 at 04:03:26PM +0200, Stephane Eranian wrote:
> Hi,
> 
> I realized I have forgotten to patch builtin-inject.c to repipe mmap2 records.
> Will resubmit V3.

OK, I already queued the previous two, it looked fine and the ack was
long in coming. If mingo manages to push out before I can pick up v3
I'll frob a delta patch.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-08-30 14:08       ` Peter Zijlstra
@ 2013-08-30 14:15         ` Stephane Eranian
  2013-08-30 17:32           ` Stephane Eranian
  0 siblings, 1 reply; 24+ messages in thread
From: Stephane Eranian @ 2013-08-30 14:15 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: LKML, mingo, ak, Arnaldo Carvalho de Melo, Jiri Olsa,
	Namhyung Kim, David Ahern

On Fri, Aug 30, 2013 at 4:08 PM, Peter Zijlstra <peterz@infradead.org> wrote:
> On Fri, Aug 30, 2013 at 04:03:26PM +0200, Stephane Eranian wrote:
>> Hi,
>>
>> I realized I have forgotten to patch builtin-inject.c to repipe mmap2 records.
>> Will resubmit V3.
>
> OK, I already queued the previous two, it looked fine and the ack was
> long in coming. If mingo manages to push out before I can pick up v3
> I'll frob a delta patch.

I can submit a separate patch to cover for builtin-inject.c

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-08-30 14:15         ` Stephane Eranian
@ 2013-08-30 17:32           ` Stephane Eranian
  2013-08-31  6:00             ` Ingo Molnar
  0 siblings, 1 reply; 24+ messages in thread
From: Stephane Eranian @ 2013-08-30 17:32 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: LKML, mingo, ak, Arnaldo Carvalho de Melo, Jiri Olsa,
	Namhyung Kim, David Ahern

False alarm, the changes in builtin-inject.c are in V2.
Nothing more to do.
Sorry about the confusion.


On Fri, Aug 30, 2013 at 4:15 PM, Stephane Eranian <eranian@google.com> wrote:
> On Fri, Aug 30, 2013 at 4:08 PM, Peter Zijlstra <peterz@infradead.org> wrote:
>> On Fri, Aug 30, 2013 at 04:03:26PM +0200, Stephane Eranian wrote:
>>> Hi,
>>>
>>> I realized I have forgotten to patch builtin-inject.c to repipe mmap2 records.
>>> Will resubmit V3.
>>
>> OK, I already queued the previous two, it looked fine and the ack was
>> long in coming. If mingo manages to push out before I can pick up v3
>> I'll frob a delta patch.
>
> I can submit a separate patch to cover for builtin-inject.c

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-08-30 17:32           ` Stephane Eranian
@ 2013-08-31  6:00             ` Ingo Molnar
  0 siblings, 0 replies; 24+ messages in thread
From: Ingo Molnar @ 2013-08-31  6:00 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: Peter Zijlstra, LKML, mingo, ak, Arnaldo Carvalho de Melo,
	Jiri Olsa, Namhyung Kim, David Ahern


* Stephane Eranian <eranian@google.com> wrote:

> False alarm, the changes in builtin-inject.c are in V2. Nothing more to 
> do. Sorry about the confusion.

ok, I'll pick up the -v2 patches from Peter.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [tip:perf/core] perf: Add attr->mmap2 attribute to an event
  2013-08-21 10:10 ` [PATCH v2 1/2] perf: add attr->mmap2 attribute to an event Stephane Eranian
  2013-08-22 15:57   ` Arnaldo Carvalho de Melo
@ 2013-09-02  7:41   ` tip-bot for Stephane Eranian
  1 sibling, 0 replies; 24+ messages in thread
From: tip-bot for Stephane Eranian @ 2013-09-02  7:41 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, eranian, hpa, mingo, peterz, tglx, viro

Commit-ID:  13d7a2410fa637f450a29ecb515ac318ee40c741
Gitweb:     http://git.kernel.org/tip/13d7a2410fa637f450a29ecb515ac318ee40c741
Author:     Stephane Eranian <eranian@google.com>
AuthorDate: Wed, 21 Aug 2013 12:10:24 +0200
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 2 Sep 2013 08:42:48 +0200

perf: Add attr->mmap2 attribute to an event

Adds a new PERF_RECORD_MMAP2 record type which is essence
an expanded version of PERF_RECORD_MMAP.

Used to request mmap records with more information about
the mapping, including device major, minor and the inode
number and generation for mappings associated with files
or shared memory segments. Works for code and data
(with attr->mmap_data set).

Existing PERF_RECORD_MMAP record is unmodified by this patch.

Signed-off-by: Stephane Eranian <eranian@google.com>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Link: http://lkml.kernel.org/r/1377079825-19057-2-git-send-email-eranian@google.com
[ Added Al to the Cc:. Are the ino, maj/min exports of vma->vm_file OK? ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 include/uapi/linux/perf_event.h | 24 ++++++++++++++++++++-
 kernel/events/core.c            | 46 +++++++++++++++++++++++++++++++++++++----
 2 files changed, 65 insertions(+), 5 deletions(-)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 42cb7b6..a77f43a 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -276,8 +276,9 @@ struct perf_event_attr {
 
 				exclude_callchain_kernel : 1, /* exclude kernel callchains */
 				exclude_callchain_user   : 1, /* exclude user callchains */
+				mmap2          :  1, /* include mmap with inode data     */
 
-				__reserved_1   : 41;
+				__reserved_1   : 40;
 
 	union {
 		__u32		wakeup_events;	  /* wakeup every n events */
@@ -651,6 +652,27 @@ enum perf_event_type {
 	 */
 	PERF_RECORD_SAMPLE			= 9,
 
+	/*
+	 * The MMAP2 records are an augmented version of MMAP, they add
+	 * maj, min, ino numbers to be used to uniquely identify each mapping
+	 *
+	 * struct {
+	 *	struct perf_event_header	header;
+	 *
+	 *	u32				pid, tid;
+	 *	u64				addr;
+	 *	u64				len;
+	 *	u64				pgoff;
+	 *	u32				maj;
+	 *	u32				min;
+	 *	u64				ino;
+	 *	u64				ino_generation;
+	 *	char				filename[];
+	 * 	struct sample_id		sample_id;
+	 * };
+	 */
+	PERF_RECORD_MMAP2			= 10,
+
 	PERF_RECORD_MAX,			/* non-ABI */
 };
 
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 15d0f24..c7ee497 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4776,7 +4776,7 @@ next:
 /*
  * task tracking -- fork/exit
  *
- * enabled by: attr.comm | attr.mmap | attr.mmap_data | attr.task
+ * enabled by: attr.comm | attr.mmap | attr.mmap2 | attr.mmap_data | attr.task
  */
 
 struct perf_task_event {
@@ -4796,8 +4796,9 @@ struct perf_task_event {
 
 static int perf_event_task_match(struct perf_event *event)
 {
-	return event->attr.comm || event->attr.mmap ||
-	       event->attr.mmap_data || event->attr.task;
+	return event->attr.comm  || event->attr.mmap ||
+	       event->attr.mmap2 || event->attr.mmap_data ||
+	       event->attr.task;
 }
 
 static void perf_event_task_output(struct perf_event *event,
@@ -4992,6 +4993,9 @@ struct perf_mmap_event {
 
 	const char		*file_name;
 	int			file_size;
+	int			maj, min;
+	u64			ino;
+	u64			ino_generation;
 
 	struct {
 		struct perf_event_header	header;
@@ -5012,7 +5016,7 @@ static int perf_event_mmap_match(struct perf_event *event,
 	int executable = vma->vm_flags & VM_EXEC;
 
 	return (!executable && event->attr.mmap_data) ||
-	       (executable && event->attr.mmap);
+	       (executable && (event->attr.mmap || event->attr.mmap2));
 }
 
 static void perf_event_mmap_output(struct perf_event *event,
@@ -5027,6 +5031,13 @@ static void perf_event_mmap_output(struct perf_event *event,
 	if (!perf_event_mmap_match(event, data))
 		return;
 
+	if (event->attr.mmap2) {
+		mmap_event->event_id.header.type = PERF_RECORD_MMAP2;
+		mmap_event->event_id.header.size += sizeof(mmap_event->maj);
+		mmap_event->event_id.header.size += sizeof(mmap_event->min);
+		mmap_event->event_id.header.size += sizeof(mmap_event->ino);
+	}
+
 	perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
 	ret = perf_output_begin(&handle, event,
 				mmap_event->event_id.header.size);
@@ -5037,6 +5048,14 @@ static void perf_event_mmap_output(struct perf_event *event,
 	mmap_event->event_id.tid = perf_event_tid(event, current);
 
 	perf_output_put(&handle, mmap_event->event_id);
+
+	if (event->attr.mmap2) {
+		perf_output_put(&handle, mmap_event->maj);
+		perf_output_put(&handle, mmap_event->min);
+		perf_output_put(&handle, mmap_event->ino);
+		perf_output_put(&handle, mmap_event->ino_generation);
+	}
+
 	__output_copy(&handle, mmap_event->file_name,
 				   mmap_event->file_size);
 
@@ -5051,6 +5070,8 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 {
 	struct vm_area_struct *vma = mmap_event->vma;
 	struct file *file = vma->vm_file;
+	int maj = 0, min = 0;
+	u64 ino = 0, gen = 0;
 	unsigned int size;
 	char tmp[16];
 	char *buf = NULL;
@@ -5059,6 +5080,8 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 	memset(tmp, 0, sizeof(tmp));
 
 	if (file) {
+		struct inode *inode;
+		dev_t dev;
 		/*
 		 * d_path works from the end of the rb backwards, so we
 		 * need to add enough zero bytes after the string to handle
@@ -5074,6 +5097,13 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 			name = strncpy(tmp, "//toolong", sizeof(tmp));
 			goto got_name;
 		}
+		inode = file_inode(vma->vm_file);
+		dev = inode->i_sb->s_dev;
+		ino = inode->i_ino;
+		gen = inode->i_generation;
+		maj = MAJOR(dev);
+		min = MINOR(dev);
+
 	} else {
 		if (arch_vma_name(mmap_event->vma)) {
 			name = strncpy(tmp, arch_vma_name(mmap_event->vma),
@@ -5104,6 +5134,10 @@ got_name:
 
 	mmap_event->file_name = name;
 	mmap_event->file_size = size;
+	mmap_event->maj = maj;
+	mmap_event->min = min;
+	mmap_event->ino = ino;
+	mmap_event->ino_generation = gen;
 
 	if (!(vma->vm_flags & VM_EXEC))
 		mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_DATA;
@@ -5140,6 +5174,10 @@ void perf_event_mmap(struct vm_area_struct *vma)
 			.len    = vma->vm_end - vma->vm_start,
 			.pgoff  = (u64)vma->vm_pgoff << PAGE_SHIFT,
 		},
+		/* .maj (attr_mmap2 only) */
+		/* .min (attr_mmap2 only) */
+		/* .ino (attr_mmap2 only) */
+		/* .ino_generation (attr_mmap2 only) */
 	};
 
 	perf_event_mmap_event(&mmap_event);

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-08-21 10:10 ` [PATCH v2 2/2] perf tools: add attr->mmap2 support Stephane Eranian
  2013-08-22 10:51   ` Peter Zijlstra
@ 2013-09-09 19:47   ` Arnaldo Carvalho de Melo
  2013-09-09 19:48     ` Arnaldo Carvalho de Melo
  2013-09-10  9:17     ` Peter Zijlstra
  2013-09-12 11:10   ` [tip:perf/urgent] perf tools: Add " tip-bot for Stephane Eranian
  2 siblings, 2 replies; 24+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-09-09 19:47 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: linux-kernel, peterz, mingo, ak, jolsa, namhyung.kim, dsahern

Em Wed, Aug 21, 2013 at 12:10:25PM +0200, Stephane Eranian escreveu:
> This patch adds support for the new PERF_RECORD_MMAP2
> record type exposed by the kernel. This is an extended
> PERF_RECORD_MMAP record. It adds for each file-backed
> mapping the device major, minor number and the inode
> number and generation. This triplet uniquely identifies
> the source of a file-backed mapping. It can be used to
> detect identical virtual mappings between processes, for
> instance.
> 
> The patch will prefer MMAP2 over MMAP.

I noticed the kernel part is in, and I'm going to use MMAP2 on that new
tool, so tried merging it, but:

I fixed it up wrt another patch that makes machine__find_thread receive pid/tid
but then 'perf test' complains about it, see below, trying to fix...

- Arnaldo


[root@sandy ~]# perf test -v 7
 7: Validate PERF_RECORD_* events & perf_sample fields     :
--- start ---
57503587100282 0 PERF_RECORD_SAMPLE
57503587104415 0 PERF_RECORD_SAMPLE
57503587106039 0 PERF_RECORD_SAMPLE
57503587107362 0 PERF_RECORD_SAMPLE
57503588263263 0 PERF_RECORD_COMM: sleep:1439
6180457940383 -1728826693 PERF_RECORD_MMAP2 1439/1439: [0x400000(0x7000) @ 0 00:1d 311442 9016]: /usr/bin/sleep
MMAP2 going backwards in time, prev=57503588263263, curr=6180457940383
MMAP2 with unexpected cpu, expected 0, got -1728826693
MMAP2 with unexpected pid, expected 1439, got 1701606191
MMAP2 with unexpected tid, expected 1439, got 28773
Unexpected perf_event->header.type 10!
6180457940383 -1728754371 PERF_RECORD_MMAP2 1439/1439: [0x3b7e000000(0x223000) @ 0 00:1d 309186 9016]: /usr/lib64/ld-2.16.so
MMAP2 with unexpected cpu, expected 0, got -1728754371
MMAP2 with unexpected pid, expected 1439, got 1932408369
MMAP2 with unexpected tid, expected 1439, got 111
Unexpected perf_event->header.type 10!
6180457940383 -1728699354 PERF_RECORD_MMAP2 1439/1439: [0x7fff2bdff000(0x1000) @ 0x7fff2bdff000 00:00 0 0]: [vdso]
MMAP2 with unexpected cpu, expected 0, got -1728699354
MMAP2 with unexpected pid, expected 1439, got 1935963739
MMAP2 with unexpected tid, expected 1439, got 23919
Unexpected perf_event->header.type 10!
6180457940383 -1728433298 PERF_RECORD_MMAP2 1439/1439: [0x3b7e400000(0x3b8000) @ 0 00:1d 309187 9016]: /usr/lib64/libc-2.16.so
MMAP2 with unexpected cpu, expected 0, got -1728433298
MMAP2 with unexpected pid, expected 1439, got 909192754
MMAP2 with unexpected tid, expected 1439, got 7303982
Unexpected perf_event->header.type 10!
57504589856948 0 PERF_RECORD_EXIT(1439:1439):(1439:1439)
PERF_RECORD_MMAP for sleep missing!
PERF_RECORD_MMAP for libc missing!
PERF_RECORD_MMAP for ld missing!
PERF_RECORD_MMAP for [vdso] missing!
---- end ----
Validate PERF_RECORD_* events & perf_sample fields: FAILED!
[root@sandy ~]#

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-09-09 19:47   ` Arnaldo Carvalho de Melo
@ 2013-09-09 19:48     ` Arnaldo Carvalho de Melo
  2013-09-10 13:00       ` Arnaldo Carvalho de Melo
  2013-09-10  9:17     ` Peter Zijlstra
  1 sibling, 1 reply; 24+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-09-09 19:48 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: linux-kernel, peterz, mingo, ak, jolsa, namhyung.kim, dsahern

Em Mon, Sep 09, 2013 at 04:47:45PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Wed, Aug 21, 2013 at 12:10:25PM +0200, Stephane Eranian escreveu:
> > This patch adds support for the new PERF_RECORD_MMAP2
> > record type exposed by the kernel. This is an extended
> > PERF_RECORD_MMAP record. It adds for each file-backed
> > mapping the device major, minor number and the inode
> > number and generation. This triplet uniquely identifies
> > the source of a file-backed mapping. It can be used to
> > detect identical virtual mappings between processes, for
> > instance.
> > 
> > The patch will prefer MMAP2 over MMAP.
> 
> I noticed the kernel part is in, and I'm going to use MMAP2 on that new
> tool, so tried merging it, but:
> 
> I fixed it up wrt another patch that makes machine__find_thread receive pid/tid
> but then 'perf test' complains about it, see below, trying to fix...

Following patch makes it progress a bit, still checking why it is not
enough...

- Arnaldo

diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 72d8881..b8a7056 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -50,7 +50,7 @@ int test__PERF_RECORD(void)
 	struct perf_sample sample;
 	const char *cmd = "sleep";
 	const char *argv[] = { cmd, "1", NULL, };
-	char *bname;
+	char *bname, *mmap_filename;
 	u64 prev_time = 0;
 	bool found_cmd_mmap = false,
 	     found_libc_mmap = false,
@@ -212,6 +212,7 @@ int test__PERF_RECORD(void)
 
 				if ((type == PERF_RECORD_COMM ||
 				     type == PERF_RECORD_MMAP ||
+				     type == PERF_RECORD_MMAP2 ||
 				     type == PERF_RECORD_FORK ||
 				     type == PERF_RECORD_EXIT) &&
 				     (pid_t)event->comm.pid != evlist->workload.pid) {
@@ -220,7 +221,8 @@ int test__PERF_RECORD(void)
 				}
 
 				if ((type == PERF_RECORD_COMM ||
-				     type == PERF_RECORD_MMAP) &&
+				     type == PERF_RECORD_MMAP ||
+				     type == PERF_RECORD_MMAP2) &&
 				     event->comm.pid != event->comm.tid) {
 					pr_debug("%s with different pid/tid!\n", name);
 					++errs;
@@ -236,7 +238,12 @@ int test__PERF_RECORD(void)
 				case PERF_RECORD_EXIT:
 					goto found_exit;
 				case PERF_RECORD_MMAP:
-					bname = strrchr(event->mmap.filename, '/');
+					mmap_filename = event->mmap.filename;
+					goto check_bname;
+				case PERF_RECORD_MMAP2:
+					mmap_filename = event->mmap2.filename;
+				check_bname:
+					bname = strrchr(mmap_filename, '/');
 					if (bname != NULL) {
 						if (!found_cmd_mmap)
 							found_cmd_mmap = !strcmp(bname + 1, cmd);
@@ -245,7 +252,7 @@ int test__PERF_RECORD(void)
 						if (!found_ld_mmap)
 							found_ld_mmap = !strncmp(bname + 1, "ld", 2);
 					} else if (!found_vdso_mmap)
-						found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]");
+						found_vdso_mmap = !strcmp(mmap_filename, "[vdso]");
 					break;
 
 				case PERF_RECORD_SAMPLE:

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-09-09 19:47   ` Arnaldo Carvalho de Melo
  2013-09-09 19:48     ` Arnaldo Carvalho de Melo
@ 2013-09-10  9:17     ` Peter Zijlstra
  1 sibling, 0 replies; 24+ messages in thread
From: Peter Zijlstra @ 2013-09-10  9:17 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Stephane Eranian, linux-kernel, mingo, ak, jolsa, namhyung.kim, dsahern

On Mon, Sep 09, 2013 at 04:47:45PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Wed, Aug 21, 2013 at 12:10:25PM +0200, Stephane Eranian escreveu:
> > This patch adds support for the new PERF_RECORD_MMAP2
> > record type exposed by the kernel. This is an extended
> > PERF_RECORD_MMAP record. It adds for each file-backed
> > mapping the device major, minor number and the inode
> > number and generation. This triplet uniquely identifies
> > the source of a file-backed mapping. It can be used to
> > detect identical virtual mappings between processes, for
> > instance.
> > 
> > The patch will prefer MMAP2 over MMAP.
> 
> I noticed the kernel part is in, and I'm going to use MMAP2 on that new
> tool, so tried merging it, but:
> 
> I fixed it up wrt another patch that makes machine__find_thread receive pid/tid
> but then 'perf test' complains about it, see below, trying to fix...

Right, so I fed both patches to Ingo, but apparently (checked IRC
backlog) the tools patch didn't apply due to collisions with patches
from acme.

Apparently Ingo forgot to prod both of you to resolve (as I was out on
PTO).

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-09-09 19:48     ` Arnaldo Carvalho de Melo
@ 2013-09-10 13:00       ` Arnaldo Carvalho de Melo
  2013-09-10 13:05         ` Stephane Eranian
  0 siblings, 1 reply; 24+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-09-10 13:00 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: linux-kernel, peterz, mingo, ak, jolsa, namhyung.kim, dsahern


Em Mon, Sep 09, 2013 at 04:48:44PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Mon, Sep 09, 2013 at 04:47:45PM -0300, Arnaldo Carvalho de Melo escreveu:
> > I noticed the kernel part is in, and I'm going to use MMAP2 on that new
> > tool, so tried merging it, but:
> > 
> > I fixed it up wrt another patch that makes machine__find_thread receive pid/tid
> > but then 'perf test' complains about it, see below, trying to fix...
> 
> Following patch makes it progress a bit, still checking why it is not
> enough...

Without your patch:

[root@sandy ~]# perf test -v 7
 7: Validate PERF_RECORD_* events & perf_sample fields     :
--- start ---
61118374953766 0 PERF_RECORD_SAMPLE
61118374958840 0 PERF_RECORD_SAMPLE
61118374961420 0 PERF_RECORD_SAMPLE
61118374964293 0 PERF_RECORD_SAMPLE
61118376117716 0 PERF_RECORD_COMM: sleep:5096
61118376153724 0 PERF_RECORD_MMAP 5096/5096: [0x400000(0x7000) @ 0]: /usr/bin/sleep
61118376190304 0 PERF_RECORD_MMAP 5096/5096: [0x3b7e000000(0x223000) @ 0]: /usr/lib64/ld-2.16.so
61118376229562 0 PERF_RECORD_MMAP 5096/5096: [0x7fff2f9ff000(0x1000) @ 0x7fff2f9ff000]: [vdso]
61118376526654 0 PERF_RECORD_MMAP 5096/5096: [0x3b7e400000(0x3b8000) @ 0]: /usr/lib64/libc-2.16.so
61119377689687 0 PERF_RECORD_EXIT(5096:5096):(5096:5096)
---- end ----
Validate PERF_RECORD_* events & perf_sample fields: Ok
[root@sandy ~]#

So the tstamp grows monotonically, then, after your patch + the patch at the
end of this message:

[root@sandy ~]# perf test -v 7
 7: Validate PERF_RECORD_* events & perf_sample fields     :
--- start ---
61315294449606 0 PERF_RECORD_SAMPLE
61315294453161 0 PERF_RECORD_SAMPLE
61315294454441 0 PERF_RECORD_SAMPLE
61315294455709 0 PERF_RECORD_SAMPLE
61315295600899 0 PERF_RECORD_COMM: sleep:6500
27917287430500 342521613 PERF_RECORD_MMAP2 6500/6500: [0x400000(0x7000) @ 0 00:1d 311442 9016]: /usr/bin/sleep
MMAP2 going backwards in time, prev=61315295600899, curr=27917287430500
MMAP2 with unexpected cpu, expected 0, got 342521613
MMAP2 with unexpected pid, expected 6500, got 1701606191
MMAP2 with unexpected tid, expected 6500, got 28773
27917287430500 342561333 PERF_RECORD_MMAP2 6500/6500: [0x3b7e000000(0x223000) @ 0 00:1d 309186 9016]: /usr/lib64/ld-2.16.so
MMAP2 with unexpected cpu, expected 0, got 342561333
MMAP2 with unexpected pid, expected 6500, got 1932408369
MMAP2 with unexpected tid, expected 6500, got 111
27917287430500 342600095 PERF_RECORD_MMAP2 6500/6500: [0x7fffbd7dc000(0x1000) @ 0x7fffbd7dc000 00:00 0 0]: [vdso]
MMAP2 with unexpected cpu, expected 0, got 342600095
MMAP2 with unexpected pid, expected 6500, got 1935963739
MMAP2 with unexpected tid, expected 6500, got 23919
27917287430500 342882834 PERF_RECORD_MMAP2 6500/6500: [0x3b7e400000(0x3b8000) @ 0 00:1d 309187 9016]: /usr/lib64/libc-2.16.so
MMAP2 with unexpected cpu, expected 0, got 342882834
MMAP2 with unexpected pid, expected 6500, got 909192754
MMAP2 with unexpected tid, expected 6500, got 7303982
61316297195411 0 PERF_RECORD_EXIT(6500:6500):(6500:6500)
---- end ----
Validate PERF_RECORD_* events & perf_sample fields: FAILED!
[root@sandy ~]#

So everything that is in perf_sample, i.e. in the variable area, selected via
sample_type, is invalid for PERF_RECORD_MMAP2.

This is on:

[root@sandy ~]# uname -a
Linux sandy.ghostprotocols.net.home 3.11.0+ #1 SMP Wed Sep 4 16:47:14 BRT 2013 x86_64 x86_64 x86_64 GNU/Linux
[root@sandy ~]#

Humm, looking at perf_event_mmap_output it seems this was missed, will rebuild
a kernel and retest...

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 2207efc..dd236b6 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5039,6 +5039,7 @@ static void perf_event_mmap_output(struct perf_event *event,
 		mmap_event->event_id.header.size += sizeof(mmap_event->maj);
 		mmap_event->event_id.header.size += sizeof(mmap_event->min);
 		mmap_event->event_id.header.size += sizeof(mmap_event->ino);
+		mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation);
 	}
 
 	perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
 
> - Arnaldo
> 
> diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
> index 72d8881..b8a7056 100644
> --- a/tools/perf/tests/perf-record.c
> +++ b/tools/perf/tests/perf-record.c
> @@ -50,7 +50,7 @@ int test__PERF_RECORD(void)
>  	struct perf_sample sample;
>  	const char *cmd = "sleep";
>  	const char *argv[] = { cmd, "1", NULL, };
> -	char *bname;
> +	char *bname, *mmap_filename;
>  	u64 prev_time = 0;
>  	bool found_cmd_mmap = false,
>  	     found_libc_mmap = false,
> @@ -212,6 +212,7 @@ int test__PERF_RECORD(void)
>  
>  				if ((type == PERF_RECORD_COMM ||
>  				     type == PERF_RECORD_MMAP ||
> +				     type == PERF_RECORD_MMAP2 ||
>  				     type == PERF_RECORD_FORK ||
>  				     type == PERF_RECORD_EXIT) &&
>  				     (pid_t)event->comm.pid != evlist->workload.pid) {
> @@ -220,7 +221,8 @@ int test__PERF_RECORD(void)
>  				}
>  
>  				if ((type == PERF_RECORD_COMM ||
> -				     type == PERF_RECORD_MMAP) &&
> +				     type == PERF_RECORD_MMAP ||
> +				     type == PERF_RECORD_MMAP2) &&
>  				     event->comm.pid != event->comm.tid) {
>  					pr_debug("%s with different pid/tid!\n", name);
>  					++errs;
> @@ -236,7 +238,12 @@ int test__PERF_RECORD(void)
>  				case PERF_RECORD_EXIT:
>  					goto found_exit;
>  				case PERF_RECORD_MMAP:
> -					bname = strrchr(event->mmap.filename, '/');
> +					mmap_filename = event->mmap.filename;
> +					goto check_bname;
> +				case PERF_RECORD_MMAP2:
> +					mmap_filename = event->mmap2.filename;
> +				check_bname:
> +					bname = strrchr(mmap_filename, '/');
>  					if (bname != NULL) {
>  						if (!found_cmd_mmap)
>  							found_cmd_mmap = !strcmp(bname + 1, cmd);
> @@ -245,7 +252,7 @@ int test__PERF_RECORD(void)
>  						if (!found_ld_mmap)
>  							found_ld_mmap = !strncmp(bname + 1, "ld", 2);
>  					} else if (!found_vdso_mmap)
> -						found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]");
> +						found_vdso_mmap = !strcmp(mmap_filename, "[vdso]");
>  					break;
>  
>  				case PERF_RECORD_SAMPLE:

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-09-10 13:00       ` Arnaldo Carvalho de Melo
@ 2013-09-10 13:05         ` Stephane Eranian
  2013-09-10 13:17           ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 24+ messages in thread
From: Stephane Eranian @ 2013-09-10 13:05 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: LKML, Peter Zijlstra, mingo, ak, Jiri Olsa, Namhyung Kim, David Ahern

On Tue, Sep 10, 2013 at 3:00 PM, Arnaldo Carvalho de Melo
<acme@ghostprotocols.net> wrote:
>
>
> Em Mon, Sep 09, 2013 at 04:48:44PM -0300, Arnaldo Carvalho de Melo escreveu:
> > Em Mon, Sep 09, 2013 at 04:47:45PM -0300, Arnaldo Carvalho de Melo escreveu:
> > > I noticed the kernel part is in, and I'm going to use MMAP2 on that new
> > > tool, so tried merging it, but:
> > >
> > > I fixed it up wrt another patch that makes machine__find_thread receive pid/tid
> > > but then 'perf test' complains about it, see below, trying to fix...
> >
> > Following patch makes it progress a bit, still checking why it is not
> > enough...
>
> Without your patch:
>
> [root@sandy ~]# perf test -v 7
>  7: Validate PERF_RECORD_* events & perf_sample fields     :
> --- start ---
> 61118374953766 0 PERF_RECORD_SAMPLE
> 61118374958840 0 PERF_RECORD_SAMPLE
> 61118374961420 0 PERF_RECORD_SAMPLE
> 61118374964293 0 PERF_RECORD_SAMPLE
> 61118376117716 0 PERF_RECORD_COMM: sleep:5096
> 61118376153724 0 PERF_RECORD_MMAP 5096/5096: [0x400000(0x7000) @ 0]: /usr/bin/sleep
> 61118376190304 0 PERF_RECORD_MMAP 5096/5096: [0x3b7e000000(0x223000) @ 0]: /usr/lib64/ld-2.16.so
> 61118376229562 0 PERF_RECORD_MMAP 5096/5096: [0x7fff2f9ff000(0x1000) @ 0x7fff2f9ff000]: [vdso]
> 61118376526654 0 PERF_RECORD_MMAP 5096/5096: [0x3b7e400000(0x3b8000) @ 0]: /usr/lib64/libc-2.16.so
> 61119377689687 0 PERF_RECORD_EXIT(5096:5096):(5096:5096)
> ---- end ----
> Validate PERF_RECORD_* events & perf_sample fields: Ok
> [root@sandy ~]#
>
> So the tstamp grows monotonically, then, after your patch + the patch at the
> end of this message:
>
> [root@sandy ~]# perf test -v 7
>  7: Validate PERF_RECORD_* events & perf_sample fields     :
> --- start ---
> 61315294449606 0 PERF_RECORD_SAMPLE
> 61315294453161 0 PERF_RECORD_SAMPLE
> 61315294454441 0 PERF_RECORD_SAMPLE
> 61315294455709 0 PERF_RECORD_SAMPLE
> 61315295600899 0 PERF_RECORD_COMM: sleep:6500
> 27917287430500 342521613 PERF_RECORD_MMAP2 6500/6500: [0x400000(0x7000) @ 0 00:1d 311442 9016]: /usr/bin/sleep
> MMAP2 going backwards in time, prev=61315295600899, curr=27917287430500
> MMAP2 with unexpected cpu, expected 0, got 342521613
> MMAP2 with unexpected pid, expected 6500, got 1701606191
> MMAP2 with unexpected tid, expected 6500, got 28773
> 27917287430500 342561333 PERF_RECORD_MMAP2 6500/6500: [0x3b7e000000(0x223000) @ 0 00:1d 309186 9016]: /usr/lib64/ld-2.16.so
> MMAP2 with unexpected cpu, expected 0, got 342561333
> MMAP2 with unexpected pid, expected 6500, got 1932408369
> MMAP2 with unexpected tid, expected 6500, got 111
> 27917287430500 342600095 PERF_RECORD_MMAP2 6500/6500: [0x7fffbd7dc000(0x1000) @ 0x7fffbd7dc000 00:00 0 0]: [vdso]
> MMAP2 with unexpected cpu, expected 0, got 342600095
> MMAP2 with unexpected pid, expected 6500, got 1935963739
> MMAP2 with unexpected tid, expected 6500, got 23919
> 27917287430500 342882834 PERF_RECORD_MMAP2 6500/6500: [0x3b7e400000(0x3b8000) @ 0 00:1d 309187 9016]: /usr/lib64/libc-2.16.so
> MMAP2 with unexpected cpu, expected 0, got 342882834
> MMAP2 with unexpected pid, expected 6500, got 909192754
> MMAP2 with unexpected tid, expected 6500, got 7303982
> 61316297195411 0 PERF_RECORD_EXIT(6500:6500):(6500:6500)
> ---- end ----
> Validate PERF_RECORD_* events & perf_sample fields: FAILED!
> [root@sandy ~]#
>
> So everything that is in perf_sample, i.e. in the variable area, selected via
> sample_type, is invalid for PERF_RECORD_MMAP2.
>
> This is on:
>
> [root@sandy ~]# uname -a
> Linux sandy.ghostprotocols.net.home 3.11.0+ #1 SMP Wed Sep 4 16:47:14 BRT 2013 x86_64 x86_64 x86_64 GNU/Linux
> [root@sandy ~]#
>
> Humm, looking at perf_event_mmap_output it seems this was missed, will rebuild
> a kernel and retest...
>
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 2207efc..dd236b6 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -5039,6 +5039,7 @@ static void perf_event_mmap_output(struct perf_event *event,
>                 mmap_event->event_id.header.size += sizeof(mmap_event->maj);
>                 mmap_event->event_id.header.size += sizeof(mmap_event->min);
>                 mmap_event->event_id.header.size += sizeof(mmap_event->ino);
> +               mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation);
>         }
>
>         perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
>
Arg, yes, this is missing.
Do you want to submit the patch?
Thanks for tracking it down.

>
> > - Arnaldo
> >
> > diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
> > index 72d8881..b8a7056 100644
> > --- a/tools/perf/tests/perf-record.c
> > +++ b/tools/perf/tests/perf-record.c
> > @@ -50,7 +50,7 @@ int test__PERF_RECORD(void)
> >       struct perf_sample sample;
> >       const char *cmd = "sleep";
> >       const char *argv[] = { cmd, "1", NULL, };
> > -     char *bname;
> > +     char *bname, *mmap_filename;
> >       u64 prev_time = 0;
> >       bool found_cmd_mmap = false,
> >            found_libc_mmap = false,
> > @@ -212,6 +212,7 @@ int test__PERF_RECORD(void)
> >
> >                               if ((type == PERF_RECORD_COMM ||
> >                                    type == PERF_RECORD_MMAP ||
> > +                                  type == PERF_RECORD_MMAP2 ||
> >                                    type == PERF_RECORD_FORK ||
> >                                    type == PERF_RECORD_EXIT) &&
> >                                    (pid_t)event->comm.pid != evlist->workload.pid) {
> > @@ -220,7 +221,8 @@ int test__PERF_RECORD(void)
> >                               }
> >
> >                               if ((type == PERF_RECORD_COMM ||
> > -                                  type == PERF_RECORD_MMAP) &&
> > +                                  type == PERF_RECORD_MMAP ||
> > +                                  type == PERF_RECORD_MMAP2) &&
> >                                    event->comm.pid != event->comm.tid) {
> >                                       pr_debug("%s with different pid/tid!\n", name);
> >                                       ++errs;
> > @@ -236,7 +238,12 @@ int test__PERF_RECORD(void)
> >                               case PERF_RECORD_EXIT:
> >                                       goto found_exit;
> >                               case PERF_RECORD_MMAP:
> > -                                     bname = strrchr(event->mmap.filename, '/');
> > +                                     mmap_filename = event->mmap.filename;
> > +                                     goto check_bname;
> > +                             case PERF_RECORD_MMAP2:
> > +                                     mmap_filename = event->mmap2.filename;
> > +                             check_bname:
> > +                                     bname = strrchr(mmap_filename, '/');
> >                                       if (bname != NULL) {
> >                                               if (!found_cmd_mmap)
> >                                                       found_cmd_mmap = !strcmp(bname + 1, cmd);
> > @@ -245,7 +252,7 @@ int test__PERF_RECORD(void)
> >                                               if (!found_ld_mmap)
> >                                                       found_ld_mmap = !strncmp(bname + 1, "ld", 2);
> >                                       } else if (!found_vdso_mmap)
> > -                                             found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]");
> > +                                             found_vdso_mmap = !strcmp(mmap_filename, "[vdso]");
> >                                       break;
> >
> >                               case PERF_RECORD_SAMPLE:

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-09-10 13:05         ` Stephane Eranian
@ 2013-09-10 13:17           ` Arnaldo Carvalho de Melo
  2013-09-10 19:58             ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 24+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-09-10 13:17 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: LKML, Peter Zijlstra, mingo, ak, Jiri Olsa, Namhyung Kim, David Ahern

Em Tue, Sep 10, 2013 at 03:05:03PM +0200, Stephane Eranian escreveu:
> On Tue, Sep 10, 2013 at 3:00 PM, Arnaldo Carvalho de Melo <acme@ghostprotocols.net> wrote:
> > Em Mon, Sep 09, 2013 at 04:48:44PM -0300, Arnaldo Carvalho de Melo escreveu:
> > > Em Mon, Sep 09, 2013 at 04:47:45PM -0300, Arnaldo Carvalho de Melo escreveu:
> > > > I noticed the kernel part is in, and I'm going to use MMAP2 on that new
> > > > tool, so tried merging it, but:
> > > >
> > > > I fixed it up wrt another patch that makes machine__find_thread receive pid/tid
> > > > but then 'perf test' complains about it, see below, trying to fix...
> > >
> > > Following patch makes it progress a bit, still checking why it is not
> > > enough...
> >
> > Without your patch:
> >
> > [root@sandy ~]# perf test -v 7
> >  7: Validate PERF_RECORD_* events & perf_sample fields     :
> > --- start ---
> > 61118374953766 0 PERF_RECORD_SAMPLE
> > 61118374958840 0 PERF_RECORD_SAMPLE
> > 61118374961420 0 PERF_RECORD_SAMPLE
> > 61118374964293 0 PERF_RECORD_SAMPLE
> > 61118376117716 0 PERF_RECORD_COMM: sleep:5096
> > 61118376153724 0 PERF_RECORD_MMAP 5096/5096: [0x400000(0x7000) @ 0]: /usr/bin/sleep
> > 61118376190304 0 PERF_RECORD_MMAP 5096/5096: [0x3b7e000000(0x223000) @ 0]: /usr/lib64/ld-2.16.so
> > 61118376229562 0 PERF_RECORD_MMAP 5096/5096: [0x7fff2f9ff000(0x1000) @ 0x7fff2f9ff000]: [vdso]
> > 61118376526654 0 PERF_RECORD_MMAP 5096/5096: [0x3b7e400000(0x3b8000) @ 0]: /usr/lib64/libc-2.16.so
> > 61119377689687 0 PERF_RECORD_EXIT(5096:5096):(5096:5096)
> > ---- end ----
> > Validate PERF_RECORD_* events & perf_sample fields: Ok
> > [root@sandy ~]#
> >
> > So the tstamp grows monotonically, then, after your patch + the patch at the
> > end of this message:
> >
> > [root@sandy ~]# perf test -v 7
> >  7: Validate PERF_RECORD_* events & perf_sample fields     :
> > --- start ---
> > 61315294449606 0 PERF_RECORD_SAMPLE
> > 61315294453161 0 PERF_RECORD_SAMPLE
> > 61315294454441 0 PERF_RECORD_SAMPLE
> > 61315294455709 0 PERF_RECORD_SAMPLE
> > 61315295600899 0 PERF_RECORD_COMM: sleep:6500
> > 27917287430500 342521613 PERF_RECORD_MMAP2 6500/6500: [0x400000(0x7000) @ 0 00:1d 311442 9016]: /usr/bin/sleep
> > MMAP2 going backwards in time, prev=61315295600899, curr=27917287430500
> > MMAP2 with unexpected cpu, expected 0, got 342521613
> > MMAP2 with unexpected pid, expected 6500, got 1701606191
> > MMAP2 with unexpected tid, expected 6500, got 28773
> > 27917287430500 342561333 PERF_RECORD_MMAP2 6500/6500: [0x3b7e000000(0x223000) @ 0 00:1d 309186 9016]: /usr/lib64/ld-2.16.so
> > MMAP2 with unexpected cpu, expected 0, got 342561333
> > MMAP2 with unexpected pid, expected 6500, got 1932408369
> > MMAP2 with unexpected tid, expected 6500, got 111
> > 27917287430500 342600095 PERF_RECORD_MMAP2 6500/6500: [0x7fffbd7dc000(0x1000) @ 0x7fffbd7dc000 00:00 0 0]: [vdso]
> > MMAP2 with unexpected cpu, expected 0, got 342600095
> > MMAP2 with unexpected pid, expected 6500, got 1935963739
> > MMAP2 with unexpected tid, expected 6500, got 23919
> > 27917287430500 342882834 PERF_RECORD_MMAP2 6500/6500: [0x3b7e400000(0x3b8000) @ 0 00:1d 309187 9016]: /usr/lib64/libc-2.16.so
> > MMAP2 with unexpected cpu, expected 0, got 342882834
> > MMAP2 with unexpected pid, expected 6500, got 909192754
> > MMAP2 with unexpected tid, expected 6500, got 7303982
> > 61316297195411 0 PERF_RECORD_EXIT(6500:6500):(6500:6500)
> > ---- end ----
> > Validate PERF_RECORD_* events & perf_sample fields: FAILED!
> > [root@sandy ~]#
> >
> > So everything that is in perf_sample, i.e. in the variable area, selected via
> > sample_type, is invalid for PERF_RECORD_MMAP2.
> >
> > This is on:
> >
> > [root@sandy ~]# uname -a
> > Linux sandy.ghostprotocols.net.home 3.11.0+ #1 SMP Wed Sep 4 16:47:14 BRT 2013 x86_64 x86_64 x86_64 GNU/Linux
> > [root@sandy ~]#
> >
> > Humm, looking at perf_event_mmap_output it seems this was missed, will rebuild
> > a kernel and retest...
> >
> > diff --git a/kernel/events/core.c b/kernel/events/core.c
> > index 2207efc..dd236b6 100644
> > --- a/kernel/events/core.c
> > +++ b/kernel/events/core.c
> > @@ -5039,6 +5039,7 @@ static void perf_event_mmap_output(struct perf_event *event,
> >                 mmap_event->event_id.header.size += sizeof(mmap_event->maj);
> >                 mmap_event->event_id.header.size += sizeof(mmap_event->min);
> >                 mmap_event->event_id.header.size += sizeof(mmap_event->ino);
> > +               mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation);
> >         }
> >
> >         perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
> >
> Arg, yes, this is missing.
> Do you want to submit the patch?

I will, in some jiffies, just rebooting with the patched kernel to
re-run tperf test.

> Thanks for tracking it down.

np :-)

- Arnaldo

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-09-10 13:17           ` Arnaldo Carvalho de Melo
@ 2013-09-10 19:58             ` Arnaldo Carvalho de Melo
  2013-09-10 20:16               ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 24+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-09-10 19:58 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: LKML, Peter Zijlstra, mingo, ak, Jiri Olsa, Namhyung Kim, David Ahern

[-- Attachment #1: Type: text/plain, Size: 2290 bytes --]

Em Tue, Sep 10, 2013 at 10:17:28AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Tue, Sep 10, 2013 at 03:05:03PM +0200, Stephane Eranian escreveu:
> > On Tue, Sep 10, 2013 at 3:00 PM, Arnaldo Carvalho de Melo <acme@ghostprotocols.net> wrote:
> > > Em Mon, Sep 09, 2013 at 04:48:44PM -0300, Arnaldo Carvalho de Melo escreveu:
> > > +++ b/kernel/events/core.c
> > > @@ -5039,6 +5039,7 @@ static void perf_event_mmap_output(struct perf_event *event,
> > >                 mmap_event->event_id.header.size += sizeof(mmap_event->maj);
> > >                 mmap_event->event_id.header.size += sizeof(mmap_event->min);
> > >                 mmap_event->event_id.header.size += sizeof(mmap_event->ino);
> > > +               mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation);
> > >         }
> > >         perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);

> > Arg, yes, this is missing.
> > Do you want to submit the patch?

> I will, in some jiffies, just rebooting with the patched kernel to
> re-run tperf test.
 
> > Thanks for tracking it down.
 
> np :-)

More fallout, this time the resulting tools fail to run on older
kernels, i.e. any kernel that doesn't have perf_event_attr.mmap2,
doesn't matter the event type:

[acme@zoo linux]$ perf record usleep 1
Error:
The sys_perf_event_open() syscall returned with 22 (Invalid argument) for event (cycles).  
/bin/dmesg may provide additional information.
No CONFIG_PERF_EVENTS=y kernel support configured?

usleep: Terminated
[acme@zoo linux]$ perf record -e cpu-clock usleep 1
Error:
The sys_perf_event_open() syscall returned with 22 (Invalid argument) for event (cpu-clock).  
/bin/dmesg may provide additional information.
No CONFIG_PERF_EVENTS=y kernel support configured?

usleep: Terminated
[acme@zoo linux]$

That is because kernel/events/core.c  perf_copy_attr() has this test:

        if (attr->__reserved_1)
                return -EINVAL;

So we must have the handling we have for other things that were added
in the past, like .sample_id_all, .exclude_guest, etc, like is done in
the attached patch, please ack.

Ingo, since you haven't merged my latest perf/urgent pull req, do you
want me to fold this into the patch that makes the tooling side use
PERF_RECORD_MMAP2?

- Arnaldo

[-- Attachment #2: perf_mmap2_fallback.patch --]
[-- Type: text/plain, Size: 1499 bytes --]

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ff2098b..404599d 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -27,6 +27,7 @@
 static struct {
 	bool sample_id_all;
 	bool exclude_guest;
+	bool mmap2;
 } perf_missing_features;
 
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
@@ -677,7 +678,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
 		attr->sample_type	|= PERF_SAMPLE_WEIGHT;
 
 	attr->mmap  = track;
-	attr->mmap2 = track;
+	attr->mmap2 = track && !perf_missing_features.mmap2;
 	attr->comm  = track;
 
 	/*
@@ -1017,6 +1018,8 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
 	}
 
 fallback_missing_features:
+	if (perf_missing_features.mmap2)
+		evsel->attr.mmap2 = 0;
 	if (perf_missing_features.exclude_guest)
 		evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
 retry_sample_id:
@@ -1081,8 +1084,11 @@ try_fallback:
 	if (err != -EINVAL || cpu > 0 || thread > 0)
 		goto out_close;
 
-	if (!perf_missing_features.exclude_guest &&
-	    (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
+	if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
+		perf_missing_features.mmap2 = true;
+		goto fallback_missing_features;
+	} else if (!perf_missing_features.exclude_guest &&
+		   (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
 		perf_missing_features.exclude_guest = true;
 		goto fallback_missing_features;
 	} else if (!perf_missing_features.sample_id_all) {

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-09-10 19:58             ` Arnaldo Carvalho de Melo
@ 2013-09-10 20:16               ` Arnaldo Carvalho de Melo
  2013-09-11 14:42                 ` Stephane Eranian
  0 siblings, 1 reply; 24+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-09-10 20:16 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: LKML, Peter Zijlstra, mingo, ak, Jiri Olsa, Namhyung Kim, David Ahern

Em Tue, Sep 10, 2013 at 04:58:47PM -0300, Arnaldo Carvalho de Melo escreveu:
> So we must have the handling we have for other things that were added
> in the past, like .sample_id_all, .exclude_guest, etc, like is done in
> the attached patch, please ack.
> 
> Ingo, since you haven't merged my latest perf/urgent pull req, do you
> want me to fold this into the patch that makes the tooling side use
> PERF_RECORD_MMAP2?
> 
> - Arnaldo


Also there was this minor thing I'll have in this patch too:

@@ -1926,6 +1932,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
                if_print(exclude_hv);
                if_print(exclude_idle);
                if_print(mmap);
+               if_print(mmap2);
                if_print(comm);
                if_print(freq);
                if_print(inherit_stat);

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-09-10 20:16               ` Arnaldo Carvalho de Melo
@ 2013-09-11 14:42                 ` Stephane Eranian
  2013-09-11 14:53                   ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 24+ messages in thread
From: Stephane Eranian @ 2013-09-11 14:42 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: LKML, Peter Zijlstra, mingo, ak, Jiri Olsa, Namhyung Kim, David Ahern

Arnaldo,

Do you have all those changes in a git tree somewhere.
I want to help test and debug this part too.
Thanks.


On Tue, Sep 10, 2013 at 10:16 PM, Arnaldo Carvalho de Melo
<acme@ghostprotocols.net> wrote:
> Em Tue, Sep 10, 2013 at 04:58:47PM -0300, Arnaldo Carvalho de Melo escreveu:
>> So we must have the handling we have for other things that were added
>> in the past, like .sample_id_all, .exclude_guest, etc, like is done in
>> the attached patch, please ack.
>>
>> Ingo, since you haven't merged my latest perf/urgent pull req, do you
>> want me to fold this into the patch that makes the tooling side use
>> PERF_RECORD_MMAP2?
>>
>> - Arnaldo
>
>
> Also there was this minor thing I'll have in this patch too:
>
> @@ -1926,6 +1932,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
>                 if_print(exclude_hv);
>                 if_print(exclude_idle);
>                 if_print(mmap);
> +               if_print(mmap2);
>                 if_print(comm);
>                 if_print(freq);
>                 if_print(inherit_stat);

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-09-11 14:42                 ` Stephane Eranian
@ 2013-09-11 14:53                   ` Arnaldo Carvalho de Melo
  2013-09-11 15:28                     ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 24+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-09-11 14:53 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: LKML, Peter Zijlstra, mingo, ak, Jiri Olsa, Namhyung Kim, David Ahern

Em Wed, Sep 11, 2013 at 04:42:57PM +0200, Stephane Eranian escreveu:
> Arnaldo,
> 
> Do you have all those changes in a git tree somewhere.
> I want to help test and debug this part too.
> Thanks.

Right now its all in my perf/urgent branch at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git
 
For reference, the affected patch, with my updates, is here:

commit 5c5e854bc760a2e2c878df3cfcf2afa4febcd511
Author: Stephane Eranian <eranian@google.com>
Date:   Wed Aug 21 12:10:25 2013 +0200

    perf tools: Add attr->mmap2 support
    
    This patch adds support for the new PERF_RECORD_MMAP2 record type
    exposed by the kernel. This is an extended PERF_RECORD_MMAP record.
    
    It adds for each file-backed mapping the device major, minor number and
    the inode number and generation.
    
    This triplet uniquely identifies the source of a file-backed mapping. It
    can be used to detect identical virtual mappings between processes, for
    instance.
    
    The patch will prefer MMAP2 over MMAP.
    
    Signed-off-by: Stephane Eranian <eranian@google.com>
    Cc: Andi Kleen <ak@linux.intel.com>
    Cc: David Ahern <dsahern@gmail.com>
    Cc: Ingo Molnar <mingo@elte.hu>
    Cc: Jiri Olsa <jolsa@redhat.com>
    Cc: Namhyung Kim <namhyung.kim@lge.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Link: http://lkml.kernel.org/r/1377079825-19057-3-git-send-email-eranian@google.com
    [ Cope with 314add6 "Change machine__findnew_thread() to set thread pid",
      fix 'perf test' regression test entry affected,
      use perf_missing_features.mmap2 to fallback to not using .mmap2 in older kernels,
      so that new tools can work with kernels where this feature is not present ]
    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index f988d38..5ebd0c3 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -277,6 +277,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
 		.tool = {
 			.sample	= process_sample_event,
 			.mmap	= perf_event__process_mmap,
+			.mmap2	= perf_event__process_mmap2,
 			.comm	= perf_event__process_comm,
 			.exit	= perf_event__process_exit,
 			.fork	= perf_event__process_fork,
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 9b336fd..423875c 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -123,6 +123,19 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,
 	return err;
 }
 
+static int perf_event__repipe_mmap2(struct perf_tool *tool,
+				   union perf_event *event,
+				   struct perf_sample *sample,
+				   struct machine *machine)
+{
+	int err;
+
+	err = perf_event__process_mmap2(tool, event, sample, machine);
+	perf_event__repipe(tool, event, sample, machine);
+
+	return err;
+}
+
 static int perf_event__repipe_fork(struct perf_tool *tool,
 				   union perf_event *event,
 				   struct perf_sample *sample,
@@ -339,6 +352,7 @@ static int __cmd_inject(struct perf_inject *inject)
 
 	if (inject->build_ids || inject->sched_stat) {
 		inject->tool.mmap	  = perf_event__repipe_mmap;
+		inject->tool.mmap2	  = perf_event__repipe_mmap2;
 		inject->tool.fork	  = perf_event__repipe_fork;
 		inject->tool.tracing_data = perf_event__repipe_tracing_data;
 	}
@@ -390,6 +404,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
 		.tool = {
 			.sample		= perf_event__repipe_sample,
 			.mmap		= perf_event__repipe,
+			.mmap2		= perf_event__repipe,
 			.comm		= perf_event__repipe,
 			.fork		= perf_event__repipe,
 			.exit		= perf_event__repipe,
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 791b432..253133a 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -190,6 +190,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
 		.tool = {
 			.sample		= process_sample_event,
 			.mmap		= perf_event__process_mmap,
+			.mmap2		= perf_event__process_mmap2,
 			.comm		= perf_event__process_comm,
 			.lost		= perf_event__process_lost,
 			.fork		= perf_event__process_fork,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 9725aa3..8e50d8d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -744,6 +744,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 		.tool = {
 			.sample		 = process_sample_event,
 			.mmap		 = perf_event__process_mmap,
+			.mmap2		 = perf_event__process_mmap2,
 			.comm		 = perf_event__process_comm,
 			.exit		 = perf_event__process_exit,
 			.fork		 = perf_event__process_fork,
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 93a34ce..7f31a3d 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -542,6 +542,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 static struct perf_tool perf_script = {
 	.sample		 = process_sample_event,
 	.mmap		 = perf_event__process_mmap,
+	.mmap2		 = perf_event__process_mmap2,
 	.comm		 = perf_event__process_comm,
 	.exit		 = perf_event__process_exit,
 	.fork		 = perf_event__process_fork,
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 72d8881..b8a7056 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -50,7 +50,7 @@ int test__PERF_RECORD(void)
 	struct perf_sample sample;
 	const char *cmd = "sleep";
 	const char *argv[] = { cmd, "1", NULL, };
-	char *bname;
+	char *bname, *mmap_filename;
 	u64 prev_time = 0;
 	bool found_cmd_mmap = false,
 	     found_libc_mmap = false,
@@ -212,6 +212,7 @@ int test__PERF_RECORD(void)
 
 				if ((type == PERF_RECORD_COMM ||
 				     type == PERF_RECORD_MMAP ||
+				     type == PERF_RECORD_MMAP2 ||
 				     type == PERF_RECORD_FORK ||
 				     type == PERF_RECORD_EXIT) &&
 				     (pid_t)event->comm.pid != evlist->workload.pid) {
@@ -220,7 +221,8 @@ int test__PERF_RECORD(void)
 				}
 
 				if ((type == PERF_RECORD_COMM ||
-				     type == PERF_RECORD_MMAP) &&
+				     type == PERF_RECORD_MMAP ||
+				     type == PERF_RECORD_MMAP2) &&
 				     event->comm.pid != event->comm.tid) {
 					pr_debug("%s with different pid/tid!\n", name);
 					++errs;
@@ -236,7 +238,12 @@ int test__PERF_RECORD(void)
 				case PERF_RECORD_EXIT:
 					goto found_exit;
 				case PERF_RECORD_MMAP:
-					bname = strrchr(event->mmap.filename, '/');
+					mmap_filename = event->mmap.filename;
+					goto check_bname;
+				case PERF_RECORD_MMAP2:
+					mmap_filename = event->mmap2.filename;
+				check_bname:
+					bname = strrchr(mmap_filename, '/');
 					if (bname != NULL) {
 						if (!found_cmd_mmap)
 							found_cmd_mmap = !strcmp(bname + 1, cmd);
@@ -245,7 +252,7 @@ int test__PERF_RECORD(void)
 						if (!found_ld_mmap)
 							found_ld_mmap = !strncmp(bname + 1, "ld", 2);
 					} else if (!found_vdso_mmap)
-						found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]");
+						found_vdso_mmap = !strcmp(mmap_filename, "[vdso]");
 					break;
 
 				case PERF_RECORD_SAMPLE:
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index fb58409..7ded71d 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -67,6 +67,7 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
 struct perf_tool build_id__mark_dso_hit_ops = {
 	.sample	= build_id__mark_dso_hit,
 	.mmap	= perf_event__process_mmap,
+	.mmap2	= perf_event__process_mmap2,
 	.fork	= perf_event__process_fork,
 	.exit	= perf_event__exit_del_thread,
 	.attr		 = perf_event__process_attr,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 8d51f21..9b393e7 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -11,6 +11,7 @@
 static const char *perf_event__names[] = {
 	[0]					= "TOTAL",
 	[PERF_RECORD_MMAP]			= "MMAP",
+	[PERF_RECORD_MMAP2]			= "MMAP2",
 	[PERF_RECORD_LOST]			= "LOST",
 	[PERF_RECORD_COMM]			= "COMM",
 	[PERF_RECORD_EXIT]			= "EXIT",
@@ -186,7 +187,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		return -1;
 	}
 
-	event->header.type = PERF_RECORD_MMAP;
+	event->header.type = PERF_RECORD_MMAP2;
 	/*
 	 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
 	 */
@@ -197,7 +198,9 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		char prot[5];
 		char execname[PATH_MAX];
 		char anonstr[] = "//anon";
+		unsigned int ino;
 		size_t size;
+		ssize_t n;
 
 		if (fgets(bf, sizeof(bf), fp) == NULL)
 			break;
@@ -206,9 +209,16 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		strcpy(execname, "");
 
 		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
-		sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n",
-		       &event->mmap.start, &event->mmap.len, prot,
-		       &event->mmap.pgoff, execname);
+		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
+		       &event->mmap2.start, &event->mmap2.len, prot,
+		       &event->mmap2.pgoff, &event->mmap2.maj,
+		       &event->mmap2.min,
+		       &ino, execname);
+
+		event->mmap2.ino = (u64)ino;
+
+		if (n != 8)
+			continue;
 
 		if (prot[2] != 'x')
 			continue;
@@ -217,15 +227,15 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 			strcpy(execname, anonstr);
 
 		size = strlen(execname) + 1;
-		memcpy(event->mmap.filename, execname, size);
+		memcpy(event->mmap2.filename, execname, size);
 		size = PERF_ALIGN(size, sizeof(u64));
-		event->mmap.len -= event->mmap.start;
-		event->mmap.header.size = (sizeof(event->mmap) -
-					   (sizeof(event->mmap.filename) - size));
-		memset(event->mmap.filename + size, 0, machine->id_hdr_size);
-		event->mmap.header.size += machine->id_hdr_size;
-		event->mmap.pid = tgid;
-		event->mmap.tid = pid;
+		event->mmap2.len -= event->mmap.start;
+		event->mmap2.header.size = (sizeof(event->mmap2) -
+					(sizeof(event->mmap2.filename) - size));
+		memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
+		event->mmap2.header.size += machine->id_hdr_size;
+		event->mmap2.pid = tgid;
+		event->mmap2.tid = pid;
 
 		if (process(tool, event, &synth_sample, machine) != 0) {
 			rc = -1;
@@ -527,6 +537,17 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
 		       event->mmap.len, event->mmap.pgoff, event->mmap.filename);
 }
 
+size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
+{
+	return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
+			   " %02x:%02x %"PRIu64" %"PRIu64"]: %s\n",
+		       event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
+		       event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
+		       event->mmap2.min, event->mmap2.ino,
+		       event->mmap2.ino_generation,
+		       event->mmap2.filename);
+}
+
 int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
 			     struct perf_sample *sample __maybe_unused,
@@ -535,6 +556,14 @@ int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
 	return machine__process_mmap_event(machine, event);
 }
 
+int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
+			     union perf_event *event,
+			     struct perf_sample *sample __maybe_unused,
+			     struct machine *machine)
+{
+	return machine__process_mmap2_event(machine, event);
+}
+
 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
 {
 	return fprintf(fp, "(%d:%d):(%d:%d)\n",
@@ -574,6 +603,9 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
 	case PERF_RECORD_MMAP:
 		ret += perf_event__fprintf_mmap(event, fp);
 		break;
+	case PERF_RECORD_MMAP2:
+		ret += perf_event__fprintf_mmap2(event, fp);
+		break;
 	default:
 		ret += fprintf(fp, "\n");
 	}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 93130d8..c67ecc4 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -17,6 +17,19 @@ struct mmap_event {
 	char filename[PATH_MAX];
 };
 
+struct mmap2_event {
+	struct perf_event_header header;
+	u32 pid, tid;
+	u64 start;
+	u64 len;
+	u64 pgoff;
+	u32 maj;
+	u32 min;
+	u64 ino;
+	u64 ino_generation;
+	char filename[PATH_MAX];
+};
+
 struct comm_event {
 	struct perf_event_header header;
 	u32 pid, tid;
@@ -159,6 +172,7 @@ struct tracing_data_event {
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
+	struct mmap2_event		mmap2;
 	struct comm_event		comm;
 	struct fork_event		fork;
 	struct lost_event		lost;
@@ -208,6 +222,10 @@ int perf_event__process_mmap(struct perf_tool *tool,
 			     union perf_event *event,
 			     struct perf_sample *sample,
 			     struct machine *machine);
+int perf_event__process_mmap2(struct perf_tool *tool,
+			     union perf_event *event,
+			     struct perf_sample *sample,
+			     struct machine *machine);
 int perf_event__process_fork(struct perf_tool *tool,
 			     union perf_event *event,
 			     struct perf_sample *sample,
@@ -238,6 +256,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
 
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf(union perf_event *event, FILE *fp);
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 3612183..0ce9feb 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -27,6 +27,7 @@
 static struct {
 	bool sample_id_all;
 	bool exclude_guest;
+	bool mmap2;
 } perf_missing_features;
 
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
@@ -676,8 +677,9 @@ void perf_evsel__config(struct perf_evsel *evsel,
 	if (opts->sample_weight)
 		attr->sample_type	|= PERF_SAMPLE_WEIGHT;
 
-	attr->mmap = track;
-	attr->comm = track;
+	attr->mmap  = track;
+	attr->mmap2 = track && !perf_missing_features.mmap2;
+	attr->comm  = track;
 
 	/*
 	 * XXX see the function comment above
@@ -1016,6 +1018,8 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
 	}
 
 fallback_missing_features:
+	if (perf_missing_features.mmap2)
+		evsel->attr.mmap2 = 0;
 	if (perf_missing_features.exclude_guest)
 		evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
 retry_sample_id:
@@ -1080,8 +1084,11 @@ try_fallback:
 	if (err != -EINVAL || cpu > 0 || thread > 0)
 		goto out_close;
 
-	if (!perf_missing_features.exclude_guest &&
-	    (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
+	if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
+		perf_missing_features.mmap2 = true;
+		goto fallback_missing_features;
+	} else if (!perf_missing_features.exclude_guest &&
+		   (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
 		perf_missing_features.exclude_guest = true;
 		goto fallback_missing_features;
 	} else if (!perf_missing_features.sample_id_all) {
@@ -1925,6 +1932,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
 		if_print(exclude_hv);
 		if_print(exclude_idle);
 		if_print(mmap);
+		if_print(mmap2);
 		if_print(comm);
 		if_print(freq);
 		if_print(inherit_stat);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a33197a..26441d0 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1351,6 +1351,9 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
 
 		fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
 
+		fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2);
+		fprintf(fp, ", attr_mmap  = %d", evsel->attr.mmap);
+		fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data);
 		if (evsel->ids) {
 			fprintf(fp, ", id = {");
 			for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 1dca61f..933d14f 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -997,6 +997,54 @@ out_problem:
 	return -1;
 }
 
+int machine__process_mmap2_event(struct machine *machine,
+				 union perf_event *event)
+{
+	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+	struct thread *thread;
+	struct map *map;
+	enum map_type type;
+	int ret = 0;
+
+	if (dump_trace)
+		perf_event__fprintf_mmap2(event, stdout);
+
+	if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
+	    cpumode == PERF_RECORD_MISC_KERNEL) {
+		ret = machine__process_kernel_mmap_event(machine, event);
+		if (ret < 0)
+			goto out_problem;
+		return 0;
+	}
+
+	thread = machine__findnew_thread(machine, event->mmap2.pid,
+					event->mmap2.pid);
+	if (thread == NULL)
+		goto out_problem;
+
+	if (event->header.misc & PERF_RECORD_MISC_MMAP_DATA)
+		type = MAP__VARIABLE;
+	else
+		type = MAP__FUNCTION;
+
+	map = map__new(&machine->user_dsos, event->mmap2.start,
+			event->mmap2.len, event->mmap2.pgoff,
+			event->mmap2.pid, event->mmap2.maj,
+			event->mmap2.min, event->mmap2.ino,
+			event->mmap2.ino_generation,
+			event->mmap2.filename, type);
+
+	if (map == NULL)
+		goto out_problem;
+
+	thread__insert_map(thread, map);
+	return 0;
+
+out_problem:
+	dump_printf("problem processing PERF_RECORD_MMAP2, skipping event.\n");
+	return 0;
+}
+
 int machine__process_mmap_event(struct machine *machine, union perf_event *event)
 {
 	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
@@ -1028,7 +1076,8 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
 
 	map = map__new(&machine->user_dsos, event->mmap.start,
 			event->mmap.len, event->mmap.pgoff,
-			event->mmap.pid, event->mmap.filename,
+			event->mmap.pid, 0, 0, 0, 0,
+			event->mmap.filename,
 			type);
 
 	if (map == NULL)
@@ -1101,6 +1150,8 @@ int machine__process_event(struct machine *machine, union perf_event *event)
 		ret = machine__process_comm_event(machine, event); break;
 	case PERF_RECORD_MMAP:
 		ret = machine__process_mmap_event(machine, event); break;
+	case PERF_RECORD_MMAP2:
+		ret = machine__process_mmap2_event(machine, event); break;
 	case PERF_RECORD_FORK:
 		ret = machine__process_fork_event(machine, event); break;
 	case PERF_RECORD_EXIT:
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 0df925b..58a6be1 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -45,6 +45,7 @@ int machine__process_exit_event(struct machine *machine, union perf_event *event
 int machine__process_fork_event(struct machine *machine, union perf_event *event);
 int machine__process_lost_event(struct machine *machine, union perf_event *event);
 int machine__process_mmap_event(struct machine *machine, union perf_event *event);
+int machine__process_mmap2_event(struct machine *machine, union perf_event *event);
 int machine__process_event(struct machine *machine, union perf_event *event);
 
 typedef void (*machine__process_t)(struct machine *machine, void *data);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 9e8304c..4f6680d 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -48,7 +48,8 @@ void map__init(struct map *map, enum map_type type,
 }
 
 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
-		     u64 pgoff, u32 pid, char *filename,
+		     u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
+		     u64 ino_gen, char *filename,
 		     enum map_type type)
 {
 	struct map *map = malloc(sizeof(*map));
@@ -62,6 +63,11 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
 		vdso = is_vdso_map(filename);
 		no_dso = is_no_dso_memory(filename);
 
+		map->maj = d_maj;
+		map->min = d_min;
+		map->ino = ino;
+		map->ino_generation = ino_gen;
+
 		if (anon) {
 			snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
 			filename = newfilename;
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 2cc93cb..4886ca2 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -36,6 +36,9 @@ struct map {
 	bool			erange_warned;
 	u32			priv;
 	u64			pgoff;
+	u32			maj, min; /* only valid for MMAP2 record */
+	u64			ino;      /* only valid for MMAP2 record */
+	u64			ino_generation;/* only valid for MMAP2 record */
 
 	/* ip -> dso rip */
 	u64			(*map_ip)(struct map *, u64);
@@ -88,8 +91,9 @@ typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
 void map__init(struct map *map, enum map_type type,
 	       u64 start, u64 end, u64 pgoff, struct dso *dso);
 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
-		     u64 pgoff, u32 pid, char *filename,
-		     enum map_type type);
+		     u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
+		     u64 ino_gen,
+		     char *filename, enum map_type type);
 struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
 void map__delete(struct map *map);
 struct map *map__clone(struct map *map);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0308d9e..51f5edf 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -351,6 +351,25 @@ static void perf_event__mmap_swap(union perf_event *event,
 	}
 }
 
+static void perf_event__mmap2_swap(union perf_event *event,
+				  bool sample_id_all)
+{
+	event->mmap2.pid   = bswap_32(event->mmap2.pid);
+	event->mmap2.tid   = bswap_32(event->mmap2.tid);
+	event->mmap2.start = bswap_64(event->mmap2.start);
+	event->mmap2.len   = bswap_64(event->mmap2.len);
+	event->mmap2.pgoff = bswap_64(event->mmap2.pgoff);
+	event->mmap2.maj   = bswap_32(event->mmap2.maj);
+	event->mmap2.min   = bswap_32(event->mmap2.min);
+	event->mmap2.ino   = bswap_64(event->mmap2.ino);
+
+	if (sample_id_all) {
+		void *data = &event->mmap2.filename;
+
+		data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
+		swap_sample_id_all(event, data);
+	}
+}
 static void perf_event__task_swap(union perf_event *event, bool sample_id_all)
 {
 	event->fork.pid	 = bswap_32(event->fork.pid);
@@ -455,6 +474,7 @@ typedef void (*perf_event__swap_op)(union perf_event *event,
 
 static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_MMAP]		  = perf_event__mmap_swap,
+	[PERF_RECORD_MMAP2]		  = perf_event__mmap2_swap,
 	[PERF_RECORD_COMM]		  = perf_event__comm_swap,
 	[PERF_RECORD_FORK]		  = perf_event__task_swap,
 	[PERF_RECORD_EXIT]		  = perf_event__task_swap,
@@ -851,7 +871,8 @@ static struct machine *
 	     (cpumode == PERF_RECORD_MISC_GUEST_USER))) {
 		u32 pid;
 
-		if (event->header.type == PERF_RECORD_MMAP)
+		if (event->header.type == PERF_RECORD_MMAP
+		    || event->header.type == PERF_RECORD_MMAP2)
 			pid = event->mmap.pid;
 		else
 			pid = sample->pid;
@@ -978,6 +999,8 @@ static int perf_session_deliver_event(struct perf_session *session,
 						    sample, evsel, machine);
 	case PERF_RECORD_MMAP:
 		return tool->mmap(tool, event, sample, machine);
+	case PERF_RECORD_MMAP2:
+		return tool->mmap2(tool, event, sample, machine);
 	case PERF_RECORD_COMM:
 		return tool->comm(tool, event, sample, machine);
 	case PERF_RECORD_FORK:
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 62b16b6..4385816 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -29,6 +29,7 @@ struct perf_tool {
 	event_sample	sample,
 			read;
 	event_op	mmap,
+			mmap2,
 			comm,
 			fork,
 			exit,

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-09-11 14:53                   ` Arnaldo Carvalho de Melo
@ 2013-09-11 15:28                     ` Arnaldo Carvalho de Melo
  2013-09-12  6:35                       ` Ingo Molnar
  0 siblings, 1 reply; 24+ messages in thread
From: Arnaldo Carvalho de Melo @ 2013-09-11 15:28 UTC (permalink / raw)
  To: Stephane Eranian
  Cc: LKML, Peter Zijlstra, mingo, ak, Jiri Olsa, Namhyung Kim, David Ahern

Em Wed, Sep 11, 2013 at 11:53:41AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Wed, Sep 11, 2013 at 04:42:57PM +0200, Stephane Eranian escreveu:
> > Do you have all those changes in a git tree somewhere.
> > I want to help test and debug this part too.
> > Thanks.
 
> Right now its all in my perf/urgent branch at:
 
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git

And these are the results on a kernel that has the PERF_RECORD_MMAP2
functionality, for a workload started from 'perf record' and for an
existing process, so that we can check the synthesizing code:

[root@zoo ~]# perf record usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.014 MB perf.data (~615 samples) ]

Now lets check the events details, just cycles, in this case, use more
if you want to check that just the first one has mmap2 set:

[root@zoo ~]# perf evlist -v
cycles: sample_freq=4000, size: 96, sample_type: IP|TID|TIME|PERIOD,
disabled: 1, inherit: 1, mmap: 1, mmap2: 1, comm: 1, freq: 1,
enable_on_exec: 1, sample_id_all: 1, exclude_guest: 1
[root@zoo ~]# 

Now lets see if MMAP2 records were produced:

[root@zoo ~]# perf report -D | grep PERF_RECORD_MMAP2
776650444880 0x3838 [0x60]: PERF_RECORD_MMAP2 2918/2918: [0x400000(0x2000) @ 0 08:07 655426 1850659034]: /usr/bin/usleep
776650454592 0x3898 [0x68]: PERF_RECORD_MMAP2 2918/2918: [0x33c1200000(0x223000) @ 0 08:07 656485 1850658205]: /usr/lib64/ld-2.16.so
776650465705 0x3900 [0x58]: PERF_RECORD_MMAP2 2918/2918: [0x7fffbc72d000(0x1000) @ 0x7fffbc72d000 00:00 0 0]: [vdso]
776650549828 0x3980 [0x70]: PERF_RECORD_MMAP2 2918/2918: [0x33d2a00000(0x20a000) @ 0 08:07 655569 1850658370]: /usr/lib64/libpopt.so.0.0.0
776650577550 0x39f0 [0x68]: PERF_RECORD_MMAP2 2918/2918: [0x33c1600000(0x3b8000) @ 0 08:07 661541 1850658206]: /usr/lib64/libc-2.16.so
[root@zoo ~]# 

Yeah, for all the userspace DSOs, the kernel modules and vmlinux
remained as MMAP records:

[root@zoo ~]# perf report -D | grep -w PERF_RECORD_MMAP | head -4
0 0xd8 [0x50]: PERF_RECORD_MMAP -1/0: [0(0xffffffff9fffffff) @ 0xffffffff81000000]: [kernel.kallsyms]_text
0 0x128 [0x70]: PERF_RECORD_MMAP -1/0: [0xffffffffa0000000(0x5fff) @ 0]: /lib/modules/3.11.0+/kernel/drivers/acpi/video.ko
0 0x198 [0x70]: PERF_RECORD_MMAP -1/0: [0xffffffffa0006000(0x5fff) @ 0]: /lib/modules/3.11.0+/kernel/fs/efivarfs/efivarfs.ko
0 0x208 [0x70]: PERF_RECORD_MMAP -1/0: [0xffffffffa000c000(0xafff) @ 0]: /lib/modules/3.11.0+/kernel/drivers/i2c/i2c-core.ko
[root@zoo ~]# 

[root@zoo ~]# perf report -D | grep PERF_RECORD_MMAP | cut -f 4 -d' ' | sort | uniq -c
    119 PERF_RECORD_MMAP
      5 PERF_RECORD_MMAP2
[root@zoo ~]

[root@zoo ~]# lsmod | grep -v '^Module.*Size.*Used by$' | wc -l
118
[root@zoo ~]# 

I.e. 118 (yeah, distros load a lot of those these days!) plus vmlinux.

And if we observe an existing thread, say the current shell interpreter:

[acme@zoo linux]$ perf record -e instructions,cycles -p 1878 usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.014 MB perf.data (~615 samples) ]
[acme@zoo linux]$ perf evlist -v
instructions: sample_freq=4000, config: 1, size: 96, sample_type: IP|TID|ID|PERIOD, read_format: ID, disabled: 1, mmap: 1, mmap2: 1, comm: 1, freq: 1, sample_id_all: 1, exclude_guest: 1
cycles: sample_freq=4000, size: 96, sample_type: IP|TID|ID|PERIOD, read_format: ID, disabled: 1, freq: 1, sample_id_all: 1, exclude_guest: 1
[acme@zoo linux]$ 

Used two to check that the second event has no mmap2 bit set, just like for
mmap, comm, etc.

[acme@zoo linux]$ perf report -D | grep PERF_RECORD_MMAP2
0x37c8 [0x60]: PERF_RECORD_MMAP2 1878/1878: [0x400000(0xda000) @ 0 08:07 662168 0]: /usr/bin/bash
0x3828 [0x68]: PERF_RECORD_MMAP2 1878/1878: [0x33c1200000(0x20000) @ 0 08:07 656485 0]: /usr/lib64/ld-2.16.so
0x3890 [0x68]: PERF_RECORD_MMAP2 1878/1878: [0x33c1600000(0x1ad000) @ 0 08:07 661541 0]: /usr/lib64/libc-2.16.so
0x38f8 [0x70]: PERF_RECORD_MMAP2 1878/1878: [0x33c1e00000(0x3000) @ 0 08:07 671656 0]: /usr/lib64/libdl-2.16.so
0x3968 [0x70]: PERF_RECORD_MMAP2 1878/1878: [0x33d9200000(0x25000) @ 0 08:07 675312 0]: /usr/lib64/libtinfo.so.5.9
0x39d8 [0x70]: PERF_RECORD_MMAP2 1878/1878: [0x7f2f70bb9000(0xc000) @ 0 08:07 662885 0]: /usr/lib64/libnss_files-2.16.so
0x3a48 [0x58]: PERF_RECORD_MMAP2 1878/1878: [0x7fffdb5ff000(0x1000) @ 0 00:00 0 0]: [vdso]
0x3aa0 [0x60]: PERF_RECORD_MMAP2 1878/1878: [0xffffffffff600000(0x1000) @ 0 00:00 0 0]: [vsyscall]
[acme@zoo linux]$

Now lets look at the exec maps for this existing thread, to check that
we rightly synthesized them:

[acme@zoo linux]$ grep xp /proc/1878/maps
00400000-004da000 r-xp 00000000 08:07 662168                             /usr/bin/bash
33c1200000-33c1220000 r-xp 00000000 08:07 656485                         /usr/lib64/ld-2.16.so
33c1600000-33c17ad000 r-xp 00000000 08:07 661541                         /usr/lib64/libc-2.16.so
33c1e00000-33c1e03000 r-xp 00000000 08:07 671656                         /usr/lib64/libdl-2.16.so
33d9200000-33d9225000 r-xp 00000000 08:07 675312                         /usr/lib64/libtinfo.so.5.9
7f2f70bb9000-7f2f70bc5000 r-xp 00000000 08:07 662885                     /usr/lib64/libnss_files-2.16.so
7fffdb5ff000-7fffdb600000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
[acme@zoo linux]$

Yeah, maj, min, inode seems all ok, i_generation is zero, as expected.

Now its just a matter of using this extra info in a tool! 8-)

I haven't performed all these tests when running on an older kernel, just checked that
PERF_RECORD_MMAP was present, PERF_RECORD_MMAP2, as expected, were not, probably they
will be present only for the synthesized events, right? The ones coming from the kernel
were all PERF_RECORD_MMAP, as expected.

- Arnaldo

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 2/2] perf tools: add attr->mmap2 support
  2013-09-11 15:28                     ` Arnaldo Carvalho de Melo
@ 2013-09-12  6:35                       ` Ingo Molnar
  0 siblings, 0 replies; 24+ messages in thread
From: Ingo Molnar @ 2013-09-12  6:35 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Stephane Eranian, LKML, Peter Zijlstra, mingo, ak, Jiri Olsa,
	Namhyung Kim, David Ahern


* Arnaldo Carvalho de Melo <acme@ghostprotocols.net> wrote:

> I haven't performed all these tests when running on an older kernel, 
> just checked that PERF_RECORD_MMAP was present, PERF_RECORD_MMAP2, as 
> expected, were not, probably they will be present only for the 
> synthesized events, right? The ones coming from the kernel were all 
> PERF_RECORD_MMAP, as expected.

Older kernel functionality looked fine here.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [tip:perf/urgent] perf tools: Add attr->mmap2 support
  2013-08-21 10:10 ` [PATCH v2 2/2] perf tools: add attr->mmap2 support Stephane Eranian
  2013-08-22 10:51   ` Peter Zijlstra
  2013-09-09 19:47   ` Arnaldo Carvalho de Melo
@ 2013-09-12 11:10   ` tip-bot for Stephane Eranian
  2 siblings, 0 replies; 24+ messages in thread
From: tip-bot for Stephane Eranian @ 2013-09-12 11:10 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, eranian, hpa, mingo, peterz, namhyung.kim,
	jolsa, ak, dsahern, tglx, mingo

Commit-ID:  5c5e854bc760a2e2c878df3cfcf2afa4febcd511
Gitweb:     http://git.kernel.org/tip/5c5e854bc760a2e2c878df3cfcf2afa4febcd511
Author:     Stephane Eranian <eranian@google.com>
AuthorDate: Wed, 21 Aug 2013 12:10:25 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 11 Sep 2013 10:09:32 -0300

perf tools: Add attr->mmap2 support

This patch adds support for the new PERF_RECORD_MMAP2 record type
exposed by the kernel. This is an extended PERF_RECORD_MMAP record.

It adds for each file-backed mapping the device major, minor number and
the inode number and generation.

This triplet uniquely identifies the source of a file-backed mapping. It
can be used to detect identical virtual mappings between processes, for
instance.

The patch will prefer MMAP2 over MMAP.

Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1377079825-19057-3-git-send-email-eranian@google.com
[ Cope with 314add6 "Change machine__findnew_thread() to set thread pid",
  fix 'perf test' regression test entry affected,
  use perf_missing_features.mmap2 to fallback to not using .mmap2 in older kernels,
  so that new tools can work with kernels where this feature is not present ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-annotate.c  |  1 +
 tools/perf/builtin-inject.c    | 15 +++++++++++
 tools/perf/builtin-mem.c       |  1 +
 tools/perf/builtin-report.c    |  1 +
 tools/perf/builtin-script.c    |  1 +
 tools/perf/tests/perf-record.c | 15 ++++++++---
 tools/perf/util/build-id.c     |  1 +
 tools/perf/util/event.c        | 56 +++++++++++++++++++++++++++++++++---------
 tools/perf/util/event.h        | 19 ++++++++++++++
 tools/perf/util/evsel.c        | 16 +++++++++---
 tools/perf/util/header.c       |  3 +++
 tools/perf/util/machine.c      | 53 ++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/machine.h      |  1 +
 tools/perf/util/map.c          |  8 +++++-
 tools/perf/util/map.h          |  8 ++++--
 tools/perf/util/session.c      | 25 ++++++++++++++++++-
 tools/perf/util/tool.h         |  1 +
 17 files changed, 200 insertions(+), 25 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index f988d38..5ebd0c3 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -277,6 +277,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
 		.tool = {
 			.sample	= process_sample_event,
 			.mmap	= perf_event__process_mmap,
+			.mmap2	= perf_event__process_mmap2,
 			.comm	= perf_event__process_comm,
 			.exit	= perf_event__process_exit,
 			.fork	= perf_event__process_fork,
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 9b336fd..423875c 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -123,6 +123,19 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,
 	return err;
 }
 
+static int perf_event__repipe_mmap2(struct perf_tool *tool,
+				   union perf_event *event,
+				   struct perf_sample *sample,
+				   struct machine *machine)
+{
+	int err;
+
+	err = perf_event__process_mmap2(tool, event, sample, machine);
+	perf_event__repipe(tool, event, sample, machine);
+
+	return err;
+}
+
 static int perf_event__repipe_fork(struct perf_tool *tool,
 				   union perf_event *event,
 				   struct perf_sample *sample,
@@ -339,6 +352,7 @@ static int __cmd_inject(struct perf_inject *inject)
 
 	if (inject->build_ids || inject->sched_stat) {
 		inject->tool.mmap	  = perf_event__repipe_mmap;
+		inject->tool.mmap2	  = perf_event__repipe_mmap2;
 		inject->tool.fork	  = perf_event__repipe_fork;
 		inject->tool.tracing_data = perf_event__repipe_tracing_data;
 	}
@@ -390,6 +404,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
 		.tool = {
 			.sample		= perf_event__repipe_sample,
 			.mmap		= perf_event__repipe,
+			.mmap2		= perf_event__repipe,
 			.comm		= perf_event__repipe,
 			.fork		= perf_event__repipe,
 			.exit		= perf_event__repipe,
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 791b432..253133a 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -190,6 +190,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
 		.tool = {
 			.sample		= process_sample_event,
 			.mmap		= perf_event__process_mmap,
+			.mmap2		= perf_event__process_mmap2,
 			.comm		= perf_event__process_comm,
 			.lost		= perf_event__process_lost,
 			.fork		= perf_event__process_fork,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 9725aa3..8e50d8d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -744,6 +744,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 		.tool = {
 			.sample		 = process_sample_event,
 			.mmap		 = perf_event__process_mmap,
+			.mmap2		 = perf_event__process_mmap2,
 			.comm		 = perf_event__process_comm,
 			.exit		 = perf_event__process_exit,
 			.fork		 = perf_event__process_fork,
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 93a34ce..7f31a3d 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -542,6 +542,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 static struct perf_tool perf_script = {
 	.sample		 = process_sample_event,
 	.mmap		 = perf_event__process_mmap,
+	.mmap2		 = perf_event__process_mmap2,
 	.comm		 = perf_event__process_comm,
 	.exit		 = perf_event__process_exit,
 	.fork		 = perf_event__process_fork,
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 72d8881..b8a7056 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -50,7 +50,7 @@ int test__PERF_RECORD(void)
 	struct perf_sample sample;
 	const char *cmd = "sleep";
 	const char *argv[] = { cmd, "1", NULL, };
-	char *bname;
+	char *bname, *mmap_filename;
 	u64 prev_time = 0;
 	bool found_cmd_mmap = false,
 	     found_libc_mmap = false,
@@ -212,6 +212,7 @@ int test__PERF_RECORD(void)
 
 				if ((type == PERF_RECORD_COMM ||
 				     type == PERF_RECORD_MMAP ||
+				     type == PERF_RECORD_MMAP2 ||
 				     type == PERF_RECORD_FORK ||
 				     type == PERF_RECORD_EXIT) &&
 				     (pid_t)event->comm.pid != evlist->workload.pid) {
@@ -220,7 +221,8 @@ int test__PERF_RECORD(void)
 				}
 
 				if ((type == PERF_RECORD_COMM ||
-				     type == PERF_RECORD_MMAP) &&
+				     type == PERF_RECORD_MMAP ||
+				     type == PERF_RECORD_MMAP2) &&
 				     event->comm.pid != event->comm.tid) {
 					pr_debug("%s with different pid/tid!\n", name);
 					++errs;
@@ -236,7 +238,12 @@ int test__PERF_RECORD(void)
 				case PERF_RECORD_EXIT:
 					goto found_exit;
 				case PERF_RECORD_MMAP:
-					bname = strrchr(event->mmap.filename, '/');
+					mmap_filename = event->mmap.filename;
+					goto check_bname;
+				case PERF_RECORD_MMAP2:
+					mmap_filename = event->mmap2.filename;
+				check_bname:
+					bname = strrchr(mmap_filename, '/');
 					if (bname != NULL) {
 						if (!found_cmd_mmap)
 							found_cmd_mmap = !strcmp(bname + 1, cmd);
@@ -245,7 +252,7 @@ int test__PERF_RECORD(void)
 						if (!found_ld_mmap)
 							found_ld_mmap = !strncmp(bname + 1, "ld", 2);
 					} else if (!found_vdso_mmap)
-						found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]");
+						found_vdso_mmap = !strcmp(mmap_filename, "[vdso]");
 					break;
 
 				case PERF_RECORD_SAMPLE:
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index fb58409..7ded71d 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -67,6 +67,7 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
 struct perf_tool build_id__mark_dso_hit_ops = {
 	.sample	= build_id__mark_dso_hit,
 	.mmap	= perf_event__process_mmap,
+	.mmap2	= perf_event__process_mmap2,
 	.fork	= perf_event__process_fork,
 	.exit	= perf_event__exit_del_thread,
 	.attr		 = perf_event__process_attr,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 8d51f21..9b393e7 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -11,6 +11,7 @@
 static const char *perf_event__names[] = {
 	[0]					= "TOTAL",
 	[PERF_RECORD_MMAP]			= "MMAP",
+	[PERF_RECORD_MMAP2]			= "MMAP2",
 	[PERF_RECORD_LOST]			= "LOST",
 	[PERF_RECORD_COMM]			= "COMM",
 	[PERF_RECORD_EXIT]			= "EXIT",
@@ -186,7 +187,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		return -1;
 	}
 
-	event->header.type = PERF_RECORD_MMAP;
+	event->header.type = PERF_RECORD_MMAP2;
 	/*
 	 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
 	 */
@@ -197,7 +198,9 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		char prot[5];
 		char execname[PATH_MAX];
 		char anonstr[] = "//anon";
+		unsigned int ino;
 		size_t size;
+		ssize_t n;
 
 		if (fgets(bf, sizeof(bf), fp) == NULL)
 			break;
@@ -206,9 +209,16 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		strcpy(execname, "");
 
 		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
-		sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n",
-		       &event->mmap.start, &event->mmap.len, prot,
-		       &event->mmap.pgoff, execname);
+		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
+		       &event->mmap2.start, &event->mmap2.len, prot,
+		       &event->mmap2.pgoff, &event->mmap2.maj,
+		       &event->mmap2.min,
+		       &ino, execname);
+
+		event->mmap2.ino = (u64)ino;
+
+		if (n != 8)
+			continue;
 
 		if (prot[2] != 'x')
 			continue;
@@ -217,15 +227,15 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 			strcpy(execname, anonstr);
 
 		size = strlen(execname) + 1;
-		memcpy(event->mmap.filename, execname, size);
+		memcpy(event->mmap2.filename, execname, size);
 		size = PERF_ALIGN(size, sizeof(u64));
-		event->mmap.len -= event->mmap.start;
-		event->mmap.header.size = (sizeof(event->mmap) -
-					   (sizeof(event->mmap.filename) - size));
-		memset(event->mmap.filename + size, 0, machine->id_hdr_size);
-		event->mmap.header.size += machine->id_hdr_size;
-		event->mmap.pid = tgid;
-		event->mmap.tid = pid;
+		event->mmap2.len -= event->mmap.start;
+		event->mmap2.header.size = (sizeof(event->mmap2) -
+					(sizeof(event->mmap2.filename) - size));
+		memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
+		event->mmap2.header.size += machine->id_hdr_size;
+		event->mmap2.pid = tgid;
+		event->mmap2.tid = pid;
 
 		if (process(tool, event, &synth_sample, machine) != 0) {
 			rc = -1;
@@ -527,6 +537,17 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
 		       event->mmap.len, event->mmap.pgoff, event->mmap.filename);
 }
 
+size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
+{
+	return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
+			   " %02x:%02x %"PRIu64" %"PRIu64"]: %s\n",
+		       event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
+		       event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
+		       event->mmap2.min, event->mmap2.ino,
+		       event->mmap2.ino_generation,
+		       event->mmap2.filename);
+}
+
 int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
 			     struct perf_sample *sample __maybe_unused,
@@ -535,6 +556,14 @@ int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
 	return machine__process_mmap_event(machine, event);
 }
 
+int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
+			     union perf_event *event,
+			     struct perf_sample *sample __maybe_unused,
+			     struct machine *machine)
+{
+	return machine__process_mmap2_event(machine, event);
+}
+
 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
 {
 	return fprintf(fp, "(%d:%d):(%d:%d)\n",
@@ -574,6 +603,9 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
 	case PERF_RECORD_MMAP:
 		ret += perf_event__fprintf_mmap(event, fp);
 		break;
+	case PERF_RECORD_MMAP2:
+		ret += perf_event__fprintf_mmap2(event, fp);
+		break;
 	default:
 		ret += fprintf(fp, "\n");
 	}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 93130d8..c67ecc4 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -17,6 +17,19 @@ struct mmap_event {
 	char filename[PATH_MAX];
 };
 
+struct mmap2_event {
+	struct perf_event_header header;
+	u32 pid, tid;
+	u64 start;
+	u64 len;
+	u64 pgoff;
+	u32 maj;
+	u32 min;
+	u64 ino;
+	u64 ino_generation;
+	char filename[PATH_MAX];
+};
+
 struct comm_event {
 	struct perf_event_header header;
 	u32 pid, tid;
@@ -159,6 +172,7 @@ struct tracing_data_event {
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
+	struct mmap2_event		mmap2;
 	struct comm_event		comm;
 	struct fork_event		fork;
 	struct lost_event		lost;
@@ -208,6 +222,10 @@ int perf_event__process_mmap(struct perf_tool *tool,
 			     union perf_event *event,
 			     struct perf_sample *sample,
 			     struct machine *machine);
+int perf_event__process_mmap2(struct perf_tool *tool,
+			     union perf_event *event,
+			     struct perf_sample *sample,
+			     struct machine *machine);
 int perf_event__process_fork(struct perf_tool *tool,
 			     union perf_event *event,
 			     struct perf_sample *sample,
@@ -238,6 +256,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
 
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf(union perf_event *event, FILE *fp);
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 3612183..0ce9feb 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -27,6 +27,7 @@
 static struct {
 	bool sample_id_all;
 	bool exclude_guest;
+	bool mmap2;
 } perf_missing_features;
 
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
@@ -676,8 +677,9 @@ void perf_evsel__config(struct perf_evsel *evsel,
 	if (opts->sample_weight)
 		attr->sample_type	|= PERF_SAMPLE_WEIGHT;
 
-	attr->mmap = track;
-	attr->comm = track;
+	attr->mmap  = track;
+	attr->mmap2 = track && !perf_missing_features.mmap2;
+	attr->comm  = track;
 
 	/*
 	 * XXX see the function comment above
@@ -1016,6 +1018,8 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
 	}
 
 fallback_missing_features:
+	if (perf_missing_features.mmap2)
+		evsel->attr.mmap2 = 0;
 	if (perf_missing_features.exclude_guest)
 		evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
 retry_sample_id:
@@ -1080,8 +1084,11 @@ try_fallback:
 	if (err != -EINVAL || cpu > 0 || thread > 0)
 		goto out_close;
 
-	if (!perf_missing_features.exclude_guest &&
-	    (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
+	if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
+		perf_missing_features.mmap2 = true;
+		goto fallback_missing_features;
+	} else if (!perf_missing_features.exclude_guest &&
+		   (evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
 		perf_missing_features.exclude_guest = true;
 		goto fallback_missing_features;
 	} else if (!perf_missing_features.sample_id_all) {
@@ -1925,6 +1932,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
 		if_print(exclude_hv);
 		if_print(exclude_idle);
 		if_print(mmap);
+		if_print(mmap2);
 		if_print(comm);
 		if_print(freq);
 		if_print(inherit_stat);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a33197a..26441d0 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1351,6 +1351,9 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
 
 		fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
 
+		fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2);
+		fprintf(fp, ", attr_mmap  = %d", evsel->attr.mmap);
+		fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data);
 		if (evsel->ids) {
 			fprintf(fp, ", id = {");
 			for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 1dca61f..933d14f 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -997,6 +997,54 @@ out_problem:
 	return -1;
 }
 
+int machine__process_mmap2_event(struct machine *machine,
+				 union perf_event *event)
+{
+	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+	struct thread *thread;
+	struct map *map;
+	enum map_type type;
+	int ret = 0;
+
+	if (dump_trace)
+		perf_event__fprintf_mmap2(event, stdout);
+
+	if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
+	    cpumode == PERF_RECORD_MISC_KERNEL) {
+		ret = machine__process_kernel_mmap_event(machine, event);
+		if (ret < 0)
+			goto out_problem;
+		return 0;
+	}
+
+	thread = machine__findnew_thread(machine, event->mmap2.pid,
+					event->mmap2.pid);
+	if (thread == NULL)
+		goto out_problem;
+
+	if (event->header.misc & PERF_RECORD_MISC_MMAP_DATA)
+		type = MAP__VARIABLE;
+	else
+		type = MAP__FUNCTION;
+
+	map = map__new(&machine->user_dsos, event->mmap2.start,
+			event->mmap2.len, event->mmap2.pgoff,
+			event->mmap2.pid, event->mmap2.maj,
+			event->mmap2.min, event->mmap2.ino,
+			event->mmap2.ino_generation,
+			event->mmap2.filename, type);
+
+	if (map == NULL)
+		goto out_problem;
+
+	thread__insert_map(thread, map);
+	return 0;
+
+out_problem:
+	dump_printf("problem processing PERF_RECORD_MMAP2, skipping event.\n");
+	return 0;
+}
+
 int machine__process_mmap_event(struct machine *machine, union perf_event *event)
 {
 	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
@@ -1028,7 +1076,8 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
 
 	map = map__new(&machine->user_dsos, event->mmap.start,
 			event->mmap.len, event->mmap.pgoff,
-			event->mmap.pid, event->mmap.filename,
+			event->mmap.pid, 0, 0, 0, 0,
+			event->mmap.filename,
 			type);
 
 	if (map == NULL)
@@ -1101,6 +1150,8 @@ int machine__process_event(struct machine *machine, union perf_event *event)
 		ret = machine__process_comm_event(machine, event); break;
 	case PERF_RECORD_MMAP:
 		ret = machine__process_mmap_event(machine, event); break;
+	case PERF_RECORD_MMAP2:
+		ret = machine__process_mmap2_event(machine, event); break;
 	case PERF_RECORD_FORK:
 		ret = machine__process_fork_event(machine, event); break;
 	case PERF_RECORD_EXIT:
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 0df925b..58a6be1 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -45,6 +45,7 @@ int machine__process_exit_event(struct machine *machine, union perf_event *event
 int machine__process_fork_event(struct machine *machine, union perf_event *event);
 int machine__process_lost_event(struct machine *machine, union perf_event *event);
 int machine__process_mmap_event(struct machine *machine, union perf_event *event);
+int machine__process_mmap2_event(struct machine *machine, union perf_event *event);
 int machine__process_event(struct machine *machine, union perf_event *event);
 
 typedef void (*machine__process_t)(struct machine *machine, void *data);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 9e8304c..4f6680d 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -48,7 +48,8 @@ void map__init(struct map *map, enum map_type type,
 }
 
 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
-		     u64 pgoff, u32 pid, char *filename,
+		     u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
+		     u64 ino_gen, char *filename,
 		     enum map_type type)
 {
 	struct map *map = malloc(sizeof(*map));
@@ -62,6 +63,11 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
 		vdso = is_vdso_map(filename);
 		no_dso = is_no_dso_memory(filename);
 
+		map->maj = d_maj;
+		map->min = d_min;
+		map->ino = ino;
+		map->ino_generation = ino_gen;
+
 		if (anon) {
 			snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
 			filename = newfilename;
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 2cc93cb..4886ca2 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -36,6 +36,9 @@ struct map {
 	bool			erange_warned;
 	u32			priv;
 	u64			pgoff;
+	u32			maj, min; /* only valid for MMAP2 record */
+	u64			ino;      /* only valid for MMAP2 record */
+	u64			ino_generation;/* only valid for MMAP2 record */
 
 	/* ip -> dso rip */
 	u64			(*map_ip)(struct map *, u64);
@@ -88,8 +91,9 @@ typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
 void map__init(struct map *map, enum map_type type,
 	       u64 start, u64 end, u64 pgoff, struct dso *dso);
 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
-		     u64 pgoff, u32 pid, char *filename,
-		     enum map_type type);
+		     u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
+		     u64 ino_gen,
+		     char *filename, enum map_type type);
 struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
 void map__delete(struct map *map);
 struct map *map__clone(struct map *map);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0308d9e..51f5edf 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -351,6 +351,25 @@ static void perf_event__mmap_swap(union perf_event *event,
 	}
 }
 
+static void perf_event__mmap2_swap(union perf_event *event,
+				  bool sample_id_all)
+{
+	event->mmap2.pid   = bswap_32(event->mmap2.pid);
+	event->mmap2.tid   = bswap_32(event->mmap2.tid);
+	event->mmap2.start = bswap_64(event->mmap2.start);
+	event->mmap2.len   = bswap_64(event->mmap2.len);
+	event->mmap2.pgoff = bswap_64(event->mmap2.pgoff);
+	event->mmap2.maj   = bswap_32(event->mmap2.maj);
+	event->mmap2.min   = bswap_32(event->mmap2.min);
+	event->mmap2.ino   = bswap_64(event->mmap2.ino);
+
+	if (sample_id_all) {
+		void *data = &event->mmap2.filename;
+
+		data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
+		swap_sample_id_all(event, data);
+	}
+}
 static void perf_event__task_swap(union perf_event *event, bool sample_id_all)
 {
 	event->fork.pid	 = bswap_32(event->fork.pid);
@@ -455,6 +474,7 @@ typedef void (*perf_event__swap_op)(union perf_event *event,
 
 static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_MMAP]		  = perf_event__mmap_swap,
+	[PERF_RECORD_MMAP2]		  = perf_event__mmap2_swap,
 	[PERF_RECORD_COMM]		  = perf_event__comm_swap,
 	[PERF_RECORD_FORK]		  = perf_event__task_swap,
 	[PERF_RECORD_EXIT]		  = perf_event__task_swap,
@@ -851,7 +871,8 @@ static struct machine *
 	     (cpumode == PERF_RECORD_MISC_GUEST_USER))) {
 		u32 pid;
 
-		if (event->header.type == PERF_RECORD_MMAP)
+		if (event->header.type == PERF_RECORD_MMAP
+		    || event->header.type == PERF_RECORD_MMAP2)
 			pid = event->mmap.pid;
 		else
 			pid = sample->pid;
@@ -978,6 +999,8 @@ static int perf_session_deliver_event(struct perf_session *session,
 						    sample, evsel, machine);
 	case PERF_RECORD_MMAP:
 		return tool->mmap(tool, event, sample, machine);
+	case PERF_RECORD_MMAP2:
+		return tool->mmap2(tool, event, sample, machine);
 	case PERF_RECORD_COMM:
 		return tool->comm(tool, event, sample, machine);
 	case PERF_RECORD_FORK:
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 62b16b6..4385816 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -29,6 +29,7 @@ struct perf_tool {
 	event_sample	sample,
 			read;
 	event_op	mmap,
+			mmap2,
 			comm,
 			fork,
 			exit,

^ permalink raw reply related	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2013-09-12 11:11 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-21 10:10 [PATCH v2 0/2] perf: add new PERF_RECORD_MMAP2 record type Stephane Eranian
2013-08-21 10:10 ` [PATCH v2 1/2] perf: add attr->mmap2 attribute to an event Stephane Eranian
2013-08-22 15:57   ` Arnaldo Carvalho de Melo
2013-09-02  7:41   ` [tip:perf/core] perf: Add " tip-bot for Stephane Eranian
2013-08-21 10:10 ` [PATCH v2 2/2] perf tools: add attr->mmap2 support Stephane Eranian
2013-08-22 10:51   ` Peter Zijlstra
2013-08-30 14:03     ` Stephane Eranian
2013-08-30 14:08       ` Peter Zijlstra
2013-08-30 14:15         ` Stephane Eranian
2013-08-30 17:32           ` Stephane Eranian
2013-08-31  6:00             ` Ingo Molnar
2013-09-09 19:47   ` Arnaldo Carvalho de Melo
2013-09-09 19:48     ` Arnaldo Carvalho de Melo
2013-09-10 13:00       ` Arnaldo Carvalho de Melo
2013-09-10 13:05         ` Stephane Eranian
2013-09-10 13:17           ` Arnaldo Carvalho de Melo
2013-09-10 19:58             ` Arnaldo Carvalho de Melo
2013-09-10 20:16               ` Arnaldo Carvalho de Melo
2013-09-11 14:42                 ` Stephane Eranian
2013-09-11 14:53                   ` Arnaldo Carvalho de Melo
2013-09-11 15:28                     ` Arnaldo Carvalho de Melo
2013-09-12  6:35                       ` Ingo Molnar
2013-09-10  9:17     ` Peter Zijlstra
2013-09-12 11:10   ` [tip:perf/urgent] perf tools: Add " tip-bot for Stephane Eranian

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.