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

Commit 9215545e authored by Tom Zanussi's avatar Tom Zanussi Committed by Ingo Molnar
Browse files

perf: Convert perf tracing data into a tracing_data event



Bypasses the tracing_data perf header code and replaces it with
a synthesized event and processing function that accomplishes
the same thing, used when reading/writing perf data to/from a
pipe.

The tracing data is pretty large, and this patch doesn't attempt
to break it down into component events.  The tracing_data event
itself doesn't actually contain the tracing data, rather it
arranges for the event processing code to skip over it after
it's read, using the skip return value added to the event
processing loop in a previous patch.

Signed-off-by: default avatarTom Zanussi <tzanussi@gmail.com>
Acked-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: fweisbec@gmail.com
Cc: rostedt@goodmis.org
Cc: k-keiichi@bx.jp.nec.com
Cc: acme@ghostprotocols.net
LKML-Reference: <1270184365-8281-8-git-send-email-tzanussi@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent cd19a035
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -104,6 +104,11 @@ static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
	pc->data_tail = tail;
}

static void advance_output(size_t size)
{
	bytes_written += size;
}

static void write_output(void *buf, size_t size)
{
	while (size) {
@@ -599,6 +604,17 @@ static int __cmd_record(int argc, const char **argv)
			pr_err("Couldn't synthesize event_types.\n");
			return err;
		}

		err = event__synthesize_tracing_data(output, attrs,
						     nr_counters,
						     process_synthesized_event,
						     session);
		if (err <= 0) {
			pr_err("Couldn't record tracing data.\n");
			return err;
		}

		advance_output(err);
	}

	err = event__synthesize_kernel_mmap(process_synthesized_event,
+1 −0
Original line number Diff line number Diff line
@@ -269,6 +269,7 @@ static struct perf_event_ops event_ops = {
	.read	= process_read_event,
	.attr	= event__process_attr,
	.event_type = event__process_event_type,
	.tracing_data = event__process_tracing_data,
};

extern volatile int session_done;
+1 −0
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ static struct perf_event_ops event_ops = {
	.comm	= event__process_comm,
	.attr	= event__process_attr,
	.event_type = event__process_event_type,
	.tracing_data = event__process_tracing_data,
};

extern volatile int session_done;
+7 −0
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ struct build_id_event {
enum perf_header_event_type { /* above any possible kernel type */
	PERF_RECORD_HEADER_ATTR			= 64,
	PERF_RECORD_HEADER_EVENT_TYPE		= 65,
	PERF_RECORD_HEADER_TRACING_DATA		= 66,
	PERF_RECORD_HEADER_MAX
};

@@ -107,6 +108,11 @@ struct event_type_event {
	struct perf_trace_event_type event_type;
};

struct tracing_data_event {
	struct perf_event_header header;
	u32 size;
};

typedef union event_union {
	struct perf_event_header	header;
	struct ip_event			ip;
@@ -118,6 +124,7 @@ typedef union event_union {
	struct sample_event		sample;
	struct attr_event		attr;
	struct event_type_event		event_type;
	struct tracing_data_event	tracing_data;
} event_t;

struct events_stats {
+52 −0
Original line number Diff line number Diff line
@@ -934,3 +934,55 @@ int event__process_event_type(event_t *self,

	return 0;
}

int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
				   int nb_events,
				   event__handler_t process,
				   struct perf_session *session __unused)
{
	event_t ev;
	ssize_t size = 0, aligned_size = 0, padding;
	int err = 0;

	memset(&ev, 0, sizeof(ev));

	ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
	size = read_tracing_data_size(fd, pattrs, nb_events);
	if (size <= 0)
		return size;
	aligned_size = ALIGN(size, sizeof(u64));
	padding = aligned_size - size;
	ev.tracing_data.header.size = sizeof(ev.tracing_data);
	ev.tracing_data.size = aligned_size;

	process(&ev, session);

	err = read_tracing_data(fd, pattrs, nb_events);
	write_padded(fd, NULL, 0, padding);

	return aligned_size;
}

int event__process_tracing_data(event_t *self,
				struct perf_session *session)
{
	ssize_t size_read, padding, size = self->tracing_data.size;
	off_t offset = lseek(session->fd, 0, SEEK_CUR);
	char buf[BUFSIZ];

	/* setup for reading amidst mmap */
	lseek(session->fd, offset + sizeof(struct tracing_data_event),
	      SEEK_SET);

	size_read = trace_report(session->fd);

	padding = ALIGN(size_read, sizeof(u64)) - size_read;

	if (read(session->fd, buf, padding) < 0)
		die("reading input file");

	if (size_read + padding != size)
		die("tracing data size mismatch");

	return size_read + padding;
}
Loading