perf tools: Fix ppid for synthesized fork events
363b785f38 added synthesized fork events and set a thread's parent id to
itself. Since we are already processing /proc/<pid>/status the ppid can
be determined properly. Make it so.
Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Don Zickus <dzickus@redhat.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Mario <jmario@redhat.com>
Link: http://lkml.kernel.org/r/1427747758-18510-2-git-send-email-dsahern@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>This commit is contained in:
		
							parent
							
								
									5aa0b030e8
								
							
						
					
					
						commit
						ca6c41c59b
					
				| @ -51,29 +51,32 @@ static struct perf_sample synth_sample = { | ||||
| 
 | ||||
| /*
 | ||||
|  * Assumes that the first 4095 bytes of /proc/pid/stat contains | ||||
|  * the comm and tgid. | ||||
|  * the comm, tgid and ppid. | ||||
|  */ | ||||
| static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) | ||||
| static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len, | ||||
| 				    pid_t *tgid, pid_t *ppid) | ||||
| { | ||||
| 	char filename[PATH_MAX]; | ||||
| 	char bf[4096]; | ||||
| 	int fd; | ||||
| 	size_t size = 0, n; | ||||
| 	pid_t tgid = -1; | ||||
| 	char *nl, *name, *tgids; | ||||
| 	char *nl, *name, *tgids, *ppids; | ||||
| 
 | ||||
| 	*tgid = -1; | ||||
| 	*ppid = -1; | ||||
| 
 | ||||
| 	snprintf(filename, sizeof(filename), "/proc/%d/status", pid); | ||||
| 
 | ||||
| 	fd = open(filename, O_RDONLY); | ||||
| 	if (fd < 0) { | ||||
| 		pr_debug("couldn't open %s\n", filename); | ||||
| 		return 0; | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	n = read(fd, bf, sizeof(bf) - 1); | ||||
| 	close(fd); | ||||
| 	if (n <= 0) { | ||||
| 		pr_warning("Couldn't get COMM and tgid for pid %d\n", | ||||
| 		pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n", | ||||
| 			   pid); | ||||
| 		return -1; | ||||
| 	} | ||||
| @ -81,6 +84,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) | ||||
| 
 | ||||
| 	name = strstr(bf, "Name:"); | ||||
| 	tgids = strstr(bf, "Tgid:"); | ||||
| 	ppids = strstr(bf, "PPid:"); | ||||
| 
 | ||||
| 	if (name) { | ||||
| 		name += 5;  /* strlen("Name:") */ | ||||
| @ -103,32 +107,45 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) | ||||
| 
 | ||||
| 	if (tgids) { | ||||
| 		tgids += 5;  /* strlen("Tgid:") */ | ||||
| 		tgid = atoi(tgids); | ||||
| 		*tgid = atoi(tgids); | ||||
| 	} else { | ||||
| 		pr_debug("Tgid: string not found for pid %d\n", pid); | ||||
| 	} | ||||
| 
 | ||||
| 	return tgid; | ||||
| 	if (ppids) { | ||||
| 		ppids += 5;  /* strlen("PPid:") */ | ||||
| 		*ppid = atoi(ppids); | ||||
| 	} else { | ||||
| 		pr_debug("PPid: string not found for pid %d\n", pid); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid, | ||||
| 					 struct machine *machine) | ||||
| static int perf_event__prepare_comm(union perf_event *event, pid_t pid, | ||||
| 				    struct machine *machine, | ||||
| 				    pid_t *tgid, pid_t *ppid) | ||||
| { | ||||
| 	size_t size; | ||||
| 	pid_t tgid; | ||||
| 
 | ||||
| 	*ppid = -1; | ||||
| 
 | ||||
| 	memset(&event->comm, 0, sizeof(event->comm)); | ||||
| 
 | ||||
| 	if (machine__is_host(machine)) | ||||
| 		tgid = perf_event__get_comm_tgid(pid, event->comm.comm, | ||||
| 						 sizeof(event->comm.comm)); | ||||
| 	else | ||||
| 		tgid = machine->pid; | ||||
| 	if (machine__is_host(machine)) { | ||||
| 		if (perf_event__get_comm_ids(pid, event->comm.comm, | ||||
| 					     sizeof(event->comm.comm), | ||||
| 					     tgid, ppid) != 0) { | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} else { | ||||
| 		*tgid = machine->pid; | ||||
| 	} | ||||
| 
 | ||||
| 	if (tgid < 0) | ||||
| 		goto out; | ||||
| 	if (*tgid < 0) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	event->comm.pid = tgid; | ||||
| 	event->comm.pid = *tgid; | ||||
| 	event->comm.header.type = PERF_RECORD_COMM; | ||||
| 
 | ||||
| 	size = strlen(event->comm.comm) + 1; | ||||
| @ -138,8 +155,8 @@ static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid, | ||||
| 				(sizeof(event->comm.comm) - size) + | ||||
| 				machine->id_hdr_size); | ||||
| 	event->comm.tid = pid; | ||||
| out: | ||||
| 	return tgid; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | ||||
| @ -147,27 +164,27 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | ||||
| 					 perf_event__handler_t process, | ||||
| 					 struct machine *machine) | ||||
| { | ||||
| 	pid_t tgid = perf_event__prepare_comm(event, pid, machine); | ||||
| 	pid_t tgid, ppid; | ||||
| 
 | ||||
| 	if (tgid == -1) | ||||
| 		goto out; | ||||
| 	if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	if (process(tool, event, &synth_sample, machine) != 0) | ||||
| 		return -1; | ||||
| 
 | ||||
| out: | ||||
| 	return tgid; | ||||
| } | ||||
| 
 | ||||
| static int perf_event__synthesize_fork(struct perf_tool *tool, | ||||
| 				       union perf_event *event, pid_t pid, | ||||
| 				       pid_t tgid, perf_event__handler_t process, | ||||
| 				       union perf_event *event, | ||||
| 				       pid_t pid, pid_t tgid, pid_t ppid, | ||||
| 				       perf_event__handler_t process, | ||||
| 				       struct machine *machine) | ||||
| { | ||||
| 	memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); | ||||
| 
 | ||||
| 	event->fork.ppid = tgid; | ||||
| 	event->fork.ptid = tgid; | ||||
| 	event->fork.ppid = ppid; | ||||
| 	event->fork.ptid = ppid; | ||||
| 	event->fork.pid  = tgid; | ||||
| 	event->fork.tid  = pid; | ||||
| 	event->fork.header.type = PERF_RECORD_FORK; | ||||
| @ -359,7 +376,7 @@ static int __event__synthesize_thread(union perf_event *comm_event, | ||||
| 	char filename[PATH_MAX]; | ||||
| 	DIR *tasks; | ||||
| 	struct dirent dirent, *next; | ||||
| 	pid_t tgid; | ||||
| 	pid_t tgid, ppid; | ||||
| 
 | ||||
| 	/* special case: only send one comm event using passed in pid */ | ||||
| 	if (!full) { | ||||
| @ -394,12 +411,12 @@ static int __event__synthesize_thread(union perf_event *comm_event, | ||||
| 		if (*end) | ||||
| 			continue; | ||||
| 
 | ||||
| 		tgid = perf_event__prepare_comm(comm_event, _pid, machine); | ||||
| 		if (tgid == -1) | ||||
| 		if (perf_event__prepare_comm(comm_event, _pid, machine, | ||||
| 					     &tgid, &ppid) != 0) | ||||
| 			return -1; | ||||
| 
 | ||||
| 		if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid, | ||||
| 						process, machine) < 0) | ||||
| 						ppid, process, machine) < 0) | ||||
| 			return -1; | ||||
| 		/*
 | ||||
| 		 * Send the prepared comm event | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user