Skip to content

Commit

Permalink
Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/acme/linux into perf/urgent

Pull perf/urgent fixes from Arnaldo Carvalho de Melo:

 * Handle perf.data files with no tracepoints in 'perf trace', fixing a
   segfault.

 * Fix up MMAP2 buffer space reservation, a problem that was caught via
   'perf test' consistency tests.

 * Add attr->mmap2 support in the tools, a patch that should've been merged
   together with the kernel counterpart:

     13d7a24 "perf: Add attr->mmap2 attribute to an event".

   Merging it allowed us to catch the MMAP buffer space reservation problem via
   'perf test'. From Stephane Eranian.

   The tools deals with older kernels by disabling this feature, resetting the
   perf_event_attr.mmap2 bit, when -EINVAL is returned by perf_event_open, just
   like with perf_event_attr.{sample_id_all,exclude_{guest,host}}.

   When such fallback happens the perf_missing_features.mmap2 flag is set to
   true and can be used by tooling that strictly needs this feature to check
   for its availability on the running kernel.

 * Make sure we can find PERF_SAMPLE_ID in the variable part of PERF_RECORD_
   ring buffer records in 'perf kvm', where direct manipulation of sample_type
   was being done.

   Fixed by making use of the perf_evlist__set_sample_bit() helper and by
   setting the evlist->id_pos in perf_evlist__open(), from Adrian Hunter.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ingo Molnar committed Sep 12, 2013
2 parents 72f4a11 + d008d52 commit e6d3818
Show file tree
Hide file tree
Showing 20 changed files with 229 additions and 67 deletions.
1 change: 1 addition & 0 deletions kernel/events/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -5039,6 +5039,7 @@ static void perf_event_mmap_output(struct perf_event *event,
mmap_event->event_id.header.size += sizeof(mmap_event->maj);
mmap_event->event_id.header.size += sizeof(mmap_event->min);
mmap_event->event_id.header.size += sizeof(mmap_event->ino);
mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation);
}

perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
Expand Down
1 change: 1 addition & 0 deletions tools/perf/builtin-annotate.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
.tool = {
.sample = process_sample_event,
.mmap = perf_event__process_mmap,
.mmap2 = perf_event__process_mmap2,
.comm = perf_event__process_comm,
.exit = perf_event__process_exit,
.fork = perf_event__process_fork,
Expand Down
15 changes: 15 additions & 0 deletions tools/perf/builtin-inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,19 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,
return err;
}

static int perf_event__repipe_mmap2(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct machine *machine)
{
int err;

err = perf_event__process_mmap2(tool, event, sample, machine);
perf_event__repipe(tool, event, sample, machine);

return err;
}

