All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 00/17] perf record: Add support to store data in directory
@ 2019-02-21  9:41 Jiri Olsa
  2019-02-21  9:41 ` [PATCH 01/17] perf data: Move size to struct perf_data_file Jiri Olsa
                   ` (16 more replies)
  0 siblings, 17 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

hi,
this patchset adds the --dir option to record command (and all
the other record command that overload cmd_record) that allows
the data to be stored in directory with multiple data files.

It's next step for multiple threads implementation in record.
It's now possible to make directory data via --dir option, like:

  $ perf record --dir perf bench sched messaging
  $ ls -l perf.data
  total 344
  -rw-------. 1 jolsa jolsa 43864 Jan 20 22:26 data.0
  -rw-------. 1 jolsa jolsa 30464 Jan 20 22:26 data.1
  -rw-------. 1 jolsa jolsa 53816 Jan 20 22:26 data.2
  -rw-------. 1 jolsa jolsa 30368 Jan 20 22:26 data.3
  -rw-------. 1 jolsa jolsa 40088 Jan 20 22:26 data.4
  -rw-------. 1 jolsa jolsa 42592 Jan 20 22:26 data.5
  -rw-------. 1 jolsa jolsa 56136 Jan 20 22:26 data.6
  -rw-------. 1 jolsa jolsa 25992 Jan 20 22:26 data.7
  -rw-------. 1 jolsa jolsa  8832 Jan 20 22:26 header

There's a data file created for every cpu and it's storing
data for those cpu maps. The report command will read it
transparently, sort it and display as single file data.

There's new DIR_FORMAT feature to describe directory data
layout/format. In future we can describe different data files
layout according to special needs.

It's possible to transform directory data into standard
perf.data file via simple inject command:
    
  $ perf inject -o perf.data.file -i perf.data

The old perf fails over the directory data with following message:
  $ perf report
  incompatible file format (rerun with -v to learn more)

I'm now testing the record threads support, so I'd like to
have some agreement on the directory data support before.

v2 changes:
  - rm_rf changes are already accepted with requested changes
  - updated doc/man plus adding perf.data-directory-format.txt
    to describe directory format/layout
  - the --switch-output options now works over directory data
  - data rollback is not part of this patchset, updated my TODO though ;-)
  - added --output-dir option to combine -o and --dir
  - added DIR_FORMAT feature to describe directory data
  - disabling directory output for aio for now

It's also available in here:
  git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
  perf/dir

thanks,
jirka


---
Jiri Olsa (17):
      perf data: Move size to struct perf_data_file
      perf data: Add global path holder
      perf data: Make check_backup work over directories
      perf data: Fail check_backup in case of error
      perf data: Add perf_data__(create_dir|close_dir) functions
      perf data: Add perf_data__open_dir_data function
      perf data: Add directory support
      perf data: Don't store auxtrace index for directory data file
      perf data: Add perf_data__update_dir function
      perf data: Make perf_data__size to work over directory
      perf header: Add DIR_FORMAT feature to describe directory data
      perf session: Add process callback to reader object
      perf session: Add __perf_session__process_dir_events function
      perf session: Add path to reader object
      perf record: Add --dir option to store data in directory
      perf record: Add --output-dir option to store data in directory
      perf record: Describe perf.data directory format

 tools/lib/subcmd/parse-options.h                        |   4 +++
 tools/perf/Documentation/perf-record.txt                |   6 ++++
 tools/perf/Documentation/perf.data-directory-format.txt |  54 ++++++++++++++++++++++++++++++++
 tools/perf/builtin-annotate.c                           |   4 +--
 tools/perf/builtin-buildid-cache.c                      |   4 +--
 tools/perf/builtin-buildid-list.c                       |   8 ++---
 tools/perf/builtin-c2c.c                                |   4 +--
 tools/perf/builtin-diff.c                               |  12 +++----
 tools/perf/builtin-evlist.c                             |   4 +--
 tools/perf/builtin-inject.c                             |  10 +++---
 tools/perf/builtin-kmem.c                               |   2 +-
 tools/perf/builtin-kvm.c                                |   8 ++---
 tools/perf/builtin-lock.c                               |   8 ++---
 tools/perf/builtin-mem.c                                |   8 ++---
 tools/perf/builtin-record.c                             | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 tools/perf/builtin-report.c                             |   6 ++--
 tools/perf/builtin-sched.c                              |  16 ++++------
 tools/perf/builtin-script.c                             |  12 +++----
 tools/perf/builtin-stat.c                               |   6 ++--
 tools/perf/builtin-timechart.c                          |   8 ++---
 tools/perf/builtin-trace.c                              |   8 ++---
 tools/perf/util/data-convert-bt.c                       |   2 +-
 tools/perf/util/data.c                                  | 254 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
 tools/perf/util/data.h                                  |  26 ++++++++++++----
 tools/perf/util/header.c                                |  44 +++++++++++++++++++++++++-
 tools/perf/util/header.h                                |   5 +++
 tools/perf/util/mmap.h                                  |  23 +++++++-------
 tools/perf/util/session.c                               | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 28 files changed, 643 insertions(+), 132 deletions(-)
 create mode 100644 tools/perf/Documentation/perf.data-directory-format.txt

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 01/17] perf data: Move size to struct perf_data_file
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-28  7:58   ` [tip:perf/core] " tip-bot for Jiri Olsa
  2019-02-21  9:41 ` [PATCH 02/17] perf data: Add global path holder Jiri Olsa
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

We are about to add support for multiple files,
so we need each file to keep its size.

Link: http://lkml.kernel.org/n/tip-gcf5gtwxds3ggegu6evl0jvn@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-record.c | 5 ++---
 tools/perf/util/data.c      | 2 +-
 tools/perf/util/data.h      | 4 ++--
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 6c3719ac901d..e5e9900c9039 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -660,10 +660,9 @@ static int process_sample_event(struct perf_tool *tool,
 
 static int process_buildids(struct record *rec)
 {
-	struct perf_data *data = &rec->data;
 	struct perf_session *session = rec->session;
 
-	if (data->size == 0)
+	if (perf_data__size(&rec->data) == 0)
 		return 0;
 
 	/*
@@ -851,7 +850,7 @@ record__finish_output(struct record *rec)
 		return;
 
 	rec->session->header.data_size += rec->bytes_written;
-	data->size = lseek(perf_data__fd(data), 0, SEEK_CUR);
+	data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR);
 
 	if (!rec->no_buildid) {
 		process_buildids(rec);
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index d8cfc19ddb10..09eceda17fc2 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -82,7 +82,7 @@ static int open_file_read(struct perf_data *data)
 		goto out_close;
 	}
 
-	data->size = st.st_size;
+	data->file.size = st.st_size;
 	return fd;
 
  out_close:
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 4828f7feea89..85f9c0dbf982 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -12,13 +12,13 @@ enum perf_data_mode {
 struct perf_data_file {
 	const char	*path;
 	int		 fd;
+	unsigned long	 size;
 };
 
 struct perf_data {
 	struct perf_data_file	 file;
 	bool			 is_pipe;
 	bool			 force;
-	unsigned long		 size;
 	enum perf_data_mode	 mode;
 };
 
@@ -44,7 +44,7 @@ static inline int perf_data__fd(struct perf_data *data)
 
 static inline unsigned long perf_data__size(struct perf_data *data)
 {
-	return data->size;
+	return data->file.size;
 }
 
 int perf_data__open(struct perf_data *data);
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 02/17] perf data: Add global path holder
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
  2019-02-21  9:41 ` [PATCH 01/17] perf data: Move size to struct perf_data_file Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-22 16:05   ` Arnaldo Carvalho de Melo
  2019-02-28  7:59   ` [tip:perf/core] " tip-bot for Jiri Olsa
  2019-02-21  9:41 ` [PATCH 03/17] perf data: Make check_backup work over directories Jiri Olsa
                   ` (14 subsequent siblings)
  16 siblings, 2 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Adding path to the struct perf_data. It will keep the
configured path for the data (const char*). The path
in struct perf_data_file is now dynamically allocated
(duped) from it.

This scheme is useful/used in following patches where
struct perf_data::path holds the 'configure' directory
path and struct perf_data_file::path holds the allocated
path for specific files.

Also it actually makes the code little simpler.

Link: http://lkml.kernel.org/n/tip-ww4tdzfaub4vlv9xxkxvwx9q@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-annotate.c      |  4 +--
 tools/perf/builtin-buildid-cache.c |  4 +--
 tools/perf/builtin-buildid-list.c  |  8 +++---
 tools/perf/builtin-c2c.c           |  4 +--
 tools/perf/builtin-diff.c          | 12 ++++-----
 tools/perf/builtin-evlist.c        |  4 +--
 tools/perf/builtin-inject.c        | 10 +++-----
 tools/perf/builtin-kmem.c          |  2 +-
 tools/perf/builtin-kvm.c           |  8 +++---
 tools/perf/builtin-lock.c          |  8 +++---
 tools/perf/builtin-mem.c           |  8 +++---
 tools/perf/builtin-record.c        |  6 ++---
 tools/perf/builtin-report.c        |  6 ++---
 tools/perf/builtin-sched.c         | 16 +++++-------
 tools/perf/builtin-script.c        | 12 ++++-----
 tools/perf/builtin-stat.c          |  6 ++---
 tools/perf/builtin-timechart.c     |  8 +++---
 tools/perf/builtin-trace.c         |  8 +++---
 tools/perf/util/data-convert-bt.c  |  2 +-
 tools/perf/util/data.c             | 39 +++++++++++++++++++++---------
 tools/perf/util/data.h             |  3 ++-
 21 files changed, 86 insertions(+), 92 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 7f3c3fea67b4..67f9d9ffacfb 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -441,7 +441,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
 	}
 
 	if (total_nr_samples == 0) {
-		ui__error("The %s file has no samples!\n", session->data->file.path);
+		ui__error("The %s data has no samples!\n", session->data->path);
 		goto out;
 	}
 
@@ -578,7 +578,7 @@ int cmd_annotate(int argc, const char **argv)
 	if (quiet)
 		perf_quiet_option();
 
-	data.file.path = input_name;
+	data.path = input_name;
 
 	annotate.session = perf_session__new(&data, false, &annotate.tool);
 	if (annotate.session == NULL)
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 115110a4796a..10457b10e568 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -416,8 +416,8 @@ int cmd_buildid_cache(int argc, const char **argv)
 		nsi = nsinfo__new(ns_id);
 
 	if (missing_filename) {
-		data.file.path = missing_filename;
-		data.force     = force;
+		data.path  = missing_filename;
+		data.force = force;
 
 		session = perf_session__new(&data, false, NULL);
 		if (session == NULL)
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 78abbe8d9d5f..f403e19488b5 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -52,11 +52,9 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
 {
 	struct perf_session *session;
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = force,
 	};
 
 	symbol__elf_init();
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index efaaab23c6fd..4272763a5e96 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -2750,8 +2750,8 @@ static int perf_c2c__report(int argc, const char **argv)
 	if (!input_name || !strlen(input_name))
 		input_name = "perf.data";
 
-	data.file.path = input_name;
-	data.force     = symbol_conf.force;
+	data.path  = input_name;
+	data.force = symbol_conf.force;
 
 	err = setup_display(display);
 	if (err)
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 751e1971456b..58fe0e88215c 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -708,7 +708,7 @@ static void data__fprintf(void)
 
 	data__for_each_file(i, d)
 		fprintf(stdout, "#  [%d] %s %s\n",
-			d->idx, d->data.file.path,
+			d->idx, d->data.path,
 			!d->idx ? "(Baseline)" : "");
 
 	fprintf(stdout, "#\n");
@@ -779,14 +779,14 @@ static int __cmd_diff(void)
 	data__for_each_file(i, d) {
 		d->session = perf_session__new(&d->data, false, &tool);
 		if (!d->session) {
-			pr_err("Failed to open %s\n", d->data.file.path);
+			pr_err("Failed to open %s\n", d->data.path);
 			ret = -1;
 			goto out_delete;
 		}
 
 		ret = perf_session__process_events(d->session);
 		if (ret) {
-			pr_err("Failed to process %s\n", d->data.file.path);
+			pr_err("Failed to process %s\n", d->data.path);
 			goto out_delete;
 		}
 
@@ -1289,9 +1289,9 @@ static int data_init(int argc, const char **argv)
 	data__for_each_file(i, d) {
 		struct perf_data *data = &d->data;
 
-		data->file.path = use_default ? defaults[i] : argv[i];
-		data->mode      = PERF_DATA_MODE_READ,
-		data->force     = force,
+		data->path  = use_default ? defaults[i] : argv[i];
+		data->mode  = PERF_DATA_MODE_READ,
+		data->force = force,
 
 		d->idx  = i;
 	}
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index e06e822ce634..6e4f63b0da4a 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -23,9 +23,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
 	struct perf_session *session;
 	struct perf_evsel *pos;
 	struct perf_data data = {
-		.file      = {
-			.path = file_name,
-		},
+		.path      = file_name,
 		.mode      = PERF_DATA_MODE_READ,
 		.force     = details->force,
 	};
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 9bb1f35d5cb7..24086b7f1b14 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -770,10 +770,8 @@ int cmd_inject(int argc, const char **argv)
 		.input_name  = "-",
 		.samples = LIST_HEAD_INIT(inject.samples),
 		.output = {
-			.file      = {
-				.path = "-",
-			},
-			.mode      = PERF_DATA_MODE_WRITE,
+			.path = "-",
+			.mode = PERF_DATA_MODE_WRITE,
 		},
 	};
 	struct perf_data data = {
@@ -786,7 +784,7 @@ int cmd_inject(int argc, const char **argv)
 			    "Inject build-ids into the output stream"),
 		OPT_STRING('i', "input", &inject.input_name, "file",
 			   "input file name"),
-		OPT_STRING('o', "output", &inject.output.file.path, "file",
+		OPT_STRING('o', "output", &inject.output.path, "file",
 			   "output file name"),
 		OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
 			    "Merge sched-stat and sched-switch for getting events "
@@ -834,7 +832,7 @@ int cmd_inject(int argc, const char **argv)
 
 	inject.tool.ordered_events = inject.sched_stat;
 
-	data.file.path = inject.input_name;
+	data.path = inject.input_name;
 	inject.session = perf_session__new(&data, true, &inject.tool);
 	if (inject.session == NULL)
 		return -1;
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index b80ec0883537..fa520f4b8095 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1949,7 +1949,7 @@ int cmd_kmem(int argc, const char **argv)
 		return __cmd_record(argc, argv);
 	}
 
-	data.file.path = input_name;
+	data.path = input_name;
 
 	kmem_session = session = perf_session__new(&data, false, &perf_kmem);
 	if (session == NULL)
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 3d4cbc4e87c7..dbb6f737a3e2 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1080,11 +1080,9 @@ static int read_events(struct perf_kvm_stat *kvm)
 		.ordered_events		= true,
 	};
 	struct perf_data file = {
-		.file      = {
-			.path = kvm->file_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = kvm->force,
+		.path  = kvm->file_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = kvm->force,
 	};
 
 	kvm->tool = eops;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 6e0189df2b3b..b9810a8d350a 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -866,11 +866,9 @@ static int __cmd_report(bool display_info)
 		.ordered_events	 = true,
 	};
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = force,
 	};
 
 	session = perf_session__new(&data, false, &eops);
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index ba7e8d87dec3..f45c8b502f63 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -239,11 +239,9 @@ static int process_sample_event(struct perf_tool *tool,
 static int report_raw_events(struct perf_mem *mem)
 {
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = mem->force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = mem->force,
 	};
 	int ret;
 	struct perf_session *session = perf_session__new(&data, false,
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e5e9900c9039..f3f7f3100336 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -918,7 +918,7 @@ record__switch_output(struct record *rec, bool at_exit)
 
 	if (!quiet)
 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
-			data->file.path, timestamp);
+			data->path, timestamp);
 
 	/* Output tracking events */
 	if (!at_exit) {
@@ -1461,7 +1461,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 
 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
 			perf_data__size(data) / 1024.0 / 1024.0,
-			data->file.path, postfix, samples);
+			data->path, postfix, samples);
 	}
 
 out_delete_session:
@@ -1862,7 +1862,7 @@ static struct option __record_options[] = {
 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
 		    "list of cpus to monitor"),
 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
-	OPT_STRING('o', "output", &record.data.file.path, "file",
+	OPT_STRING('o', "output", &record.data.path, "file",
 		    "output file name"),
 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
 			&record.opts.no_inherit_set,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 2e8c74d6430c..1532ebde6c4b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -899,7 +899,7 @@ static int __cmd_report(struct report *rep)
 		rep->nr_entries += evsel__hists(pos)->nr_entries;
 
 	if (rep->nr_entries == 0) {
-		ui__error("The %s file has no samples!\n", data->file.path);
+		ui__error("The %s data has no samples!\n", data->path);
 		return 0;
 	}
 
@@ -1207,8 +1207,8 @@ int cmd_report(int argc, const char **argv)
 			input_name = "perf.data";
 	}
 
-	data.file.path = input_name;
-	data.force     = symbol_conf.force;
+	data.path  = input_name;
+	data.force = symbol_conf.force;
 
 repeat:
 	session = perf_session__new(&data, false, &report.tool);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 640558e9352e..275f2d92a7bf 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1785,11 +1785,9 @@ static int perf_sched__read_events(struct perf_sched *sched)
 	};
 	struct perf_session *session;
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = sched->force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = sched->force,
 	};
 	int rc = -1;
 
@@ -2958,11 +2956,9 @@ static int perf_sched__timehist(struct perf_sched *sched)
 		{ "sched:sched_migrate_task", timehist_migrate_task_event, },
 	};
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = sched->force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = sched->force,
 	};
 
 	struct perf_session *session;
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 373ea151dc60..5b1543f42290 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -2951,10 +2951,8 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
 	DIR *scripts_dir, *lang_dir;
 	struct perf_session *session;
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
+		.path = input_name,
+		.mode = PERF_DATA_MODE_READ,
 	};
 	char *temp;
 	int i = 0;
