perf header: Add DIR_FORMAT feature to describe directory data
authorJiri Olsa <jolsa@kernel.org>
Fri, 8 Mar 2019 13:47:39 +0000 (14:47 +0100)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 11 Mar 2019 14:56:03 +0000 (11:56 -0300)
The data files layout is described by HEADER_DIR_FORMAT feature.
Currently it holds only version number (1):

     uint64_t version;

The current version holds only version value (1) means that data files:

  - Follow the 'data.*' name format.

  - Contain raw events data in standard perf format as read from kernel
    (and need to be sorted)

Future versions are expected to describe different data files layout
according to special needs.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexey Budankov <alexey.budankov@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/20190308134745.5057-6-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-record.c
tools/perf/util/data.c
tools/perf/util/data.h
tools/perf/util/header.c
tools/perf/util/header.h

index e983c8d71a794c185092ffe7a83dcc537da492ad..a468d882e74f3c66a8703891d0c7f3805d07d886 100644 (file)
@@ -837,6 +837,8 @@ static void record__init_features(struct record *rec)
        if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns))
                perf_header__clear_feat(&session->header, HEADER_CLOCKID);
 
+       perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);
+
        perf_header__clear_feat(&session->header, HEADER_STAT);
 }
 
index b71c441cafbb21011f5f8fcb14a97328161b0a2e..c6b67efea11a15f26c795402f52e40d14fdf819d 100644 (file)
@@ -14,6 +14,7 @@
 #include "data.h"
 #include "util.h"
 #include "debug.h"
+#include "header.h"
 
 static void close_dir(struct perf_data_file *files, int nr)
 {
@@ -41,8 +42,9 @@ int perf_data__create_dir(struct perf_data *data, int nr)
        if (!files)
                return -ENOMEM;
 
-       data->dir.files = files;
-       data->dir.nr    = nr;
+       data->dir.version = PERF_DIR_VERSION;
+       data->dir.files   = files;
+       data->dir.nr      = nr;
 
        for (i = 0; i < nr; i++) {
                struct perf_data_file *file = &files[i];
@@ -75,6 +77,10 @@ int perf_data__open_dir(struct perf_data *data)
        if (WARN_ON(!data->is_dir))
                return -EINVAL;
 
+       /* The version is provided by DIR_FORMAT feature. */
+       if (WARN_ON(data->dir.version != PERF_DIR_VERSION))
+               return -1;
+
        dir = opendir(data->path);
        if (!dir)
                return -EINVAL;
index d342469bdfda04500cdec37ea7339a12be47b008..6aef8746469f4bc8a7ea73b84bb7eae1441962b4 100644 (file)
@@ -24,6 +24,7 @@ struct perf_data {
        enum perf_data_mode      mode;
 
        struct {
+               u64                      version;
                struct perf_data_file   *files;
                int                      nr;
        } dir;
index 01b324c275b9d1ba0bd771f30b49952550038295..b0683bf4d9f3eae0924c8d9d213eebeddbad1589 100644 (file)
@@ -861,6 +861,21 @@ static int write_clockid(struct feat_fd *ff,
                        sizeof(ff->ph->env.clockid_res_ns));
 }
 
+static int write_dir_format(struct feat_fd *ff,
+                           struct perf_evlist *evlist __maybe_unused)
+{
+       struct perf_session *session;
+       struct perf_data *data;
+
+       session = container_of(ff->ph, struct perf_session, header);
+       data = session->data;
+
+       if (WARN_ON(!perf_data__is_dir(data)))
+               return -1;
+
+       return do_write(ff, &data->dir.version, sizeof(data->dir.version));
+}
+
 static int cpu_cache_level__sort(const void *a, const void *b)
 {
        struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
@@ -1341,6 +1356,17 @@ static void print_clockid(struct feat_fd *ff, FILE *fp)
                ff->ph->env.clockid_res_ns * 1000);
 }
 
+static void print_dir_format(struct feat_fd *ff, FILE *fp)
+{
+       struct perf_session *session;
+       struct perf_data *data;
+
+       session = container_of(ff->ph, struct perf_session, header);
+       data = session->data;
+
+       fprintf(fp, "# directory data version : %"PRIu64"\n", data->dir.version);
+}
+
 static void free_event_desc(struct perf_evsel *events)
 {
        struct perf_evsel *evsel;
@@ -2373,6 +2399,21 @@ static int process_clockid(struct feat_fd *ff,
        return 0;
 }
 
+static int process_dir_format(struct feat_fd *ff,
+                             void *_data __maybe_unused)
+{
+       struct perf_session *session;
+       struct perf_data *data;
+
+       session = container_of(ff->ph, struct perf_session, header);
+       data = session->data;
+
+       if (WARN_ON(!perf_data__is_dir(data)))
+               return -1;
+
+       return do_read_u64(ff, &data->dir.version);
+}
+
 struct feature_ops {
        int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
        void (*print)(struct feat_fd *ff, FILE *fp);
@@ -2432,7 +2473,8 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
        FEAT_OPN(CACHE,         cache,          true),
        FEAT_OPR(SAMPLE_TIME,   sample_time,    false),
        FEAT_OPR(MEM_TOPOLOGY,  mem_topology,   true),
-       FEAT_OPR(CLOCKID,       clockid,        false)
+       FEAT_OPR(CLOCKID,       clockid,        false),
+       FEAT_OPN(DIR_FORMAT,    dir_format,     false)
 };
 
 struct header_print_data {
index 0d553ddca0a3049f941d96a0ae0d68b71ea7a49c..6a231340238d2c4f1ed172436bf3ae53226c6fca 100644 (file)
@@ -39,6 +39,7 @@ enum {
        HEADER_SAMPLE_TIME,
        HEADER_MEM_TOPOLOGY,
        HEADER_CLOCKID,
+       HEADER_DIR_FORMAT,
        HEADER_LAST_FEATURE,
        HEADER_FEAT_BITS        = 256,
 };
@@ -48,6 +49,10 @@ enum perf_header_version {
        PERF_HEADER_VERSION_2,
 };
 
+enum perf_dir_version {
+       PERF_DIR_VERSION        = 1,
+};
+
 struct perf_file_section {
        u64 offset;
        u64 size;