diff options
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r-- | tools/perf/builtin-record.c | 70 |
1 files changed, 48 insertions, 22 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8648c6d3003d..404ab3434052 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -190,16 +190,30 @@ out: | |||
190 | return rc; | 190 | return rc; |
191 | } | 191 | } |
192 | 192 | ||
193 | static int process_sample_event(struct perf_tool *tool, | ||
194 | union perf_event *event, | ||
195 | struct perf_sample *sample, | ||
196 | struct perf_evsel *evsel, | ||
197 | struct machine *machine) | ||
198 | { | ||
199 | struct record *rec = container_of(tool, struct record, tool); | ||
200 | |||
201 | rec->samples++; | ||
202 | |||
203 | return build_id__mark_dso_hit(tool, event, sample, evsel, machine); | ||
204 | } | ||
205 | |||
193 | static int process_buildids(struct record *rec) | 206 | static int process_buildids(struct record *rec) |
194 | { | 207 | { |
195 | struct perf_data_file *file = &rec->file; | 208 | struct perf_data_file *file = &rec->file; |
196 | struct perf_session *session = rec->session; | 209 | struct perf_session *session = rec->session; |
197 | u64 start = session->header.data_offset; | ||
198 | 210 | ||
199 | u64 size = lseek(file->fd, 0, SEEK_CUR); | 211 | u64 size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); |
200 | if (size == 0) | 212 | if (size == 0) |
201 | return 0; | 213 | return 0; |
202 | 214 | ||
215 | file->size = size; | ||
216 | |||
203 | /* | 217 | /* |
204 | * During this process, it'll load kernel map and replace the | 218 | * During this process, it'll load kernel map and replace the |
205 | * dso->long_name to a real pathname it found. In this case | 219 | * dso->long_name to a real pathname it found. In this case |
@@ -211,9 +225,7 @@ static int process_buildids(struct record *rec) | |||
211 | */ | 225 | */ |
212 | symbol_conf.ignore_vmlinux_buildid = true; | 226 | symbol_conf.ignore_vmlinux_buildid = true; |
213 | 227 | ||
214 | return __perf_session__process_events(session, start, | 228 | return perf_session__process_events(session, &rec->tool); |
215 | size - start, | ||
216 | size, &build_id__mark_dso_hit_ops); | ||
217 | } | 229 | } |
218 | 230 | ||
219 | static void perf_event__synthesize_guest_os(struct machine *machine, void *data) | 231 | static void perf_event__synthesize_guest_os(struct machine *machine, void *data) |
@@ -322,6 +334,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
322 | struct perf_data_file *file = &rec->file; | 334 | struct perf_data_file *file = &rec->file; |
323 | struct perf_session *session; | 335 | struct perf_session *session; |
324 | bool disabled = false, draining = false; | 336 | bool disabled = false, draining = false; |
337 | int fd; | ||
325 | 338 | ||
326 | rec->progname = argv[0]; | 339 | rec->progname = argv[0]; |
327 | 340 | ||
@@ -336,6 +349,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
336 | return -1; | 349 | return -1; |
337 | } | 350 | } |
338 | 351 | ||
352 | fd = perf_data_file__fd(file); | ||
339 | rec->session = session; | 353 | rec->session = session; |
340 | 354 | ||
341 | record__init_features(rec); | 355 | record__init_features(rec); |
@@ -360,12 +374,11 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
360 | perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); | 374 | perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); |
361 | 375 | ||
362 | if (file->is_pipe) { | 376 | if (file->is_pipe) { |
363 | err = perf_header__write_pipe(file->fd); | 377 | err = perf_header__write_pipe(fd); |
364 | if (err < 0) | 378 | if (err < 0) |
365 | goto out_child; | 379 | goto out_child; |
366 | } else { | 380 | } else { |
367 | err = perf_session__write_header(session, rec->evlist, | 381 | err = perf_session__write_header(session, rec->evlist, fd, false); |
368 | file->fd, false); | ||
369 | if (err < 0) | 382 | if (err < 0) |
370 | goto out_child; | 383 | goto out_child; |
371 | } | 384 | } |
@@ -397,7 +410,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
397 | * return this more properly and also | 410 | * return this more properly and also |
398 | * propagate errors that now are calling die() | 411 | * propagate errors that now are calling die() |
399 | */ | 412 | */ |
400 | err = perf_event__synthesize_tracing_data(tool, file->fd, rec->evlist, | 413 | err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, |
401 | process_synthesized_event); | 414 | process_synthesized_event); |
402 | if (err <= 0) { | 415 | if (err <= 0) { |
403 | pr_err("Couldn't record tracing data.\n"); | 416 | pr_err("Couldn't record tracing data.\n"); |
@@ -504,19 +517,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
504 | goto out_child; | 517 | goto out_child; |
505 | } | 518 | } |
506 | 519 | ||
507 | if (!quiet) { | 520 | if (!quiet) |
508 | fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); | 521 | fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); |
509 | 522 | ||
510 | /* | ||
511 | * Approximate RIP event size: 24 bytes. | ||
512 | */ | ||
513 | fprintf(stderr, | ||
514 | "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", | ||
515 | (double)rec->bytes_written / 1024.0 / 1024.0, | ||
516 | file->path, | ||
517 | rec->bytes_written / 24); | ||
518 | } | ||
519 | |||
520 | out_child: | 523 | out_child: |
521 | if (forks) { | 524 | if (forks) { |
522 | int exit_status; | 525 | int exit_status; |
@@ -535,13 +538,29 @@ out_child: | |||
535 | } else | 538 | } else |
536 | status = err; | 539 | status = err; |
537 | 540 | ||
541 | /* this will be recalculated during process_buildids() */ | ||
542 | rec->samples = 0; | ||
543 | |||
538 | if (!err && !file->is_pipe) { | 544 | if (!err && !file->is_pipe) { |
539 | rec->session->header.data_size += rec->bytes_written; | 545 | rec->session->header.data_size += rec->bytes_written; |
540 | 546 | ||
541 | if (!rec->no_buildid) | 547 | if (!rec->no_buildid) |
542 | process_buildids(rec); | 548 | process_buildids(rec); |
543 | perf_session__write_header(rec->session, rec->evlist, | 549 | perf_session__write_header(rec->session, rec->evlist, fd, true); |
544 | file->fd, true); | 550 | } |
551 | |||
552 | if (!err && !quiet) { | ||
553 | char samples[128]; | ||
554 | |||
555 | if (rec->samples) | ||
556 | scnprintf(samples, sizeof(samples), | ||
557 | " (%" PRIu64 " samples)", rec->samples); | ||
558 | else | ||
559 | samples[0] = '\0'; | ||
560 | |||
561 | fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", | ||
562 | perf_data_file__size(file) / 1024.0 / 1024.0, | ||
563 | file->path, samples); | ||
545 | } | 564 | } |
546 | 565 | ||
547 | out_delete_session: | 566 | out_delete_session: |
@@ -720,6 +739,13 @@ static struct record record = { | |||
720 | .default_per_cpu = true, | 739 | .default_per_cpu = true, |
721 | }, | 740 | }, |
722 | }, | 741 | }, |
742 | .tool = { | ||
743 | .sample = process_sample_event, | ||
744 | .fork = perf_event__process_fork, | ||
745 | .comm = perf_event__process_comm, | ||
746 | .mmap = perf_event__process_mmap, | ||
747 | .mmap2 = perf_event__process_mmap2, | ||
748 | }, | ||
723 | }; | 749 | }; |
724 | 750 | ||
725 | #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " | 751 | #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " |