Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e907caf3 authored by Hari Bathini's avatar Hari Bathini Committed by Arnaldo Carvalho de Melo
Browse files

perf record: Synthesize namespace events for current processes



Synthesize PERF_RECORD_NAMESPACES events for processes that were running prior
to invocation of perf record. The data for this is taken from /proc/$PID/ns.
These changes make way for analyzing events with regard to namespaces.

Committer notes:

Check if 'tool' is NULL in perf_event__synthesize_namespaces(), as in the
test__mmap_thread_lookup case, i.e. 'perf test Lookup mmap thread".

Testing it:

  # ps axH > /tmp/allthreads
  # perf record -a --namespaces usleep 1
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 1.169 MB perf.data (8 samples) ]
  # perf report -D | grep PERF_RECORD_NAMESPACES | wc -l
  602
  # wc -l /tmp/allthreads
  601 /tmp/allthreads
  # tail /tmp/allthreads
  16951 pts/4    T      0:00 git rebase -i a033bf1bfacdaa25642e6bcc857a7d0f67cc3c92^
  16952 pts/4    T      0:00 /bin/sh /usr/libexec/git-core/git-rebase -i a033bf1bfacdaa25642e6bcc857a7d0f67cc3c92^
  17176 pts/4    T      0:00 git commit --amend --no-post-rewrite
  17204 pts/4    T      0:00 vim /home/acme/git/linux/.git/COMMIT_EDITMSG
  18939 ?        S      0:00 [kworker/2:1]
  18947 ?        S      0:00 [kworker/3:0]
  18974 ?        S      0:00 [kworker/1:0]
  19047 ?        S      0:00 [kworker/0:1]
  19152 pts/6    S+     0:00 weechat
  19153 pts/7    R+     0:00 ps axH
  # perf report -D | grep PERF_RECORD_NAMESPACES | tail
  0 0 0x125068 [0xa0]: PERF_RECORD_NAMESPACES 17176/17176 - nr_namespaces: 7
  0 0 0x1255b8 [0xa0]: PERF_RECORD_NAMESPACES 17204/17204 - nr_namespaces: 7
  0 0 0x125df0 [0xa0]: PERF_RECORD_NAMESPACES 18939/18939 - nr_namespaces: 7
  0 0 0x125f00 [0xa0]: PERF_RECORD_NAMESPACES 18947/18947 - nr_namespaces: 7
  0 0 0x126010 [0xa0]: PERF_RECORD_NAMESPACES 18974/18974 - nr_namespaces: 7
  0 0 0x126120 [0xa0]: PERF_RECORD_NAMESPACES 19047/19047 - nr_namespaces: 7
  0 0 0x126230 [0xa0]: PERF_RECORD_NAMESPACES 19152/19152 - nr_namespaces: 7
  0 0 0x129330 [0xa0]: PERF_RECORD_NAMESPACES 19154/19154 - nr_namespaces: 7
  0 0 0x12a1f8 [0xa0]: PERF_RECORD_NAMESPACES 19155/19155 - nr_namespaces: 7
  0 0 0x12b0b8 [0xa0]: PERF_RECORD_NAMESPACES 19155/19155 - nr_namespaces: 7
  #

Humm, investigate why we got two record for the 19155 pid/tid...