static int perf_event__repipe_fork(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
Expand Down Expand Up @@ -339,6 +352,7 @@ static int __cmd_inject(struct perf_inject *inject)

if (inject->build_ids || inject->sched_stat) {
inject->tool.mmap = perf_event__repipe_mmap;
inject->tool.mmap2 = perf_event__repipe_mmap2;
inject->tool.fork = perf_event__repipe_fork;
inject->tool.tracing_data = perf_event__repipe_tracing_data;
}
Expand Down Expand Up @@ -390,6 +404,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
.tool = {
.sample = perf_event__repipe_sample,
.mmap = perf_event__repipe,
.mmap2 = perf_event__repipe,
.comm = perf_event__repipe,
.fork = perf_event__repipe,
.exit = perf_event__repipe,
Expand Down
18 changes: 9 additions & 9 deletions tools/perf/builtin-kvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1165,16 +1165,16 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
struct perf_event_attr *attr = &pos->attr;

/* make sure these *are* set */
attr->sample_type |= PERF_SAMPLE_TID;
attr->sample_type |= PERF_SAMPLE_TIME;
attr->sample_type |= PERF_SAMPLE_CPU;
attr->sample_type |= PERF_SAMPLE_RAW;
perf_evsel__set_sample_bit(pos, TID);
perf_evsel__set_sample_bit(pos, TIME);
perf_evsel__set_sample_bit(pos, CPU);
perf_evsel__set_sample_bit(pos, RAW);
/* make sure these are *not*; want as small a sample as possible */
attr->sample_type &= ~PERF_SAMPLE_PERIOD;
attr->sample_type &= ~PERF_SAMPLE_IP;
attr->sample_type &= ~PERF_SAMPLE_CALLCHAIN;
attr->sample_type &= ~PERF_SAMPLE_ADDR;
attr->sample_type &= ~PERF_SAMPLE_READ;
perf_evsel__reset_sample_bit(pos, PERIOD);
perf_evsel__reset_sample_bit(pos, IP);
perf_evsel__reset_sample_bit(pos, CALLCHAIN);
perf_evsel__reset_sample_bit(pos, ADDR);
perf_evsel__reset_sample_bit(pos, READ);
attr->mmap = 0;
attr->comm = 0;
attr->task = 0;
Expand Down
1 change: 1 addition & 0 deletions tools/perf/builtin-mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
.tool = {
.sample = process_sample_event,
.mmap = perf_event__process_mmap,
.mmap2 = perf_event__process_mmap2,
.comm = perf_event__process_comm,
.lost = perf_event__process_lost,
.fork = perf_event__process_fork,
Expand Down
1 change: 1 addition & 0 deletions tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
.tool = {
.sample = process_sample_event,
.mmap = perf_event__process_mmap,
.mmap2 = perf_event__process_mmap2,
.comm = perf_event__process_comm,
.exit = perf_event__process_exit,
.fork = perf_event__process_fork,
Expand Down
1 change: 1 addition & 0 deletions tools/perf/builtin-script.c
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
static struct perf_tool perf_script = {
.sample = process_sample_event,
.mmap = perf_event__process_mmap,
.mmap2 = perf_event__process_mmap2,
.comm = perf_event__process_comm,
.exit = perf_event__process_exit,
.fork = perf_event__process_fork,
Expand Down
15 changes: 11 additions & 4 deletions tools/perf/tests/perf-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ int test__PERF_RECORD(void)
struct perf_sample sample;
const char *cmd = "sleep";
const char *argv[] = { cmd, "1", NULL, };
char *bname;
char *bname, *mmap_filename;
u64 prev_time = 0;
bool found_cmd_mmap = false,
found_libc_mmap = false,
Expand Down Expand Up @@ -212,6 +212,7 @@ int test__PERF_RECORD(void)

if ((type == PERF_RECORD_COMM ||
type == PERF_RECORD_MMAP ||
type == PERF_RECORD_MMAP2 ||
type == PERF_RECORD_FORK ||
type == PERF_RECORD_EXIT) &&
(pid_t)event->comm.pid != evlist->workload.pid) {
Expand All @@ -220,7 +221,8 @@ int test__PERF_RECORD(void)
}

if ((type == PERF_RECORD_COMM ||
type == PERF_RECORD_MMAP) &&
type == PERF_RECORD_MMAP ||
type == PERF_RECORD_MMAP2) &&
event->comm.pid != event->comm.tid) {
pr_debug("%s with different pid/tid!\n", name);
++errs;
Expand All @@ -236,7 +238,12 @@ int test__PERF_RECORD(void)
case PERF_RECORD_EXIT:
goto found_exit;
case PERF_RECORD_MMAP:
bname = strrchr(event->mmap.filename, '/');
mmap_filename = event->mmap.filename;
goto check_bname;
case PERF_RECORD_MMAP2:
mmap_filename = event->mmap2.filename;
check_bname:
bname = strrchr(mmap_filename, '/');
if (bname != NULL) {
if (!found_cmd_mmap)
found_cmd_mmap = !strcmp(bname + 1, cmd);
Expand All @@ -245,7 +252,7 @@ int test__PERF_RECORD(void)
if (!found_ld_mmap)
found_ld_mmap = !strncmp(bname + 1, "ld", 2);
} else if (!found_vdso_mmap)
found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]");
found_vdso_mmap = !strcmp(mmap_filename, "[vdso]");
break;

case PERF_RECORD_SAMPLE:
Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/build-id.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
struct perf_tool build_id__mark_dso_hit_ops = {
.sample = build_id__mark_dso_hit,
.mmap = perf_event__process_mmap,
.mmap2 = perf_event__process_mmap2,
.fork = perf_event__process_fork,
.exit = perf_event__exit_del_thread,
.attr = perf_event__process_attr,
Expand Down
56 changes: 44 additions & 12 deletions tools/perf/util/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
static const char *perf_event__names[] = {
[0] = "TOTAL",
[PERF_RECORD_MMAP] = "MMAP",
[PERF_RECORD_MMAP2] = "MMAP2",
[PERF_RECORD_LOST] = "LOST",
[PERF_RECORD_COMM] = "COMM",
[PERF_RECORD_EXIT] = "EXIT",
Expand Down Expand Up @@ -186,7 +187,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
return -1;
}

event->header.type = PERF_RECORD_MMAP;
event->header.type = PERF_RECORD_MMAP2;
/*
* Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
*/
Expand All @@ -197,7 +198,9 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
char prot[5];
char execname[PATH_MAX];
char anonstr[] = "//anon";
unsigned int ino;
size_t size;
ssize_t n;

if (fgets(bf, sizeof(bf), fp) == NULL)
break;
Expand All @@ -206,9 +209,16 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
strcpy(execname, "");

/* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n",
&event->mmap.start, &event->mmap.len, prot,
&event->mmap.pgoff, execname);
n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
&event->mmap2.start, &event->mmap2.len, prot,
&event->mmap2.pgoff, &event->mmap2.maj,
&event->mmap2.min,
&ino, execname);

event->mmap2.ino = (u64)ino;

if (n != 8)
continue;

if (prot[2] != 'x')
continue;
Expand All @@ -217,15 +227,15 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
strcpy(execname, anonstr);

size = strlen(execname) + 1;
memcpy(event->mmap.filename, execname, size);
memcpy(event->mmap2.filename, execname, size);
size = PERF_ALIGN(size, sizeof(u64));
event->mmap.len -= event->mmap.start;
event->mmap.header.size = (sizeof(event->mmap) -
(sizeof(event->mmap.filename) - size));
memset(event->mmap.filename + size, 0, machine->id_hdr_size);
event->mmap.header.size += machine->id_hdr_size;
event->mmap.pid = tgid;
event->mmap.tid = pid;
event->mmap2.len -= event->mmap.start;
event->mmap2.header.size = (sizeof(event->mmap2) -
(sizeof(event->mmap2.filename) - size));
memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
event->mmap2.header.size += machine->id_hdr_size;
event->mmap2.pid = tgid;
event->mmap2.tid = pid;

if (process(tool, event, &synth_sample, machine) != 0) {
rc = -1;
Expand Down Expand Up @@ -527,6 +537,17 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
event->mmap.len, event->mmap.pgoff, event->mmap.filename);
}

size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
{
return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
" %02x:%02x %"PRIu64" %"PRIu64"]: %s\n",
event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
event->mmap2.min, event->mmap2.ino,
event->mmap2.ino_generation,
event->mmap2.filename);
}

int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample __maybe_unused,
Expand All @@ -535,6 +556,14 @@ int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
return machine__process_mmap_event(machine, event);
}

int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample __maybe_unused,
struct machine *machine)
{
return machine__process_mmap2_event(machine, event);
}

size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
{
return fprintf(fp, "(%d:%d):(%d:%d)\n",
Expand Down Expand Up @@ -574,6 +603,9 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
case PERF_RECORD_MMAP:
ret += perf_event__fprintf_mmap(event, fp);
break;
case PERF_RECORD_MMAP2:
ret += perf_event__fprintf_mmap2(event, fp);
break;
default:
ret += fprintf(fp, "\n");
}
Expand Down
19 changes: 19 additions & 0 deletions tools/perf/util/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ struct mmap_event {
char filename[PATH_MAX];
};

struct mmap2_event {
struct perf_event_header header;
u32 pid, tid;
u64 start;
u64 len;
u64 pgoff;
u32 maj;
u32 min;
u64 ino;
u64 ino_generation;
char filename[PATH_MAX];
};

struct comm_event {
struct perf_event_header header;
u32 pid, tid;
Expand Down Expand Up @@ -159,6 +172,7 @@ struct tracing_data_event {
union perf_event {
struct perf_event_header header;
struct mmap_event mmap;
struct mmap2_event mmap2;
struct comm_event comm;
struct fork_event fork;
struct lost_event lost;
Expand Down Expand Up @@ -208,6 +222,10 @@ int perf_event__process_mmap(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct machine *machine);
int perf_event__process_mmap2(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct machine *machine);
int perf_event__process_fork(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
Expand Down Expand Up @@ -238,6 +256,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,

size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
size_t perf_event__fprintf(union perf_event *event, FILE *fp);

Expand Down
12 changes: 12 additions & 0 deletions tools/perf/util/evlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ void perf_evlist__set_id_pos(struct perf_evlist *evlist)
evlist->is_pos = first->is_pos;
}

static void perf_evlist__update_id_pos(struct perf_evlist *evlist)
{
struct perf_evsel *evsel;

list_for_each_entry(evsel, &evlist->entries, node)
perf_evsel__calc_id_pos(evsel);

perf_evlist__set_id_pos(evlist);
}

static void perf_evlist__purge(struct perf_evlist *evlist)
{
struct perf_evsel *pos, *n;
Expand Down Expand Up @@ -920,6 +930,8 @@ int perf_evlist__open(struct perf_evlist *evlist)
struct perf_evsel *evsel;
int err;

perf_evlist__update_id_pos(evlist);

list_for_each_entry(evsel, &evlist->entries, node) {
err = perf_evsel__open(evsel, evlist->cpus, evlist->threads);
if (err < 0)
Expand Down
16 changes: 12 additions & 4 deletions tools/perf/util/evsel.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
static struct {
bool sample_id_all;
bool exclude_guest;
bool mmap2;
} perf_missing_features;

#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
Expand Down Expand Up @@ -676,8 +677,9 @@ void perf_evsel__config(struct perf_evsel *evsel,
if (opts->sample_weight)
attr->sample_type |= PERF_SAMPLE_WEIGHT;

attr->mmap = track;
attr->comm = track;
attr->mmap = track;
attr->mmap2 = track && !perf_missing_features.mmap2;
attr->comm = track;

/*
* XXX see the function comment above
Expand Down Expand Up @@ -1016,6 +1018,8 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
}

fallback_missing_features:
if (perf_missing_features.mmap2)
evsel->attr.mmap2 = 0;
if (perf_missing_features.exclude_guest)
evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
retry_sample_id:
Expand Down Expand Up @@ -1080,8 +1084,11 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
if (err != -EINVAL || cpu > 0 || thread > 0)
goto out_close;

if (!perf_missing_features.exclude_guest &&
(evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
perf_missing_features.mmap2 = true;
goto fallback_missing_features;
} else if (!perf_missing_features.exclude_guest &&
(evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
perf_missing_features.exclude_guest = true;
goto fallback_missing_features;
} else if (!perf_missing_features.sample_id_all) {
Expand Down Expand Up @@ -1925,6 +1932,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
if_print(exclude_hv);
if_print(exclude_idle);
if_print(mmap);
if_print(mmap2);
if_print(comm);
if_print(freq);
if_print(inherit_stat);
Expand Down
Loading

0 comments on commit e6d3818

Please sign in to comment.