Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8e50d384 authored by Zhouyi Zhou's avatar Zhouyi Zhou Committed by Arnaldo Carvalho de Melo
Browse files

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: default avatarZhouyi 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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent ae779a63
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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;
+6 −4
Original line number Diff line number Diff line
@@ -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);
@@ -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:
@@ -847,7 +847,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
			 */
			/* Fall thru */
		default:
			continue;
			goto next_event;
		}


@@ -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);
	}
}

+5 −3
Original line number Diff line number Diff line
@@ -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)
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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;
		}
+1 −0
Original line number Diff line number Diff line
@@ -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;
Loading