@@ -3427,8 +3425,8 @@ int cmd_script(int argc, const char **argv)
 	argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 
-	data.file.path = input_name;
-	data.force     = symbol_conf.force;
+	data.path  = input_name;
+	data.force = symbol_conf.force;
 
 	if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
 		rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
@@ -3654,7 +3652,7 @@ int cmd_script(int argc, const char **argv)
 			goto out_delete;
 		}
 
-		input = open(data.file.path, O_RDONLY);	/* input_name */
+		input = open(data.path, O_RDONLY);	/* input_name */
 		if (input < 0) {
 			err = -errno;
 			perror("failed to open file");
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index bb24f9c17f9a..7b8f09b0b8bf 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1322,7 +1322,7 @@ static int __cmd_record(int argc, const char **argv)
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 
 	if (output_name)
-		data->file.path = output_name;
+		data->path = output_name;
 
 	if (stat_config.run_count != 1 || forever) {
 		pr_err("Cannot use -r option with perf stat record.\n");
@@ -1523,8 +1523,8 @@ static int __cmd_report(int argc, const char **argv)
 			input_name = "perf.data";
 	}
 
-	perf_stat.data.file.path = input_name;
-	perf_stat.data.mode      = PERF_DATA_MODE_READ;
+	perf_stat.data.path = input_name;
+	perf_stat.data.mode = PERF_DATA_MODE_READ;
 
 	session = perf_session__new(&perf_stat.data, false, &perf_stat.tool);
 	if (session == NULL)
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 775b99833e51..9b98687a27b9 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1602,11 +1602,9 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
 		{ "syscalls:sys_exit_select",		process_exit_poll },
 	};
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = tchart->force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = tchart->force,
 	};
 
 	struct perf_session *session = perf_session__new(&data, false,
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 1a11fe656afc..f5b3a1e9c1dd 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -3154,11 +3154,9 @@ static int trace__replay(struct trace *trace)
 		{ "probe:vfs_getname",	     trace__vfs_getname, },
 	};
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = trace->force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = trace->force,
 	};
 	struct perf_session *session;
 	struct perf_evsel *evsel;
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 2a36fab76994..ea742a254aa5 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -1650,7 +1650,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
 
 	fprintf(stderr,
 		"[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
-		data.file.path, path);
+		data.path, path);
 
 	fprintf(stderr,
 		"[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 09eceda17fc2..e16d06ed1100 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -19,11 +19,11 @@ static bool check_pipe(struct perf_data *data)
 	int fd = perf_data__is_read(data) ?
 		 STDIN_FILENO : STDOUT_FILENO;
 
-	if (!data->file.path) {
+	if (!data->path) {
 		if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
 			is_pipe = true;
 	} else {
-		if (!strcmp(data->file.path, "-"))
+		if (!strcmp(data->path, "-"))
 			is_pipe = true;
 	}
 
@@ -37,13 +37,13 @@ static int check_backup(struct perf_data *data)
 {
 	struct stat st;
 
-	if (!stat(data->file.path, &st) && st.st_size) {
+	if (!stat(data->path, &st) && st.st_size) {
 		/* TODO check errors properly */
 		char oldname[PATH_MAX];
 		snprintf(oldname, sizeof(oldname), "%s.old",
-			 data->file.path);
+			 data->path);
 		unlink(oldname);
-		rename(data->file.path, oldname);
+		rename(data->path, oldname);
 	}
 
 	return 0;
@@ -115,8 +115,22 @@ static int open_file(struct perf_data *data)
 	fd = perf_data__is_read(data) ?
 	     open_file_read(data) : open_file_write(data);
 
+	if (fd < 0) {
+		free(data->file.path);
+		return -1;
+	}
+
 	data->file.fd = fd;
-	return fd < 0 ? -1 : 0;
+	return 0;
+}
+
+static int open_file_dup(struct perf_data *data)
+{
+	data->file.path = strdup(data->path);
+	if (!data->file.path)
+		return -ENOMEM;
+
+	return open_file(data);
 }
 
 int perf_data__open(struct perf_data *data)
@@ -124,14 +138,15 @@ int perf_data__open(struct perf_data *data)
 	if (check_pipe(data))
 		return 0;
 
-	if (!data->file.path)
-		data->file.path = "perf.data";
+	if (!data->path)
+		data->path = "perf.data";
 
-	return open_file(data);
+	return open_file_dup(data);
 }
 
 void perf_data__close(struct perf_data *data)
 {
+	free(data->file.path);
 	close(data->file.fd);
 }
 
@@ -159,15 +174,15 @@ int perf_data__switch(struct perf_data *data,
 	if (perf_data__is_read(data))
 		return -EINVAL;
 
-	if (asprintf(&new_filepath, "%s.%s", data->file.path, postfix) < 0)
+	if (asprintf(&new_filepath, "%s.%s", data->path, postfix) < 0)
 		return -ENOMEM;
 
 	/*
 	 * Only fire a warning, don't return error, continue fill
 	 * original file.
 	 */
-	if (rename(data->file.path, new_filepath))
-		pr_warning("Failed to rename %s to %s\n", data->file.path, new_filepath);
+	if (rename(data->path, new_filepath))
+		pr_warning("Failed to rename %s to %s\n", data->path, new_filepath);
 
 	if (!at_exit) {
 		close(data->file.fd);
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 85f9c0dbf982..2bce28117ccf 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -10,12 +10,13 @@ enum perf_data_mode {
 };
 
 struct perf_data_file {
-	const char	*path;
+	char		*path;
 	int		 fd;
 	unsigned long	 size;
 };
 
 struct perf_data {
+	const char		*path;
 	struct perf_data_file	 file;
 	bool			 is_pipe;
 	bool			 force;
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 03/17] perf data: Make check_backup work over directories
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
  2019-02-21  9:41 ` [PATCH 01/17] perf data: Move size to struct perf_data_file Jiri Olsa
  2019-02-21  9:41 ` [PATCH 02/17] perf data: Add global path holder Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21  9:41 ` [PATCH 04/17] perf data: Fail check_backup in case of error Jiri Olsa
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Changing check_backup to call rm_rf instead of unlink to work
over directory paths. Also moving the call earlier in the code,
before we fork for file/dir, so it can backup also directory data.

Link: http://lkml.kernel.org/n/tip-j4lwm20en1yk1hsaqb8zpxkr@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/data.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index e16d06ed1100..0a3051cc0ea0 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -37,12 +37,15 @@ static int check_backup(struct perf_data *data)
 {
 	struct stat st;
 
+	if (perf_data__is_read(data))
+		return 0;
+
 	if (!stat(data->path, &st) && st.st_size) {
 		/* TODO check errors properly */
 		char oldname[PATH_MAX];
 		snprintf(oldname, sizeof(oldname), "%s.old",
 			 data->path);
-		unlink(oldname);
+		rm_rf(oldname);
 		rename(data->path, oldname);
 	}
 
@@ -95,9 +98,6 @@ static int open_file_write(struct perf_data *data)
 	int fd;
 	char sbuf[STRERR_BUFSIZE];
 
-	if (check_backup(data))
-		return -1;
-
 	fd = open(data->file.path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC,
 		  S_IRUSR|S_IWUSR);
 
@@ -141,6 +141,9 @@ int perf_data__open(struct perf_data *data)
 	if (!data->path)
 		data->path = "perf.data";
 
+	if (check_backup(data))
+		return -1;
+
 	return open_file_dup(data);
 }
 
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 04/17] perf data: Fail check_backup in case of error
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (2 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 03/17] perf data: Make check_backup work over directories Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21 22:23   ` Andi Kleen
  2019-02-21  9:41 ` [PATCH 05/17] perf data: Add perf_data__(create_dir|close_dir) functions Jiri Olsa
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

And display the error message from removing
the old data file:

  $ perf record ls
  Can't remove old data: Permission denied (perf.data.old)
  Perf session creation failed.

Not sure how to make fail the rename (after we successfully
remove the destination file/dir) to show the message,
anyway let's have it there.

Link: http://lkml.kernel.org/n/tip-6k0tikvlyugms7xxqs794jxz@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/data.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 0a3051cc0ea0..18e5d94b0e97 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -41,12 +41,24 @@ static int check_backup(struct perf_data *data)
 		return 0;
 
 	if (!stat(data->path, &st) && st.st_size) {
-		/* TODO check errors properly */
 		char oldname[PATH_MAX];
+
 		snprintf(oldname, sizeof(oldname), "%s.old",
 			 data->path);
-		rm_rf(oldname);
-		rename(data->path, oldname);
+
+		if (rm_rf(oldname)) {
+			pr_err("Can't remove old data: %s (%s)\n",
+			       strerror(errno), oldname);
+
+			return -1;
+		}
+
+		if (rename(data->path, oldname)) {
+			pr_err("Can't move data: %s (%s to %s)\n",
+			       strerror(errno),
+			       data->path, oldname);
+			return -1;
+		}
 	}
 
 	return 0;
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 05/17] perf data: Add perf_data__(create_dir|close_dir) functions
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (3 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 04/17] perf data: Fail check_backup in case of error Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-23  5:07   ` Namhyung Kim
  2019-02-21  9:41 ` [PATCH 06/17] perf data: Add perf_data__open_dir_data function Jiri Olsa
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Adding perf_data__create_dir to create nr files inside
struct perf_data path directory:
  int perf_data__create_dir(struct perf_data *data, int nr);

and function to close that data:
  void perf_data__close_dir(struct perf_data *data);

Link: http://lkml.kernel.org/n/tip-kl4s1f13cg6wycrg367p85qm@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/data.c | 47 ++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/data.h |  8 +++++++
 2 files changed, 55 insertions(+)

diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 18e5d94b0e97..7f13fbd9c043 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -7,11 +7,58 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <string.h>
+#include <asm/bug.h>
 
 #include "data.h"
 #include "util.h"
 #include "debug.h"
 
+static void close_dir(struct perf_data_file *files, int nr)
+{
+	while (--nr >= 1) {
+		close(files[nr].fd);
+		free(files[nr].path);
+	}
+	free(files);
+}
+
+void perf_data__close_dir(struct perf_data *data)
+{
+	close_dir(data->dir.files, data->dir.nr);
+}
+
+int perf_data__create_dir(struct perf_data *data, int nr)
+{
+	struct perf_data_file *files = NULL;
+	int i, ret = -1;
+
+	files = malloc(nr * sizeof(*files));
+	if (!files)
+		return -ENOMEM;
+
+	data->dir.files = files;
+	data->dir.nr    = nr;
+
+	for (i = 0; i < nr; i++) {
+		struct perf_data_file *file = &files[i];
+
+		if (asprintf(&file->path, "%s/data.%d", data->path, i) < 0)
+			goto out_err;
+
+		ret = open(file->path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
+		if (ret < 0)
+			goto out_err;
+
+		file->fd = ret;
+	}
+
+	return 0;
+
+out_err:
+	close_dir(files, i);
+	return ret;
+}
+
 static bool check_pipe(struct perf_data *data)
 {
 	struct stat st;
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 2bce28117ccf..2d0d015a7d4d 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -21,6 +21,11 @@ struct perf_data {
 	bool			 is_pipe;
 	bool			 force;
 	enum perf_data_mode	 mode;
+
+	struct {
+		struct perf_data_file	*files;
+		int			 nr;
+	} dir;
 };
 
 static inline bool perf_data__is_read(struct perf_data *data)
@@ -64,4 +69,7 @@ ssize_t perf_data_file__write(struct perf_data_file *file,
 int perf_data__switch(struct perf_data *data,
 			   const char *postfix,
 			   size_t pos, bool at_exit);
+
+int perf_data__create_dir(struct perf_data *data, int nr);
+void perf_data__close_dir(struct perf_data *data);
 #endif /* __PERF_DATA_H */
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 06/17] perf data: Add perf_data__open_dir_data function
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (4 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 05/17] perf data: Add perf_data__(create_dir|close_dir) functions Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21  9:41 ` [PATCH 07/17] perf data: Add directory support Jiri Olsa
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Adding perf_data__open_dir_data to open files inside
struct perf_data path directory:
   static int perf_data__open_dir(struct perf_data *data);

Link: http://lkml.kernel.org/n/tip-sv97z5mh9j273mz2cthzaq4n@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/data.c | 59 ++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/data.h |  1 +
 2 files changed, 60 insertions(+)

diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 7f13fbd9c043..d9e766a16e70 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -8,6 +8,8 @@
 #include <unistd.h>
 #include <string.h>
 #include <asm/bug.h>
+#include <sys/types.h>
+#include <dirent.h>
 
 #include "data.h"
 #include "util.h"
@@ -59,6 +61,63 @@ int perf_data__create_dir(struct perf_data *data, int nr)
 	return ret;
 }
 
+int perf_data__open_dir(struct perf_data *data)
+{
+	struct perf_data_file *files = NULL;
+	struct dirent *dent;
+	int ret = -1;
+	DIR *dir;
+	int nr = 0;
+
+	dir = opendir(data->path);
+	if (!dir)
+		return -EINVAL;
+
+	while ((dent = readdir(dir)) != NULL) {
+		struct perf_data_file *file;
+		char path[PATH_MAX];
+		struct stat st;
+
+		snprintf(path, sizeof(path), "%s/%s", data->path, dent->d_name);
+		if (stat(path, &st))
+			continue;
+
+		if (!S_ISREG(st.st_mode) || strncmp(dent->d_name, "data", 4))
+			continue;
+
+		ret = -ENOMEM;
+
+		file = realloc(files, (nr + 1) * sizeof(*files));
+		if (!file)
+			goto out_err;
+
+		files = file;
+		file = &files[nr++];
+
+		file->path = strdup(path);
+		if (!file->path)
+			goto out_err;
+
+		ret = open(file->path, O_RDONLY);
+		if (ret < 0)
+			goto out_err;
+
+		file->fd = ret;
+		file->size = st.st_size;
+	}
+
+	if (!files)
+		return -EINVAL;
+
+	data->dir.files = files;
+	data->dir.nr    = nr;
+	return 0;
+
+out_err:
+	close_dir(files, nr);
+	return ret;
+}
+
 static bool check_pipe(struct perf_data *data)
 {
 	struct stat st;
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 2d0d015a7d4d..14b47be2bd69 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -71,5 +71,6 @@ int perf_data__switch(struct perf_data *data,
 			   size_t pos, bool at_exit);
 
 int perf_data__create_dir(struct perf_data *data, int nr);
+int perf_data__open_dir(struct perf_data *data);
 void perf_data__close_dir(struct perf_data *data);
 #endif /* __PERF_DATA_H */
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 07/17] perf data: Add directory support
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (5 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 06/17] perf data: Add perf_data__open_dir_data function Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21  9:41 ` [PATCH 08/17] perf data: Don't store auxtrace index for directory data file Jiri Olsa
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Adding support to have directory as perf.data.

The caller needs to set 'struct perf_data::is_dir flag
and the path will be treated as directory.

The 'struct perf_data::file' is initialized and open
as 'path/header' file.

Adding check to direcory interface functions to check
on is_dir flag.

Link: http://lkml.kernel.org/n/tip-pvot1aywiem9epgqpfi1agaj@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/data.c    | 41 ++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/data.h    |  6 ++++++
 tools/perf/util/session.c |  4 ++++
 3 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index d9e766a16e70..f6c94dcee1b8 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -34,6 +34,9 @@ int perf_data__create_dir(struct perf_data *data, int nr)
 	struct perf_data_file *files = NULL;
 	int i, ret = -1;
 
+	if (WARN_ON(!data->is_dir))
+		return -EINVAL;
+
 	files = malloc(nr * sizeof(*files));
 	if (!files)
 		return -ENOMEM;
@@ -69,6 +72,9 @@ int perf_data__open_dir(struct perf_data *data)
 	DIR *dir;
 	int nr = 0;
 
+	if (WARN_ON(!data->is_dir))
+		return -EINVAL;
+
 	dir = opendir(data->path);
 	if (!dir)
 		return -EINVAL;
@@ -170,6 +176,16 @@ static int check_backup(struct perf_data *data)
 	return 0;
 }
 
+static bool is_dir(struct perf_data *data)
+{
+	struct stat st;
+
+	if (stat(data->path, &st))
+		return false;
+
+	return (st.st_mode & S_IFMT) == S_IFDIR;
+}
+
 static int open_file_read(struct perf_data *data)
 {
 	struct stat st;
@@ -251,6 +267,22 @@ static int open_file_dup(struct perf_data *data)
 	return open_file(data);
 }
 
+static int open_dir(struct perf_data *data)
+{
+	if (perf_data__is_write(data) &&
+	    mkdir(data->path, S_IRWXU) < 0)
+		return -1;
+
+	/*
+	 * So far we open only the header, so we
+	 * can read the data version and layout.
+	 */
+	if (asprintf(&data->file.path, "%s/header", data->path) < 0)
+		return -ENOMEM;
+
+	return open_file(data);
+}
+
 int perf_data__open(struct perf_data *data)
 {
 	if (check_pipe(data))
@@ -262,11 +294,18 @@ int perf_data__open(struct perf_data *data)
 	if (check_backup(data))
 		return -1;
 
-	return open_file_dup(data);
+	if (perf_data__is_read(data))
+		data->is_dir = is_dir(data);
+
+	return perf_data__is_dir(data) ?
+	       open_dir(data) : open_file_dup(data);
 }
 
 void perf_data__close(struct perf_data *data)
 {
+	if (perf_data__is_dir(data))
+		perf_data__close_dir(data);
+
 	free(data->file.path);
 	close(data->file.fd);
 }
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 14b47be2bd69..06aefeda311f 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -19,6 +19,7 @@ struct perf_data {
 	const char		*path;
 	struct perf_data_file	 file;
 	bool			 is_pipe;
+	bool			 is_dir;
 	bool			 force;
 	enum perf_data_mode	 mode;
 
@@ -43,6 +44,11 @@ static inline int perf_data__is_pipe(struct perf_data *data)
 	return data->is_pipe;
 }
 
+static inline bool perf_data__is_dir(struct perf_data *data)
+{
+	return data->is_dir;
+}
+
 static inline int perf_data__fd(struct perf_data *data)
 {
 	return data->file.fd;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index c764bbc91009..9991e9a8bc12 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -152,6 +152,10 @@ struct perf_session *perf_session__new(struct perf_data *data,
 			}
 
 			perf_evlist__init_trace_event_sample_raw(session->evlist);
+
+			/* Open the directory data. */
+			if (data->is_dir && perf_data__open_dir(data))
+				goto out_close;
 		}
 	} else  {
 		session->machines.host.env = &perf_env;
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 08/17] perf data: Don't store auxtrace index for directory data file
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (6 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 07/17] perf data: Add directory support Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21  9:41 ` [PATCH 09/17] perf data: Add perf_data__update_dir function Jiri Olsa
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

We can't store auxtrace index when we store to multiple files,
because we keep only offset for it, not the file.

The auxtrace data will be processed correctly in the 'pipe' mode.

Link: http://lkml.kernel.org/n/tip-og11od5s6nfxuf0ftxyu8m6k@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-record.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f3f7f3100336..e983c8d71a79 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -392,7 +392,7 @@ static int record__process_auxtrace(struct perf_tool *tool,
 	size_t padding;
 	u8 pad[8] = {0};
 
-	if (!perf_data__is_pipe(data)) {
+	if (!perf_data__is_pipe(data) && !perf_data__is_dir(data)) {
 		off_t file_offset;
 		int fd = perf_data__fd(data);
 		int err;
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 09/17] perf data: Add perf_data__update_dir function
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (7 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 08/17] perf data: Don't store auxtrace index for directory data file Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21  9:41 ` [PATCH 10/17] perf data: Make perf_data__size to work over directory Jiri Olsa
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Adding perf_data__update_dir function to update
size for every file within the perf.data directory.

Link: http://lkml.kernel.org/n/tip-3ii12l48u4tyvrzxo1797w7e@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/data.c | 20 ++++++++++++++++++++
 tools/perf/util/data.h |  1 +
 2 files changed, 21 insertions(+)

diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index f6c94dcee1b8..d6a7fa4c2768 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -124,6 +124,26 @@ int perf_data__open_dir(struct perf_data *data)
 	return ret;
 }
 
+int perf_data__update_dir(struct perf_data *data)
+{
+	int i;
+
+	if (WARN_ON(!data->is_dir))
+		return -EINVAL;
+
+	for (i = 0; i < data->dir.nr; i++) {
+		struct perf_data_file *file = &data->dir.files[i];
+		struct stat st;
+
+		if (fstat(file->fd, &st))
+			return -1;
+
+		file->size = st.st_size;
+	}
+
+	return 0;
+}
+
 static bool check_pipe(struct perf_data *data)
 {
 	struct stat st;
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 06aefeda311f..0deeb1af9f54 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -79,4 +79,5 @@ int perf_data__switch(struct perf_data *data,
 int perf_data__create_dir(struct perf_data *data, int nr);
 int perf_data__open_dir(struct perf_data *data);
 void perf_data__close_dir(struct perf_data *data);
+int perf_data__update_dir(struct perf_data *data);
 #endif /* __PERF_DATA_H */
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 10/17] perf data: Make perf_data__size to work over directory
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (8 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 09/17] perf data: Add perf_data__update_dir function Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21  9:41 ` [PATCH 11/17] perf header: Add DIR_FORMAT feature to describe directory data Jiri Olsa
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Making perf_data__size to return proper size
for directory data.

Link: http://lkml.kernel.org/n/tip-t4dm8cctat2ginmy2bb08xe8@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/data.c | 17 +++++++++++++++++
 tools/perf/util/data.h |  6 +-----
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index d6a7fa4c2768..5681a25aea88 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -382,3 +382,20 @@ int perf_data__switch(struct perf_data *data,
 	free(new_filepath);
 	return ret;
 }
+
+unsigned long perf_data__size(struct perf_data *data)
+{
+	u64 size = data->file.size;
+	int i;
+
+	if (!data->is_dir)
+		return size;
+
+	for (i = 0; i < data->dir.nr; i++) {
+		struct perf_data_file *file = &data->dir.files[i];
+
+		size += file->size;
+	}
+
+	return size;
+}
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 0deeb1af9f54..d342469bdfda 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -54,11 +54,6 @@ static inline int perf_data__fd(struct perf_data *data)
 	return data->file.fd;
 }
 
-static inline unsigned long perf_data__size(struct perf_data *data)
-{
-	return data->file.size;
-}
-
 int perf_data__open(struct perf_data *data);
 void perf_data__close(struct perf_data *data);
 ssize_t perf_data__write(struct perf_data *data,
@@ -80,4 +75,5 @@ int perf_data__create_dir(struct perf_data *data, int nr);
 int perf_data__open_dir(struct perf_data *data);
 void perf_data__close_dir(struct perf_data *data);
 int perf_data__update_dir(struct perf_data *data);
+unsigned long perf_data__size(struct perf_data *data);
 #endif /* __PERF_DATA_H */
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 11/17] perf header: Add DIR_FORMAT feature to describe directory data
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (9 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 10/17] perf data: Make perf_data__size to work over directory Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21  9:41 ` [PATCH 12/17] perf session: Add process callback to reader object Jiri Olsa
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

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.

Link: http://lkml.kernel.org/n/tip-6l53s3oabwr1r4n6wke21d8g@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-record.c |  2 ++
 tools/perf/util/data.c      | 10 +++++++--
 tools/perf/util/data.h      |  1 +
 tools/perf/util/header.c    | 44 ++++++++++++++++++++++++++++++++++++-
 tools/perf/util/header.h    |  5 +++++
 5 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e983c8d71a79..a468d882e74f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -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);
 }
 
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 5681a25aea88..dbbbb258497e 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -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;
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index d342469bdfda..6aef8746469f 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -24,6 +24,7 @@ struct perf_data {
 	enum perf_data_mode	 mode;
 
 	struct {
+		u64			 version;
 		struct perf_data_file	*files;
 		int			 nr;
 	} dir;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a2323d777dae..4adfbcdc551a 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -867,6 +867,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;
@@ -1347,6 +1362,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;
@@ -2379,6 +2405,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);
@@ -2438,7 +2479,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 {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 0d553ddca0a3..6a231340238d 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -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;
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 12/17] perf session: Add process callback to reader object
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (10 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 11/17] perf header: Add DIR_FORMAT feature to describe directory data Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21  9:41 ` [PATCH 13/17] perf session: Add __perf_session__process_dir_events function Jiri Olsa
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Adding callback function to reader object so
callers can process data in different ways.

Link: http://lkml.kernel.org/n/tip-8g1islzz6xkl36tz0z1nkuff@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/session.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 9991e9a8bc12..90cec49903b9 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1849,10 +1849,17 @@ fetch_mmaped_event(struct perf_session *session,
 #define NUM_MMAPS 128
 #endif
 
+struct reader;
+
+typedef s64 (*reader_cb_t)(struct perf_session *session,
+			   union perf_event *event,
+			   u64 file_offset);
+
 struct reader {
-	int	fd;
-	u64	data_size;
-	u64	data_offset;
+	int		 fd;
+	u64		 data_size;
+	u64		 data_offset;
+	reader_cb_t	 process;
 };
 
 static int
@@ -1923,7 +1930,7 @@ reader__process_events(struct reader *rd, struct perf_session *session,
 	size = event->header.size;
 
 	if (size < sizeof(struct perf_event_header) ||
-	    (skip = perf_session__process_event(session, event, file_pos)) < 0) {
+	    (skip = rd->process(session, event, file_pos)) < 0) {
 		pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
 		       file_offset + head, event->header.size,
 		       event->header.type);
@@ -1949,12 +1956,20 @@ reader__process_events(struct reader *rd, struct perf_session *session,
 	return err;
 }
 
+static s64 process_simple(struct perf_session *session,
+			  union perf_event *event,
+			  u64 file_offset)
+{
+	return perf_session__process_event(session, event, file_offset);
+}
+
 static int __perf_session__process_events(struct perf_session *session)
 {
 	struct reader rd = {
 		.fd		= perf_data__fd(session->data),
 		.data_size	= session->header.data_size,
 		.data_offset	= session->header.data_offset,
+		.process	= process_simple,
 	};
 	struct ordered_events *oe = &session->ordered_events;
 	struct perf_tool *tool = session->tool;
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 13/17] perf session: Add __perf_session__process_dir_events function
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (11 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 12/17] perf session: Add process callback to reader object Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21  9:41 ` [PATCH 14/17] perf session: Add path to reader object Jiri Olsa
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Adding __perf_session__process_dir_events function
to process events over the directory data.

All directory events are pushed into sessions ordered
data and flushed for processing.

Link: http://lkml.kernel.org/n/tip-n3zl0wo3z18tatv5x7epmjrh@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/session.c | 88 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 86 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 90cec49903b9..1f183bd1a208 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1878,8 +1878,6 @@ reader__process_events(struct reader *rd, struct perf_session *session,
 	file_offset = page_offset;
 	head = rd->data_offset - page_offset;
 
-	ui_progress__init_size(prog, data_size, "Processing events...");
-
 	data_size += rd->data_offset;
 
 	mmap_size = MMAP_SIZE;
@@ -2008,6 +2006,89 @@ static int __perf_session__process_events(struct perf_session *session)
 	return err;
 }
 
