diff options
author | Jiri Olsa <jolsa@redhat.com> | 2013-10-15 10:27:32 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-10-21 16:33:24 -0400 |
commit | f5fc14124c5cefdd052a2b2a6a3f0ed531540113 (patch) | |
tree | 9cef9b2a75334478486869ff002749679a9e488d /tools/perf/builtin-record.c | |
parent | 09600e0f9ebb06235b852a646a3644b7d4a71aca (diff) |
perf tools: Add data object to handle perf data file
This patch is adding 'struct perf_data_file' object as a placeholder for
all attributes regarding perf.data file handling. Changing
perf_session__new to take it as an argument.
The rest of the functionality will be added later to keep this change
simple enough, because all the places using perf_session are changed
now.
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1381847254-28809-2-git-send-email-jolsa@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r-- | tools/perf/builtin-record.c | 61 |
1 files changed, 32 insertions, 29 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index d269dfa3ab08..4ea46ffbfc1c 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "util/symbol.h" | 24 | #include "util/symbol.h" |
25 | #include "util/cpumap.h" | 25 | #include "util/cpumap.h" |
26 | #include "util/thread_map.h" | 26 | #include "util/thread_map.h" |
27 | #include "util/data.h" | ||
27 | 28 | ||
28 | #include <unistd.h> | 29 | #include <unistd.h> |
29 | #include <sched.h> | 30 | #include <sched.h> |
@@ -65,11 +66,10 @@ struct perf_record { | |||
65 | struct perf_tool tool; | 66 | struct perf_tool tool; |
66 | struct perf_record_opts opts; | 67 | struct perf_record_opts opts; |
67 | u64 bytes_written; | 68 | u64 bytes_written; |
68 | const char *output_name; | 69 | struct perf_data_file file; |
69 | struct perf_evlist *evlist; | 70 | struct perf_evlist *evlist; |
70 | struct perf_session *session; | 71 | struct perf_session *session; |
71 | const char *progname; | 72 | const char *progname; |
72 | int output; | ||
73 | int realtime_prio; | 73 | int realtime_prio; |
74 | bool no_buildid; | 74 | bool no_buildid; |
75 | bool no_buildid_cache; | 75 | bool no_buildid_cache; |
@@ -84,8 +84,10 @@ static void advance_output(struct perf_record *rec, size_t size) | |||
84 | 84 | ||
85 | static int write_output(struct perf_record *rec, void *buf, size_t size) | 85 | static int write_output(struct perf_record *rec, void *buf, size_t size) |
86 | { | 86 | { |
87 | struct perf_data_file *file = &rec->file; | ||
88 | |||
87 | while (size) { | 89 | while (size) { |
88 | int ret = write(rec->output, buf, size); | 90 | int ret = write(file->fd, buf, size); |
89 | 91 | ||
90 | if (ret < 0) { | 92 | if (ret < 0) { |
91 | pr_err("failed to write perf data, error: %m\n"); | 93 | pr_err("failed to write perf data, error: %m\n"); |
@@ -248,13 +250,15 @@ out: | |||
248 | 250 | ||
249 | static int process_buildids(struct perf_record *rec) | 251 | static int process_buildids(struct perf_record *rec) |
250 | { | 252 | { |
251 | u64 size = lseek(rec->output, 0, SEEK_CUR); | 253 | struct perf_data_file *file = &rec->file; |
254 | struct perf_session *session = rec->session; | ||
252 | 255 | ||
256 | u64 size = lseek(file->fd, 0, SEEK_CUR); | ||
253 | if (size == 0) | 257 | if (size == 0) |
254 | return 0; | 258 | return 0; |
255 | 259 | ||
256 | rec->session->fd = rec->output; | 260 | session->fd = file->fd; |
257 | return __perf_session__process_events(rec->session, rec->post_processing_offset, | 261 | return __perf_session__process_events(session, rec->post_processing_offset, |
258 | size - rec->post_processing_offset, | 262 | size - rec->post_processing_offset, |
259 | size, &build_id__mark_dso_hit_ops); | 263 | size, &build_id__mark_dso_hit_ops); |
260 | } | 264 | } |
@@ -262,17 +266,18 @@ static int process_buildids(struct perf_record *rec) | |||
262 | static void perf_record__exit(int status, void *arg) | 266 | static void perf_record__exit(int status, void *arg) |
263 | { | 267 | { |
264 | struct perf_record *rec = arg; | 268 | struct perf_record *rec = arg; |
269 | struct perf_data_file *file = &rec->file; | ||
265 | 270 | ||
266 | if (status != 0) | 271 | if (status != 0) |
267 | return; | 272 | return; |
268 | 273 | ||
269 | if (!rec->opts.pipe_output) { | 274 | if (!file->is_pipe) { |
270 | rec->session->header.data_size += rec->bytes_written; | 275 | rec->session->header.data_size += rec->bytes_written; |
271 | 276 | ||
272 | if (!rec->no_buildid) | 277 | if (!rec->no_buildid) |
273 | process_buildids(rec); | 278 | process_buildids(rec); |
274 | perf_session__write_header(rec->session, rec->evlist, | 279 | perf_session__write_header(rec->session, rec->evlist, |
275 | rec->output, true); | 280 | file->fd, true); |
276 | perf_session__delete(rec->session); | 281 | perf_session__delete(rec->session); |
277 | perf_evlist__delete(rec->evlist); | 282 | perf_evlist__delete(rec->evlist); |
278 | symbol__exit(); | 283 | symbol__exit(); |
@@ -342,14 +347,15 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
342 | { | 347 | { |
343 | struct stat st; | 348 | struct stat st; |
344 | int flags; | 349 | int flags; |
345 | int err, output, feat; | 350 | int err, feat; |
346 | unsigned long waking = 0; | 351 | unsigned long waking = 0; |
347 | const bool forks = argc > 0; | 352 | const bool forks = argc > 0; |
348 | struct machine *machine; | 353 | struct machine *machine; |
349 | struct perf_tool *tool = &rec->tool; | 354 | struct perf_tool *tool = &rec->tool; |
350 | struct perf_record_opts *opts = &rec->opts; | 355 | struct perf_record_opts *opts = &rec->opts; |
351 | struct perf_evlist *evsel_list = rec->evlist; | 356 | struct perf_evlist *evsel_list = rec->evlist; |
352 | const char *output_name = rec->output_name; | 357 | struct perf_data_file *file = &rec->file; |
358 | const char *output_name = file->path; | ||
353 | struct perf_session *session; | 359 | struct perf_session *session; |
354 | bool disabled = false; | 360 | bool disabled = false; |
355 | 361 | ||
@@ -363,13 +369,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
363 | 369 | ||
364 | if (!output_name) { | 370 | if (!output_name) { |
365 | if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) | 371 | if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) |
366 | opts->pipe_output = true; | 372 | file->is_pipe = true; |
367 | else | 373 | else |
368 | rec->output_name = output_name = "perf.data"; | 374 | file->path = output_name = "perf.data"; |
369 | } | 375 | } |
370 | if (output_name) { | 376 | if (output_name) { |
371 | if (!strcmp(output_name, "-")) | 377 | if (!strcmp(output_name, "-")) |
372 | opts->pipe_output = true; | 378 | file->is_pipe = true; |
373 | else if (!stat(output_name, &st) && st.st_size) { | 379 | else if (!stat(output_name, &st) && st.st_size) { |
374 | char oldname[PATH_MAX]; | 380 | char oldname[PATH_MAX]; |
375 | snprintf(oldname, sizeof(oldname), "%s.old", | 381 | snprintf(oldname, sizeof(oldname), "%s.old", |
@@ -381,19 +387,16 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
381 | 387 | ||
382 | flags = O_CREAT|O_RDWR|O_TRUNC; | 388 | flags = O_CREAT|O_RDWR|O_TRUNC; |
383 | 389 | ||
384 | if (opts->pipe_output) | 390 | if (file->is_pipe) |
385 | output = STDOUT_FILENO; | 391 | file->fd = STDOUT_FILENO; |
386 | else | 392 | else |
387 | output = open(output_name, flags, S_IRUSR | S_IWUSR); | 393 | file->fd = open(output_name, flags, S_IRUSR | S_IWUSR); |
388 | if (output < 0) { | 394 | if (file->fd < 0) { |
389 | perror("failed to create output file"); | 395 | perror("failed to create output file"); |
390 | return -1; | 396 | return -1; |
391 | } | 397 | } |
392 | 398 | ||
393 | rec->output = output; | 399 | session = perf_session__new(file, false, NULL); |
394 | |||
395 | session = perf_session__new(output_name, O_WRONLY, | ||
396 | true, false, NULL); | ||
397 | if (session == NULL) { | 400 | if (session == NULL) { |
398 | pr_err("Not enough memory for reading perf file header\n"); | 401 | pr_err("Not enough memory for reading perf file header\n"); |
399 | return -1; | 402 | return -1; |
@@ -415,7 +418,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
415 | 418 | ||
416 | if (forks) { | 419 | if (forks) { |
417 | err = perf_evlist__prepare_workload(evsel_list, &opts->target, | 420 | err = perf_evlist__prepare_workload(evsel_list, &opts->target, |
418 | argv, opts->pipe_output, | 421 | argv, file->is_pipe, |
419 | true); | 422 | true); |
420 | if (err < 0) { | 423 | if (err < 0) { |
421 | pr_err("Couldn't run the workload!\n"); | 424 | pr_err("Couldn't run the workload!\n"); |
@@ -436,13 +439,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
436 | */ | 439 | */ |
437 | on_exit(perf_record__exit, rec); | 440 | on_exit(perf_record__exit, rec); |
438 | 441 | ||
439 | if (opts->pipe_output) { | 442 | if (file->is_pipe) { |
440 | err = perf_header__write_pipe(output); | 443 | err = perf_header__write_pipe(file->fd); |
441 | if (err < 0) | 444 | if (err < 0) |
442 | goto out_delete_session; | 445 | goto out_delete_session; |
443 | } else { | 446 | } else { |
444 | err = perf_session__write_header(session, evsel_list, | 447 | err = perf_session__write_header(session, evsel_list, |
445 | output, false); | 448 | file->fd, false); |
446 | if (err < 0) | 449 | if (err < 0) |
447 | goto out_delete_session; | 450 | goto out_delete_session; |
448 | } | 451 | } |
@@ -455,11 +458,11 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
455 | goto out_delete_session; | 458 | goto out_delete_session; |
456 | } | 459 | } |
457 | 460 | ||
458 | rec->post_processing_offset = lseek(output, 0, SEEK_CUR); | 461 | rec->post_processing_offset = lseek(file->fd, 0, SEEK_CUR); |
459 | 462 | ||
460 | machine = &session->machines.host; | 463 | machine = &session->machines.host; |
461 | 464 | ||
462 | if (opts->pipe_output) { | 465 | if (file->is_pipe) { |
463 | err = perf_event__synthesize_attrs(tool, session, | 466 | err = perf_event__synthesize_attrs(tool, session, |
464 | process_synthesized_event); | 467 | process_synthesized_event); |
465 | if (err < 0) { | 468 | if (err < 0) { |
@@ -476,7 +479,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
476 | * return this more properly and also | 479 | * return this more properly and also |
477 | * propagate errors that now are calling die() | 480 | * propagate errors that now are calling die() |
478 | */ | 481 | */ |
479 | err = perf_event__synthesize_tracing_data(tool, output, evsel_list, | 482 | err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list, |
480 | process_synthesized_event); | 483 | process_synthesized_event); |
481 | if (err <= 0) { | 484 | if (err <= 0) { |
482 | pr_err("Couldn't record tracing data.\n"); | 485 | pr_err("Couldn't record tracing data.\n"); |
@@ -845,7 +848,7 @@ const struct option record_options[] = { | |||
845 | OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", | 848 | OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", |
846 | "list of cpus to monitor"), | 849 | "list of cpus to monitor"), |
847 | OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), | 850 | OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), |
848 | OPT_STRING('o', "output", &record.output_name, "file", | 851 | OPT_STRING('o', "output", &record.file.path, "file", |
849 | "output file name"), | 852 | "output file name"), |
850 | OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, | 853 | OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, |
851 | "child tasks do not inherit counters"), | 854 | "child tasks do not inherit counters"), |