diff mbox series

[v2,18/22] libtracefs: Add tracefs_instance_set/get_subbuf_size()

Message ID 20231228215433.54854-19-rostedt@goodmis.org (mailing list archive)
State Accepted
Commit 8c57eb4c8d5385b22eedc7d41f1fd9080ae60efb
Headers show
Series libtracefs: Several updates | expand

Commit Message

Steven Rostedt Dec. 28, 2023, 9:52 p.m. UTC
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>

Add API to retrieve and modify the current sub-buffer size.

  tracefs_instance_set_subbuf_size()
  tracefs_instance_get_subbuf_size()

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 Documentation/libtracefs-instances-subbuf.txt | 152 ++++++++++++++++++
 Documentation/libtracefs.txt                  |   4 +
 include/tracefs.h                             |   2 +
 samples/Makefile                              |   1 +
 src/tracefs-instance.c                        |  37 +++++
 5 files changed, 196 insertions(+)
 create mode 100644 Documentation/libtracefs-instances-subbuf.txt
diff mbox series

Patch

diff --git a/Documentation/libtracefs-instances-subbuf.txt b/Documentation/libtracefs-instances-subbuf.txt
new file mode 100644
index 000000000000..8d5c3e0ed3bd
--- /dev/null
+++ b/Documentation/libtracefs-instances-subbuf.txt
@@ -0,0 +1,152 @@ 
+libtracefs(3)
+=============
+
+NAME
+----
+tracefs_instance_get_subbuf_size, tracefs_instance_set_subbuf_size - Helper functions for working with ring buffer sub buffers.
+
+SYNOPSIS
+--------
+[verse]
+--
+*#include <tracefs.h>*
+
+size_t *tracefs_instance_get_subbuf_size*(struct tracefs_instance pass:[*]_instance_);
+int *tracefs_instance_set_subbuf_size*(struct tracefs_instance pass:[*]_instance_, size_t _size_);
+--
+
+DESCRIPTION
+-----------
+Helper functions for working with the sub-buffers of the tracing ring buffer.
+The tracing ring buffer is broken up into *sub-buffers*. An event can not be
+bigger than the data section of the sub-buffer (see *tep_get_sub_buffer_data_size*(3)).
+By default, the ring buffer uses the architectures *page_size* as the default
+size of the sub-buffer, but this can be limiting if there is a need for large
+events, for example, the application wants to write large strings into
+the trace_marker file.
+
+The *tracefs_instance_get_subbuf_size()* returns the current size in kilobytes
+fo the ring buffer sub-buffers.
+
+The *tracefs_instance_set_subbuf_size()* will write the size in kilobytes of
+what the new sub-buffer size should be. Note, that this is only a hint to what
+the minimum sub-buffer size should be. It also does not take into account the
+meta-data that is used by the sub-buffer, so the size written should be no less
+than 16 bytes more than the maximum event size that will be used. The kernel
+will likely make the sub-buffer size larger than specified, as it may need to
+align the size for implementation purposes.
+
+RETURN VALUE
+------------
+The *tracefs_instance_get_subbuf_size()* returns the size of the current
+sub-buffer for the given _instance_ ring buffer or -1 on error.
+
+The *tracefs_instance_set_subbuf_size()* will return 0 if it successfully set
+the _instance_ ring buffer sub-buffer size in kilobytes, or -1 on error.
+
+EXAMPLE
+-------
+[source,c]
+--
+#include <stdlib.h>
+#include <tracefs.h>
+#include <errno.h>
+
+int main(int argc, char **argv)
+{
+	struct tep_handle *tep;
+	ssize_t save_subsize;
+	ssize_t subsize;
+	char *trace;
+	char buf[3000];
+	int meta_size;
+	int ret;
+	int i;
+
+	tep = tep_alloc();
+	ret = tracefs_load_headers(NULL, tep);
+	tep_free(tep);
+
+	if (ret < 0) {
+		perror("reading headers");
+		exit(-1);
+	}
+
+	meta_size = tep_get_sub_buffer_size(tep) - tep_get_sub_buffer_data_size(tep);
+
+	save_subsize = tracefs_instance_get_subbuf_size(NULL);
+	if (save_subsize < 0) {
+		printf("Changing sub-buffer size not available\n");
+		exit(-1);
+	}
+
+	subsize = save_subsize * 1024;
+
+	/* Have at least 4 writes fit on a sub-buffer */
+	if (subsize - meta_size < sizeof(buf) *4 ) {
+		subsize = ((sizeof(buf) * 4 + meta_size) + 1023) / 1024;
+		tracefs_instance_set_subbuf_size(NULL, subsize);
+	}
+
+	for (i = 0; i < sizeof(buf) - 1; i++) {
+		buf[i] = '0' + i % 10;
+	}
+	buf[i] = '\0';
+
+	tracefs_instance_clear(NULL);
+
+	for (i = 0; i < 4; i++) {
+		ret = tracefs_printf(NULL, "%s\n", buf);
+		if (ret < 0)
+			perror("write");
+	}
+
+	trace = tracefs_instance_file_read(NULL, "trace", NULL);
+	printf("%s\n", trace);
+	free(trace);
+
+	printf("Buffer size was: %zd * 1024\n",
+	       tracefs_instance_get_subbuf_size(NULL));
+
+	tracefs_instance_set_subbuf_size(NULL, save_subsize);
+}
+--
+FILES
+-----
+[verse]
+--
+*tracefs.h*
+	Header file to include in order to have access to the library APIs.
+*-ltracefs*
+	Linker switch to add when building a program that uses the library.
+--
+
+SEE ALSO
+--------
+*libtracefs*(3),
+*libtraceevent*(3),
+*trace-cmd*(1)
+
+AUTHOR
+------
+[verse]
+--
+*Steven Rostedt* <rostedt@goodmis.org>
+*Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>
+--
+REPORTING BUGS
+--------------
+Report bugs to  <linux-trace-devel@vger.kernel.org>
+
+LICENSE
+-------
+libtracefs is Free Software licensed under the GNU LGPL 2.1
+
+RESOURCES
+---------
+https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/
+
+COPYING
+-------
+Copyright \(C) 2020 VMware, Inc. Free use of this software is granted under
+the terms of the GNU Public License (GPL).
diff --git a/Documentation/libtracefs.txt b/Documentation/libtracefs.txt
index 6752ed3c9b98..1962b3b34622 100644
--- a/Documentation/libtracefs.txt
+++ b/Documentation/libtracefs.txt
@@ -324,6 +324,10 @@  Recording of trace_pipe_raw files:
 	struct kbuffer pass:[*]*tracefs_cpu_buffered_read_buf*(struct tracefs_cpu pass:[*]_tcpu_, bool _nonblock_);
 	struct kbuffer pass:[*]*tracefs_cpu_flush_buf*(struct tracefs_cpu pass:[*]_tcpu_);
 
