Em Tue, Feb 21, 2017 at 07:31:44PM +0530, Hari Bathini escreveu:
> Synthesize PERF_RECORD_NAMESPACES events for processes that were
> running prior to invocation of perf record, the data for which is
> taken from /proc/$PID/ns. These changes make way for analyzing
> events with regard to namespaces.
> 
> Signed-off-by: Hari Bathini <hbath...@linux.vnet.ibm.com>
> ---
>  tools/perf/builtin-record.c |   27 +++++++++--
>  tools/perf/util/event.c     |  107 
> +++++++++++++++++++++++++++++++++++++++++--
>  tools/perf/util/event.h     |    6 ++
>  3 files changed, 130 insertions(+), 10 deletions(-)
> 
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index a8b9a78..f4bf6a6 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -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,10 +1000,28 @@ 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,
> -                                         rec->evlist->workload.pid,
> -                                         process_synthesized_event,
> -                                         machine);
> +             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) + 
> 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);
> diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
> index f118eac..c8c112a 100644
> --- a/tools/perf/util/event.c
> +++ b/tools/perf/util/event.c
> @@ -50,6 +50,16 @@ static const char *perf_event__names[] = {
>       [PERF_RECORD_TIME_CONV]                 = "TIME_CONV",
>  };
>  
> +static const char *perf_ns__names[] = {
> +     [NET_NS_INDEX]          = "net",
> +     [UTS_NS_INDEX]          = "uts",
> +     [IPC_NS_INDEX]          = "ipc",
> +     [PID_NS_INDEX]          = "pid",
> +     [USER_NS_INDEX]         = "user",
> +     [MNT_NS_INDEX]          = "mnt",
> +     [CGROUP_NS_INDEX]       = "cgroup",
> +};
> +
>  const char *perf_event__name(unsigned int id)
>  {
>       if (id >= ARRAY_SIZE(perf_event__names))
> @@ -59,6 +69,13 @@ const char *perf_event__name(unsigned int id)
>       return perf_event__names[id];
>  }
>  
> +static const char *perf_ns__name(unsigned int id)
> +{
> +     if (id >= ARRAY_SIZE(perf_ns__names))
> +             return "UNKNOWN";
> +     return perf_ns__names[id];
> +}
> +
>  static int perf_tool__process_synth_event(struct perf_tool *tool,
>                                         union perf_event *event,
>                                         struct machine *machine,
> @@ -204,6 +221,56 @@ 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->namespace_events)
> +             return 0;
> +
> +     memset(&event->namespaces, 0,
> +            sizeof(event->namespaces) + machine->id_hdr_size);
> +
> +     event->namespaces.pid = tgid;
> +     event->namespaces.tid = pid;
> +
> +     event->namespaces.nr_namespaces = NR_NAMESPACES;

Huh? Don't you have to first figure out how many namespaces a process is
in to then set this field? 

> +     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) +
> +                                      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,
> @@ -435,8 +502,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,
> @@ -456,6 +524,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);
> @@ -489,6 +562,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
>                */
> @@ -517,6 +595,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);
> @@ -531,10 +610,15 @@ 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) +
> +                               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)) {
> @@ -560,7 +644,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)) {
> @@ -569,6 +653,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);
> @@ -588,6 +674,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))
> @@ -605,11 +692,16 @@ int perf_event__synthesize_threads(struct perf_tool 
> *tool,
>       if (fork_event == NULL)
>               goto out_free_mmap;
>  
> +     namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
> +                               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;
> @@ -621,13 +713,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:
> diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
> index 4e90b09..c73ad47 100644
> --- a/tools/perf/util/event.h
> +++ b/tools/perf/util/event.h
> @@ -650,6 +650,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,

Reply via email to