diff options
-rw-r--r-- | tools/perf/util/header.c | 27 | ||||
-rw-r--r-- | tools/perf/util/trace-event-info.c | 112 | ||||
-rw-r--r-- | tools/perf/util/trace-event.h | 13 |
3 files changed, 123 insertions, 29 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 6a9c041134bb..76c0b2c49eb8 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -2218,15 +2218,29 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, | |||
2218 | struct perf_session *session __unused) | 2218 | struct perf_session *session __unused) |
2219 | { | 2219 | { |
2220 | union perf_event ev; | 2220 | union perf_event ev; |
2221 | struct tracing_data *tdata; | ||
2221 | ssize_t size = 0, aligned_size = 0, padding; | 2222 | ssize_t size = 0, aligned_size = 0, padding; |
2222 | int err __used = 0; | 2223 | int err __used = 0; |
2223 | 2224 | ||
2225 | /* | ||
2226 | * We are going to store the size of the data followed | ||
2227 | * by the data contents. Since the fd descriptor is a pipe, | ||
2228 | * we cannot seek back to store the size of the data once | ||
2229 | * we know it. Instead we: | ||
2230 | * | ||
2231 | * - write the tracing data to the temp file | ||
2232 | * - get/write the data size to pipe | ||
2233 | * - write the tracing data from the temp file | ||
2234 | * to the pipe | ||
2235 | */ | ||
2236 | tdata = tracing_data_get(&evlist->entries, fd, true); | ||
2237 | if (!tdata) | ||
2238 | return -1; | ||
2239 | |||
2224 | memset(&ev, 0, sizeof(ev)); | 2240 | memset(&ev, 0, sizeof(ev)); |
2225 | 2241 | ||
2226 | ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; | 2242 | ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; |
2227 | size = read_tracing_data_size(fd, &evlist->entries); | 2243 | size = tdata->size; |
2228 | if (size <= 0) | ||
2229 | return size; | ||
2230 | aligned_size = ALIGN(size, sizeof(u64)); | 2244 | aligned_size = ALIGN(size, sizeof(u64)); |
2231 | padding = aligned_size - size; | 2245 | padding = aligned_size - size; |
2232 | ev.tracing_data.header.size = sizeof(ev.tracing_data); | 2246 | ev.tracing_data.header.size = sizeof(ev.tracing_data); |
@@ -2234,7 +2248,12 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, | |||
2234 | 2248 | ||
2235 | process(&ev, NULL, session); | 2249 | process(&ev, NULL, session); |
2236 | 2250 | ||
2237 | err = read_tracing_data(fd, &evlist->entries); | 2251 | /* |
2252 | * The put function will copy all the tracing data | ||
2253 | * stored in temp file to the pipe. | ||
2254 | */ | ||
2255 | tracing_data_put(tdata); | ||
2256 | |||
2238 | write_padded(fd, NULL, 0, padding); | 2257 | write_padded(fd, NULL, 0, padding); |
2239 | 2258 | ||
2240 | return aligned_size; | 2259 | return aligned_size; |
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 3403f814ad72..2d530cf74f43 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c | |||
@@ -196,7 +196,8 @@ static void record_file(const char *file, size_t hdr_sz) | |||
196 | die("Can't read '%s'", file); | 196 | die("Can't read '%s'", file); |
197 | 197 | ||
198 | /* put in zeros for file size, then fill true size later */ | 198 | /* put in zeros for file size, then fill true size later */ |
199 | write_or_die(&size, hdr_sz); | 199 | if (hdr_sz) |
200 | write_or_die(&size, hdr_sz); | ||
200 | 201 | ||
201 | do { | 202 | do { |
202 | r = read(fd, buf, BUFSIZ); | 203 | r = read(fd, buf, BUFSIZ); |
@@ -212,7 +213,7 @@ static void record_file(const char *file, size_t hdr_sz) | |||
212 | if (bigendian()) | 213 | if (bigendian()) |
213 | sizep += sizeof(u64) - hdr_sz; | 214 | sizep += sizeof(u64) - hdr_sz; |
214 | 215 | ||
215 | if (pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0) | 216 | if (hdr_sz && pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0) |
216 | die("writing to %s", output_file); | 217 | die("writing to %s", output_file); |
217 | } | 218 | } |
218 | 219 | ||
@@ -428,6 +429,19 @@ get_tracepoints_path(struct list_head *pattrs) | |||
428 | return nr_tracepoints > 0 ? path.next : NULL; | 429 | return nr_tracepoints > 0 ? path.next : NULL; |
429 | } | 430 | } |
430 | 431 | ||
432 | static void | ||
433 | put_tracepoints_path(struct tracepoint_path *tps) | ||
434 | { | ||
435 | while (tps) { | ||
436 | struct tracepoint_path *t = tps; | ||
437 | |||
438 | tps = tps->next; | ||
439 | free(t->name); | ||
440 | free(t->system); | ||
441 | free(t); | ||
442 | } | ||
443 | } | ||
444 | |||
431 | bool have_tracepoints(struct list_head *pattrs) | 445 | bool have_tracepoints(struct list_head *pattrs) |
432 | { | 446 | { |
433 | struct perf_evsel *pos; | 447 | struct perf_evsel *pos; |
@@ -439,19 +453,11 @@ bool have_tracepoints(struct list_head *pattrs) | |||
439 | return false; | 453 | return false; |
440 | } | 454 | } |
441 | 455 | ||
442 | int read_tracing_data(int fd, struct list_head *pattrs) | 456 | static void tracing_data_header(void) |
443 | { | 457 | { |
444 | char buf[BUFSIZ]; | 458 | char buf[20]; |
445 | struct tracepoint_path *tps = get_tracepoints_path(pattrs); | ||
446 | |||
447 | /* | ||
448 | * What? No tracepoints? No sense writing anything here, bail out. | ||
449 | */ | ||
450 | if (tps == NULL) | ||
451 | return -1; | ||
452 | |||
453 | output_fd = fd; | ||
454 | 459 | ||
460 | /* just guessing this is someone's birthday.. ;) */ | ||
455 | buf[0] = 23; | 461 | buf[0] = 23; |
456 | buf[1] = 8; | 462 | buf[1] = 8; |
457 | buf[2] = 68; | 463 | buf[2] = 68; |
@@ -476,28 +482,86 @@ int read_tracing_data(int fd, struct list_head *pattrs) | |||
476 | /* save page_size */ | 482 | /* save page_size */ |
477 | page_size = sysconf(_SC_PAGESIZE); | 483 | page_size = sysconf(_SC_PAGESIZE); |
478 | write_or_die(&page_size, 4); | 484 | write_or_die(&page_size, 4); |
485 | } | ||
486 | |||
487 | struct tracing_data *tracing_data_get(struct list_head *pattrs, | ||
488 | int fd, bool temp) | ||
489 | { | ||
490 | struct tracepoint_path *tps; | ||
491 | struct tracing_data *tdata; | ||
492 | |||
493 | output_fd = fd; | ||
494 | |||
495 | tps = get_tracepoints_path(pattrs); | ||
496 | if (!tps) | ||
497 | return NULL; | ||
479 | 498 | ||
499 | tdata = malloc_or_die(sizeof(*tdata)); | ||
500 | tdata->temp = temp; | ||
501 | tdata->size = 0; | ||
502 | |||
503 | if (temp) { | ||
504 | int temp_fd; | ||
505 | |||
506 | snprintf(tdata->temp_file, sizeof(tdata->temp_file), | ||
507 | "/tmp/perf-XXXXXX"); | ||
508 | if (!mkstemp(tdata->temp_file)) | ||
509 | die("Can't make temp file"); | ||
510 | |||
511 | temp_fd = open(tdata->temp_file, O_RDWR); | ||
512 | if (temp_fd < 0) | ||
513 | die("Can't read '%s'", tdata->temp_file); | ||
514 | |||
515 | /* | ||
516 | * Set the temp file the default output, so all the | ||
517 | * tracing data are stored into it. | ||
518 | */ | ||
519 | output_fd = temp_fd; | ||
520 | } | ||
521 | |||
522 | tracing_data_header(); | ||
480 | read_header_files(); | 523 | read_header_files(); |
481 | read_ftrace_files(tps); | 524 | read_ftrace_files(tps); |
482 | read_event_files(tps); | 525 | read_event_files(tps); |
483 | read_proc_kallsyms(); | 526 | read_proc_kallsyms(); |
484 | read_ftrace_printk(); | 527 | read_ftrace_printk(); |
485 | 528 | ||
486 | return 0; | 529 | /* |
530 | * All tracing data are stored by now, we can restore | ||
531 | * the default output file in case we used temp file. | ||
532 | */ | ||
533 | if (temp) { | ||
534 | tdata->size = lseek(output_fd, 0, SEEK_CUR); | ||
535 | close(output_fd); | ||
536 | output_fd = fd; | ||
537 | } | ||
538 | |||
539 | put_tracepoints_path(tps); | ||
540 | return tdata; | ||
487 | } | 541 | } |
488 | 542 | ||
489 | ssize_t read_tracing_data_size(int fd, struct list_head *pattrs) | 543 | void tracing_data_put(struct tracing_data *tdata) |
490 | { | 544 | { |
491 | ssize_t size; | 545 | if (tdata->temp) { |
492 | int err = 0; | 546 | record_file(tdata->temp_file, 0); |
547 | unlink(tdata->temp_file); | ||
548 | } | ||
493 | 549 | ||
494 | calc_data_size = 1; | 550 | free(tdata); |
495 | err = read_tracing_data(fd, pattrs); | 551 | } |
496 | size = calc_data_size - 1; | ||
497 | calc_data_size = 0; | ||
498 | 552 | ||
499 | if (err < 0) | 553 | int read_tracing_data(int fd, struct list_head *pattrs) |
500 | return err; | 554 | { |
555 | struct tracing_data *tdata; | ||
501 | 556 | ||
502 | return size; | 557 | /* |
558 | * We work over the real file, so we can write data | ||
559 | * directly, no temp file is needed. | ||
560 | */ | ||
561 | tdata = tracing_data_get(pattrs, fd, false); | ||
562 | if (!tdata) | ||
563 | return -ENOMEM; | ||
564 | |||
565 | tracing_data_put(tdata); | ||
566 | return 0; | ||
503 | } | 567 | } |
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index f674dda3363b..a84100817649 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h | |||
@@ -263,7 +263,18 @@ void *raw_field_ptr(struct event *event, const char *name, void *data); | |||
263 | unsigned long long eval_flag(const char *flag); | 263 | unsigned long long eval_flag(const char *flag); |
264 | 264 | ||
265 | int read_tracing_data(int fd, struct list_head *pattrs); | 265 | int read_tracing_data(int fd, struct list_head *pattrs); |
266 | ssize_t read_tracing_data_size(int fd, struct list_head *pattrs); | 266 | |
267 | struct tracing_data { | ||
268 | /* size is only valid if temp is 'true' */ | ||
269 | ssize_t size; | ||
270 | bool temp; | ||
271 | char temp_file[50]; | ||
272 | }; | ||
273 | |||
274 | struct tracing_data *tracing_data_get(struct list_head *pattrs, | ||
275 | int fd, bool temp); | ||
276 | void tracing_data_put(struct tracing_data *tdata); | ||
277 | |||
267 | 278 | ||
268 | /* taken from kernel/trace/trace.h */ | 279 | /* taken from kernel/trace/trace.h */ |
269 | enum trace_flag_type { | 280 | enum trace_flag_type { |