|
@@ -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,8 +504,9 @@ 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,
|
|
|
+ perf_event__handler_t process,
|
|
|
struct perf_tool *tool,
|
|
|
struct machine *machine,
|
|
|
bool mmap_data,
|
|
@@ -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:
|