Commit 72f4a11d2fb16792f5e5107922652366194cfd66

Authored by Ingo Molnar

Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/g…

…it/acme/linux into perf/urgent

Pull perf/urgent fixes from Arnaldo Carvalho de Melo:

 * Fix parsing with no sample_id_all bit set, this regression prevents perf
   from reading old perf.data files generated in systems where
   perf_event_attr.sample_id_all isn't available, from Adrian Hunter.

 * Add signal checking to the inner 'perf trace' event processing loop, allowing
   faster response to control+C.

 * Fix formatting of long symbol names removing the hardcoding of a buffer
   size used to format histogram entries, which was truncating the lines.

 * Separate progress bar update when processing events, reducing potentially big
   overhead in not needed TUI progress bar screen updates, from Jiri Olsa.

 * Fix 'perf trace' build in architectures where MAP_32BIT is not defined, from
   Kyle McMartin.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>

Showing 8 changed files Side-by-side Diff

... ... @@ -394,6 +394,8 @@
394 394 LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
395 395 endif
396 396 LIB_OBJS += $(OUTPUT)tests/code-reading.o
  397 +LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
  398 +LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
397 399  
398 400 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
399 401 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
... ... @@ -439,7 +441,6 @@
439 441 ifneq ($(OUTPUT),)
440 442 CFLAGS += -I$(OUTPUT)
441 443 endif
442   -LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
443 444  
444 445 ifdef NO_LIBELF
445 446 EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
tools/perf/builtin-trace.c
... ... @@ -100,7 +100,9 @@
100 100  
101 101 P_MMAP_FLAG(SHARED);
102 102 P_MMAP_FLAG(PRIVATE);
  103 +#ifdef MAP_32BIT
103 104 P_MMAP_FLAG(32BIT);
  105 +#endif
104 106 P_MMAP_FLAG(ANONYMOUS);
105 107 P_MMAP_FLAG(DENYWRITE);
106 108 P_MMAP_FLAG(EXECUTABLE);
... ... @@ -994,6 +996,9 @@
994 996  
995 997 handler = evsel->handler.func;
996 998 handler(trace, evsel, &sample);
  999 +
  1000 + if (done)
  1001 + goto out_unmap_evlist;
997 1002 }
998 1003 }
999 1004  
tools/perf/tests/builtin-test.c
... ... @@ -112,6 +112,10 @@
112 112 .func = test__keep_tracking,
113 113 },
114 114 {
  115 + .desc = "Test parsing with no sample_id_all bit set",
  116 + .func = test__parse_no_sample_id_all,
  117 + },
  118 + {
115 119 .func = NULL,
116 120 },
117 121 };
tools/perf/tests/parse-no-sample-id-all.c
  1 +#include <sys/types.h>
  2 +#include <stddef.h>
  3 +
  4 +#include "tests.h"
  5 +
  6 +#include "event.h"
  7 +#include "evlist.h"
  8 +#include "header.h"
  9 +#include "util.h"
  10 +
  11 +static int process_event(struct perf_evlist **pevlist, union perf_event *event)
  12 +{
  13 + struct perf_sample sample;
  14 +
  15 + if (event->header.type == PERF_RECORD_HEADER_ATTR) {
  16 + if (perf_event__process_attr(NULL, event, pevlist)) {
  17 + pr_debug("perf_event__process_attr failed\n");
  18 + return -1;
  19 + }
  20 + return 0;
  21 + }
  22 +
  23 + if (event->header.type >= PERF_RECORD_USER_TYPE_START)
  24 + return -1;
  25 +
  26 + if (!*pevlist)
  27 + return -1;
  28 +
  29 + if (perf_evlist__parse_sample(*pevlist, event, &sample)) {
  30 + pr_debug("perf_evlist__parse_sample failed\n");
  31 + return -1;
  32 + }
  33 +
  34 + return 0;
  35 +}
  36 +
  37 +static int process_events(union perf_event **events, size_t count)
  38 +{
  39 + struct perf_evlist *evlist = NULL;
  40 + int err = 0;
  41 + size_t i;
  42 +
  43 + for (i = 0; i < count && !err; i++)
  44 + err = process_event(&evlist, events[i]);
  45 +
  46 + if (evlist)
  47 + perf_evlist__delete(evlist);
  48 +
  49 + return err;
  50 +}
  51 +
  52 +struct test_attr_event {
  53 + struct attr_event attr;
  54 + u64 id;
  55 +};
  56 +
  57 +/**
  58 + * test__parse_no_sample_id_all - test parsing with no sample_id_all bit set.
  59 + *
  60 + * This function tests parsing data produced on kernel's that do not support the
  61 + * sample_id_all bit. Without the sample_id_all bit, non-sample events (such as
  62 + * mmap events) do not have an id sample appended, and consequently logic
  63 + * designed to determine the id will not work. That case happens when there is
  64 + * more than one selected event, so this test processes three events: 2
  65 + * attributes representing the selected events and one mmap event.
  66 + *
  67 + * Return: %0 on success, %-1 if the test fails.
  68 + */
  69 +int test__parse_no_sample_id_all(void)
  70 +{
  71 + int err;
  72 +
  73 + struct test_attr_event event1 = {
  74 + .attr = {
  75 + .header = {
  76 + .type = PERF_RECORD_HEADER_ATTR,
  77 + .size = sizeof(struct test_attr_event),
  78 + },
  79 + },
  80 + .id = 1,
  81 + };
  82 + struct test_attr_event event2 = {
  83 + .attr = {
  84 + .header = {
  85 + .type = PERF_RECORD_HEADER_ATTR,
  86 + .size = sizeof(struct test_attr_event),
  87 + },
  88 + },
  89 + .id = 2,
  90 + };
  91 + struct mmap_event event3 = {
  92 + .header = {
  93 + .type = PERF_RECORD_MMAP,
  94 + .size = sizeof(struct mmap_event),
  95 + },
  96 + };
  97 + union perf_event *events[] = {
  98 + (union perf_event *)&event1,
  99 + (union perf_event *)&event2,
  100 + (union perf_event *)&event3,
  101 + };
  102 +
  103 + err = process_events(events, ARRAY_SIZE(events));
  104 + if (err)
  105 + return -1;
  106 +
  107 + return 0;
  108 +}
