aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-record.c158
1 files changed, 109 insertions, 49 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 479ff2a038fc..7b8b891d4d56 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -71,19 +71,23 @@ static void advance_output(struct perf_record *rec, size_t size)
71 rec->bytes_written += size; 71 rec->bytes_written += size;
72} 72}
73 73
74static void write_output(struct perf_record *rec, void *buf, size_t size) 74static int write_output(struct perf_record *rec, void *buf, size_t size)
75{ 75{
76 while (size) { 76 while (size) {
77 int ret = write(rec->output, buf, size); 77 int ret = write(rec->output, buf, size);
78 78
79 if (ret < 0) 79 if (ret < 0) {
80 die("failed to write"); 80 pr_err("failed to write\n");
81 return -1;
82 }
81 83
82 size -= ret; 84 size -= ret;
83 buf += ret; 85 buf += ret;
84 86
85 rec->bytes_written += ret; 87 rec->bytes_written += ret;
86 } 88 }
89
90 return 0;
87} 91}
88 92
89static int process_synthesized_event(struct perf_tool *tool, 93static int process_synthesized_event(struct perf_tool *tool,
@@ -92,11 +96,13 @@ static int process_synthesized_event(struct perf_tool *tool,
92 struct machine *machine __used) 96 struct machine *machine __used)
93{ 97{
94 struct perf_record *rec = container_of(tool, struct perf_record, tool); 98 struct perf_record *rec = container_of(tool, struct perf_record, tool);
95 write_output(rec, event, event->header.size); 99 if (write_output(rec, event, event->header.size) < 0)
100 return -1;
101
96 return 0; 102 return 0;
97} 103}
98 104
99static void perf_record__mmap_read(struct perf_record *rec, 105static int perf_record__mmap_read(struct perf_record *rec,
100 struct perf_mmap *md) 106 struct perf_mmap *md)
101{ 107{
102 unsigned int head = perf_mmap__read_head(md); 108 unsigned int head = perf_mmap__read_head(md);
@@ -104,9 +110,10 @@ static void perf_record__mmap_read(struct perf_record *rec,
104 unsigned char *data = md->base + rec->page_size; 110 unsigned char *data = md->base + rec->page_size;
105 unsigned long size; 111 unsigned long size;
106 void *buf; 112 void *buf;
113 int rc = 0;
107 114
108 if (old == head) 115 if (old == head)
109 return; 116 return 0;
110 117
111 rec->samples++; 118 rec->samples++;
112 119
@@ -117,17 +124,26 @@ static void perf_record__mmap_read(struct perf_record *rec,
117 size = md->mask + 1 - (old & md->mask); 124 size = md->mask + 1 - (old & md->mask);
118 old += size; 125 old += size;
119 126
120 write_output(rec, buf, size); 127 if (write_output(rec, buf, size) < 0) {
128 rc = -1;
129 goto out;
130 }
121 } 131 }
122 132
123 buf = &data[old & md->mask]; 133 buf = &data[old & md->mask];
124 size = head - old; 134 size = head - old;
125 old += size; 135 old += size;
126 136
127 write_output(rec, buf, size); 137 if (write_output(rec, buf, size) < 0) {
138 rc = -1;
139 goto out;
140 }
128 141
129 md->prev = old; 142 md->prev = old;
130 perf_mmap__write_tail(md, old); 143 perf_mmap__write_tail(md, old);
144
145out:
146 return rc;
131} 147}
132 148
133static volatile int done = 0; 149static volatile int done = 0;
@@ -183,12 +199,13 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
183 return true; 199 return true;
184} 200}
185 201
186static void perf_record__open(struct perf_record *rec) 202static int perf_record__open(struct perf_record *rec)
187{ 203{
188 struct perf_evsel *pos; 204 struct perf_evsel *pos;
189 struct perf_evlist *evlist = rec->evlist; 205 struct perf_evlist *evlist = rec->evlist;
190 struct perf_session *session = rec->session; 206 struct perf_session *session = rec->session;
191 struct perf_record_opts *opts = &rec->opts; 207 struct perf_record_opts *opts = &rec->opts;
208 int rc = 0;
192 209
193 perf_evlist__config_attrs(evlist, opts); 210 perf_evlist__config_attrs(evlist, opts);
194 211
@@ -222,10 +239,13 @@ try_again:
222 239
223 if (err == EPERM || err == EACCES) { 240 if (err == EPERM || err == EACCES) {
224 ui__error_paranoid(); 241 ui__error_paranoid();
225 exit(EXIT_FAILURE); 242 rc = -err;
243 goto out;
226 } else if (err == ENODEV && opts->target.cpu_list) { 244 } else if (err == ENODEV && opts->target.cpu_list) {
227 die("No such device - did you specify" 245 pr_err("No such device - did you specify"
228 " an out-of-range profile CPU?\n"); 246 " an out-of-range profile CPU?\n");
247 rc = -err;
248 goto out;
229 } else if (err == EINVAL) { 249 } else if (err == EINVAL) {
230 if (!opts->exclude_guest_missing && 250 if (!opts->exclude_guest_missing &&
231 (attr->exclude_guest || attr->exclude_host)) { 251 (attr->exclude_guest || attr->exclude_host)) {
@@ -272,7 +292,8 @@ try_again:
272 if (err == ENOENT) { 292 if (err == ENOENT) {
273 ui__error("The %s event is not supported.\n", 293 ui__error("The %s event is not supported.\n",
274 perf_evsel__name(pos)); 294 perf_evsel__name(pos));
275 exit(EXIT_FAILURE); 295 rc = -err;
296 goto out;
276 } 297 }
277 298
278 printf("\n"); 299 printf("\n");
@@ -280,34 +301,46 @@ try_again:
280 err, strerror(err)); 301 err, strerror(err));
281 302
282#if defined(__i386__) || defined(__x86_64__) 303#if defined(__i386__) || defined(__x86_64__)
283 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 304 if (attr->type == PERF_TYPE_HARDWARE &&
284 die("No hardware sampling interrupt available." 305 err == EOPNOTSUPP) {
285 " No APIC? If so then you can boot the kernel" 306 pr_err("No hardware sampling interrupt available."
286 " with the \"lapic\" boot parameter to" 307 " No APIC? If so then you can boot the kernel"
287 " force-enable it.\n"); 308 " with the \"lapic\" boot parameter to"
309 " force-enable it.\n");
310 rc = -err;
311 goto out;
312 }
288#endif 313#endif
289 314
290 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 315 pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
316 rc = -err;
317 goto out;
291 } 318 }
292 } 319 }
293 320
294 if (perf_evlist__set_filters(evlist)) { 321 if (perf_evlist__set_filters(evlist)) {
295 error("failed to set filter with %d (%s)\n", errno, 322 error("failed to set filter with %d (%s)\n", errno,
296 strerror(errno)); 323 strerror(errno));
297 exit(-1); 324 rc = -1;
325 goto out;
298 } 326 }
299 327
300 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 328 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
301 if (errno == EPERM) 329 if (errno == EPERM) {
302 die("Permission error mapping pages.\n" 330 pr_err("Permission error mapping pages.\n"
303 "Consider increasing " 331 "Consider increasing "
304 "/proc/sys/kernel/perf_event_mlock_kb,\n" 332 "/proc/sys/kernel/perf_event_mlock_kb,\n"
305 "or try again with a smaller value of -m/--mmap_pages.\n" 333 "or try again with a smaller value of -m/--mmap_pages.\n"
306 "(current value: %d)\n", opts->mmap_pages); 334 "(current value: %d)\n", opts->mmap_pages);
307 else if (!is_power_of_2(opts->mmap_pages)) 335 rc = -errno;
308 die("--mmap_pages/-m value must be a power of two."); 336 } else if (!is_power_of_2(opts->mmap_pages)) {
309 337 pr_err("--mmap_pages/-m value must be a power of two.");
310 die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 338 rc = -EINVAL;
339 } else {
340 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
341 rc = -errno;
342 }
343 goto out;
311 } 344 }
312 345
313 if (rec->file_new) 346 if (rec->file_new)
@@ -315,11 +348,14 @@ try_again:
315 else { 348 else {
316 if (!perf_evlist__equal(session->evlist, evlist)) { 349 if (!perf_evlist__equal(session->evlist, evlist)) {
317 fprintf(stderr, "incompatible append\n"); 350 fprintf(stderr, "incompatible append\n");
318 exit(-1); 351 rc = -1;
352 goto out;
319 } 353 }
320 } 354 }
321 355
322 perf_session__set_id_hdr_size(session); 356 perf_session__set_id_hdr_size(session);
357out:
358 return rc;
323} 359}
324 360
325static int process_buildids(struct perf_record *rec) 361static int process_buildids(struct perf_record *rec)
@@ -335,10 +371,13 @@ static int process_buildids(struct perf_record *rec)
335 size, &build_id__mark_dso_hit_ops); 371 size, &build_id__mark_dso_hit_ops);
336} 372}
337 373
338static void perf_record__exit(int status __used, void *arg) 374static void perf_record__exit(int status, void *arg)
339{ 375{
340 struct perf_record *rec = arg; 376 struct perf_record *rec = arg;
341 377
378 if (status != 0)
379 return;
380
342 if (!rec->opts.pipe_output) { 381 if (!rec->opts.pipe_output) {
343 rec->session->header.data_size += rec->bytes_written; 382 rec->session->header.data_size += rec->bytes_written;
344 383
@@ -393,17 +432,26 @@ static struct perf_event_header finished_round_event = {
393 .type = PERF_RECORD_FINISHED_ROUND, 432 .type = PERF_RECORD_FINISHED_ROUND,
394}; 433};
395 434
396static void perf_record__mmap_read_all(struct perf_record *rec) 435static int perf_record__mmap_read_all(struct perf_record *rec)
397{ 436{
398 int i; 437 int i;
438 int rc = 0;
399 439
400 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 440 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
401 if (rec->evlist->mmap[i].base) 441 if (rec->evlist->mmap[i].base) {
402 perf_record__mmap_read(rec, &rec->evlist->mmap[i]); 442 if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
443 rc = -1;
444 goto out;
445 }
446 }
403 } 447 }
404 448
405 if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 449 if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
406 write_output(rec, &finished_round_event, sizeof(finished_round_event)); 450 rc = write_output(rec, &finished_round_event,
451 sizeof(finished_round_event));
452
453out:
454 return rc;
407} 455}
408 456
409static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 457static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
@@ -463,7 +511,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
463 output = open(output_name, flags, S_IRUSR | S_IWUSR); 511 output = open(output_name, flags, S_IRUSR | S_IWUSR);
464 if (output < 0) { 512 if (output < 0) {
465 perror("failed to create output file"); 513 perror("failed to create output file");
466 exit(-1); 514 return -1;
467 } 515 }
468 516
469 rec->output = output; 517 rec->output = output;
@@ -503,7 +551,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
503 } 551 }
504 } 552 }
505 553
506 perf_record__open(rec); 554 if (perf_record__open(rec) != 0) {
555 err = -1;
556 goto out_delete_session;
557 }
507 558
508 /* 559 /*
509 * perf_session__delete(session) will be called at perf_record__exit() 560 * perf_session__delete(session) will be called at perf_record__exit()
@@ -513,19 +564,20 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
513 if (opts->pipe_output) { 564 if (opts->pipe_output) {
514 err = perf_header__write_pipe(output); 565 err = perf_header__write_pipe(output);
515 if (err < 0) 566 if (err < 0)
516 return err; 567 goto out_delete_session;
517 } else if (rec->file_new) { 568 } else if (rec->file_new) {
518 err = perf_session__write_header(session, evsel_list, 569 err = perf_session__write_header(session, evsel_list,
519 output, false); 570 output, false);
520 if (err < 0) 571 if (err < 0)
521 return err; 572 goto out_delete_session;
522 } 573 }
523 574
524 if (!rec->no_buildid 575 if (!rec->no_buildid
525 && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 576 && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
526 pr_err("Couldn't generate buildids. " 577 pr_err("Couldn't generate buildids. "
527 "Use --no-buildid to profile anyway.\n"); 578 "Use --no-buildid to profile anyway.\n");
528 return -1; 579 err = -1;
580 goto out_delete_session;
529 } 581 }
530 582
531 rec->post_processing_offset = lseek(output, 0, SEEK_CUR); 583 rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
@@ -533,7 +585,8 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
533 machine = perf_session__find_host_machine(session); 585 machine = perf_session__find_host_machine(session);
534 if (!machine) { 586 if (!machine) {
535 pr_err("Couldn't find native kernel information.\n"); 587 pr_err("Couldn't find native kernel information.\n");
536 return -1; 588 err = -1;
589 goto out_delete_session;
537 } 590 }
538 591
539 if (opts->pipe_output) { 592 if (opts->pipe_output) {
@@ -541,14 +594,14 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
541 process_synthesized_event); 594 process_synthesized_event);
542 if (err < 0) { 595 if (err < 0) {
543 pr_err("Couldn't synthesize attrs.\n"); 596 pr_err("Couldn't synthesize attrs.\n");
544 return err; 597 goto out_delete_session;
545 } 598 }
546 599
547 err = perf_event__synthesize_event_types(tool, process_synthesized_event, 600 err = perf_event__synthesize_event_types(tool, process_synthesized_event,
548 machine); 601 machine);
549 if (err < 0) { 602 if (err < 0) {
550 pr_err("Couldn't synthesize event_types.\n"); 603 pr_err("Couldn't synthesize event_types.\n");
551 return err; 604 goto out_delete_session;
552 } 605 }
553 606
554 if (have_tracepoints(&evsel_list->entries)) { 607 if (have_tracepoints(&evsel_list->entries)) {
@@ -564,7 +617,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
564 process_synthesized_event); 617 process_synthesized_event);
565 if (err <= 0) { 618 if (err <= 0) {
566 pr_err("Couldn't record tracing data.\n"); 619 pr_err("Couldn't record tracing data.\n");
567 return err; 620 goto out_delete_session;
568 } 621 }
569 advance_output(rec, err); 622 advance_output(rec, err);
570 } 623 }
@@ -592,20 +645,24 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
592 perf_event__synthesize_guest_os); 645 perf_event__synthesize_guest_os);
593 646
594 if (!opts->target.system_wide) 647 if (!opts->target.system_wide)
595 perf_event__synthesize_thread_map(tool, evsel_list->threads, 648 err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
596 process_synthesized_event, 649 process_synthesized_event,
597 machine); 650 machine);
598 else 651 else
599 perf_event__synthesize_threads(tool, process_synthesized_event, 652 err = perf_event__synthesize_threads(tool, process_synthesized_event,
600 machine); 653 machine);
601 654
655 if (err != 0)
656 goto out_delete_session;
657
602 if (rec->realtime_prio) { 658 if (rec->realtime_prio) {
603 struct sched_param param; 659 struct sched_param param;
604 660
605 param.sched_priority = rec->realtime_prio; 661 param.sched_priority = rec->realtime_prio;
606 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 662 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
607 pr_err("Could not set realtime priority.\n"); 663 pr_err("Could not set realtime priority.\n");
608 exit(-1); 664 err = -1;
665 goto out_delete_session;
609 } 666 }
610 } 667 }
611 668
@@ -620,7 +677,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
620 for (;;) { 677 for (;;) {
621 int hits = rec->samples; 678 int hits = rec->samples;
622 679
623 perf_record__mmap_read_all(rec); 680 if (perf_record__mmap_read_all(rec) < 0) {
681 err = -1;
682 goto out_delete_session;
683 }
624 684
625 if (hits == rec->samples) { 685 if (hits == rec->samples) {
626 if (done) 686 if (done)