Skip to content

Commit

Permalink
perf tools: Fixup mmap event consumption
Browse files Browse the repository at this point in the history
The tail position of the event buffer should only be modified after
actually use that event.

If not the event buffer could be invalid before use, and segment fault
occurs when invoking perf top -G.

Signed-off-by: Zhouyi Zhou <yizhouzhou@ict.ac.cn>
Cc: David Ahern <dsahern@gmail.com>
Cc: Zhouyi Zhou <yizhouzhou@ict.ac.cn>
Link: http://lkml.kernel.org/r/1382600613-32177-1-git-send-email-zhouzhouyi@gmail.com
[ Simplified the logic using exit gotos and renamed write_tail method to mmap_consume ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Zhouyi Zhou authored and Arnaldo Carvalho de Melo committed Oct 28, 2013
1 parent ae779a6 commit 8e50d38
Show file tree
Hide file tree
Showing 14 changed files with 49 additions and 16 deletions.
7 changes: 7 additions & 0 deletions tools/perf/builtin-kvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -888,11 +888,18 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) {
err = perf_evlist__parse_sample(kvm->evlist, event, &sample);
if (err) {
perf_evlist__mmap_consume(kvm->evlist, idx);
pr_err("Failed to parse sample\n");
return -1;
}

err = perf_session_queue_event(kvm->session, event, &sample, 0);
/*
* FIXME: Here we can't consume the event, as perf_session_queue_event will
* point to it, and it'll get possibly overwritten by the kernel.
*/
perf_evlist__mmap_consume(kvm->evlist, idx);

if (err) {
pr_err("Failed to enqueue sample: %d\n", err);
return -1;
Expand Down
10 changes: 6 additions & 4 deletions tools/perf/builtin-top.c
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
ret = perf_evlist__parse_sample(top->evlist, event, &sample);
if (ret) {
pr_err("Can't parse sample, err = %d\n", ret);
continue;
goto next_event;
}

evsel = perf_evlist__id2evsel(session->evlist, sample.id);
Expand All @@ -825,13 +825,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
case PERF_RECORD_MISC_USER:
++top->us_samples;
if (top->hide_user_symbols)
continue;
goto next_event;
machine = &session->machines.host;
break;
case PERF_RECORD_MISC_KERNEL:
++top->kernel_samples;
if (top->hide_kernel_symbols)
continue;
goto next_event;
machine = &session->machines.host;
break;
case PERF_RECORD_MISC_GUEST_KERNEL:
Expand All @@ -847,7 +847,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
*/
/* Fall thru */
default:
continue;
goto next_event;
}


Expand All @@ -859,6 +859,8 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
machine__process_event(machine, event);
} else
++session->stats.nr_unknown_events;
next_event:
perf_evlist__mmap_consume(top->evlist, idx);
}
}

Expand Down
8 changes: 5 additions & 3 deletions tools/perf/builtin-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -987,7 +987,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
err = perf_evlist__parse_sample(evlist, event, &sample);
if (err) {
fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
continue;
goto next_event;
}

if (trace->base_time == 0)
Expand All @@ -1001,18 +1001,20 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
evsel = perf_evlist__id2evsel(evlist, sample.id);
if (evsel == NULL) {
fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
continue;
goto next_event;
}

if (sample.raw_data == NULL) {
fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
perf_evsel__name(evsel), sample.tid,
sample.cpu, sample.raw_size);
continue;
goto next_event;
}

handler = evsel->handler.func;
handler(trace, evsel, &sample);
next_event:
perf_evlist__mmap_consume(evlist, i);