Signed-off-by: default avatarHari Bathini <hbathini@linux.vnet.ibm.com>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Cc: Aravinda Prasad <aravinda@linux.vnet.ibm.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Sargun Dhillon <sargun@sargun.me>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/148891931111.25309.11073854609798681633.stgit@hbathini.in.ibm.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent f3b3614a
Loading
Loading
Loading
Loading
+25 −4
Original line number Diff line number Diff line
@@ -986,6 +986,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
	 */
	if (forks) {
		union perf_event *event;
		pid_t tgid;

		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
		if (event == NULL) {
@@ -999,12 +1000,32 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
		 * cannot see a correct process name for those events.
		 * Synthesize COMM event to prevent it.
		 */
		perf_event__synthesize_comm(tool, event,
		tgid = perf_event__synthesize_comm(tool, event,
						   rec->evlist->workload.pid,
						   process_synthesized_event,
						   machine);
		free(event);

		if (tgid == -1)
			goto out_child;

		event = malloc(sizeof(event->namespaces) +
			       (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
			       machine->id_hdr_size);
		if (event == NULL) {
			err = -ENOMEM;
			goto out_child;
		}

		/*
		 * Synthesize NAMESPACES event for the command specified.
		 */
		perf_event__synthesize_namespaces(tool, event,
						  rec->evlist->workload.pid,
						  tgid, process_synthesized_event,
						  machine);
		free(event);

		perf_evlist__start_workload(rec->evlist);
	}

+88 −6
Original line number Diff line number Diff line
@@ -221,6 +221,58 @@ pid_t perf_event__synthesize_comm(struct perf_tool *tool,
	return tgid;
}

static void perf_event__get_ns_link_info(pid_t pid, const char *ns,
					 struct perf_ns_link_info *ns_link_info)
{
	struct stat64 st;
	char proc_ns[128];

	sprintf(proc_ns, "/proc/%u/ns/%s", pid, ns);
	if (stat64(proc_ns, &st) == 0) {
		ns_link_info->dev = st.st_dev;
		ns_link_info->ino = st.st_ino;
	}
}

int perf_event__synthesize_namespaces(struct perf_tool *tool,
				      union perf_event *event,
				      pid_t pid, pid_t tgid,
				      perf_event__handler_t process,
				      struct machine *machine)
{
	u32 idx;
	struct perf_ns_link_info *ns_link_info;

	if (!tool || !tool->namespace_events)
		return 0;

	memset(&event->namespaces, 0, (sizeof(event->namespaces) +
	       (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
	       machine->id_hdr_size));

	event->namespaces.pid = tgid;
	event->namespaces.tid = pid;

	event->namespaces.nr_namespaces = NR_NAMESPACES;

	ns_link_info = event->namespaces.link_info;

	for (idx = 0; idx < event->namespaces.nr_namespaces; idx++)
		perf_event__get_ns_link_info(pid, perf_ns__name(idx),
					     &ns_link_info[idx]);

	event->namespaces.header.type = PERF_RECORD_NAMESPACES;

	event->namespaces.header.size = (sizeof(event->namespaces) +
			(NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
			machine->id_hdr_size);

	if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
		return -1;

	return 0;
}

static int perf_event__synthesize_fork(struct perf_tool *tool,
				       union perf_event *event,
				       pid_t pid, pid_t tgid, pid_t ppid,
@@ -452,6 +504,7 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
static int __event__synthesize_thread(union perf_event *comm_event,
				      union perf_event *mmap_event,
				      union perf_event *fork_event,
				      union perf_event *namespaces_event,
				      pid_t pid, int full,
				      perf_event__handler_t process,
				      struct perf_tool *tool,
@@ -473,6 +526,11 @@ static int __event__synthesize_thread(union perf_event *comm_event,
		if (tgid == -1)
			return -1;

		if (perf_event__synthesize_namespaces(tool, namespaces_event, pid,
						      tgid, process, machine) < 0)
			return -1;


		return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
							  process, machine, mmap_data,
							  proc_map_timeout);
@@ -506,6 +564,11 @@ static int __event__synthesize_thread(union perf_event *comm_event,
		if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
						ppid, process, machine) < 0)
			break;

		if (perf_event__synthesize_namespaces(tool, namespaces_event, _pid,
						      tgid, process, machine) < 0)
			break;

		/*
		 * Send the prepared comm event
		 */
@@ -534,6 +597,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
				      unsigned int proc_map_timeout)
{
	union perf_event *comm_event, *mmap_event, *fork_event;
	union perf_event *namespaces_event;
	int err = -1, thread, j;

	comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
@@ -548,10 +612,16 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
	if (fork_event == NULL)
		goto out_free_mmap;

	namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
				  (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
				  machine->id_hdr_size);
	if (namespaces_event == NULL)
		goto out_free_fork;

	err = 0;
	for (thread = 0; thread < threads->nr; ++thread) {
		if (__event__synthesize_thread(comm_event, mmap_event,
					       fork_event,
					       fork_event, namespaces_event,
					       thread_map__pid(threads, thread), 0,
					       process, tool, machine,
					       mmap_data, proc_map_timeout)) {
@@ -577,7 +647,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
			/* if not, generate events for it */
			if (need_leader &&
			    __event__synthesize_thread(comm_event, mmap_event,
						       fork_event,
						       fork_event, namespaces_event,
						       comm_event->comm.pid, 0,
						       process, tool, machine,
						       mmap_data, proc_map_timeout)) {
@@ -586,6 +656,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
			}
		}
	}
	free(namespaces_event);
out_free_fork:
	free(fork_event);
out_free_mmap:
	free(mmap_event);
@@ -605,6 +677,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
	char proc_path[PATH_MAX];
	struct dirent *dirent;
	union perf_event *comm_event, *mmap_event, *fork_event;
	union perf_event *namespaces_event;
	int err = -1;

	if (machine__is_default_guest(machine))
@@ -622,11 +695,17 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
	if (fork_event == NULL)
		goto out_free_mmap;

	namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
				  (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
				  machine->id_hdr_size);
	if (namespaces_event == NULL)
		goto out_free_fork;

	snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
	proc = opendir(proc_path);

	if (proc == NULL)
		goto out_free_fork;
		goto out_free_namespaces;

	while ((dirent = readdir(proc)) != NULL) {
		char *end;
@@ -638,13 +717,16 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
 		 * We may race with exiting thread, so don't stop just because
 		 * one thread couldn't be synthesized.
 		 */
		__event__synthesize_thread(comm_event, mmap_event, fork_event, pid,
					   1, process, tool, machine, mmap_data,
		__event__synthesize_thread(comm_event, mmap_event, fork_event,
					   namespaces_event, pid, 1, process,
					   tool, machine, mmap_data,
					   proc_map_timeout);
	}

	err = 0;
	closedir(proc);
out_free_namespaces:
	free(namespaces_event);
out_free_fork:
	free(fork_event);
out_free_mmap:
+6 −0
Original line number Diff line number Diff line
@@ -648,6 +648,12 @@ pid_t perf_event__synthesize_comm(struct perf_tool *tool,
				  perf_event__handler_t process,
				  struct machine *machine);

int perf_event__synthesize_namespaces(struct perf_tool *tool,
				      union perf_event *event,
				      pid_t pid, pid_t tgid,
				      perf_event__handler_t process,
				      struct machine *machine);

int perf_event__synthesize_mmap_events(struct perf_tool *tool,
				       union perf_event *event,
				       pid_t pid, pid_t tgid,