* [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 +
| 44 ++++++++++++++++++++++++++++++++++++-
| 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;
--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 {
--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, ×tamp);
+ 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.