提交 8e50d384 编写于 作者: Z Zhouyi Zhou 提交者: Arnaldo Carvalho de Melo

perf tools: Fixup mmap event consumption

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: NZhouyi 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: NArnaldo Carvalho de Melo <acme@redhat.com>
上级 ae779a63
...@@ -888,11 +888,18 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx, ...@@ -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) { while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) {
err = perf_evlist__parse_sample(kvm->evlist, event, &sample); err = perf_evlist__parse_sample(kvm->evlist, event, &sample);
if (err) { if (err) {
perf_evlist__mmap_consume(kvm->evlist, idx);
pr_err("Failed to parse sample\n"); pr_err("Failed to parse sample\n");
return -1; return -1;
} }
err = perf_session_queue_event(kvm->session, event, &sample, 0); 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) { if (err) {
pr_err("Failed to enqueue sample: %d\n", err); pr_err("Failed to enqueue sample: %d\n", err);
return -1; return -1;
......
...@@ -810,7 +810,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) ...@@ -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); ret = perf_evlist__parse_sample(top->evlist, event, &sample);
if (ret) { if (ret) {
pr_err("Can't parse sample, err = %d\n", ret); pr_err("Can't parse sample, err = %d\n", ret);
continue; goto next_event;
} }
evsel = perf_evlist__id2evsel(session->evlist, sample.id); evsel = perf_evlist__id2evsel(session->evlist, sample.id);
...@@ -825,13 +825,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) ...@@ -825,13 +825,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
case PERF_RECORD_MISC_USER: case PERF_RECORD_MISC_USER:
++top->us_samples; ++top->us_samples;
if (top->hide_user_symbols) if (top->hide_user_symbols)
continue; goto next_event;
machine = &session->machines.host; machine = &session->machines.host;
break; break;
case PERF_RECORD_MISC_KERNEL: case PERF_RECORD_MISC_KERNEL:
++top->kernel_samples; ++top->kernel_samples;
if (top->hide_kernel_symbols) if (top->hide_kernel_symbols)
continue; goto next_event;
machine = &session->machines.host; machine = &session->machines.host;
break; break;
case PERF_RECORD_MISC_GUEST_KERNEL: case PERF_RECORD_MISC_GUEST_KERNEL:
...@@ -847,7 +847,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) ...@@ -847,7 +847,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
*/ */
/* Fall thru */ /* Fall thru */
default: default:
continue; goto next_event;
} }
...@@ -859,6 +859,8 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) ...@@ -859,6 +859,8 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
machine__process_event(machine, event); machine__process_event(machine, event);
} else } else
++session->stats.nr_unknown_events; ++session->stats.nr_unknown_events;
next_event:
perf_evlist__mmap_consume(top->evlist, idx);
} }
} }
......
...@@ -987,7 +987,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -987,7 +987,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
err = perf_evlist__parse_sample(evlist, event, &sample); err = perf_evlist__parse_sample(evlist, event, &sample);
if (err) { if (err) {
fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err); fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
continue; goto next_event;
} }
if (trace->base_time == 0) if (trace->base_time == 0)
...@@ -1001,18 +1001,20 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -1001,18 +1001,20 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
evsel = perf_evlist__id2evsel(evlist, sample.id); evsel = perf_evlist__id2evsel(evlist, sample.id);
if (evsel == NULL) { if (evsel == NULL) {
fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id); fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
continue; goto next_event;
} }
if (sample.raw_data == NULL) { if (sample.raw_data == NULL) {
fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
perf_evsel__name(evsel), sample.tid, perf_evsel__name(evsel), sample.tid,
sample.cpu, sample.raw_size); sample.cpu, sample.raw_size);
continue; goto next_event;
} }
handler = evsel->handler.func; handler = evsel->handler.func;
handler(trace, evsel, &sample); handler(trace, evsel, &sample);
next_event:
perf_evlist__mmap_consume(evlist, i);
if (done) if (done)
goto out_unmap_evlist; goto out_unmap_evlist;
......
...@@ -290,6 +290,7 @@ static int process_events(struct machine *machine, struct perf_evlist *evlist, ...@@ -290,6 +290,7 @@ static int process_events(struct machine *machine, struct perf_evlist *evlist,
for (i = 0; i < evlist->nr_mmaps; i++) { for (i = 0; i < evlist->nr_mmaps; i++) {
while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
ret = process_event(machine, evlist, event, state); ret = process_event(machine, evlist, event, state);
perf_evlist__mmap_consume(evlist, i);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
......
...@@ -36,6 +36,7 @@ static int find_comm(struct perf_evlist *evlist, const char *comm) ...@@ -36,6 +36,7 @@ static int find_comm(struct perf_evlist *evlist, const char *comm)
(pid_t)event->comm.tid == getpid() && (pid_t)event->comm.tid == getpid() &&
strcmp(event->comm.comm, comm) == 0) strcmp(event->comm.comm, comm) == 0)
found += 1; found += 1;
perf_evlist__mmap_consume(evlist, i);
} }
} }
return found; return found;
......
...@@ -122,6 +122,7 @@ int test__basic_mmap(void) ...@@ -122,6 +122,7 @@ int test__basic_mmap(void)
goto out_munmap; goto out_munmap;
} }
nr_events[evsel->idx]++; nr_events[evsel->idx]++;
perf_evlist__mmap_consume(evlist, 0);
} }
err = 0; err = 0;
......
...@@ -77,8 +77,10 @@ int test__syscall_open_tp_fields(void) ...@@ -77,8 +77,10 @@ int test__syscall_open_tp_fields(void)
++nr_events; ++nr_events;
if (type != PERF_RECORD_SAMPLE) if (type != PERF_RECORD_SAMPLE) {
perf_evlist__mmap_consume(evlist, i);
continue; continue;
}
err = perf_evsel__parse_sample(evsel, event, &sample); err = perf_evsel__parse_sample(evsel, event, &sample);
if (err) { if (err) {
......
...@@ -263,6 +263,8 @@ int test__PERF_RECORD(void) ...@@ -263,6 +263,8 @@ int test__PERF_RECORD(void)
type); type);
++errs; ++errs;
} }
perf_evlist__mmap_consume(evlist, i);
} }
} }
......
...@@ -122,7 +122,7 @@ int test__perf_time_to_tsc(void) ...@@ -122,7 +122,7 @@ int test__perf_time_to_tsc(void)
if (event->header.type != PERF_RECORD_COMM || if (event->header.type != PERF_RECORD_COMM ||
(pid_t)event->comm.pid != getpid() || (pid_t)event->comm.pid != getpid() ||
(pid_t)event->comm.tid != getpid()) (pid_t)event->comm.tid != getpid())
continue; goto next_event;
if (strcmp(event->comm.comm, comm1) == 0) { if (strcmp(event->comm.comm, comm1) == 0) {
CHECK__(perf_evsel__parse_sample(evsel, event, CHECK__(perf_evsel__parse_sample(evsel, event,
...@@ -134,6 +134,8 @@ int test__perf_time_to_tsc(void) ...@@ -134,6 +134,8 @@ int test__perf_time_to_tsc(void)
&sample)); &sample));
comm2_time = sample.time; comm2_time = sample.time;
} }
next_event:
perf_evlist__mmap_consume(evlist, i);
} }
} }
......
...@@ -78,7 +78,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) ...@@ -78,7 +78,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
struct perf_sample sample; struct perf_sample sample;
if (event->header.type != PERF_RECORD_SAMPLE) if (event->header.type != PERF_RECORD_SAMPLE)
continue; goto next_event;
err = perf_evlist__parse_sample(evlist, event, &sample); err = perf_evlist__parse_sample(evlist, event, &sample);
if (err < 0) { if (err < 0) {
...@@ -88,6 +88,8 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) ...@@ -88,6 +88,8 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
total_periods += sample.period; total_periods += sample.period;
nr_samples++; nr_samples++;
next_event:
perf_evlist__mmap_consume(evlist, 0);
} }
if ((u64) nr_samples == total_periods) { if ((u64) nr_samples == total_periods) {
......
...@@ -96,10 +96,10 @@ int test__task_exit(void) ...@@ -96,10 +96,10 @@ int test__task_exit(void)
retry: retry:
while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) {
if (event->header.type != PERF_RECORD_EXIT) if (event->header.type == PERF_RECORD_EXIT)
continue; nr_exit++;
nr_exit++; perf_evlist__mmap_consume(evlist, 0);
} }
if (!exited || !nr_exit) { if (!exited || !nr_exit) {
......
...@@ -545,12 +545,19 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) ...@@ -545,12 +545,19 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
md->prev = old; md->prev = old;
if (!evlist->overwrite)
perf_mmap__write_tail(md, old);
return event; 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) static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
{ {
if (evlist->mmap[idx].base != NULL) { if (evlist->mmap[idx].base != NULL) {
......
...@@ -89,6 +89,8 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); ...@@ -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); 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); int perf_evlist__open(struct perf_evlist *evlist);
void perf_evlist__close(struct perf_evlist *evlist); void perf_evlist__close(struct perf_evlist *evlist);
......
...@@ -822,6 +822,8 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, ...@@ -822,6 +822,8 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
PyObject *pyevent = pyrf_event__new(event); PyObject *pyevent = pyrf_event__new(event);
struct pyrf_event *pevent = (struct pyrf_event *)pyevent; struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
perf_evlist__mmap_consume(evlist, cpu);
if (pyevent == NULL) if (pyevent == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册