if (done)
goto out_unmap_evlist;
Expand Down
1 change: 1 addition & 0 deletions tools/perf/tests/code-reading.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ static int process_events(struct machine *machine, struct perf_evlist *evlist,
for (i = 0; i < evlist->nr_mmaps; i++) {
while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
ret = process_event(machine, evlist, event, state);
perf_evlist__mmap_consume(evlist, i);
if (ret < 0)
return ret;
}
Expand Down
1 change: 1 addition & 0 deletions tools/perf/tests/keep-tracking.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ static int find_comm(struct perf_evlist *evlist, const char *comm)
(pid_t)event->comm.tid == getpid() &&
strcmp(event->comm.comm, comm) == 0)
found += 1;
perf_evlist__mmap_consume(evlist, i);
}
}
return found;
Expand Down
1 change: 1 addition & 0 deletions tools/perf/tests/mmap-basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ int test__basic_mmap(void)
goto out_munmap;
}
nr_events[evsel->idx]++;
perf_evlist__mmap_consume(evlist, 0);
}

err = 0;
Expand Down
4 changes: 3 additions & 1 deletion tools/perf/tests/open-syscall-tp-fields.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ int test__syscall_open_tp_fields(void)

++nr_events;

if (type != PERF_RECORD_SAMPLE)
if (type != PERF_RECORD_SAMPLE) {
perf_evlist__mmap_consume(evlist, i);
continue;
}

err = perf_evsel__parse_sample(evsel, event, &sample);
if (err) {
Expand Down
2 changes: 2 additions & 0 deletions tools/perf/tests/perf-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ int test__PERF_RECORD(void)
type);
++errs;
}

perf_evlist__mmap_consume(evlist, i);
}
}

Expand Down
4 changes: 3 additions & 1 deletion tools/perf/tests/perf-time-to-tsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ int test__perf_time_to_tsc(void)
if (event->header.type != PERF_RECORD_COMM ||
(pid_t)event->comm.pid != getpid() ||
(pid_t)event->comm.tid != getpid())
continue;
goto next_event;

if (strcmp(event->comm.comm, comm1) == 0) {
CHECK__(perf_evsel__parse_sample(evsel, event,
Expand All @@ -134,6 +134,8 @@ int test__perf_time_to_tsc(void)
&sample));
comm2_time = sample.time;
}
next_event:
perf_evlist__mmap_consume(evlist, i);
}
}

Expand Down
4 changes: 3 additions & 1 deletion tools/perf/tests/sw-clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
struct perf_sample sample;

if (event->header.type != PERF_RECORD_SAMPLE)
continue;
goto next_event;

err = perf_evlist__parse_sample(evlist, event, &sample);
if (err < 0) {
Expand All @@ -88,6 +88,8 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)

total_periods += sample.period;
nr_samples++;
next_event:
perf_evlist__mmap_consume(evlist, 0);
}

if ((u64) nr_samples == total_periods) {
Expand Down
6 changes: 3 additions & 3 deletions tools/perf/tests/task-exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ int test__task_exit(void)

retry:
while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) {
if (event->header.type != PERF_RECORD_EXIT)
continue;
if (event->header.type == PERF_RECORD_EXIT)
nr_exit++;

nr_exit++;
perf_evlist__mmap_consume(evlist, 0);
}

if (!exited || !nr_exit) {
Expand Down
13 changes: 10 additions & 3 deletions tools/perf/util/evlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,12 +545,19 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)

md->prev = old;

if (!evlist->overwrite)
perf_mmap__write_tail(md, old);

return event;
}

void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
{
if (!evlist->overwrite) {
struct perf_mmap *md = &evlist->mmap[idx];
unsigned int old = md->prev;

perf_mmap__write_tail(md, old);
}
}

static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
{
if (evlist->mmap[idx].base != NULL) {
Expand Down
2 changes: 2 additions & 0 deletions tools/perf/util/evlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);

union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);

void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);

int perf_evlist__open(struct perf_evlist *evlist);
void perf_evlist__close(struct perf_evlist *evlist);

Expand Down
2 changes: 2 additions & 0 deletions tools/perf/util/python.c
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,8 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
PyObject *pyevent = pyrf_event__new(event);
struct pyrf_event *pevent = (struct pyrf_event *)pyevent;

perf_evlist__mmap_consume(evlist, cpu);

if (pyevent == NULL)
return PyErr_NoMemory();

Expand Down

0 comments on commit 8e50d38

Please sign in to comment.