+Helper functions for modifying the ring buffer sub-buffers:
+	size_t *tracefs_instance_get_subbuf_size*(struct tracefs_instance pass:[*]_instance_);
+	int *tracefs_instance_set_subbuf_size*(struct tracefs_instance pass:[*]_instance_, size_t _size_);
+
 Helper functions for guest tracing:
 	char pass:[*]*tracefs_find_cid_pid*(int _cid_);
 	char pass:[*]*tracefs_instance_find_cid_pid*(struct tracefs_instance pass:[*]_instance_, int _cid_);
diff --git a/include/tracefs.h b/include/tracefs.h
index 3ae78d4f3af7..c66bfd2edf0b 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -63,6 +63,8 @@  int tracefs_instance_get_affinity_set(struct tracefs_instance *instance,
 				      cpu_set_t *set, size_t set_size);
 ssize_t tracefs_instance_get_buffer_size(struct tracefs_instance *instance, int cpu);
 int tracefs_instance_set_buffer_size(struct tracefs_instance *instance, size_t size, int cpu);
+ssize_t tracefs_instance_get_subbuf_size(struct tracefs_instance *instance);
+int tracefs_instance_set_subbuf_size(struct tracefs_instance *instance, size_t size);
 char **tracefs_instances(const char *regex);
 
 int tracefs_instance_get_buffer_percent(struct tracefs_instance *instance);
diff --git a/samples/Makefile b/samples/Makefile
index 787d28769051..77739c8b0aa7 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -25,6 +25,7 @@  EXAMPLES += cpu
 EXAMPLES += guest
 EXAMPLES += cpu-buf
 EXAMPLES += instances-stat
+EXAMPLES += instances-subbuf
 
 TARGETS :=
 TARGETS += sqlhist
diff --git a/src/tracefs-instance.c b/src/tracefs-instance.c
index 2162424ad3a7..8d9dd0e21498 100644
--- a/src/tracefs-instance.c
+++ b/src/tracefs-instance.c
@@ -441,6 +441,43 @@  int tracefs_instance_set_buffer_size(struct tracefs_instance *instance, size_t s
 	return ret < 0 ? -1 : 0;
 }
 
+/**
+ * tracefs_instance_get_subbuf_size - return the sub-buffer size of the ring buffer
+ * @instance: The instance to get the buffer size from
+ *
+ * Returns the sub-buffer size in kilobytes.
+ * Returns -1 on error.
+ */
+ssize_t tracefs_instance_get_subbuf_size(struct tracefs_instance *instance)
+{
+	long long size;
+	int ret;
+
+	ret = tracefs_instance_file_read_number(instance, "buffer_subbuf_size_kb", &size);
+	if (ret < 0)
+		return ret;
+
+	return size;
+}
+
+/**
+ * tracefs_instance_set_buffer_size - modify the ring buffer sub-buffer size
+ * @instance: The instance to modify (NULL for the top level)
+ * @size: The size in kilobytes to to set the sub-buffer size to
+ *
+ * Sets the sub-buffer size in kilobytes for the given ring buffer.
+ *
+ * Returns 0 on success and -1 on error.
+ */
+int tracefs_instance_set_subbuf_size(struct tracefs_instance *instance, size_t size)
+{
+	int ret;
+
+	ret = tracefs_instance_file_write_number(instance, "buffer_subbuf_size_kb", size);
+
+	return ret < 0 ? -1 : 0;
+}
+
 /**
  * tracefs_instance_get_trace_dir - return the top trace directory, where the instance is confuigred
  * @instance: ftrace instance