+static s64 process_index(struct perf_session *session,
+			 union perf_event *event,
+			 u64 file_offset)
+{
+	struct perf_evlist *evlist = session->evlist;
+	u64 timestamp;
+	s64 ret;
+
+	if (session->header.needs_swap)
+		event_swap(event, perf_evlist__sample_id_all(evlist));
+
+	if (event->header.type >= PERF_RECORD_HEADER_MAX)
+		return -EINVAL;
+
+	events_stats__inc(&evlist->stats, event->header.type);
+
+	if (event->header.type >= PERF_RECORD_USER_TYPE_START)
+		return perf_session__process_user_event(session, event, file_offset);
+
+	ret = perf_evlist__parse_sample_timestamp(evlist, event, &timestamp);
+	if (ret)
+		return ret;
+
+	return ordered_events__queue(&session->ordered_events, event,
+				     timestamp, file_offset);
+}
+
+static int __perf_session__process_dir_events(struct perf_session *session)
+{
+	struct perf_data *data = session->data;
+	struct perf_tool *tool = session->tool;
+	struct reader rd = {
+		.fd		= perf_data__fd(session->data),
+		.data_size	= session->header.data_size,
+		.data_offset	= session->header.data_offset,
+		.process	= process_simple,
+	};
+	int i, ret = 0;
+	struct ui_progress prog;
+	u64 total_size = perf_data__size(session->data);
+
+	perf_tool__fill_defaults(tool);
+
+	ui_progress__init_size(&prog, total_size, "Processing events...");
+
+	/* Read data from the header file.. */
+	ret = reader__process_events(&rd, session, &prog);
+	if (ret)
+		goto out_err;
+
+	/* ... and continue with data files. */
+	for (i = 0; i < data->dir.nr ; i++) {
+		struct perf_data_file *file = &data->dir.files[i];
+
+		if (file->size == 0)
+			continue;
+
+		rd = (struct reader) {
+			.fd		= file->fd,
+			.data_size	= file->size,
+			.data_offset	= 0,
+			.process	= process_index,
+		};
+
+		ret = reader__process_events(&rd, session, &prog);
+		if (ret)
+			goto out_err;
+	}
+
+	ret = ordered_events__flush(&session->ordered_events, OE_FLUSH__FINAL);
+
+out_err:
+	if (!tool->no_warn)
+		perf_session__warn_about_errors(session);
+
+	/*
+	 * We may switching perf.data output, make ordered_events
+	 * reusable.
+	 */
+	ordered_events__reinit(&session->ordered_events);
+	return ret;
+}
+
 int perf_session__process_events(struct perf_session *session)
 {
 	if (perf_session__register_idle_thread(session) < 0)
@@ -2016,6 +2097,9 @@ int perf_session__process_events(struct perf_session *session)
 	if (perf_data__is_pipe(session->data))
 		return __perf_session__process_pipe_events(session);
 
+	if (perf_data__is_dir(session->data))
+		return __perf_session__process_dir_events(session);
+
 	return __perf_session__process_events(session);
 }
 
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 14/17] perf session: Add path to reader object
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (12 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 13/17] perf session: Add __perf_session__process_dir_events function Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21  9:41 ` [PATCH 15/17] perf record: Add --dir option to store data in directory Jiri Olsa
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Adding path to reader object, so we can display file
the processing fails for (string in [] brackets).

  $ perf report --stdio
  0x5e0 [perf.data/data.3] [0xa200]: failed to process type: -1577027574

Link: http://lkml.kernel.org/n/tip-4bjnoy4sln7adqtd3505q29q@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/session.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 1f183bd1a208..c2bc0c58112a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1860,6 +1860,7 @@ struct reader {
 	u64		 data_size;
 	u64		 data_offset;
 	reader_cb_t	 process;
+	char		*path;
 };
 
 static int
@@ -1874,6 +1875,8 @@ reader__process_events(struct reader *rd, struct perf_session *session,
 	union perf_event *event;
 	s64 skip;
 
+	pr_debug("reader processing %s\n", rd->path);
+
 	page_offset = page_size * (rd->data_offset / page_size);
 	file_offset = page_offset;
 	head = rd->data_offset - page_offset;
@@ -1929,8 +1932,8 @@ reader__process_events(struct reader *rd, struct perf_session *session,
 
 	if (size < sizeof(struct perf_event_header) ||
 	    (skip = rd->process(session, event, file_pos)) < 0) {
-		pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
-		       file_offset + head, event->header.size,
+		pr_err("%#" PRIx64 " [%s] [%#x]: failed to process type: %d\n",
+		       file_offset + head, rd->path, event->header.size,
 		       event->header.type);
 		err = -EINVAL;
 		goto out;
@@ -1968,6 +1971,7 @@ static int __perf_session__process_events(struct perf_session *session)
 		.data_size	= session->header.data_size,
 		.data_offset	= session->header.data_offset,
 		.process	= process_simple,
+		.path		= session->data->file.path,
 	};
 	struct ordered_events *oe = &session->ordered_events;
 	struct perf_tool *tool = session->tool;
@@ -2042,6 +2046,7 @@ static int __perf_session__process_dir_events(struct perf_session *session)
 		.data_size	= session->header.data_size,
 		.data_offset	= session->header.data_offset,
 		.process	= process_simple,
+		.path		= session->data->file.path,
 	};
 	int i, ret = 0;
 	struct ui_progress prog;
@@ -2068,6 +2073,7 @@ static int __perf_session__process_dir_events(struct perf_session *session)
 			.data_size	= file->size,
 			.data_offset	= 0,
 			.process	= process_index,
+			.path		= file->path,
 		};
 
 		ret = reader__process_events(&rd, session, &prog);
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 15/17] perf record: Add --dir option to store data in directory
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (13 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 14/17] perf session: Add path to reader object Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21  9:41 ` [PATCH 16/17] perf record: Add --output-dir " Jiri Olsa
  2019-02-21  9:41 ` [PATCH 17/17] perf record: Describe perf.data directory format Jiri Olsa
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Adding --dir option to store data in directory. It's next
step for multiple threads in record. It's now possible to
make directory data via --dir option, like:

  $ perf record --dir perf bench sched messaging
  $ ls -l perf.data
  total 344
  -rw-------. 1 jolsa jolsa 43864 Jan 20 22:26 data.0
  -rw-------. 1 jolsa jolsa 30464 Jan 20 22:26 data.1
  -rw-------. 1 jolsa jolsa 53816 Jan 20 22:26 data.2
  -rw-------. 1 jolsa jolsa 30368 Jan 20 22:26 data.3
  -rw-------. 1 jolsa jolsa 40088 Jan 20 22:26 data.4
  -rw-------. 1 jolsa jolsa 42592 Jan 20 22:26 data.5
  -rw-------. 1 jolsa jolsa 56136 Jan 20 22:26 data.6
  -rw-------. 1 jolsa jolsa 25992 Jan 20 22:26 data.7
  -rw-------. 1 jolsa jolsa  8832 Jan 20 22:26 header

There's a data file created for every cpu and it's storing
data for those cpu maps.

It's possible to transform directory data into standard
perf.data file via following inject command:

  $ perf inject -o perf.data.file -i perf.data

The --dir option enabled DIR_FORMAT feature to be stored
in header file to indicate the directory layout.

Don't allow to use --dir with --aio yet. It needs
to be investigated first.

Link: http://lkml.kernel.org/n/tip-0kjm8wpglzu2tm18tpagfm4d@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/Documentation/perf-record.txt |  3 +
 tools/perf/builtin-record.c              | 80 ++++++++++++++++++++++--
 tools/perf/util/mmap.h                   | 23 +++----
 3 files changed, 90 insertions(+), 16 deletions(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 8f0c2be34848..445b7a4eb130 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -524,6 +524,9 @@ config terms. For example: 'cycles/overwrite/' and 'instructions/no-overwrite/'.
 
 Implies --tail-synthesize.
 
+--dir::
+Store data into directory with one data file for cpu.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a468d882e74f..26981be13aa0 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -112,10 +112,13 @@ static bool switch_output_time(struct record *rec)
 	       trigger_is_ready(&switch_output_trigger);
 }
 
-static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused,
+static int record__write(struct record *rec, struct perf_mmap *map,
 			 void *bf, size_t size)
 {
-	struct perf_data_file *file = &rec->session->data->file;
+	struct perf_data_file *file = &rec->data.file;
+
+	if (map && map->file)
+		file = map->file;
 
 	if (perf_data_file__write(file, bf, size) < 0) {
 		pr_err("failed to write perf data, error: %m\n");
@@ -124,6 +127,15 @@ static int record__write(struct record *rec, struct perf_mmap *map __maybe_unuse
 
 	rec->bytes_written += size;
 
+	/*
+	 * Update header file size manualy, data files size are
+	 * ok to be updated by stat command, but header files
+	 * contains more stuff, so we need to track data size
+	 * manualy.
+	 */
+	if (file == &rec->data.file)
+		rec->session->header.data_size += size;
+
 	if (switch_output_size(rec))
 		trigger_hit(&switch_output_trigger);
 
@@ -247,6 +259,7 @@ static int record__aio_pushfn(void *to, struct aiocb *cblock, void *bf, size_t s
 	ret = record__aio_write(cblock, trace_fd, bf, size, off);
 	if (!ret) {
 		rec->bytes_written += size;
+		rec->session->header.data_size += size;
 		if (switch_output_size(rec))
 			trigger_hit(&switch_output_trigger);
 	}
@@ -564,6 +577,25 @@ static int record__mmap_evlist(struct record *rec,
 	return 0;
 }
 
+static int record__mmap_dir_data(struct record *rec)
+{
+	struct perf_evlist *evlist = rec->evlist;
+	struct perf_data *data = &rec->data;
+	int i, ret, nr = evlist->nr_mmaps;
+
+	ret = perf_data__create_dir(data, nr);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < nr; i++) {
+		struct perf_mmap *map = &evlist->mmap[i];
+
+		map->file = &data->dir.files[i];
+	}
+
+	return 0;
+}
+
 static int record__mmap(struct record *rec)
 {
 	return record__mmap_evlist(rec, rec->evlist);
@@ -793,8 +825,12 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
 	/*
 	 * Mark the round finished in case we wrote
 	 * at least one event.
+	 *
+	 * No need for round events in directory mode,
+	 * because per-cpu files/maps have sorted data
+	 * from kernel.
 	 */
-	if (bytes_written != rec->bytes_written)
+	if (!perf_data__is_dir(&rec->data) && bytes_written != rec->bytes_written)
 		rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
 
 	if (overwrite)
@@ -837,7 +873,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);
+	if (!perf_data__is_dir(session->data))
+		perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);
 
 	perf_header__clear_feat(&session->header, HEADER_STAT);
 }
@@ -851,9 +888,11 @@ record__finish_output(struct record *rec)
 	if (data->is_pipe)
 		return;
 
-	rec->session->header.data_size += rec->bytes_written;
 	data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR);
 
+	if (perf_data__is_dir(data))
+		perf_data__update_dir(data);
+
 	if (!rec->no_buildid) {
 		process_buildids(rec);
 
@@ -924,6 +963,12 @@ record__switch_output(struct record *rec, bool at_exit)
 
 	/* Output tracking events */
 	if (!at_exit) {
+		if (perf_data__is_dir(data)) {
+			err = record__mmap_dir_data(rec);
+			if (err)
+				return -1;
+		}
+
 		record__synthesize(rec, false);
 
 		/*
@@ -1173,11 +1218,23 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 	if (data->is_pipe && rec->evlist->nr_entries == 1)
 		rec->opts.sample_id = true;
 
+	if (data->is_pipe && perf_data__is_dir(data)) {
+		pr_err("Directory output is not allowed for pipe output\n");
+		err = -1;
+		goto out_child;
+	}
+
 	if (record__open(rec) != 0) {
 		err = -1;
 		goto out_child;
 	}
 
+	if (perf_data__is_dir(data)) {
+		err = record__mmap_dir_data(rec);
+		if (err)
+			goto out_child;
+	}
+
 	err = bpf__apply_obj_config();
 	if (err) {
 		char errbuf[BUFSIZ];
@@ -1983,6 +2040,8 @@ static struct option __record_options[] = {
 	OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu",
 		     "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer",
 		     record__parse_affinity),
+	OPT_BOOLEAN(0, "dir", &record.data.is_dir,
+		    "Store data into directory perf.data"),
 	OPT_END()
 };
 
@@ -2134,6 +2193,17 @@ int cmd_record(int argc, const char **argv)
 		goto out;
 	}
 
+	if (perf_data__is_dir(&rec->data)) {
+		if (!rec->opts.sample_time) {
+			pr_err("Sample timestamp is required for indexing\n");
+			goto out;
+		}
+		if (record__aio_enabled(rec)) {
+			pr_err("Cannot use both --dir and --aio yet.\n");
+			goto out;
+		}
+	}
+
 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
 		rec->opts.no_inherit = true;
 
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index e566c19b242b..3e8595a8d6ce 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -19,17 +19,18 @@ struct aiocb;
  * @refcnt - e.g. code using PERF_EVENT_IOC_SET_OUTPUT to share this
  */
 struct perf_mmap {
-	void		 *base;
-	int		 mask;
-	int		 fd;
-	int		 cpu;
-	refcount_t	 refcnt;
-	u64		 prev;
-	u64		 start;
-	u64		 end;
-	bool		 overwrite;
-	struct auxtrace_mmap auxtrace_mmap;
-	char		 event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8);
+	void			 *base;
+	int			 mask;
+	int			 fd;
+	int			 cpu;
+	refcount_t		 refcnt;
+	u64			 prev;
+	u64			 start;
+	u64			 end;
+	bool			 overwrite;
+	struct auxtrace_mmap	 auxtrace_mmap;
+	struct perf_data_file	*file;
+	char			 event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8);
 #ifdef HAVE_AIO_SUPPORT
 	struct {
 		void		 **data;
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 16/17] perf record: Add --output-dir option to store data in directory
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (14 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 15/17] perf record: Add --dir option to store data in directory Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  2019-02-21  9:41 ` [PATCH 17/17] perf record: Describe perf.data directory format Jiri Olsa
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Adding --output-dir option to mimic -o and --dir options.
following commands do the same:

  $ perf record -o perf.dir.data --dir ...
  $ perf record --output-dir perf.dir.data ...

