lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Mon, 2 Mar 2015 22:22:32 -0800
From:	tip-bot for Arnaldo Carvalho de Melo <tipbot@...or.com>
To:	linux-tip-commits@...r.kernel.org
Cc:	jolsa@...hat.com, linux-kernel@...r.kernel.org, bp@...e.de,
	adrian.hunter@...el.com, mingo@...nel.org, fweisbec@...il.com,
	dzickus@...hat.com, dsahern@...il.com, hpa@...or.com,
	namhyung@...nel.org, tglx@...utronix.de, eranian@...gle.com,
	acme@...hat.com
Subject: [tip:perf/core] perf tools:
  Fix FORK after COMM when synthesizing records for pre-existing threads

Commit-ID:  4aa5f4f7bb8bc41cba15bcd0d80c4fb085027d6b
Gitweb:     http://git.kernel.org/tip/4aa5f4f7bb8bc41cba15bcd0d80c4fb085027d6b
Author:     Arnaldo Carvalho de Melo <acme@...hat.com>
AuthorDate: Fri, 27 Feb 2015 19:52:10 -0300
Committer:  Arnaldo Carvalho de Melo <acme@...hat.com>
CommitDate: Mon, 2 Mar 2015 11:51:30 -0300

perf tools: Fix FORK after COMM when synthesizing records for pre-existing threads

In this commit:

  commit 363b785f3805a2632eb09a8b430842461c21a640
  Author: Don Zickus <dzickus@...hat.com>
  Date:   Fri Mar 14 10:43:44 2014 -0400

      perf tools: Speed up thread map generation

We ended up emitting PERF_RECORD_FORK events after their corresponding
PERF_RECORD_COMM, so the code below will remove the "existing thread"
and then recreates it, unnecessarily:

  [root@...andy ~]# perf probe -x ~/bin/perf -L machine__process_fork_event
  <machine__process_fork_event@...me/acme/git/linux/tools/perf/util/machine.c:0>
      0  int machine__process_fork_event(struct machine *machine, union perf_event *event,
                                        struct perf_sample *sample)
      2  {
      3         struct thread *thread = machine__find_thread(machine,
                                                             event->fork.pid,
                                                             event->fork.tid);
      6         struct thread *parent = machine__findnew_thread(machine,
                                                                event->fork.ppid,
                                                                event->fork.ptid);

                /* if a thread currently exists for the thread id remove it */
                if (thread != NULL)
     12                 machine__remove_thread(machine, thread);

     14         thread = machine__findnew_thread(machine, event->fork.pid,
                                                 event->fork.tid);
     16         if (dump_trace)
     17                 perf_event__fprintf_task(event, stdout);

     19         if (thread == NULL || parent == NULL ||
     20             thread__fork(thread, parent, sample->time) < 0) {
     21                 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
     22                 return -1;
                }

     25         return 0;
     26  }

  [root@...andy ~]# perf probe -x ~/bin/perf fork_after_comm=machine__process_fork_event:12
  Added new event:
    probe_perf:fork_after_comm (on machine__process_fork_event:12 in /home/acme/bin/perf)

  You can now use it in all perf tools, such as:

	perf record -e probe_perf:fork_after_comm -aR sleep 1

  [root@...andy ~]#

  [root@...andy ~]# perf record -g -e probe_perf:* trace -o /tmp/bla
  ^C[ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.021 MB perf.data (30 samples) ]
  Terminated
  [root@...andy ~]#

  [root@...andy ~]# perf report --no-children --show-total-period --stdio
  # To display the perf.data header info, please use --header/--header-only options.
  #
  # Samples: 30  of event 'probe_perf:fork_after_comm'
  # Event count (approx.): 30
  #
  # Overhead        Period  Command  Shared Object  Symbol
  # ........  ............  .......  .............  ...............................
  #
     100.00%            30  trace    trace          [.] machine__process_fork_event
                |
                ---machine__process_fork_event
                   __event__synthesize_thread.part.2
                   perf_event__synthesize_threads
                   cmd_trace
                   main
                   __libc_start_main

  [root@...andy ~]#

  And Looking at 'perf report -D' output we see it:

  0 0 0x8698 [0x30]: PERF_RECORD_COMM: auditd:703/707
  0 0 0x86c8 [0x38]: PERF_RECORD_FORK(703:707):(703:703)

Fix it by more closely mimicking how the kernel generates those records
when a new fork happens, i.e. first a PERF_RECORD_FORK, then a
PERF_RECORD_COMM.

Cc: Adrian Hunter <adrian.hunter@...el.com>
Cc: Borislav Petkov <bp@...e.de>
Cc: David Ahern <dsahern@...il.com>
Cc: Don Zickus <dzickus@...hat.com>
Cc: Frederic Weisbecker <fweisbec@...il.com>
Cc: Jiri Olsa <jolsa@...hat.com>
Cc: Namhyung Kim <namhyung@...nel.org>
Cc: Stephane Eranian <eranian@...gle.com>
Link: http://lkml.kernel.org/n/tip-h0emvymi2t3mw8dlqd6d6z73@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@...hat.com>
---
 tools/perf/util/event.c | 34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 9e806d8..d5efa50 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -95,9 +95,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
 	return tgid;
 }
 
-static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
-					 union perf_event *event, pid_t pid,
-					 perf_event__handler_t process,
+static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid,
 					 struct machine *machine)
 {
 	size_t size;
@@ -124,6 +122,19 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
 				(sizeof(event->comm.comm) - size) +
 				machine->id_hdr_size);
 	event->comm.tid = pid;
+out:
+	return tgid;
+}
+
+static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
+					 union perf_event *event, pid_t pid,
+					 perf_event__handler_t process,
+					 struct machine *machine)
+{
+	pid_t tgid = perf_event__prepare_comm(event, pid, machine);
+
+	if (tgid == -1)
+		goto out;
 
 	if (process(tool, event, &synth_sample, machine) != 0)
 		return -1;
@@ -139,7 +150,6 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
 {
 	memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
 
-	/* this is really a clone event but we use fork to synthesize it */
 	event->fork.ppid = tgid;
 	event->fork.ptid = tgid;
 	event->fork.pid  = tgid;
@@ -368,19 +378,23 @@ static int __event__synthesize_thread(union perf_event *comm_event,
 		if (*end)
 			continue;
 
-		tgid = perf_event__synthesize_comm(tool, comm_event, _pid,
-						   process, machine);
+		tgid = perf_event__prepare_comm(comm_event, _pid, machine);
 		if (tgid == -1)
 			return -1;
 
+		if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
+						process, machine) < 0)
+			return -1;
+		/*
+		 * Send the prepared comm event
+		 */
+		if (process(tool, comm_event, &synth_sample, machine) != 0)
+			return -1;
+
 		if (_pid == pid) {
 			/* process the parent's maps too */
 			rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
 						process, machine, mmap_data);
-		} else {
-			/* only fork the tid's map, to save time */
-			rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
-						 process, machine);
 		}
 
 		if (rc)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