On Thursday 02 March 2017 02:35 AM, Arnaldo Carvalho de Melo wrote:
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?


NR_NAMESPACES is the total number of namespaces. For synthesized namespace
events, data is obtained from /proc/<pid>/ns/ dir. Looking at this dir, it
is difficult to arrive at the total number of namespaces in kernel, as
some namespaces can be compiled in/out of the kernel. NR_NAMESPACES is
used instead. Its value is most likely the same for kernel and perf tool
unless a new namespace is introduced - the warning in previous patch is
intended to alert the user about such scenario.

Thanks
Hari

Reply via email to