User cannot use both -o and output-dir together,
error is displayed.

Link: http://lkml.kernel.org/n/tip-76ldd2ss6vjvlnjgwy7wxfzt@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/lib/subcmd/parse-options.h         |  4 ++++
 tools/perf/Documentation/perf-record.txt |  3 +++
 tools/perf/builtin-record.c              | 13 +++++++++++--
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h
index af9def589863..8a3be77a3346 100644
--- a/tools/lib/subcmd/parse-options.h
+++ b/tools/lib/subcmd/parse-options.h
@@ -146,6 +146,10 @@ struct option {
 	  .value = check_vtype(v, const char **), .argh = (a), .help = (h), \
 	  .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d), \
 	  .set = check_vtype(os, bool *)}
+#define OPT_STRING_SET(s, l, v, os, a, h) \
+	{ .type = OPTION_STRING, .short_name = (s), .long_name = (l), \
+	  .value = check_vtype(v, const char **), .argh = (a), .help = (h), \
+	  .set = check_vtype(os, bool *)}
 #define OPT_STRING_NOEMPTY(s, l, v, a, h)   { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), .argh = (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
 #define OPT_DATE(s, l, v, h) \
 	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 445b7a4eb130..aac609887fb7 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -527,6 +527,9 @@ Implies --tail-synthesize.
 --dir::
 Store data into directory with one data file for cpu.
 
+--output-dir::
+Same as --dir option, can't be used together with -o option.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 26981be13aa0..115316e94b34 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -80,6 +80,7 @@ struct record {
 	bool			buildid_all;
 	bool			timestamp_filename;
 	bool			timestamp_boundary;
+	bool			output_is_file;
 	struct switch_output	switch_output;
 	unsigned long long	samples;
 	cpu_set_t		affinity_mask;
@@ -1921,8 +1922,10 @@ static struct option __record_options[] = {
 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
 		    "list of cpus to monitor"),
 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
-	OPT_STRING('o', "output", &record.data.path, "file",
-		    "output file name"),
+	OPT_STRING_SET('o', "output", &record.data.path, &record.output_is_file,
+		       "file", "output file name"),
+	OPT_STRING_SET(0, "output-dir", &record.data.path, &record.data.is_dir,
+		       "file", "output directory name"),
 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
 			&record.opts.no_inherit_set,
 			"child tasks do not inherit counters"),
@@ -2101,6 +2104,12 @@ int cmd_record(int argc, const char **argv)
 			"cgroup monitoring only available in system-wide mode");
 
 	}
+
+	if (perf_data__is_dir(&rec->data) && record.output_is_file) {
+		ui__error("cannot use both -o and --output-dir\n");
+		return -EINVAL;
+	}
+
 	if (rec->opts.record_switch_events &&
 	    !perf_can_record_switch_events()) {
 		ui__error("kernel does not support recording context switch events\n");
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 17/17] perf record: Describe perf.data directory format
  2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
                   ` (15 preceding siblings ...)
  2019-02-21  9:41 ` [PATCH 16/17] perf record: Add --output-dir " Jiri Olsa
@ 2019-02-21  9:41 ` Jiri Olsa
  16 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-21  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Adding perf.data-directory-format.txt to describe the
directory data layout.

Link: http://lkml.kernel.org/n/tip-1c8u1thx63v2ldwfdas4xc5d@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 .../perf.data-directory-format.txt            | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 tools/perf/Documentation/perf.data-directory-format.txt

diff --git a/tools/perf/Documentation/perf.data-directory-format.txt b/tools/perf/Documentation/perf.data-directory-format.txt
new file mode 100644
index 000000000000..bbd6d31b10c8
--- /dev/null
+++ b/tools/perf/Documentation/perf.data-directory-format.txt
@@ -0,0 +1,54 @@
+perf.data directory format
+
+DISCLAIMER This is not ABI yet and is subject to possible change
+           in following versions of perf. We will remove this
+           disclaimer once the directory format soaks in.
+
+
+This document describes the on-disk perf.data format, generated
+by perf record with --dir option and consumed by the other perf
+tools.
+
+The directory perf.data is created by perf record command by
+using the --dir option:
+
+  $ perf record --dir perf bench sched messaging
+  $ ls -l perf.data
+      total 344
+      -rw-------. 1 jolsa jolsa 43864 Jan 20 22:26 data.0
+      -rw-------. 1 jolsa jolsa 30464 Jan 20 22:26 data.1
+      -rw-------. 1 jolsa jolsa 53816 Jan 20 22:26 data.2
+      -rw-------. 1 jolsa jolsa 30368 Jan 20 22:26 data.3
+      -rw-------. 1 jolsa jolsa 40088 Jan 20 22:26 data.4
+      -rw-------. 1 jolsa jolsa 42592 Jan 20 22:26 data.5
+      -rw-------. 1 jolsa jolsa 56136 Jan 20 22:26 data.6
+      -rw-------. 1 jolsa jolsa 25992 Jan 20 22:26 data.7
+      -rw-------. 1 jolsa jolsa  8832 Jan 20 22:26 header
+
+The header file keeps the standard perf.data file header,
+and the data.* files keep data.
+
+header file
+-----------
+The header file following the standard format describe in
+Documentation/perf.data-file-format doc. Including its data
+portion that is used to store manually synthesized events.
+
+data file
+---------
+The data files layout is described by HEADER_DIR_FORMAT feature.
+Currently it holds only version number (1):
+
+  HEADER_DIR_FORMAT = 24
+
+  struct {
+     uint64_t version;
+  }
+
+The current only only version value 1 means that data files:
+  - follow the 'data.*' 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.
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 04/17] perf data: Fail check_backup in case of error
  2019-02-21  9:41 ` [PATCH 04/17] perf data: Fail check_backup in case of error Jiri Olsa
@ 2019-02-21 22:23   ` Andi Kleen
  2019-02-22 12:23     ` Jiri Olsa
  0 siblings, 1 reply; 26+ messages in thread
From: Andi Kleen @ 2019-02-21 22:23 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Arnaldo Carvalho de Melo, lkml, Ingo Molnar, Namhyung Kim,
	Alexander Shishkin, Peter Zijlstra, Adrian Hunter,
	Stephane Eranian, Alexey Budankov

On Thu, Feb 21, 2019 at 10:41:32AM +0100, Jiri Olsa wrote:
> And display the error message from removing
> the old data file:
> 
>   $ perf record ls
>   Can't remove old data: Permission denied (perf.data.old)
>   Perf session creation failed.
> 
> Not sure how to make fail the rename (after we successfully
> remove the destination file/dir) to show the message,
> anyway let's have it there.

The use of rm_rf is really scary. So I simple command line typo could turn
this into rm -rf / ? 

Please add some sanity checks to not remove multiple levels,
and only remove files which look like they are generated
by perf.

-Andi

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 04/17] perf data: Fail check_backup in case of error
  2019-02-21 22:23   ` Andi Kleen
@ 2019-02-22 12:23     ` Jiri Olsa
  0 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-22 12:23 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, lkml, Ingo Molnar,
	Namhyung Kim, Alexander Shishkin, Peter Zijlstra, Adrian Hunter,
	Stephane Eranian, Alexey Budankov

On Thu, Feb 21, 2019 at 02:23:30PM -0800, Andi Kleen wrote:
> On Thu, Feb 21, 2019 at 10:41:32AM +0100, Jiri Olsa wrote:
> > And display the error message from removing
> > the old data file:
> > 
> >   $ perf record ls
> >   Can't remove old data: Permission denied (perf.data.old)
> >   Perf session creation failed.
> > 
> > Not sure how to make fail the rename (after we successfully
> > remove the destination file/dir) to show the message,
> > anyway let's have it there.
> 
> The use of rm_rf is really scary. So I simple command line typo could turn
> this into rm -rf / ? 
> 
> Please add some sanity checks to not remove multiple levels,
> and only remove files which look like they are generated
> by perf.

right, will do

jirka

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 02/17] perf data: Add global path holder
  2019-02-21  9:41 ` [PATCH 02/17] perf data: Add global path holder Jiri Olsa
@ 2019-02-22 16:05   ` Arnaldo Carvalho de Melo
  2019-02-22 16:07     ` Arnaldo Carvalho de Melo
  2019-02-28  7:59   ` [tip:perf/core] " tip-bot for Jiri Olsa
  1 sibling, 1 reply; 26+ messages in thread
From: Arnaldo Carvalho de Melo @ 2019-02-22 16:05 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Em Thu, Feb 21, 2019 at 10:41:30AM +0100, Jiri Olsa escreveu:
> Adding path to the struct perf_data. It will keep the
> configured path for the data (const char*). The path
> in struct perf_data_file is now dynamically allocated
> (duped) from it.
> 
> This scheme is useful/used in following patches where
> struct perf_data::path holds the 'configure' directory
> path and struct perf_data_file::path holds the allocated
> path for specific files.

  CC       /tmp/build/perf/util/jitdump.o
util/data-convert-bt.c: In function ‘bt_convert__perf2ctf’:
util/data-convert-bt.c:1581:26: error: initialization discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
   .file      = { .path = input, .fd = -1 },
                          ^~~~~
cc1: all warnings being treated as errors

Trying to fix now
 
