diff mbox series

[1/7] libtracefs: Have mapping work with the other tracefs_cpu* functions

Message ID 20240110030116.81837-2-rostedt@goodmis.org (mailing list archive)
State Accepted
Commit dee0448b2e75eababc19e8bc6d6abd8f274a2df2
Headers show
Series libtracefs: More fixes for memory mapping ring buffer API | expand

Commit Message

Steven Rostedt Jan. 10, 2024, 2:51 a.m. UTC
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>

If the tracefs_cpu is opened with tracefs_cpu_open_mapped() and it
successfully maps, then still allow the other tracefs_cpu*() functions to
work with the mapping. That is:

 tracefs_cpu_buffered_read() will act like tracefs_cpu_read()
 tracefs_cpu_buffered_read_buf() will act like tracefs_cpu_read_buf()

and tracefs_cpu_write() and tracefs_cpu_pipe() will read from the mapping
instead of using splice.

Update tracefs_iterate_raw_events() to always use
tracefs_cpu_buffered_read_buf() as it will do the right thing when buffered.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 Documentation/libtracefs-cpu-map.txt | 29 +++++++++++++++++++++------
 src/tracefs-events.c                 |  8 +-------
 src/tracefs-record.c                 | 30 ++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+), 13 deletions(-)
diff mbox series

Patch

diff --git a/Documentation/libtracefs-cpu-map.txt b/Documentation/libtracefs-cpu-map.txt
index 2c80d0894f87..ed62c96f83a1 100644
--- a/Documentation/libtracefs-cpu-map.txt
+++ b/Documentation/libtracefs-cpu-map.txt
@@ -29,11 +29,16 @@  memory mapping via either *tracefs_cpu_map()* or by *tracefs_cpu_open_mapped()*
 then the functions *tracefs_cpu_read*(3) and *tracefs_cpu_read_buf*(3) will use
 the mapping directly instead of calling the read system call.
 
-Note, mapping can also slow down *tracefs_cpu_buffered_read*(3) and
-*tracefs_cpu_buffered_read_buf*(3), as those use splice piping and when the
-kernel ring buffer is memory mapped, splice does a copy instead of using the
-ring buffer directly. Thus care must be used when determining to map the
-ring buffer or not, and why it does not get mapped by default.
+Note, mapping will cause *tracefs_cpu_buffered_read*(3) and *tracefs_cpu_buffered_read_buf*(3)
+to act just like *tracefs_cpu_read*(3) and *tracefs_cpu_read_buf*(3) respectively
+as it doesn't make sense to use a splice pipe when mapped. The kernel will do
+a copy for splice reads on mapping, and then another copy in the function when
+it can avoid the copying if the ring buffer is memory mapped.
+
+If the _tcpu_ is memory mapped it will also force *tracefs_cpu_write*(3) and
+*tracefs_cpu_pipe*(3) to copy from the mapping instead of using splice.
+Thus care must be used when determining to map the ring buffer or not,
+and why it does not get mapped by default.
 
 The *tracefs_cpu_is_mapped()* function will return true if _tcpu_ currently has
 its ring buffer memory mapped and false otherwise. This does not return whether or