tools/perf/tests/tests.h
... ... @@ -39,6 +39,7 @@
39 39 int test__code_reading(void);
40 40 int test__sample_parsing(void);
41 41 int test__keep_tracking(void);
  42 +int test__parse_no_sample_id_all(void);
42 43  
43 44 #endif /* TESTS_H */
tools/perf/ui/stdio/hist.c
... ... @@ -350,9 +350,9 @@
350 350 }
351 351  
352 352 static int hist_entry__fprintf(struct hist_entry *he, size_t size,
353   - struct hists *hists, FILE *fp)
  353 + struct hists *hists,
  354 + char *bf, size_t bfsz, FILE *fp)
354 355 {
355   - char bf[512];
356 356 int ret;
357 357 struct perf_hpp hpp = {
358 358 .buf = bf,
... ... @@ -360,8 +360,8 @@
360 360 };
361 361 bool color = !symbol_conf.field_sep;
362 362  
363   - if (size == 0 || size > sizeof(bf))
364   - size = hpp.size = sizeof(bf);
  363 + if (size == 0 || size > bfsz)
  364 + size = hpp.size = bfsz;
365 365  
366 366 ret = hist_entry__period_snprintf(&hpp, he, color);
367 367 hist_entry__sort_snprintf(he, bf + ret, size - ret, hists);
... ... @@ -392,6 +392,8 @@
392 392 .ptr = hists_to_evsel(hists),
393 393 };
394 394 bool first = true;
  395 + size_t linesz;
  396 + char *line = NULL;
395 397  
396 398 init_rem_hits();
397 399  
... ... @@ -479,6 +481,13 @@
479 481 goto out;
480 482  
481 483 print_entries:
  484 + linesz = hists__sort_list_width(hists) + 3 + 1;
  485 + line = malloc(linesz);
  486 + if (line == NULL) {
  487 + ret = -1;
  488 + goto out;
  489 + }
  490 +
482 491 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
483 492 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
484 493 float percent = h->stat.period * 100.0 /
485 494  
... ... @@ -490,10 +499,10 @@
490 499 if (percent < min_pcnt)
491 500 continue;
492 501  
493   - ret += hist_entry__fprintf(h, max_cols, hists, fp);
  502 + ret += hist_entry__fprintf(h, max_cols, hists, line, linesz, fp);
494 503  
495 504 if (max_rows && ++nr_rows >= max_rows)
496   - goto out;
  505 + break;
497 506  
498 507 if (h->ms.map == NULL && verbose > 1) {
499 508 __map_groups__fprintf_maps(&h->thread->mg,
... ... @@ -501,6 +510,8 @@
501 510 fprintf(fp, "%.10s end\n", graph_dotted_line);
502 511 }
503 512 }
  513 +
  514 + free(line);
504 515 out:
505 516 free(rem_sq_bracket);
506 517  
tools/perf/util/evlist.c
... ... @@ -446,20 +446,25 @@
446 446 static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
447 447 union perf_event *event)
448 448 {
  449 + struct perf_evsel *first = perf_evlist__first(evlist);
449 450 struct hlist_head *head;
450 451 struct perf_sample_id *sid;
451 452 int hash;
452 453 u64 id;
453 454  
454 455 if (evlist->nr_entries == 1)
455   - return perf_evlist__first(evlist);
  456 + return first;
456 457  
  458 + if (!first->attr.sample_id_all &&
  459 + event->header.type != PERF_RECORD_SAMPLE)
  460 + return first;
  461 +
457 462 if (perf_evlist__event2id(evlist, event, &id))
458 463 return NULL;
459 464  
460 465 /* Synthesized events have an id of zero */
461 466 if (!id)
462   - return perf_evlist__first(evlist);
  467 + return first;
463 468  
464 469 hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
465 470 head = &evlist->heads[hash];
tools/perf/util/session.c
... ... @@ -504,6 +504,7 @@
504 504 u64 limit = os->next_flush;
505 505 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
506 506 unsigned idx = 0, progress_next = os->nr_samples / 16;
  507 + bool show_progress = limit == ULLONG_MAX;
507 508 int ret;
508 509  
509 510 if (!tool->ordered_samples || !limit)
... ... @@ -526,7 +527,7 @@
526 527 os->last_flush = iter->timestamp;
527 528 list_del(&iter->list);
528 529 list_add(&iter->list, &os->sample_cache);
529   - if (++idx >= progress_next) {
  530 + if (show_progress && (++idx >= progress_next)) {
530 531 progress_next += os->nr_samples / 16;
531 532 ui_progress__update(idx, os->nr_samples,
532 533 "Processing time ordered events...");