> Also it actually makes the code little simpler.
> 
> Link: http://lkml.kernel.org/n/tip-ww4tdzfaub4vlv9xxkxvwx9q@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/builtin-annotate.c      |  4 +--
>  tools/perf/builtin-buildid-cache.c |  4 +--
>  tools/perf/builtin-buildid-list.c  |  8 +++---
>  tools/perf/builtin-c2c.c           |  4 +--
>  tools/perf/builtin-diff.c          | 12 ++++-----
>  tools/perf/builtin-evlist.c        |  4 +--
>  tools/perf/builtin-inject.c        | 10 +++-----
>  tools/perf/builtin-kmem.c          |  2 +-
>  tools/perf/builtin-kvm.c           |  8 +++---
>  tools/perf/builtin-lock.c          |  8 +++---
>  tools/perf/builtin-mem.c           |  8 +++---
>  tools/perf/builtin-record.c        |  6 ++---
>  tools/perf/builtin-report.c        |  6 ++---
>  tools/perf/builtin-sched.c         | 16 +++++-------
>  tools/perf/builtin-script.c        | 12 ++++-----
>  tools/perf/builtin-stat.c          |  6 ++---
>  tools/perf/builtin-timechart.c     |  8 +++---
>  tools/perf/builtin-trace.c         |  8 +++---
>  tools/perf/util/data-convert-bt.c  |  2 +-
>  tools/perf/util/data.c             | 39 +++++++++++++++++++++---------
>  tools/perf/util/data.h             |  3 ++-
>  21 files changed, 86 insertions(+), 92 deletions(-)
> 
> diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
> index 7f3c3fea67b4..67f9d9ffacfb 100644
> --- a/tools/perf/builtin-annotate.c
> +++ b/tools/perf/builtin-annotate.c
> @@ -441,7 +441,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
>  	}
>  
>  	if (total_nr_samples == 0) {
> -		ui__error("The %s file has no samples!\n", session->data->file.path);
> +		ui__error("The %s data has no samples!\n", session->data->path);
>  		goto out;
>  	}
>  
> @@ -578,7 +578,7 @@ int cmd_annotate(int argc, const char **argv)
>  	if (quiet)
>  		perf_quiet_option();
>  
> -	data.file.path = input_name;
> +	data.path = input_name;
>  
>  	annotate.session = perf_session__new(&data, false, &annotate.tool);
>  	if (annotate.session == NULL)
> diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
> index 115110a4796a..10457b10e568 100644
> --- a/tools/perf/builtin-buildid-cache.c
> +++ b/tools/perf/builtin-buildid-cache.c
> @@ -416,8 +416,8 @@ int cmd_buildid_cache(int argc, const char **argv)
>  		nsi = nsinfo__new(ns_id);
>  
>  	if (missing_filename) {
> -		data.file.path = missing_filename;
> -		data.force     = force;
> +		data.path  = missing_filename;
> +		data.force = force;
>  
>  		session = perf_session__new(&data, false, NULL);
>  		if (session == NULL)
> diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
> index 78abbe8d9d5f..f403e19488b5 100644
> --- a/tools/perf/builtin-buildid-list.c
> +++ b/tools/perf/builtin-buildid-list.c
> @@ -52,11 +52,9 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
>  {
>  	struct perf_session *session;
>  	struct perf_data data = {
> -		.file      = {
> -			.path = input_name,
> -		},
> -		.mode      = PERF_DATA_MODE_READ,
> -		.force     = force,
> +		.path  = input_name,
> +		.mode  = PERF_DATA_MODE_READ,
> +		.force = force,
>  	};
>  
>  	symbol__elf_init();
> diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
> index efaaab23c6fd..4272763a5e96 100644
> --- a/tools/perf/builtin-c2c.c
> +++ b/tools/perf/builtin-c2c.c
> @@ -2750,8 +2750,8 @@ static int perf_c2c__report(int argc, const char **argv)
>  	if (!input_name || !strlen(input_name))
>  		input_name = "perf.data";
>  
> -	data.file.path = input_name;
> -	data.force     = symbol_conf.force;
> +	data.path  = input_name;
> +	data.force = symbol_conf.force;
>  
>  	err = setup_display(display);
>  	if (err)
> diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
> index 751e1971456b..58fe0e88215c 100644
> --- a/tools/perf/builtin-diff.c
> +++ b/tools/perf/builtin-diff.c
> @@ -708,7 +708,7 @@ static void data__fprintf(void)
>  
>  	data__for_each_file(i, d)
>  		fprintf(stdout, "#  [%d] %s %s\n",
> -			d->idx, d->data.file.path,
> +			d->idx, d->data.path,
>  			!d->idx ? "(Baseline)" : "");
>  
>  	fprintf(stdout, "#\n");
> @@ -779,14 +779,14 @@ static int __cmd_diff(void)
>  	data__for_each_file(i, d) {
>  		d->session = perf_session__new(&d->data, false, &tool);
>  		if (!d->session) {
> -			pr_err("Failed to open %s\n", d->data.file.path);
> +			pr_err("Failed to open %s\n", d->data.path);
>  			ret = -1;
>  			goto out_delete;
>  		}
>  
>  		ret = perf_session__process_events(d->session);
>  		if (ret) {
> -			pr_err("Failed to process %s\n", d->data.file.path);
> +			pr_err("Failed to process %s\n", d->data.path);
>  			goto out_delete;
>  		}
>  
> @@ -1289,9 +1289,9 @@ static int data_init(int argc, const char **argv)
>  	data__for_each_file(i, d) {
>  		struct perf_data *data = &d->data;
>  
> -		data->file.path = use_default ? defaults[i] : argv[i];
> -		data->mode      = PERF_DATA_MODE_READ,
> -		data->force     = force,
> +		data->path  = use_default ? defaults[i] : argv[i];
> +		data->mode  = PERF_DATA_MODE_READ,
> +		data->force = force,
>  
>  		d->idx  = i;
>  	}
> diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
> index e06e822ce634..6e4f63b0da4a 100644
> --- a/tools/perf/builtin-evlist.c
> +++ b/tools/perf/builtin-evlist.c
> @@ -23,9 +23,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
>  	struct perf_session *session;
>  	struct perf_evsel *pos;
>  	struct perf_data data = {
> -		.file      = {
> -			.path = file_name,
> -		},
> +		.path      = file_name,
>  		.mode      = PERF_DATA_MODE_READ,
>  		.force     = details->force,
>  	};
> diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
> index 9bb1f35d5cb7..24086b7f1b14 100644
> --- a/tools/perf/builtin-inject.c
> +++ b/tools/perf/builtin-inject.c
> @@ -770,10 +770,8 @@ int cmd_inject(int argc, const char **argv)
>  		.input_name  = "-",
>  		.samples = LIST_HEAD_INIT(inject.samples),
>  		.output = {
> -			.file      = {
> -				.path = "-",
> -			},
> -			.mode      = PERF_DATA_MODE_WRITE,
> +			.path = "-",
> +			.mode = PERF_DATA_MODE_WRITE,
>  		},
>  	};
>  	struct perf_data data = {
> @@ -786,7 +784,7 @@ int cmd_inject(int argc, const char **argv)
>  			    "Inject build-ids into the output stream"),
>  		OPT_STRING('i', "input", &inject.input_name, "file",
>  			   "input file name"),
> -		OPT_STRING('o', "output", &inject.output.file.path, "file",
> +		OPT_STRING('o', "output", &inject.output.path, "file",
>  			   "output file name"),
>  		OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
>  			    "Merge sched-stat and sched-switch for getting events "
> @@ -834,7 +832,7 @@ int cmd_inject(int argc, const char **argv)
>  
>  	inject.tool.ordered_events = inject.sched_stat;
>  
> -	data.file.path = inject.input_name;
> +	data.path = inject.input_name;
>  	inject.session = perf_session__new(&data, true, &inject.tool);
>  	if (inject.session == NULL)
>  		return -1;
> diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
> index b80ec0883537..fa520f4b8095 100644
> --- a/tools/perf/builtin-kmem.c
> +++ b/tools/perf/builtin-kmem.c
> @@ -1949,7 +1949,7 @@ int cmd_kmem(int argc, const char **argv)
>  		return __cmd_record(argc, argv);
>  	}
>  
> -	data.file.path = input_name;
> +	data.path = input_name;
>  
>  	kmem_session = session = perf_session__new(&data, false, &perf_kmem);
>  	if (session == NULL)
> diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
> index 3d4cbc4e87c7..dbb6f737a3e2 100644
> --- a/tools/perf/builtin-kvm.c
> +++ b/tools/perf/builtin-kvm.c
> @@ -1080,11 +1080,9 @@ static int read_events(struct perf_kvm_stat *kvm)
>  		.ordered_events		= true,
>  	};
>  	struct perf_data file = {
> -		.file      = {
> -			.path = kvm->file_name,
> -		},
> -		.mode      = PERF_DATA_MODE_READ,
> -		.force     = kvm->force,
> +		.path  = kvm->file_name,
> +		.mode  = PERF_DATA_MODE_READ,
> +		.force = kvm->force,
>  	};
>  
>  	kvm->tool = eops;
> diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
> index 6e0189df2b3b..b9810a8d350a 100644
> --- a/tools/perf/builtin-lock.c
> +++ b/tools/perf/builtin-lock.c
> @@ -866,11 +866,9 @@ static int __cmd_report(bool display_info)
>  		.ordered_events	 = true,
>  	};
>  	struct perf_data data = {
> -		.file      = {
> -			.path = input_name,
> -		},
> -		.mode      = PERF_DATA_MODE_READ,
> -		.force     = force,
> +		.path  = input_name,
> +		.mode  = PERF_DATA_MODE_READ,
> +		.force = force,
>  	};
>  
>  	session = perf_session__new(&data, false, &eops);
> diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
> index ba7e8d87dec3..f45c8b502f63 100644
> --- a/tools/perf/builtin-mem.c
> +++ b/tools/perf/builtin-mem.c
> @@ -239,11 +239,9 @@ static int process_sample_event(struct perf_tool *tool,
>  static int report_raw_events(struct perf_mem *mem)
>  {
>  	struct perf_data data = {
> -		.file      = {
> -			.path = input_name,
> -		},
> -		.mode      = PERF_DATA_MODE_READ,
> -		.force     = mem->force,
> +		.path  = input_name,
> +		.mode  = PERF_DATA_MODE_READ,
> +		.force = mem->force,
>  	};
>  	int ret;
>  	struct perf_session *session = perf_session__new(&data, false,
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index e5e9900c9039..f3f7f3100336 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -918,7 +918,7 @@ record__switch_output(struct record *rec, bool at_exit)
>  
>  	if (!quiet)
>  		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
> -			data->file.path, timestamp);
> +			data->path, timestamp);
>  
>  	/* Output tracking events */
>  	if (!at_exit) {
> @@ -1461,7 +1461,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
>  
>  		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
>  			perf_data__size(data) / 1024.0 / 1024.0,
> -			data->file.path, postfix, samples);
> +			data->path, postfix, samples);
>  	}
>  
>  out_delete_session:
> @@ -1862,7 +1862,7 @@ static struct option __record_options[] = {
>  	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
>  		    "list of cpus to monitor"),
>  	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
> -	OPT_STRING('o', "output", &record.data.file.path, "file",
> +	OPT_STRING('o', "output", &record.data.path, "file",
>  		    "output file name"),
>  	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
>  			&record.opts.no_inherit_set,
> diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
> index 2e8c74d6430c..1532ebde6c4b 100644
> --- a/tools/perf/builtin-report.c
> +++ b/tools/perf/builtin-report.c
> @@ -899,7 +899,7 @@ static int __cmd_report(struct report *rep)
>  		rep->nr_entries += evsel__hists(pos)->nr_entries;
>  
>  	if (rep->nr_entries == 0) {
> -		ui__error("The %s file has no samples!\n", data->file.path);
> +		ui__error("The %s data has no samples!\n", data->path);
>  		return 0;
>  	}
>  
> @@ -1207,8 +1207,8 @@ int cmd_report(int argc, const char **argv)
>  			input_name = "perf.data";
>  	}
>  
> -	data.file.path = input_name;
> -	data.force     = symbol_conf.force;
> +	data.path  = input_name;
> +	data.force = symbol_conf.force;
>  
>  repeat:
>  	session = perf_session__new(&data, false, &report.tool);
> diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
> index 640558e9352e..275f2d92a7bf 100644
> --- a/tools/perf/builtin-sched.c
> +++ b/tools/perf/builtin-sched.c
> @@ -1785,11 +1785,9 @@ static int perf_sched__read_events(struct perf_sched *sched)
>  	};
>  	struct perf_session *session;
>  	struct perf_data data = {
> -		.file      = {
> -			.path = input_name,
> -		},
> -		.mode      = PERF_DATA_MODE_READ,
> -		.force     = sched->force,
> +		.path  = input_name,
> +		.mode  = PERF_DATA_MODE_READ,
> +		.force = sched->force,
>  	};
>  	int rc = -1;
>  
> @@ -2958,11 +2956,9 @@ static int perf_sched__timehist(struct perf_sched *sched)
>  		{ "sched:sched_migrate_task", timehist_migrate_task_event, },
>  	};
>  	struct perf_data data = {
> -		.file      = {
> -			.path = input_name,
> -		},
> -		.mode      = PERF_DATA_MODE_READ,
> -		.force     = sched->force,
> +		.path  = input_name,
> +		.mode  = PERF_DATA_MODE_READ,
> +		.force = sched->force,
>  	};
>  
>  	struct perf_session *session;
> diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
> index 373ea151dc60..5b1543f42290 100644
> --- a/tools/perf/builtin-script.c
> +++ b/tools/perf/builtin-script.c
> @@ -2951,10 +2951,8 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
>  	DIR *scripts_dir, *lang_dir;
>  	struct perf_session *session;
>  	struct perf_data data = {
> -		.file      = {
> -			.path = input_name,
> -		},
> -		.mode      = PERF_DATA_MODE_READ,
> +		.path = input_name,
> +		.mode = PERF_DATA_MODE_READ,
>  	};
>  	char *temp;
>  	int i = 0;
> @@ -3427,8 +3425,8 @@ int cmd_script(int argc, const char **argv)
>  	argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
>  			     PARSE_OPT_STOP_AT_NON_OPTION);
>  
> -	data.file.path = input_name;
> -	data.force     = symbol_conf.force;
> +	data.path  = input_name;
> +	data.force = symbol_conf.force;
>  
>  	if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
>  		rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
> @@ -3654,7 +3652,7 @@ int cmd_script(int argc, const char **argv)
>  			goto out_delete;
>  		}
>  
> -		input = open(data.file.path, O_RDONLY);	/* input_name */
> +		input = open(data.path, O_RDONLY);	/* input_name */
>  		if (input < 0) {
>  			err = -errno;
>  			perror("failed to open file");
> diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
> index bb24f9c17f9a..7b8f09b0b8bf 100644
> --- a/tools/perf/builtin-stat.c
> +++ b/tools/perf/builtin-stat.c
> @@ -1322,7 +1322,7 @@ static int __cmd_record(int argc, const char **argv)
>  			     PARSE_OPT_STOP_AT_NON_OPTION);
>  
>  	if (output_name)
> -		data->file.path = output_name;
> +		data->path = output_name;
>  
>  	if (stat_config.run_count != 1 || forever) {
>  		pr_err("Cannot use -r option with perf stat record.\n");
> @@ -1523,8 +1523,8 @@ static int __cmd_report(int argc, const char **argv)
>  			input_name = "perf.data";
>  	}
>  
> -	perf_stat.data.file.path = input_name;
> -	perf_stat.data.mode      = PERF_DATA_MODE_READ;
> +	perf_stat.data.path = input_name;
> +	perf_stat.data.mode = PERF_DATA_MODE_READ;
>  
>  	session = perf_session__new(&perf_stat.data, false, &perf_stat.tool);
>  	if (session == NULL)
> diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
> index 775b99833e51..9b98687a27b9 100644
> --- a/tools/perf/builtin-timechart.c
> +++ b/tools/perf/builtin-timechart.c
> @@ -1602,11 +1602,9 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
>  		{ "syscalls:sys_exit_select",		process_exit_poll },
>  	};
>  	struct perf_data data = {
> -		.file      = {
> -			.path = input_name,
> -		},
> -		.mode      = PERF_DATA_MODE_READ,
> -		.force     = tchart->force,
> +		.path  = input_name,
> +		.mode  = PERF_DATA_MODE_READ,
> +		.force = tchart->force,
>  	};
>  
>  	struct perf_session *session = perf_session__new(&data, false,
> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> index 1a11fe656afc..f5b3a1e9c1dd 100644
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c
> @@ -3154,11 +3154,9 @@ static int trace__replay(struct trace *trace)
>  		{ "probe:vfs_getname",	     trace__vfs_getname, },
>  	};
>  	struct perf_data data = {
> -		.file      = {
> -			.path = input_name,
> -		},
> -		.mode      = PERF_DATA_MODE_READ,
> -		.force     = trace->force,
> +		.path  = input_name,
> +		.mode  = PERF_DATA_MODE_READ,
> +		.force = trace->force,
>  	};
>  	struct perf_session *session;
>  	struct perf_evsel *evsel;
> diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
> index 2a36fab76994..ea742a254aa5 100644
> --- a/tools/perf/util/data-convert-bt.c
> +++ b/tools/perf/util/data-convert-bt.c
> @@ -1650,7 +1650,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
>  
>  	fprintf(stderr,
>  		"[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
> -		data.file.path, path);
> +		data.path, path);
>  
>  	fprintf(stderr,
>  		"[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
> diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
> index 09eceda17fc2..e16d06ed1100 100644
> --- a/tools/perf/util/data.c
> +++ b/tools/perf/util/data.c
> @@ -19,11 +19,11 @@ static bool check_pipe(struct perf_data *data)
>  	int fd = perf_data__is_read(data) ?
>  		 STDIN_FILENO : STDOUT_FILENO;
>  
> -	if (!data->file.path) {
> +	if (!data->path) {
>  		if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
>  			is_pipe = true;
>  	} else {
> -		if (!strcmp(data->file.path, "-"))
> +		if (!strcmp(data->path, "-"))
>  			is_pipe = true;
>  	}
>  
> @@ -37,13 +37,13 @@ static int check_backup(struct perf_data *data)
>  {
>  	struct stat st;
>  
> -	if (!stat(data->file.path, &st) && st.st_size) {
> +	if (!stat(data->path, &st) && st.st_size) {
>  		/* TODO check errors properly */
>  		char oldname[PATH_MAX];
>  		snprintf(oldname, sizeof(oldname), "%s.old",
> -			 data->file.path);
> +			 data->path);
>  		unlink(oldname);
> -		rename(data->file.path, oldname);
> +		rename(data->path, oldname);
>  	}
>  
>  	return 0;
> @@ -115,8 +115,22 @@ static int open_file(struct perf_data *data)
>  	fd = perf_data__is_read(data) ?
>  	     open_file_read(data) : open_file_write(data);
>  
> +	if (fd < 0) {
> +		free(data->file.path);
> +		return -1;
> +	}
> +
>  	data->file.fd = fd;
> -	return fd < 0 ? -1 : 0;
> +	return 0;
> +}
> +
> +static int open_file_dup(struct perf_data *data)
> +{
> +	data->file.path = strdup(data->path);
> +	if (!data->file.path)
> +		return -ENOMEM;
> +
> +	return open_file(data);
>  }
>  
>  int perf_data__open(struct perf_data *data)
> @@ -124,14 +138,15 @@ int perf_data__open(struct perf_data *data)
>  	if (check_pipe(data))
>  		return 0;
>  
> -	if (!data->file.path)
> -		data->file.path = "perf.data";
> +	if (!data->path)
> +		data->path = "perf.data";
>  
> -	return open_file(data);
> +	return open_file_dup(data);
>  }
>  
>  void perf_data__close(struct perf_data *data)
>  {
> +	free(data->file.path);
>  	close(data->file.fd);
>  }
>  
> @@ -159,15 +174,15 @@ int perf_data__switch(struct perf_data *data,
>  	if (perf_data__is_read(data))
>  		return -EINVAL;
>  
> -	if (asprintf(&new_filepath, "%s.%s", data->file.path, postfix) < 0)
> +	if (asprintf(&new_filepath, "%s.%s", data->path, postfix) < 0)
>  		return -ENOMEM;
>  
>  	/*
>  	 * Only fire a warning, don't return error, continue fill
>  	 * original file.
>  	 */
> -	if (rename(data->file.path, new_filepath))
> -		pr_warning("Failed to rename %s to %s\n", data->file.path, new_filepath);
> +	if (rename(data->path, new_filepath))
> +		pr_warning("Failed to rename %s to %s\n", data->path, new_filepath);
>  
>  	if (!at_exit) {
>  		close(data->file.fd);
> diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
> index 85f9c0dbf982..2bce28117ccf 100644
> --- a/tools/perf/util/data.h
> +++ b/tools/perf/util/data.h
> @@ -10,12 +10,13 @@ enum perf_data_mode {
>  };
>  
>  struct perf_data_file {
> -	const char	*path;
> +	char		*path;
>  	int		 fd;
>  	unsigned long	 size;
>  };
>  
>  struct perf_data {
> +	const char		*path;
>  	struct perf_data_file	 file;
>  	bool			 is_pipe;
>  	bool			 force;
> -- 
> 2.17.2

-- 

- Arnaldo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 02/17] perf data: Add global path holder
  2019-02-22 16:05   ` Arnaldo Carvalho de Melo
@ 2019-02-22 16:07     ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 26+ messages in thread
From: Arnaldo Carvalho de Melo @ 2019-02-22 16:07 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

Em Fri, Feb 22, 2019 at 01:05:54PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Thu, Feb 21, 2019 at 10:41:30AM +0100, Jiri Olsa escreveu:
> > Adding path to the struct perf_data. It will keep the
> > configured path for the data (const char*). The path
> > in struct perf_data_file is now dynamically allocated
> > (duped) from it.
> > 
> > This scheme is useful/used in following patches where
> > struct perf_data::path holds the 'configure' directory
> > path and struct perf_data_file::path holds the allocated
> > path for specific files.
> 
>   CC       /tmp/build/perf/util/jitdump.o
> util/data-convert-bt.c: In function ‘bt_convert__perf2ctf’:
> util/data-convert-bt.c:1581:26: error: initialization discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
>    .file      = { .path = input, .fd = -1 },
>                           ^~~~~
> cc1: all warnings being treated as errors
> 
> Trying to fix now

This did the trick

diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index ea742a254aa5..26af43ad9ddd 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -1578,7 +1578,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
 {
 	struct perf_session *session;
 	struct perf_data data = {
-		.file      = { .path = input, .fd = -1 },
+		.path	   = input,
 		.mode      = PERF_DATA_MODE_READ,
 		.force     = opts->force,
 	};
  
> > Also it actually makes the code little simpler.
> > 
> > Link: http://lkml.kernel.org/n/tip-ww4tdzfaub4vlv9xxkxvwx9q@git.kernel.org
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> >  tools/perf/builtin-annotate.c      |  4 +--
> >  tools/perf/builtin-buildid-cache.c |  4 +--
> >  tools/perf/builtin-buildid-list.c  |  8 +++---
> >  tools/perf/builtin-c2c.c           |  4 +--
> >  tools/perf/builtin-diff.c          | 12 ++++-----
> >  tools/perf/builtin-evlist.c        |  4 +--
> >  tools/perf/builtin-inject.c        | 10 +++-----
> >  tools/perf/builtin-kmem.c          |  2 +-
> >  tools/perf/builtin-kvm.c           |  8 +++---
> >  tools/perf/builtin-lock.c          |  8 +++---
> >  tools/perf/builtin-mem.c           |  8 +++---
> >  tools/perf/builtin-record.c        |  6 ++---
> >  tools/perf/builtin-report.c        |  6 ++---
> >  tools/perf/builtin-sched.c         | 16 +++++-------
> >  tools/perf/builtin-script.c        | 12 ++++-----
> >  tools/perf/builtin-stat.c          |  6 ++---
> >  tools/perf/builtin-timechart.c     |  8 +++---
> >  tools/perf/builtin-trace.c         |  8 +++---
> >  tools/perf/util/data-convert-bt.c  |  2 +-
> >  tools/perf/util/data.c             | 39 +++++++++++++++++++++---------
> >  tools/perf/util/data.h             |  3 ++-
> >  21 files changed, 86 insertions(+), 92 deletions(-)
> > 
> > diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
> > index 7f3c3fea67b4..67f9d9ffacfb 100644
> > --- a/tools/perf/builtin-annotate.c
> > +++ b/tools/perf/builtin-annotate.c
> > @@ -441,7 +441,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
> >  	}
> >  
> >  	if (total_nr_samples == 0) {
> > -		ui__error("The %s file has no samples!\n", session->data->file.path);
> > +		ui__error("The %s data has no samples!\n", session->data->path);
> >  		goto out;
> >  	}
> >  
> > @@ -578,7 +578,7 @@ int cmd_annotate(int argc, const char **argv)
> >  	if (quiet)
> >  		perf_quiet_option();
> >  
> > -	data.file.path = input_name;
> > +	data.path = input_name;
> >  
> >  	annotate.session = perf_session__new(&data, false, &annotate.tool);
> >  	if (annotate.session == NULL)
> > diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
> > index 115110a4796a..10457b10e568 100644
> > --- a/tools/perf/builtin-buildid-cache.c
> > +++ b/tools/perf/builtin-buildid-cache.c
> > @@ -416,8 +416,8 @@ int cmd_buildid_cache(int argc, const char **argv)
> >  		nsi = nsinfo__new(ns_id);
> >  
> >  	if (missing_filename) {
> > -		data.file.path = missing_filename;
> > -		data.force     = force;
> > +		data.path  = missing_filename;
> > +		data.force = force;
> >  
> >  		session = perf_session__new(&data, false, NULL);
> >  		if (session == NULL)
> > diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
> > index 78abbe8d9d5f..f403e19488b5 100644
> > --- a/tools/perf/builtin-buildid-list.c
> > +++ b/tools/perf/builtin-buildid-list.c
> > @@ -52,11 +52,9 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
> >  {
> >  	struct perf_session *session;
> >  	struct perf_data data = {
> > -		.file      = {
> > -			.path = input_name,
> > -		},
> > -		.mode      = PERF_DATA_MODE_READ,
> > -		.force     = force,
> > +		.path  = input_name,
> > +		.mode  = PERF_DATA_MODE_READ,
> > +		.force = force,
> >  	};
> >  
> >  	symbol__elf_init();
> > diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
> > index efaaab23c6fd..4272763a5e96 100644
> > --- a/tools/perf/builtin-c2c.c
> > +++ b/tools/perf/builtin-c2c.c
> > @@ -2750,8 +2750,8 @@ static int perf_c2c__report(int argc, const char **argv)
> >  	if (!input_name || !strlen(input_name))
> >  		input_name = "perf.data";
> >  
> > -	data.file.path = input_name;
> > -	data.force     = symbol_conf.force;
> > +	data.path  = input_name;
> > +	data.force = symbol_conf.force;
> >  
> >  	err = setup_display(display);
> >  	if (err)
> > diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
> > index 751e1971456b..58fe0e88215c 100644
> > --- a/tools/perf/builtin-diff.c
> > +++ b/tools/perf/builtin-diff.c
> > @@ -708,7 +708,7 @@ static void data__fprintf(void)
> >  
> >  	data__for_each_file(i, d)
> >  		fprintf(stdout, "#  [%d] %s %s\n",
> > -			d->idx, d->data.file.path,
> > +			d->idx, d->data.path,
> >  			!d->idx ? "(Baseline)" : "");
> >  
> >  	fprintf(stdout, "#\n");
> > @@ -779,14 +779,14 @@ static int __cmd_diff(void)
> >  	data__for_each_file(i, d) {
> >  		d->session = perf_session__new(&d->data, false, &tool);
> >  		if (!d->session) {
> > -			pr_err("Failed to open %s\n", d->data.file.path);
> > +			pr_err("Failed to open %s\n", d->data.path);
> >  			ret = -1;
> >  			goto out_delete;
> >  		}
> >  
> >  		ret = perf_session__process_events(d->session);
> >  		if (ret) {
> > -			pr_err("Failed to process %s\n", d->data.file.path);
> > +			pr_err("Failed to process %s\n", d->data.path);
> >  			goto out_delete;
> >  		}
> >  
> > @@ -1289,9 +1289,9 @@ static int data_init(int argc, const char **argv)
> >  	data__for_each_file(i, d) {
> >  		struct perf_data *data = &d->data;
> >  
> > -		data->file.path = use_default ? defaults[i] : argv[i];
> > -		data->mode      = PERF_DATA_MODE_READ,
> > -		data->force     = force,
> > +		data->path  = use_default ? defaults[i] : argv[i];
> > +		data->mode  = PERF_DATA_MODE_READ,
> > +		data->force = force,
> >  
> >  		d->idx  = i;
> >  	}
> > diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
> > index e06e822ce634..6e4f63b0da4a 100644
> > --- a/tools/perf/builtin-evlist.c
> > +++ b/tools/perf/builtin-evlist.c
> > @@ -23,9 +23,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
> >  	struct perf_session *session;
> >  	struct perf_evsel *pos;
> >  	struct perf_data data = {
> > -		.file      = {
> > -			.path = file_name,
> > -		},
> > +		.path      = file_name,
> >  		.mode      = PERF_DATA_MODE_READ,
> >  		.force     = details->force,
> >  	};
> > diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
> > index 9bb1f35d5cb7..24086b7f1b14 100644
> > --- a/tools/perf/builtin-inject.c
> > +++ b/tools/perf/builtin-inject.c
> > @@ -770,10 +770,8 @@ int cmd_inject(int argc, const char **argv)
> >  		.input_name  = "-",
> >  		.samples = LIST_HEAD_INIT(inject.samples),
> >  		.output = {
> > -			.file      = {
> > -				.path = "-",
> > -			},
> > -			.mode      = PERF_DATA_MODE_WRITE,
> > +			.path = "-",
> > +			.mode = PERF_DATA_MODE_WRITE,
> >  		},
> >  	};
> >  	struct perf_data data = {
> > @@ -786,7 +784,7 @@ int cmd_inject(int argc, const char **argv)
> >  			    "Inject build-ids into the output stream"),
> >  		OPT_STRING('i', "input", &inject.input_name, "file",
> >  			   "input file name"),
> > -		OPT_STRING('o', "output", &inject.output.file.path, "file",
> > +		OPT_STRING('o', "output", &inject.output.path, "file",
> >  			   "output file name"),
> >  		OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
> >  			    "Merge sched-stat and sched-switch for getting events "
> > @@ -834,7 +832,7 @@ int cmd_inject(int argc, const char **argv)
> >  
> >  	inject.tool.ordered_events = inject.sched_stat;
> >  
> > -	data.file.path = inject.input_name;
> > +	data.path = inject.input_name;
> >  	inject.session = perf_session__new(&data, true, &inject.tool);
> >  	if (inject.session == NULL)
> >  		return -1;
> > diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
> > index b80ec0883537..fa520f4b8095 100644
> > --- a/tools/perf/builtin-kmem.c
> > +++ b/tools/perf/builtin-kmem.c
> > @@ -1949,7 +1949,7 @@ int cmd_kmem(int argc, const char **argv)
> >  		return __cmd_record(argc, argv);
> >  	}
> >  
> > -	data.file.path = input_name;
> > +	data.path = input_name;
> >  
> >  	kmem_session = session = perf_session__new(&data, false, &perf_kmem);
> >  	if (session == NULL)
> > diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
> > index 3d4cbc4e87c7..dbb6f737a3e2 100644
> > --- a/tools/perf/builtin-kvm.c
> > +++ b/tools/perf/builtin-kvm.c
> > @@ -1080,11 +1080,9 @@ static int read_events(struct perf_kvm_stat *kvm)
> >  		.ordered_events		= true,
> >  	};
> >  	struct perf_data file = {
> > -		.file      = {
> > -			.path = kvm->file_name,
> > -		},
> > -		.mode      = PERF_DATA_MODE_READ,
> > -		.force     = kvm->force,
> > +		.path  = kvm->file_name,
> > +		.mode  = PERF_DATA_MODE_READ,
> > +		.force = kvm->force,
> >  	};
> >  
> >  	kvm->tool = eops;
> > diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
> > index 6e0189df2b3b..b9810a8d350a 100644
> > --- a/tools/perf/builtin-lock.c
> > +++ b/tools/perf/builtin-lock.c
> > @@ -866,11 +866,9 @@ static int __cmd_report(bool display_info)
> >  		.ordered_events	 = true,
> >  	};
> >  	struct perf_data data = {
> > -		.file      = {
> > -			.path = input_name,
> > -		},
> > -		.mode      = PERF_DATA_MODE_READ,
> > -		.force     = force,
> > +		.path  = input_name,
> > +		.mode  = PERF_DATA_MODE_READ,
> > +		.force = force,
> >  	};
> >  
> >  	session = perf_session__new(&data, false, &eops);
> > diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
> > index ba7e8d87dec3..f45c8b502f63 100644
> > --- a/tools/perf/builtin-mem.c
> > +++ b/tools/perf/builtin-mem.c
> > @@ -239,11 +239,9 @@ static int process_sample_event(struct perf_tool *tool,
> >  static int report_raw_events(struct perf_mem *mem)
> >  {
> >  	struct perf_data data = {
> > -		.file      = {
> > -			.path = input_name,
> > -		},
> > -		.mode      = PERF_DATA_MODE_READ,
> > -		.force     = mem->force,
> > +		.path  = input_name,
> > +		.mode  = PERF_DATA_MODE_READ,
> > +		.force = mem->force,
> >  	};
> >  	int ret;
> >  	struct perf_session *session = perf_session__new(&data, false,
> > diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> > index e5e9900c9039..f3f7f3100336 100644
> > --- a/tools/perf/builtin-record.c
> > +++ b/tools/perf/builtin-record.c
> > @@ -918,7 +918,7 @@ record__switch_output(struct record *rec, bool at_exit)
> >  
> >  	if (!quiet)
> >  		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
> > -			data->file.path, timestamp);
> > +			data->path, timestamp);
> >  
> >  	/* Output tracking events */
> >  	if (!at_exit) {
> > @@ -1461,7 +1461,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
> >  
> >  		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
> >  			perf_data__size(data) / 1024.0 / 1024.0,
> > -			data->file.path, postfix, samples);
> > +			data->path, postfix, samples);
> >  	}
> >  
> >  out_delete_session:
> > @@ -1862,7 +1862,7 @@ static struct option __record_options[] = {
> >  	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
> >  		    "list of cpus to monitor"),
> >  	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
> > -	OPT_STRING('o', "output", &record.data.file.path, "file",
> > +	OPT_STRING('o', "output", &record.data.path, "file",
> >  		    "output file name"),
> >  	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
> >  			&record.opts.no_inherit_set,
> > diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
> > index 2e8c74d6430c..1532ebde6c4b 100644
> > --- a/tools/perf/builtin-report.c
> > +++ b/tools/perf/builtin-report.c
> > @@ -899,7 +899,7 @@ static int __cmd_report(struct report *rep)
> >  		rep->nr_entries += evsel__hists(pos)->nr_entries;
> >  
> >  	if (rep->nr_entries == 0) {
> > -		ui__error("The %s file has no samples!\n", data->file.path);
> > +		ui__error("The %s data has no samples!\n", data->path);
> >  		return 0;
> >  	}
> >  
> > @@ -1207,8 +1207,8 @@ int cmd_report(int argc, const char **argv)
> >  			input_name = "perf.data";
> >  	}
> >  
> > -	data.file.path = input_name;
> > -	data.force     = symbol_conf.force;
> > +	data.path  = input_name;
> > +	data.force = symbol_conf.force;
> >  
> >  repeat:
> >  	session = perf_session__new(&data, false, &report.tool);
> > diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
> > index 640558e9352e..275f2d92a7bf 100644
> > --- a/tools/perf/builtin-sched.c
> > +++ b/tools/perf/builtin-sched.c
> > @@ -1785,11 +1785,9 @@ static int perf_sched__read_events(struct perf_sched *sched)
> >  	};
> >  	struct perf_session *session;
> >  	struct perf_data data = {
> > -		.file      = {
> > -			.path = input_name,
> > -		},
> > -		.mode      = PERF_DATA_MODE_READ,
> > -		.force     = sched->force,
> > +		.path  = input_name,
> > +		.mode  = PERF_DATA_MODE_READ,
> > +		.force = sched->force,
> >  	};
> >  	int rc = -1;
> >  
> > @@ -2958,11 +2956,9 @@ static int perf_sched__timehist(struct perf_sched *sched)
> >  		{ "sched:sched_migrate_task", timehist_migrate_task_event, },
> >  	};
> >  	struct perf_data data = {
> > -		.file      = {
> > -			.path = input_name,
> > -		},
> > -		.mode      = PERF_DATA_MODE_READ,
> > -		.force     = sched->force,
> > +		.path  = input_name,
> > +		.mode  = PERF_DATA_MODE_READ,
> > +		.force = sched->force,
> >  	};
> >  
> >  	struct perf_session *session;
> > diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
> > index 373ea151dc60..5b1543f42290 100644
> > --- a/tools/perf/builtin-script.c
> > +++ b/tools/perf/builtin-script.c
> > @@ -2951,10 +2951,8 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
> >  	DIR *scripts_dir, *lang_dir;
> >  	struct perf_session *session;
> >  	struct perf_data data = {
> > -		.file      = {
> > -			.path = input_name,
> > -		},
> > -		.mode      = PERF_DATA_MODE_READ,
> > +		.path = input_name,
> > +		.mode = PERF_DATA_MODE_READ,
> >  	};
> >  	char *temp;
> >  	int i = 0;
> > @@ -3427,8 +3425,8 @@ int cmd_script(int argc, const char **argv)
> >  	argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
> >  			     PARSE_OPT_STOP_AT_NON_OPTION);
> >  
> > -	data.file.path = input_name;
> > -	data.force     = symbol_conf.force;
> > +	data.path  = input_name;
> > +	data.force = symbol_conf.force;
> >  
> >  	if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
> >  		rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
> > @@ -3654,7 +3652,7 @@ int cmd_script(int argc, const char **argv)
> >  			goto out_delete;
> >  		}
> >  
> > -		input = open(data.file.path, O_RDONLY);	/* input_name */
> > +		input = open(data.path, O_RDONLY);	/* input_name */
> >  		if (input < 0) {
> >  			err = -errno;
> >  			perror("failed to open file");
> > diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
> > index bb24f9c17f9a..7b8f09b0b8bf 100644
> > --- a/tools/perf/builtin-stat.c
> > +++ b/tools/perf/builtin-stat.c
> > @@ -1322,7 +1322,7 @@ static int __cmd_record(int argc, const char **argv)
> >  			     PARSE_OPT_STOP_AT_NON_OPTION);
> >  
> >  	if (output_name)
> > -		data->file.path = output_name;
> > +		data->path = output_name;
> >  
> >  	if (stat_config.run_count != 1 || forever) {
> >  		pr_err("Cannot use -r option with perf stat record.\n");
> > @@ -1523,8 +1523,8 @@ static int __cmd_report(int argc, const char **argv)
> >  			input_name = "perf.data";
> >  	}
> >  
> > -	perf_stat.data.file.path = input_name;
> > -	perf_stat.data.mode      = PERF_DATA_MODE_READ;
> > +	perf_stat.data.path = input_name;
> > +	perf_stat.data.mode = PERF_DATA_MODE_READ;
> >  
> >  	session = perf_session__new(&perf_stat.data, false, &perf_stat.tool);
> >  	if (session == NULL)
> > diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
> > index 775b99833e51..9b98687a27b9 100644
> > --- a/tools/perf/builtin-timechart.c
> > +++ b/tools/perf/builtin-timechart.c
> > @@ -1602,11 +1602,9 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
> >  		{ "syscalls:sys_exit_select",		process_exit_poll },
> >  	};
> >  	struct perf_data data = {
> > -		.file      = {
> > -			.path = input_name,
> > -		},
> > -		.mode      = PERF_DATA_MODE_READ,
> > -		.force     = tchart->force,
> > +		.path  = input_name,
> > +		.mode  = PERF_DATA_MODE_READ,
> > +		.force = tchart->force,
> >  	};
> >  
> >  	struct perf_session *session = perf_session__new(&data, false,
> > diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> > index 1a11fe656afc..f5b3a1e9c1dd 100644
> > --- a/tools/perf/builtin-trace.c
> > +++ b/tools/perf/builtin-trace.c
> > @@ -3154,11 +3154,9 @@ static int trace__replay(struct trace *trace)
> >  		{ "probe:vfs_getname",	     trace__vfs_getname, },
> >  	};
> >  	struct perf_data data = {
> > -		.file      = {
> > -			.path = input_name,
> > -		},
> > -		.mode      = PERF_DATA_MODE_READ,
> > -		.force     = trace->force,
> > +		.path  = input_name,
> > +		.mode  = PERF_DATA_MODE_READ,
> > +		.force = trace->force,
> >  	};
> >  	struct perf_session *session;
> >  	struct perf_evsel *evsel;
> > diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
> > index 2a36fab76994..ea742a254aa5 100644
> > --- a/tools/perf/util/data-convert-bt.c
> > +++ b/tools/perf/util/data-convert-bt.c
> > @@ -1650,7 +1650,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
> >  
> >  	fprintf(stderr,
> >  		"[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
> > -		data.file.path, path);
> > +		data.path, path);
> >  
> >  	fprintf(stderr,
> >  		"[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
> > diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
> > index 09eceda17fc2..e16d06ed1100 100644
> > --- a/tools/perf/util/data.c
> > +++ b/tools/perf/util/data.c
> > @@ -19,11 +19,11 @@ static bool check_pipe(struct perf_data *data)
> >  	int fd = perf_data__is_read(data) ?
> >  		 STDIN_FILENO : STDOUT_FILENO;
> >  
> > -	if (!data->file.path) {
> > +	if (!data->path) {
> >  		if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
> >  			is_pipe = true;
> >  	} else {
> > -		if (!strcmp(data->file.path, "-"))
> > +		if (!strcmp(data->path, "-"))
> >  			is_pipe = true;
> >  	}
> >  
> > @@ -37,13 +37,13 @@ static int check_backup(struct perf_data *data)
> >  {
> >  	struct stat st;
> >  
> > -	if (!stat(data->file.path, &st) && st.st_size) {
> > +	if (!stat(data->path, &st) && st.st_size) {
> >  		/* TODO check errors properly */
> >  		char oldname[PATH_MAX];
> >  		snprintf(oldname, sizeof(oldname), "%s.old",
> > -			 data->file.path);
> > +			 data->path);
> >  		unlink(oldname);
> > -		rename(data->file.path, oldname);
> > +		rename(data->path, oldname);
> >  	}
> >  
> >  	return 0;
> > @@ -115,8 +115,22 @@ static int open_file(struct perf_data *data)
> >  	fd = perf_data__is_read(data) ?
> >  	     open_file_read(data) : open_file_write(data);
> >  
> > +	if (fd < 0) {
> > +		free(data->file.path);
> > +		return -1;
> > +	}
> > +
> >  	data->file.fd = fd;
> > -	return fd < 0 ? -1 : 0;
> > +	return 0;
> > +}
> > +
> > +static int open_file_dup(struct perf_data *data)
> > +{
> > +	data->file.path = strdup(data->path);
> > +	if (!data->file.path)
> > +		return -ENOMEM;
> > +
> > +	return open_file(data);
> >  }
> >  
> >  int perf_data__open(struct perf_data *data)
> > @@ -124,14 +138,15 @@ int perf_data__open(struct perf_data *data)
> >  	if (check_pipe(data))
> >  		return 0;
> >  
> > -	if (!data->file.path)
> > -		data->file.path = "perf.data";
> > +	if (!data->path)
> > +		data->path = "perf.data";
> >  
> > -	return open_file(data);
> > +	return open_file_dup(data);
> >  }
> >  
> >  void perf_data__close(struct perf_data *data)
> >  {
> > +	free(data->file.path);
> >  	close(data->file.fd);
> >  }
> >  
> > @@ -159,15 +174,15 @@ int perf_data__switch(struct perf_data *data,
> >  	if (perf_data__is_read(data))
> >  		return -EINVAL;
> >  
> > -	if (asprintf(&new_filepath, "%s.%s", data->file.path, postfix) < 0)
> > +	if (asprintf(&new_filepath, "%s.%s", data->path, postfix) < 0)
> >  		return -ENOMEM;
> >  
> >  	/*
> >  	 * Only fire a warning, don't return error, continue fill
> >  	 * original file.
> >  	 */
> > -	if (rename(data->file.path, new_filepath))
> > -		pr_warning("Failed to rename %s to %s\n", data->file.path, new_filepath);
> > +	if (rename(data->path, new_filepath))
> > +		pr_warning("Failed to rename %s to %s\n", data->path, new_filepath);
> >  
> >  	if (!at_exit) {
> >  		close(data->file.fd);
> > diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
> > index 85f9c0dbf982..2bce28117ccf 100644
> > --- a/tools/perf/util/data.h
> > +++ b/tools/perf/util/data.h
> > @@ -10,12 +10,13 @@ enum perf_data_mode {
> >  };
> >  
> >  struct perf_data_file {
> > -	const char	*path;
> > +	char		*path;
> >  	int		 fd;
> >  	unsigned long	 size;
> >  };
> >  
> >  struct perf_data {
> > +	const char		*path;
> >  	struct perf_data_file	 file;
> >  	bool			 is_pipe;
> >  	bool			 force;
> > -- 
> > 2.17.2
> 
> -- 
> 
> - Arnaldo

-- 

- Arnaldo

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 05/17] perf data: Add perf_data__(create_dir|close_dir) functions
  2019-02-21  9:41 ` [PATCH 05/17] perf data: Add perf_data__(create_dir|close_dir) functions Jiri Olsa
@ 2019-02-23  5:07   ` Namhyung Kim
  2019-02-24 13:32     ` Jiri Olsa
  0 siblings, 1 reply; 26+ messages in thread
From: Namhyung Kim @ 2019-02-23  5:07 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Arnaldo Carvalho de Melo, lkml, Ingo Molnar, Alexander Shishkin,
	Peter Zijlstra, Adrian Hunter, Andi Kleen, Stephane Eranian,
	Alexey Budankov

On Thu, Feb 21, 2019 at 6:42 PM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Adding perf_data__create_dir to create nr files inside
> struct perf_data path directory:
>   int perf_data__create_dir(struct perf_data *data, int nr);
>
> and function to close that data:
>   void perf_data__close_dir(struct perf_data *data);
>
> Link: http://lkml.kernel.org/n/tip-kl4s1f13cg6wycrg367p85qm@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/util/data.c | 47 ++++++++++++++++++++++++++++++++++++++++++
>  tools/perf/util/data.h |  8 +++++++
>  2 files changed, 55 insertions(+)
>
> diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
> index 18e5d94b0e97..7f13fbd9c043 100644
> --- a/tools/perf/util/data.c
> +++ b/tools/perf/util/data.c
> @@ -7,11 +7,58 @@
>  #include <fcntl.h>
>  #include <unistd.h>
>  #include <string.h>
> +#include <asm/bug.h>
>
>  #include "data.h"
>  #include "util.h"
>  #include "debug.h"
>
> +static void close_dir(struct perf_data_file *files, int nr)
> +{
> +       while (--nr >= 1) {
> +               close(files[nr].fd);
> +               free(files[nr].path);
> +       }
> +       free(files);
> +}
> +
> +void perf_data__close_dir(struct perf_data *data)
> +{
> +       close_dir(data->dir.files, data->dir.nr);
> +}
> +
> +int perf_data__create_dir(struct perf_data *data, int nr)
> +{
> +       struct perf_data_file *files = NULL;
> +       int i, ret = -1;
> +
> +       files = malloc(nr * sizeof(*files));
> +       if (!files)
> +               return -ENOMEM;
> +
> +       data->dir.files = files;
> +       data->dir.nr    = nr;
> +
> +       for (i = 0; i < nr; i++) {
> +               struct perf_data_file *file = &files[i];
> +
> +               if (asprintf(&file->path, "%s/data.%d", data->path, i) < 0)
> +                       goto out_err;
> +
> +               ret = open(file->path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
> +               if (ret < 0)
> +                       goto out_err;

It seems you need to free the file->path here.

Thanks,
Namhyung


> +
> +               file->fd = ret;
> +       }
> +
> +       return 0;
> +
> +out_err:
> +       close_dir(files, i);
> +       return ret;
> +}
> +
>  static bool check_pipe(struct perf_data *data)
>  {
>         struct stat st;
> diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
> index 2bce28117ccf..2d0d015a7d4d 100644
> --- a/tools/perf/util/data.h
> +++ b/tools/perf/util/data.h
> @@ -21,6 +21,11 @@ struct perf_data {
>         bool                     is_pipe;
>         bool                     force;
>         enum perf_data_mode      mode;
> +
> +       struct {
> +               struct perf_data_file   *files;
> +               int                      nr;
> +       } dir;
>  };
>
>  static inline bool perf_data__is_read(struct perf_data *data)
> @@ -64,4 +69,7 @@ ssize_t perf_data_file__write(struct perf_data_file *file,
>  int perf_data__switch(struct perf_data *data,
>                            const char *postfix,
>                            size_t pos, bool at_exit);
> +
> +int perf_data__create_dir(struct perf_data *data, int nr);
> +void perf_data__close_dir(struct perf_data *data);
>  #endif /* __PERF_DATA_H */
> --
> 2.17.2
>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 05/17] perf data: Add perf_data__(create_dir|close_dir) functions
  2019-02-23  5:07   ` Namhyung Kim
@ 2019-02-24 13:32     ` Jiri Olsa
  0 siblings, 0 replies; 26+ messages in thread
From: Jiri Olsa @ 2019-02-24 13:32 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, lkml, Ingo Molnar,
	Alexander Shishkin, Peter Zijlstra, Adrian Hunter, Andi Kleen,
	Stephane Eranian, Alexey Budankov

On Sat, Feb 23, 2019 at 02:07:53PM +0900, Namhyung Kim wrote:

SNIP

> > +static void close_dir(struct perf_data_file *files, int nr)
> > +{
> > +       while (--nr >= 1) {
> > +               close(files[nr].fd);
> > +               free(files[nr].path);
> > +       }
> > +       free(files);
> > +}
> > +
> > +void perf_data__close_dir(struct perf_data *data)
> > +{
> > +       close_dir(data->dir.files, data->dir.nr);
> > +}
> > +
> > +int perf_data__create_dir(struct perf_data *data, int nr)
> > +{
> > +       struct perf_data_file *files = NULL;
> > +       int i, ret = -1;
> > +
> > +       files = malloc(nr * sizeof(*files));
> > +       if (!files)
> > +               return -ENOMEM;
> > +
> > +       data->dir.files = files;
> > +       data->dir.nr    = nr;
> > +
> > +       for (i = 0; i < nr; i++) {
> > +               struct perf_data_file *file = &files[i];
> > +
> > +               if (asprintf(&file->path, "%s/data.%d", data->path, i) < 0)
> > +                       goto out_err;
> > +
> > +               ret = open(file->path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
> > +               if (ret < 0)
> > +                       goto out_err;
> 
> It seems you need to free the file->path here.

it'll be freed in the close_dir call below,
I need to call zalloc to make sure it's ok

jirka

> 
> Thanks,
> Namhyung
> 
> 
> > +
> > +               file->fd = ret;
> > +       }
> > +
> > +       return 0;
> > +
> > +out_err:
> > +       close_dir(files, i);
> > +       return ret;
> > +}
> > +
> >  static bool check_pipe(struct perf_data *data)
> >  {
> >         struct stat st;

SNIP


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [tip:perf/core] perf data: Move size to struct perf_data_file
  2019-02-21  9:41 ` [PATCH 01/17] perf data: Move size to struct perf_data_file Jiri Olsa
@ 2019-02-28  7:58   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 26+ messages in thread
From: tip-bot for Jiri Olsa @ 2019-02-28  7:58 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, linux-kernel, namhyung, tglx, alexander.shishkin, acme,
	adrian.hunter, eranian, alexey.budankov, mingo, ak, hpa, jolsa

Commit-ID:  45112e89a8b2b4c9a004147cbfb448b1200cfbf7
Gitweb:     https://git.kernel.org/tip/45112e89a8b2b4c9a004147cbfb448b1200cfbf7
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 21 Feb 2019 10:41:29 +0100
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 22 Feb 2019 16:52:07 -0300

perf data: Move size to struct perf_data_file

We are about to add support for multiple files, so we need each file to
keep its size.

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/20190221094145.9151-2-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c | 5 ++---
 tools/perf/util/data.c      | 2 +-
 tools/perf/util/data.h      | 4 ++--
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 6c3719ac901d..e5e9900c9039 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -660,10 +660,9 @@ static int process_sample_event(struct perf_tool *tool,
 
 static int process_buildids(struct record *rec)
 {
-	struct perf_data *data = &rec->data;
 	struct perf_session *session = rec->session;
 
-	if (data->size == 0)
+	if (perf_data__size(&rec->data) == 0)
 		return 0;
 
 	/*
@@ -851,7 +850,7 @@ record__finish_output(struct record *rec)
 		return;
 
 	rec->session->header.data_size += rec->bytes_written;
-	data->size = lseek(perf_data__fd(data), 0, SEEK_CUR);
+	data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR);
 
 	if (!rec->no_buildid) {
 		process_buildids(rec);
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index d8cfc19ddb10..09eceda17fc2 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -82,7 +82,7 @@ static int open_file_read(struct perf_data *data)
 		goto out_close;
 	}
 
-	data->size = st.st_size;
+	data->file.size = st.st_size;
 	return fd;
 
  out_close:
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 4828f7feea89..85f9c0dbf982 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -12,13 +12,13 @@ enum perf_data_mode {
 struct perf_data_file {
 	const char	*path;
 	int		 fd;
+	unsigned long	 size;
 };
 
 struct perf_data {
 	struct perf_data_file	 file;
 	bool			 is_pipe;
 	bool			 force;
-	unsigned long		 size;
 	enum perf_data_mode	 mode;
 };
 
@@ -44,7 +44,7 @@ static inline int perf_data__fd(struct perf_data *data)
 
 static inline unsigned long perf_data__size(struct perf_data *data)
 {
-	return data->size;
+	return data->file.size;
 }
 
 int perf_data__open(struct perf_data *data);

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [tip:perf/core] perf data: Add global path holder
  2019-02-21  9:41 ` [PATCH 02/17] perf data: Add global path holder Jiri Olsa
  2019-02-22 16:05   ` Arnaldo Carvalho de Melo
@ 2019-02-28  7:59   ` tip-bot for Jiri Olsa
  1 sibling, 0 replies; 26+ messages in thread
From: tip-bot for Jiri Olsa @ 2019-02-28  7:59 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: alexander.shishkin, peterz, tglx, hpa, jolsa, alexey.budankov,
	adrian.hunter, linux-kernel, acme, mingo, namhyung, ak, eranian

Commit-ID:  2d4f27999b8877409f326682fd8cc40c52f47cea
Gitweb:     https://git.kernel.org/tip/2d4f27999b8877409f326682fd8cc40c52f47cea
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 21 Feb 2019 10:41:30 +0100
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 22 Feb 2019 16:52:07 -0300

perf data: Add global path holder

Add a 'path' member to 'struct perf_data'. It will keep the configured
path for the data (const char *). The path in struct perf_data_file is
now dynamically allocated (duped) from it.

This scheme is useful/used in following patches where struct
perf_data::path holds the 'configure' directory path and struct
perf_data_file::path holds the allocated path for specific files.

Also it actually makes the code little simpler.

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/20190221094145.9151-3-jolsa@kernel.org
[ Fixup data-convert-bt.c missing conversion ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-annotate.c      |  4 ++--
 tools/perf/builtin-buildid-cache.c |  4 ++--
 tools/perf/builtin-buildid-list.c  |  8 +++-----
 tools/perf/builtin-c2c.c           |  4 ++--
 tools/perf/builtin-diff.c          | 12 ++++++------
 tools/perf/builtin-evlist.c        |  4 +---
 tools/perf/builtin-inject.c        | 10 ++++------
 tools/perf/builtin-kmem.c          |  2 +-
 tools/perf/builtin-kvm.c           |  8 +++-----
 tools/perf/builtin-lock.c          |  8 +++-----
 tools/perf/builtin-mem.c           |  8 +++-----
 tools/perf/builtin-record.c        |  6 +++---
 tools/perf/builtin-report.c        |  6 +++---
 tools/perf/builtin-sched.c         | 16 ++++++----------
 tools/perf/builtin-script.c        | 12 +++++-------
 tools/perf/builtin-stat.c          |  6 +++---
 tools/perf/builtin-timechart.c     |  8 +++-----
 tools/perf/builtin-trace.c         |  8 +++-----
 tools/perf/util/data-convert-bt.c  |  4 ++--
 tools/perf/util/data.c             | 39 ++++++++++++++++++++++++++------------
 tools/perf/util/data.h             |  3 ++-
 21 files changed, 87 insertions(+), 93 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 7f3c3fea67b4..67f9d9ffacfb 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -441,7 +441,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
 	}
 
 	if (total_nr_samples == 0) {
-		ui__error("The %s file has no samples!\n", session->data->file.path);
+		ui__error("The %s data has no samples!\n", session->data->path);
 		goto out;
 	}
 
@@ -578,7 +578,7 @@ int cmd_annotate(int argc, const char **argv)
 	if (quiet)
 		perf_quiet_option();
 
-	data.file.path = input_name;
+	data.path = input_name;
 
 	annotate.session = perf_session__new(&data, false, &annotate.tool);
 	if (annotate.session == NULL)
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 115110a4796a..10457b10e568 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -416,8 +416,8 @@ int cmd_buildid_cache(int argc, const char **argv)
 		nsi = nsinfo__new(ns_id);
 
 	if (missing_filename) {
-		data.file.path = missing_filename;
-		data.force     = force;
+		data.path  = missing_filename;
+		data.force = force;
 
 		session = perf_session__new(&data, false, NULL);
 		if (session == NULL)
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 78abbe8d9d5f..f403e19488b5 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -52,11 +52,9 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
 {
 	struct perf_session *session;
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = force,
 	};
 
 	symbol__elf_init();
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index efaaab23c6fd..4272763a5e96 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -2750,8 +2750,8 @@ static int perf_c2c__report(int argc, const char **argv)
 	if (!input_name || !strlen(input_name))
 		input_name = "perf.data";
 
-	data.file.path = input_name;
-	data.force     = symbol_conf.force;
+	data.path  = input_name;
+	data.force = symbol_conf.force;
 
 	err = setup_display(display);
 	if (err)
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 751e1971456b..58fe0e88215c 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -708,7 +708,7 @@ static void data__fprintf(void)
 
 	data__for_each_file(i, d)
 		fprintf(stdout, "#  [%d] %s %s\n",
-			d->idx, d->data.file.path,
+			d->idx, d->data.path,
 			!d->idx ? "(Baseline)" : "");
 
 	fprintf(stdout, "#\n");
@@ -779,14 +779,14 @@ static int __cmd_diff(void)
 	data__for_each_file(i, d) {
 		d->session = perf_session__new(&d->data, false, &tool);
 		if (!d->session) {
-			pr_err("Failed to open %s\n", d->data.file.path);
+			pr_err("Failed to open %s\n", d->data.path);
 			ret = -1;
 			goto out_delete;
 		}
 
 		ret = perf_session__process_events(d->session);
 		if (ret) {
-			pr_err("Failed to process %s\n", d->data.file.path);
+			pr_err("Failed to process %s\n", d->data.path);
 			goto out_delete;
 		}
 
@@ -1289,9 +1289,9 @@ static int data_init(int argc, const char **argv)
 	data__for_each_file(i, d) {
 		struct perf_data *data = &d->data;
 
-		data->file.path = use_default ? defaults[i] : argv[i];
-		data->mode      = PERF_DATA_MODE_READ,
-		data->force     = force,
+		data->path  = use_default ? defaults[i] : argv[i];
+		data->mode  = PERF_DATA_MODE_READ,
+		data->force = force,
 
 		d->idx  = i;
 	}
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index e06e822ce634..6e4f63b0da4a 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -23,9 +23,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
 	struct perf_session *session;
 	struct perf_evsel *pos;
 	struct perf_data data = {
-		.file      = {
-			.path = file_name,
-		},
+		.path      = file_name,
 		.mode      = PERF_DATA_MODE_READ,
 		.force     = details->force,
 	};
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 9bb1f35d5cb7..24086b7f1b14 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -770,10 +770,8 @@ int cmd_inject(int argc, const char **argv)
 		.input_name  = "-",
 		.samples = LIST_HEAD_INIT(inject.samples),
 		.output = {
-			.file      = {
-				.path = "-",
-			},
-			.mode      = PERF_DATA_MODE_WRITE,
+			.path = "-",
+			.mode = PERF_DATA_MODE_WRITE,
 		},
 	};
 	struct perf_data data = {
@@ -786,7 +784,7 @@ int cmd_inject(int argc, const char **argv)
 			    "Inject build-ids into the output stream"),
 		OPT_STRING('i', "input", &inject.input_name, "file",
 			   "input file name"),
-		OPT_STRING('o', "output", &inject.output.file.path, "file",
+		OPT_STRING('o', "output", &inject.output.path, "file",
 			   "output file name"),
 		OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
 			    "Merge sched-stat and sched-switch for getting events "
@@ -834,7 +832,7 @@ int cmd_inject(int argc, const char **argv)
 
 	inject.tool.ordered_events = inject.sched_stat;
 
-	data.file.path = inject.input_name;
+	data.path = inject.input_name;
 	inject.session = perf_session__new(&data, true, &inject.tool);
 	if (inject.session == NULL)
 		return -1;
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index b80ec0883537..fa520f4b8095 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1949,7 +1949,7 @@ int cmd_kmem(int argc, const char **argv)
 		return __cmd_record(argc, argv);
 	}
 
-	data.file.path = input_name;
+	data.path = input_name;
 
 	kmem_session = session = perf_session__new(&data, false, &perf_kmem);
 	if (session == NULL)
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 3d4cbc4e87c7..dbb6f737a3e2 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1080,11 +1080,9 @@ static int read_events(struct perf_kvm_stat *kvm)
 		.ordered_events		= true,
 	};
 	struct perf_data file = {
-		.file      = {
-			.path = kvm->file_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = kvm->force,
+		.path  = kvm->file_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = kvm->force,
 	};
 
 	kvm->tool = eops;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 6e0189df2b3b..b9810a8d350a 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -866,11 +866,9 @@ static int __cmd_report(bool display_info)
 		.ordered_events	 = true,
 	};
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = force,
 	};
 
 	session = perf_session__new(&data, false, &eops);
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index ba7e8d87dec3..f45c8b502f63 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -239,11 +239,9 @@ static int process_sample_event(struct perf_tool *tool,
 static int report_raw_events(struct perf_mem *mem)
 {
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = mem->force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = mem->force,
 	};
 	int ret;
 	struct perf_session *session = perf_session__new(&data, false,
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e5e9900c9039..f3f7f3100336 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -918,7 +918,7 @@ record__switch_output(struct record *rec, bool at_exit)
 
 	if (!quiet)
 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
-			data->file.path, timestamp);
+			data->path, timestamp);
 
 	/* Output tracking events */
 	if (!at_exit) {
@@ -1461,7 +1461,7 @@ out_child:
 
 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
 			perf_data__size(data) / 1024.0 / 1024.0,
-			data->file.path, postfix, samples);
+			data->path, postfix, samples);
 	}
 
 out_delete_session:
@@ -1862,7 +1862,7 @@ static struct option __record_options[] = {
 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
 		    "list of cpus to monitor"),
 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
-	OPT_STRING('o', "output", &record.data.file.path, "file",
+	OPT_STRING('o', "output", &record.data.path, "file",
 		    "output file name"),
 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
 			&record.opts.no_inherit_set,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 2e8c74d6430c..1532ebde6c4b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -899,7 +899,7 @@ static int __cmd_report(struct report *rep)
 		rep->nr_entries += evsel__hists(pos)->nr_entries;
 
 	if (rep->nr_entries == 0) {
-		ui__error("The %s file has no samples!\n", data->file.path);
+		ui__error("The %s data has no samples!\n", data->path);
 		return 0;
 	}
 
@@ -1207,8 +1207,8 @@ int cmd_report(int argc, const char **argv)
 			input_name = "perf.data";
 	}
 
-	data.file.path = input_name;
-	data.force     = symbol_conf.force;
+	data.path  = input_name;
+	data.force = symbol_conf.force;
 
 repeat:
 	session = perf_session__new(&data, false, &report.tool);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 640558e9352e..275f2d92a7bf 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1785,11 +1785,9 @@ static int perf_sched__read_events(struct perf_sched *sched)
 	};
 	struct perf_session *session;
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = sched->force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = sched->force,
 	};
 	int rc = -1;
 
@@ -2958,11 +2956,9 @@ static int perf_sched__timehist(struct perf_sched *sched)
 		{ "sched:sched_migrate_task", timehist_migrate_task_event, },
 	};
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = sched->force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = sched->force,
 	};
 
 	struct perf_session *session;
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 373ea151dc60..5b1543f42290 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -2951,10 +2951,8 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
 	DIR *scripts_dir, *lang_dir;
 	struct perf_session *session;
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
+		.path = input_name,
+		.mode = PERF_DATA_MODE_READ,
 	};
 	char *temp;
 	int i = 0;