@@ -78,6 +83,7 @@  static void read_subbuf(struct tep_handle *tep, struct kbuffer *kbuf)
 {
 	static struct trace_seq seq;
 	struct tep_record record;
+	int missed_events;
 
 	if (seq.buffer)
 		trace_seq_reset(&seq);
@@ -86,6 +92,14 @@  static void read_subbuf(struct tep_handle *tep, struct kbuffer *kbuf)
 
 	while ((record.data = kbuffer_read_event(kbuf, &record.ts))) {
 		record.size = kbuffer_event_size(kbuf);
+		missed_events = kbuffer_missed_events(kbuf);
+		if (missed_events) {
+			printf("[MISSED EVENTS");
+			if (missed_events > 0)
+				printf(": %d]\n", missed_events);
+			else
+				printf("]\n");
+		}
 		kbuffer_next_event(kbuf, NULL);
 		tep_print_event(tep, &seq, &record,
 				"%s-%d %6.1000d\t%s: %s\n",
@@ -128,7 +142,10 @@  int main (int argc, char **argv)
 
 	/*
 	 * If this kernel supports mapping, use normal read,
-	 * otherwise use the piped buffer read.
+	 * otherwise use the piped buffer read, although if
+	 * the mapping succeeded, tracefs_cpu_buffered_read_buf()
+	 * acts the same as tracefs_cpu_read_buf(). But this is just
+	 * an example on how to use tracefs_cpu_is_mapped().
 	 */
 	mapped = tracefs_cpu_is_mapped(tcpu);
 	if (!mapped)
diff --git a/src/tracefs-events.c b/src/tracefs-events.c
index 9f620abebdda..1b1693cf0923 100644
--- a/src/tracefs-events.c
+++ b/src/tracefs-events.c
@@ -32,7 +32,6 @@  struct cpu_iterate {
 	struct tep_event *event;
 	struct kbuffer *kbuf;
 	int cpu;
-	bool mapped;
 };
 
 static int read_kbuf_record(struct cpu_iterate *cpu)
@@ -67,11 +66,7 @@  int read_next_page(struct tep_handle *tep, struct cpu_iterate *cpu)
 	if (!cpu->tcpu)
 		return -1;
 
-	/* Do not do buffered reads if it is mapped */
-	if (cpu->mapped)
-		kbuf = tracefs_cpu_read_buf(cpu->tcpu, true);
-	else
-		kbuf = tracefs_cpu_buffered_read_buf(cpu->tcpu, true);
+	kbuf = tracefs_cpu_buffered_read_buf(cpu->tcpu, true);
 	/*
 	 * tracefs_cpu_buffered_read_buf() only reads in full subbuffer size,
 	 * but this wants partial buffers as well. If the function returns
@@ -295,7 +290,6 @@  static int open_cpu_files(struct tracefs_instance *instance, cpu_set_t *cpus,
 
 		tmp[i].tcpu = tcpu;
 		tmp[i].cpu = cpu;
-		tmp[i].mapped = tracefs_cpu_is_mapped(tcpu);
 		i++;
 	}
 	*count = i;
diff --git a/src/tracefs-record.c b/src/tracefs-record.c
index fca3ddf9afbe..881f49256dc2 100644
--- a/src/tracefs-record.c
+++ b/src/tracefs-record.c
@@ -571,6 +571,9 @@  int tracefs_cpu_buffered_read(struct tracefs_cpu *tcpu, void *buffer, bool nonbl
 	if (ret <= 0)
 		return ret;
 
+	if (tcpu->mapping)
+		return trace_mmap_read(tcpu->mapping, buffer);
+
 	if (tcpu->flags & TC_NONBLOCK)
 		mode |= SPLICE_F_NONBLOCK;
 
@@ -617,6 +620,16 @@  struct kbuffer *tracefs_cpu_buffered_read_buf(struct tracefs_cpu *tcpu, bool non
 {
 	int ret;
 
+	/* If mapping is enabled, just use it directly */
+	if (tcpu->mapping) {
+		ret = wait_on_input(tcpu, nonblock);
+		if (ret <= 0)
+			return NULL;
+
+		ret = trace_mmap_load_subbuf(tcpu->mapping, tcpu->kbuf);
+		return ret > 0 ? tcpu->kbuf : NULL;
+	}
+
 	if (!get_buffer(tcpu))
 		return NULL;
 
@@ -795,6 +808,20 @@  int tracefs_cpu_write(struct tracefs_cpu *tcpu, int wfd, bool nonblock)
 	int tot;
 	int ret;
 
+	if (tcpu->mapping) {
+		int r = tracefs_cpu_read(tcpu, buffer, nonblock);
+		if (r < 0)
+			return r;
+		do {
+			ret = write(wfd, buffer, r);
+			if (ret < 0)
+				return ret;
+			r -= ret;
+			tot_write += ret;
+		} while (r > 0);
+		return tot_write;
+	}
+
 	ret = wait_on_input(tcpu, nonblock);
 	if (ret <= 0)
 		return ret;
@@ -860,6 +887,9 @@  int tracefs_cpu_pipe(struct tracefs_cpu *tcpu, int wfd, bool nonblock)
 	int mode = SPLICE_F_MOVE;
 	int ret;
 
+	if (tcpu->mapping)
+		return tracefs_cpu_write(tcpu, wfd, nonblock);
+
 	ret = wait_on_input(tcpu, nonblock);
 	if (ret <= 0)
 		return ret;