@@ -3427,8 +3425,8 @@ int cmd_script(int argc, const char **argv)
 	argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 
-	data.file.path = input_name;
-	data.force     = symbol_conf.force;
+	data.path  = input_name;
+	data.force = symbol_conf.force;
 
 	if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
 		rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
@@ -3654,7 +3652,7 @@ int cmd_script(int argc, const char **argv)
 			goto out_delete;
 		}
 
-		input = open(data.file.path, O_RDONLY);	/* input_name */
+		input = open(data.path, O_RDONLY);	/* input_name */
 		if (input < 0) {
 			err = -errno;
 			perror("failed to open file");
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index bb24f9c17f9a..7b8f09b0b8bf 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1322,7 +1322,7 @@ static int __cmd_record(int argc, const char **argv)
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 
 	if (output_name)
-		data->file.path = output_name;
+		data->path = output_name;
 
 	if (stat_config.run_count != 1 || forever) {
 		pr_err("Cannot use -r option with perf stat record.\n");
@@ -1523,8 +1523,8 @@ static int __cmd_report(int argc, const char **argv)
 			input_name = "perf.data";
 	}
 
-	perf_stat.data.file.path = input_name;
-	perf_stat.data.mode      = PERF_DATA_MODE_READ;
+	perf_stat.data.path = input_name;
+	perf_stat.data.mode = PERF_DATA_MODE_READ;
 
 	session = perf_session__new(&perf_stat.data, false, &perf_stat.tool);
 	if (session == NULL)
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 775b99833e51..9b98687a27b9 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1602,11 +1602,9 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
 		{ "syscalls:sys_exit_select",		process_exit_poll },
 	};
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = tchart->force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = tchart->force,
 	};
 
 	struct perf_session *session = perf_session__new(&data, false,
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 1a11fe656afc..f5b3a1e9c1dd 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -3154,11 +3154,9 @@ static int trace__replay(struct trace *trace)
 		{ "probe:vfs_getname",	     trace__vfs_getname, },
 	};
 	struct perf_data data = {
-		.file      = {
-			.path = input_name,
-		},
-		.mode      = PERF_DATA_MODE_READ,
-		.force     = trace->force,
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = trace->force,
 	};
 	struct perf_session *session;
 	struct perf_evsel *evsel;
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 2a36fab76994..26af43ad9ddd 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -1578,7 +1578,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
 {
 	struct perf_session *session;
 	struct perf_data data = {
-		.file      = { .path = input, .fd = -1 },
+		.path	   = input,
 		.mode      = PERF_DATA_MODE_READ,
 		.force     = opts->force,
 	};
@@ -1650,7 +1650,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
 
 	fprintf(stderr,
 		"[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
-		data.file.path, path);
+		data.path, path);
 
 	fprintf(stderr,
 		"[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 09eceda17fc2..e16d06ed1100 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -19,11 +19,11 @@ static bool check_pipe(struct perf_data *data)
 	int fd = perf_data__is_read(data) ?
 		 STDIN_FILENO : STDOUT_FILENO;
 
-	if (!data->file.path) {
+	if (!data->path) {
 		if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
 			is_pipe = true;
 	} else {
-		if (!strcmp(data->file.path, "-"))
+		if (!strcmp(data->path, "-"))
 			is_pipe = true;
 	}
 
@@ -37,13 +37,13 @@ static int check_backup(struct perf_data *data)
 {
 	struct stat st;
 
-	if (!stat(data->file.path, &st) && st.st_size) {
+	if (!stat(data->path, &st) && st.st_size) {
 		/* TODO check errors properly */
 		char oldname[PATH_MAX];
 		snprintf(oldname, sizeof(oldname), "%s.old",
-			 data->file.path);
+			 data->path);
 		unlink(oldname);
-		rename(data->file.path, oldname);
+		rename(data->path, oldname);
 	}
 
 	return 0;
@@ -115,8 +115,22 @@ static int open_file(struct perf_data *data)
 	fd = perf_data__is_read(data) ?
 	     open_file_read(data) : open_file_write(data);
 
+	if (fd < 0) {
+		free(data->file.path);
+		return -1;
+	}
+
 	data->file.fd = fd;
-	return fd < 0 ? -1 : 0;
+	return 0;
+}
+
+static int open_file_dup(struct perf_data *data)
+{
+	data->file.path = strdup(data->path);
+	if (!data->file.path)
+		return -ENOMEM;
+
+	return open_file(data);
 }
 
 int perf_data__open(struct perf_data *data)
@@ -124,14 +138,15 @@ int perf_data__open(struct perf_data *data)
 	if (check_pipe(data))
 		return 0;
 
-	if (!data->file.path)
-		data->file.path = "perf.data";
+	if (!data->path)
+		data->path = "perf.data";
 
-	return open_file(data);
+	return open_file_dup(data);
 }
 
 void perf_data__close(struct perf_data *data)
 {
+	free(data->file.path);
 	close(data->file.fd);
 }
 
@@ -159,15 +174,15 @@ int perf_data__switch(struct perf_data *data,
 	if (perf_data__is_read(data))
 		return -EINVAL;
 
-	if (asprintf(&new_filepath, "%s.%s", data->file.path, postfix) < 0)
+	if (asprintf(&new_filepath, "%s.%s", data->path, postfix) < 0)
 		return -ENOMEM;
 
 	/*
 	 * Only fire a warning, don't return error, continue fill
 	 * original file.
 	 */
-	if (rename(data->file.path, new_filepath))
-		pr_warning("Failed to rename %s to %s\n", data->file.path, new_filepath);
+	if (rename(data->path, new_filepath))
+		pr_warning("Failed to rename %s to %s\n", data->path, new_filepath);
 
 	if (!at_exit) {
 		close(data->file.fd);
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 85f9c0dbf982..2bce28117ccf 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -10,12 +10,13 @@ enum perf_data_mode {
 };
 
 struct perf_data_file {
-	const char	*path;
+	char		*path;
 	int		 fd;
 	unsigned long	 size;
 };
 
 struct perf_data {
+	const char		*path;
 	struct perf_data_file	 file;
 	bool			 is_pipe;
 	bool			 force;

^ permalink raw reply related	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2019-02-28  7:59 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-21  9:41 [PATCHv2 00/17] perf record: Add support to store data in directory Jiri Olsa
2019-02-21  9:41 ` [PATCH 01/17] perf data: Move size to struct perf_data_file Jiri Olsa
2019-02-28  7:58   ` [tip:perf/core] " tip-bot for Jiri Olsa
2019-02-21  9:41 ` [PATCH 02/17] perf data: Add global path holder Jiri Olsa
2019-02-22 16:05   ` Arnaldo Carvalho de Melo
2019-02-22 16:07     ` Arnaldo Carvalho de Melo
2019-02-28  7:59   ` [tip:perf/core] " tip-bot for Jiri Olsa
2019-02-21  9:41 ` [PATCH 03/17] perf data: Make check_backup work over directories Jiri Olsa
2019-02-21  9:41 ` [PATCH 04/17] perf data: Fail check_backup in case of error Jiri Olsa
2019-02-21 22:23   ` Andi Kleen
2019-02-22 12:23     ` Jiri Olsa
2019-02-21  9:41 ` [PATCH 05/17] perf data: Add perf_data__(create_dir|close_dir) functions Jiri Olsa
2019-02-23  5:07   ` Namhyung Kim
2019-02-24 13:32     ` Jiri Olsa
2019-02-21  9:41 ` [PATCH 06/17] perf data: Add perf_data__open_dir_data function Jiri Olsa
2019-02-21  9:41 ` [PATCH 07/17] perf data: Add directory support Jiri Olsa
2019-02-21  9:41 ` [PATCH 08/17] perf data: Don't store auxtrace index for directory data file Jiri Olsa
2019-02-21  9:41 ` [PATCH 09/17] perf data: Add perf_data__update_dir function Jiri Olsa
2019-02-21  9:41 ` [PATCH 10/17] perf data: Make perf_data__size to work over directory Jiri Olsa
2019-02-21  9:41 ` [PATCH 11/17] perf header: Add DIR_FORMAT feature to describe directory data Jiri Olsa
2019-02-21  9:41 ` [PATCH 12/17] perf session: Add process callback to reader object Jiri Olsa
2019-02-21  9:41 ` [PATCH 13/17] perf session: Add __perf_session__process_dir_events function Jiri Olsa
2019-02-21  9:41 ` [PATCH 14/17] perf session: Add path to reader object Jiri Olsa
2019-02-21  9:41 ` [PATCH 15/17] perf record: Add --dir option to store data in directory Jiri Olsa
2019-02-21  9:41 ` [PATCH 16/17] perf record: Add --output-dir " Jiri Olsa
2019-02-21  9:41 ` [PATCH 17/17] perf record: Describe perf.data directory format Jiri Olsa

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.