* [PATCH 1/6] libtraceevent: Add tep_get_sub_buffer_commit_offset()
2023-12-24 19:15 [PATCH 0/6] libtraceevent/kbuffer: Add more kbuffer APIs Steven Rostedt
@ 2023-12-24 19:15 ` Steven Rostedt
2023-12-24 19:15 ` [PATCH 2/6] libtraceevent: Fix tep_kbuffer() to have kbuf assign long_size Steven Rostedt
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2023-12-24 19:15 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Steven Rostedt (Google)
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>
Add a function that retrieves the offset on the sub-buffer to find where the
"commit" variable of the sub buffer is located.
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
Documentation/libtraceevent-page_size.txt | 9 +++++++++
Documentation/libtraceevent.txt | 1 +
include/traceevent/event-parse.h | 1 +
src/event-parse-api.c | 15 +++++++++++++++
4 files changed, 26 insertions(+)
diff --git a/Documentation/libtraceevent-page_size.txt b/Documentation/libtraceevent-page_size.txt
index 6d0dd36e3d68..0264e528e08a 100644
--- a/Documentation/libtraceevent-page_size.txt
+++ b/Documentation/libtraceevent-page_size.txt
@@ -15,6 +15,7 @@ SYNOPSIS
int *tep_get_page_size*(struct tep_handle pass:[*]_tep_);
void *tep_set_page_size*(struct tep_handle pass:[*]_tep_, int _page_size_);
int *tep_get_sub_buffer_size*(struct tep_handle pass:[*]_tep_);
+int *tep_get_sub_buffer_commit_offset*(struct tep_handle pass:[*]_tep_);
--
DESCRIPTION
@@ -32,6 +33,11 @@ The *tep_get_sub_buffer_size()* returns the size of each "sub buffer" of the
ring buffer. The Linux kernel ring buffer is broken up into sections called
sub buffers. This returns the size of those buffers.
+The *tep_get_sub_buffer_commit_offset()* returns the offset on the sub buffer
+that holds the committed portion of data. This number contains the index from
+the data portion of the sub buffer that is the end of the last element on the
+sub buffer.
+
RETURN VALUE
------------
The *tep_get_page_size()* function returns size of the memory page, in bytes.
@@ -39,6 +45,9 @@ The *tep_get_page_size()* function returns size of the memory page, in bytes.
The *tep_get_sub_buffer_size()* function returns the number of bytes each sub
buffer is made up of.
+The *tep_get_sub_buffer_commit_offset()* function returns the location on the
+sub buffer that contains the index of the last element.
+
EXAMPLE
-------
[source,c]
diff --git a/Documentation/libtraceevent.txt b/Documentation/libtraceevent.txt
index 2ae6628bd324..07b9a2dffb68 100644
--- a/Documentation/libtraceevent.txt
+++ b/Documentation/libtraceevent.txt
@@ -27,6 +27,7 @@ Management of tep handler data structure and access of its members:
int *tep_get_page_size*(struct tep_handle pass:[*]_tep_);
void *tep_set_page_size*(struct tep_handle pass:[*]_tep_, int _page_size_);
int *tep_get_sub_buffer_size*(struct tep_handle pass:[*]_tep_);
+ int *tep_get_sub_buffer_commit_offset*(struct tep_handle pass:[*]_tep_);
int *tep_get_header_page_size*(struct tep_handle pass:[*]_tep_);
int *tep_get_header_timestamp_size*(struct tep_handle pass:[*]_tep_);
bool *tep_is_old_format*(struct tep_handle pass:[*]_tep_);
diff --git a/include/traceevent/event-parse.h b/include/traceevent/event-parse.h
index e0785f7fe1d4..adfb770aa4ee 100644
--- a/include/traceevent/event-parse.h
+++ b/include/traceevent/event-parse.h
@@ -588,6 +588,7 @@ int tep_get_long_size(struct tep_handle *tep);
void tep_set_long_size(struct tep_handle *tep, int long_size);
int tep_get_page_size(struct tep_handle *tep);
int tep_get_sub_buffer_size(struct tep_handle *tep);
+int tep_get_sub_buffer_commit_offset(struct tep_handle *tep);
void tep_set_page_size(struct tep_handle *tep, int _page_size);
bool tep_is_file_bigendian(struct tep_handle *tep);
void tep_set_file_bigendian(struct tep_handle *tep, enum tep_endian endian);
diff --git a/src/event-parse-api.c b/src/event-parse-api.c
index 268a58609419..1a9457352875 100644
--- a/src/event-parse-api.c
+++ b/src/event-parse-api.c
@@ -277,6 +277,21 @@ int tep_get_sub_buffer_size(struct tep_handle *tep)
return tep->header_page_data_size + tep->header_page_data_offset;
}
+/**
+ * tep_get_sub_buffer_commit_offset - return offset of the commit location
+ * @tep: the handle to the tep_handle
+ *
+ * Returns the offset of where to find the "commit" field of the offset.
+ * Use tep_get_header_page_size() to find the size of the commit field.
+ */
+int tep_get_sub_buffer_commit_offset(struct tep_handle *tep)
+{
+ if (!tep)
+ return -1;
+
+ return tep->header_page_size_offset;
+}
+
/**
* tep_is_file_bigendian - return the endian of the file
* @tep: a handle to the tep_handle
--
2.42.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 2/6] libtraceevent: Fix tep_kbuffer() to have kbuf assign long_size
2023-12-24 19:15 [PATCH 0/6] libtraceevent/kbuffer: Add more kbuffer APIs Steven Rostedt
2023-12-24 19:15 ` [PATCH 1/6] libtraceevent: Add tep_get_sub_buffer_commit_offset() Steven Rostedt
@ 2023-12-24 19:15 ` Steven Rostedt
2023-12-24 19:16 ` [PATCH 3/6] kbuffer: Add kbuffer_read_buffer() Steven Rostedt
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2023-12-24 19:15 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Steven Rostedt (Google)
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>
If the tep handle that returns the kbuf from tep_kbuffer() did not have its
long_size initialized, neither will the kbuffer it returns. This can cause
inconsistent results. Default the long_size to the "commit" size of the header
page as that should also be the size of long.
Fixes: 21ba6336 ("libtraceevent: Add kbuffer_create()")
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
src/parse-utils.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/parse-utils.c b/src/parse-utils.c
index 9c38e1e644d7..b434e24e44df 100644
--- a/src/parse-utils.c
+++ b/src/parse-utils.c
@@ -137,6 +137,11 @@ struct kbuffer *tep_kbuffer(struct tep_handle *tep)
int long_size;
long_size = tep_get_long_size(tep);
+
+ /* If the long_size is not set, then use the commit size */
+ if (!long_size)
+ long_size = tep_get_header_page_size(tep);
+
if (long_size == 8)
long_size = KBUFFER_LSIZE_8;
else
--
2.42.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 3/6] kbuffer: Add kbuffer_read_buffer()
2023-12-24 19:15 [PATCH 0/6] libtraceevent/kbuffer: Add more kbuffer APIs Steven Rostedt
2023-12-24 19:15 ` [PATCH 1/6] libtraceevent: Add tep_get_sub_buffer_commit_offset() Steven Rostedt
2023-12-24 19:15 ` [PATCH 2/6] libtraceevent: Fix tep_kbuffer() to have kbuf assign long_size Steven Rostedt
@ 2023-12-24 19:16 ` Steven Rostedt
2023-12-24 19:16 ` [PATCH 4/6] kbuffer: Add kbuffer_dup() Steven Rostedt
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2023-12-24 19:16 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Steven Rostedt (Google)
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>
The kbuffer_read_buffer() function will fill the given buffer from the
kbuf the same way the kernel would do a read system call. That is, if the
length len is less than the sub buffer size, or the current index is
non-zero, it will start from the next event to read, and create buffer as a new
sub buffer (with a timestamp and commit header) with that event that was found
and including all events after that can fit within len.
The len must include the size of the sub buffer header as
well as the events to include. That is, len is the allocate size of buffer
that can be filled. The return from this function is the index of the end of
the last event that was added. If there are no more events then zero is
returned, and if the buffer can not copy any events because len was too small,
then -1 is returned.
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
Documentation/libtraceevent-kbuffer-read.txt | 19 +-
Documentation/libtraceevent.txt | 1 +
include/traceevent/kbuffer.h | 1 +
src/kbuffer-parse.c | 172 ++++++++++++++++---
4 files changed, 171 insertions(+), 22 deletions(-)
diff --git a/Documentation/libtraceevent-kbuffer-read.txt b/Documentation/libtraceevent-kbuffer-read.txt
index 68184ad69ed7..ade42f33d8fc 100644
--- a/Documentation/libtraceevent-kbuffer-read.txt
+++ b/Documentation/libtraceevent-kbuffer-read.txt
@@ -4,7 +4,7 @@ libtraceevent(3)
NAME
----
kbuffer_read_event, kbuffer_next_event, kbuffer_missed_events, kbuffer_event_size, kbuffer_curr_size,
-kbuffer_curr_offset, kbuffer_curr_index -
+kbuffer_curr_offset, kbuffer_curr_index, kbuffer_read_buffer -
Functions to read through the kbuffer sub buffer.
SYNOPSIS
@@ -21,6 +21,7 @@ int *kbuffer_event_size*(struct kbuffer pass:[*]_kbuf_);
int *kbuffer_curr_size*(struct kbuffer pass:[*]_kbuf_);
int *kbuffer_curr_offset*(struct kbuffer pass:[*]_kbuf_);
int *kbuffer_curr_index*(struct kbuffer pass:[*]_kbuf_);
+int *kbuffer_read_buffer*(struct kbuffer pass:[*]_kbuf_, void pass:[*]_buffer_, int _len_);
--
DESCRIPTION
@@ -64,6 +65,18 @@ The *kbuffer_curr_index()* function returns the index from the beginning of the
portion of the sub-buffer where the current evnet's meta data is located.
The first event will likely be zero, but may not be if there's a timestamp attached to it.
+The *kbuffer_read_buffer()* function will fill the given _buffer_ from the _kbuf_ the same
+way the kernel would do a read system call. That is, if the length _len_ is less than the
+sub buffer size, or the kbuffer current index is non-zero, it will start copying from the
+_kbuf_ current event and create _buffer_ as a new sub buffer (with a timestamp
+and commit header) with that event that was found and including all events after that can
+fit within _len_. The _len_ must include the size of the sub buffer header as well as the
+events to include. That is, _len_ is the allocate size of _buffer_ that can be filled.
+The return from this function is the index of the end of the last event that was added.
+If there are no more events then zero is returned, and if the buffer can not
+copy any events because _len_ was too small, then -1 is returned.
+
+
RETURN VALUE
------------
*kbuffer_read_event()* returns the event that the _kbuf_ descriptor is currently at,
@@ -92,6 +105,10 @@ sub-buffer.
*kbuf_curr_index()* returns the index of the current record from the beginning of the _kbuf_
data section.
+*kbuf_read_buffer()* returns the index of the end of the last event that was filled in
+_buffer_. If there are no more events to copy from _start_ then 0 is returned. If _len_
+is not big enough to hold any events, then -1 is returned.
+
EXAMPLE
-------
[source,c]
diff --git a/Documentation/libtraceevent.txt b/Documentation/libtraceevent.txt
index 07b9a2dffb68..407c06809269 100644
--- a/Documentation/libtraceevent.txt
+++ b/Documentation/libtraceevent.txt
@@ -195,6 +195,7 @@ kbuffer parsing:
int *kbuffer_curr_size*(struct kbuffer pass:[*]_kbuf_);
int *kbuffer_curr_offset*(struct kbuffer pass:[*]_kbuf_);
int *kbuffer_curr_index*(struct kbuffer pass:[*]_kbuf_);
+ int *kbuffer_read_buffer*(struct kbuffer pass:[*]_kbuf_, void pass:[*]_buffer_, int _start_, int _len_);
--
DESCRIPTION
diff --git a/include/traceevent/kbuffer.h b/include/traceevent/kbuffer.h
index ca638bc06dba..e5d377bf0e60 100644
--- a/include/traceevent/kbuffer.h
+++ b/include/traceevent/kbuffer.h
@@ -42,6 +42,7 @@ unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr);
void *kbuffer_translate_data(int swap, void *data, unsigned int *size);
void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset, unsigned long long *ts);
+int kbuffer_read_buffer(struct kbuffer *kbuf, void *buffer, int len);
int kbuffer_curr_index(struct kbuffer *kbuf);
diff --git a/src/kbuffer-parse.c b/src/kbuffer-parse.c
index 390a789b20fb..b86c8f0b9d4f 100644
--- a/src/kbuffer-parse.c
+++ b/src/kbuffer-parse.c
@@ -86,6 +86,42 @@ static int do_swap(struct kbuffer *kbuf)
ENDIAN_MASK;
}
+static unsigned long long swap_8(unsigned long data)
+{
+ return ((data & 0xffULL) << 56) |
+ ((data & (0xffULL << 8)) << 40) |
+ ((data & (0xffULL << 16)) << 24) |
+ ((data & (0xffULL << 24)) << 8) |
+ ((data & (0xffULL << 32)) >> 8) |
+ ((data & (0xffULL << 40)) >> 24) |
+ ((data & (0xffULL << 48)) >> 40) |
+ ((data & (0xffULL << 56)) >> 56);
+}
+
+static unsigned int swap_4(unsigned int data)
+{
+ return ((data & 0xffULL) << 24) |
+ ((data & (0xffULL << 8)) << 8) |
+ ((data & (0xffULL << 16)) >> 8) |
+ ((data & (0xffULL << 24)) >> 24);
+}
+
+static void write_8(bool do_swap, void *ptr, unsigned long long data)
+{
+ if (do_swap)
+ *(unsigned long long *)ptr = swap_8(data);
+ else
+ *(unsigned long long *)ptr = data;
+}
+
+static void write_4(bool do_swap, void *ptr, unsigned int data)
+{
+ if (do_swap)
+ *(unsigned int *)ptr = swap_4(data);
+ else
+ *(unsigned int *)ptr = data;
+}
+
static unsigned long long __read_8(void *ptr)
{
unsigned long long data = *(unsigned long long *)ptr;
@@ -96,18 +132,8 @@ static unsigned long long __read_8(void *ptr)
static unsigned long long __read_8_sw(void *ptr)
{
unsigned long long data = *(unsigned long long *)ptr;
- unsigned long long swap;
- swap = ((data & 0xffULL) << 56) |
- ((data & (0xffULL << 8)) << 40) |
- ((data & (0xffULL << 16)) << 24) |
- ((data & (0xffULL << 24)) << 8) |
- ((data & (0xffULL << 32)) >> 8) |
- ((data & (0xffULL << 40)) >> 24) |
- ((data & (0xffULL << 48)) >> 40) |
- ((data & (0xffULL << 56)) >> 56);
-
- return swap;
+ return swap_8(data);
}
static unsigned int __read_4(void *ptr)
@@ -120,14 +146,8 @@ static unsigned int __read_4(void *ptr)
static unsigned int __read_4_sw(void *ptr)
{
unsigned int data = *(unsigned int *)ptr;
- unsigned int swap;
- swap = ((data & 0xffULL) << 24) |
- ((data & (0xffULL << 8)) << 8) |
- ((data & (0xffULL << 16)) >> 8) |
- ((data & (0xffULL << 24)) >> 24);
-
- return swap;
+ return swap_4(data);
}
static unsigned long long read_8(struct kbuffer *kbuf, void *ptr)
@@ -295,6 +315,13 @@ static unsigned int ts4host(struct kbuffer *kbuf,
return type_len_ts >> 5;
}
+static void set_curr_to_end(struct kbuffer *kbuf)
+{
+ kbuf->curr = kbuf->size;
+ kbuf->next = kbuf->size;
+ kbuf->index = kbuf->size;
+}
+
/*
* Linux 2.6.30 and earlier (not much ealier) had a different
* ring buffer format. It should be obsolete, but we handle it anyway.
@@ -339,9 +366,7 @@ static unsigned int old_update_pointers(struct kbuffer *kbuf)
case OLD_RINGBUF_TYPE_TIME_STAMP:
/* should never happen! */
- kbuf->curr = kbuf->size;
- kbuf->next = kbuf->size;
- kbuf->index = kbuf->size;
+ set_curr_to_end(kbuf);
return -1;
default:
if (len)
@@ -846,3 +871,108 @@ kbuffer_raw_get(struct kbuffer *kbuf, void *subbuf, struct kbuffer_raw_info *inf
return info;
}
+
+/**
+ * kbuffer_read_buffer - read a buffer like the kernel would perform a read
+ * @kbuf: the kbuffer handle
+ * @buffer: where to write the data into
+ * @len; The length of @buffer
+ *
+ * This will read the saved sub buffer within @kbuf like the systemcall
+ * of read() to the trace_pipe_raw would do. That is, if either @len
+ * can not fit the entire buffer, or if the current index in @kbuf
+ * is non-zero, it will write to @buffer a new subbuffer that could be
+ * loaded into kbuffer_load_subbuffer(). That is, it will write into
+ * @buffer a legitimate sub-buffer with a header and all that has the
+ * proper timestamp and commit fields.
+ *
+ * Returns the index after the last element written.
+ * 0 if nothing was copied.
+ * -1 on error (which includes not having enough space in len to
+ * copy the subbuffer header or any of its content. In otherwords,
+ * do not try again!
+ *
+ * @kbuf current index will be set to the next element to read.
+ */
+int kbuffer_read_buffer(struct kbuffer *kbuf, void *buffer, int len)
+{
+ int subbuf_size = kbuf->start + kbuf->size;
+ unsigned long long ts;
+ unsigned int type_len_ts;
+ bool do_swap = false;
+ int last_next;
+ int save_curr;
+
+ if (!kbuf->curr && len >= subbuf_size) {
+ memcpy(buffer, kbuf->subbuffer, subbuf_size);
+ set_curr_to_end(kbuf);
+ return kbuf->size;
+ }
+
+ /* Are we at the end of the buffer */
+ if (kbuf->curr >= kbuf->size)
+ return 0;
+
+ /* If we can not copy anyting, return -1 */
+ if (len < kbuf->start)
+ return -1;
+
+ /* Check if the first event can fit */
+ if (len < (kbuf->next - kbuf->curr) + kbuf->start)
+ return -1;
+
+ if (kbuf->read_8 == __read_8_sw)
+ do_swap = true;
+
+ /* Have this subbuffer timestamp be the current timestamp */
+ write_8(do_swap, buffer, kbuf->timestamp);
+
+ len -= kbuf->start;
+
+ save_curr = kbuf->curr;
+
+ /* Copy the rest of the buffer if it fits */
+ if (len >= kbuf->size - kbuf->curr) {
+ set_curr_to_end(kbuf);
+ last_next = kbuf->size;
+ } else {
+ /*
+ * The length doesn't hold the rest,
+ * need to find the last that fits
+ */
+
+ /* Due to timestamps, we must save the current next to use */
+ last_next = kbuf->next;
+
+ while (len > kbuf->next - save_curr) {
+ last_next = kbuf->next;
+ if (!kbuffer_next_event(kbuf, &ts))
+ break;
+ }
+ }
+
+ len = last_next - save_curr;
+ /* No event was found? */
+ if (!len)
+ return 0;
+
+ memcpy(buffer + kbuf->start, kbuf->data + save_curr, len);
+
+ /* Zero out the delta, as the sub-buffer has the timestamp */
+ type_len_ts = read_4(kbuf, buffer + kbuf->start);
+
+ if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
+ type_len_ts &= ~(((1 << 27) - 1));
+ else
+ type_len_ts &= ((1 << 5) - 1);
+
+ write_4(do_swap, buffer + kbuf->start, type_len_ts);
+
+ /* Update the size */
+ if (kbuf->read_long == __read_long_8)
+ write_8(do_swap, buffer + 8, len);
+ else
+ write_4(do_swap, buffer + 8, len);
+
+ return last_next;
+}
--
2.42.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 4/6] kbuffer: Add kbuffer_dup()
2023-12-24 19:15 [PATCH 0/6] libtraceevent/kbuffer: Add more kbuffer APIs Steven Rostedt
` (2 preceding siblings ...)
2023-12-24 19:16 ` [PATCH 3/6] kbuffer: Add kbuffer_read_buffer() Steven Rostedt
@ 2023-12-24 19:16 ` Steven Rostedt
2023-12-24 19:16 ` [PATCH 5/6] kbuffer: Add kbuffer_subbuffer() API Steven Rostedt
2023-12-24 19:16 ` [PATCH 6/6] kbuffer: Add kbuffer_refresh() API Steven Rostedt
5 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2023-12-24 19:16 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Steven Rostedt (Google)
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>
Add the function kbuffer_dup() that will duplicate a current kbuffer structure
that can be used separately on the same subbuffer or load a new buffer on it.
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
.../libtraceevent-kbuffer-create.txt | 8 +++++++-
Documentation/libtraceevent.txt | 1 +
include/traceevent/kbuffer.h | 1 +
src/kbuffer-parse.c | 20 +++++++++++++++++++
4 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/Documentation/libtraceevent-kbuffer-create.txt b/Documentation/libtraceevent-kbuffer-create.txt
index 12e5d6cd6b80..7279dbe56b01 100644
--- a/Documentation/libtraceevent-kbuffer-create.txt
+++ b/Documentation/libtraceevent-kbuffer-create.txt
@@ -3,7 +3,7 @@ libtraceevent(3)
NAME
----
-kbuffer_alloc, kbuffer_free, kbuffer_load_subbuffer, kbuffer_subbuffer_size, kbuffer_start_of_data - Creating of kbuffer element to parse
+kbuffer_alloc, kbuffer_dup, kbuffer_free, kbuffer_load_subbuffer, kbuffer_subbuffer_size, kbuffer_start_of_data - Creating of kbuffer element to parse
the Linux kernel tracing ring buffer
SYNOPSIS
@@ -28,6 +28,7 @@ struct kbuffer;
struct tep_handle;
struct kbuffer pass:[*]*kbuffer_alloc*(enum kbuffer_long_size _size_, enum kbuffer_endian _endian_);
+struct kbuffer pass:[*]*kbuffer_dup*(struct kbuffer pass:[*]_kbuf_);
void *kbuffer_free*(struct kbuffer pass:[*]_kbuf_);
int *kbuffer_load_subbuffer*(struct kbuffer pass:[*]_kbuf_, void pass:[*]_subbuffer_);
int *kbuffer_subbuffer_size*(struct kbuffer pass:[*]_kbuf);
@@ -59,6 +60,11 @@ will then perform a *uname(2)* call, and if the _machine_ field has the string "
in it, it will be set to 8 byte long size and not 4 byte. This is because the
ring buffer long size is dependent on the kernel and not user space.
+The *kbuffer_dup()* function will duplicate an existing kbuffer structure with
+an allocated new one. It will have all the properties of the passed in _kbuf_,
+including pointing to the same subbuffer that was loaded in the _kbuf_.
+It must be freed with *kbuffer_free()*.
+
The *kbuffer_free()* function will free the resources created by *kbuffer_alloc()*.
The *kbuffer_load_subbuffer()* will take a _subbuffer_ which is a raw data blob
diff --git a/Documentation/libtraceevent.txt b/Documentation/libtraceevent.txt
index 407c06809269..8b63982e541e 100644
--- a/Documentation/libtraceevent.txt
+++ b/Documentation/libtraceevent.txt
@@ -181,6 +181,7 @@ Trace sequences:
kbuffer parsing:
#include <kbuffer.h>
struct kbuffer pass:[*]*kbuffer_alloc*(enum kbuffer_long_size _size_, enum kbuffer_endian _endian_);
+ struct kbuffer pass:[*]*kbuffer_dup*(struct kbuffer pass:[*]_kbuf_);
void *kbuffer_free*(struct kbuffer pass:[*]_kbuf_);
int *kbuffer_load_subbuffer*(struct kbuffer pass:[*]_kbuf_, void pass:[*]_subbuffer_);
int *kbuffer_subbuffer_size*(struct kbuffer pass:[*]_kbuf);
diff --git a/include/traceevent/kbuffer.h b/include/traceevent/kbuffer.h
index e5d377bf0e60..7086e0303e5c 100644
--- a/include/traceevent/kbuffer.h
+++ b/include/traceevent/kbuffer.h
@@ -31,6 +31,7 @@ enum {
struct kbuffer;
struct kbuffer *kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian);
+struct kbuffer *kbuffer_dup(struct kbuffer *kbuf);
void kbuffer_free(struct kbuffer *kbuf);
int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer);
void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts);
diff --git a/src/kbuffer-parse.c b/src/kbuffer-parse.c
index b86c8f0b9d4f..b117094856bc 100644
--- a/src/kbuffer-parse.c
+++ b/src/kbuffer-parse.c
@@ -269,6 +269,26 @@ kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian)
return kbuf;
}
+/**
+ * kbuffer_dup - duplicate a given kbuffer
+ * @kbuf_orig; The kbuffer to duplicate
+ *
+ * Allocates a new kbuffer based off of anothe kbuffer.
+ * Returns the duplicate on success or NULL on error.
+ */
+struct kbuffer *kbuffer_dup(struct kbuffer *kbuf_orig)
+{
+ struct kbuffer *kbuf;
+
+ kbuf = malloc(sizeof(*kbuf));
+ if (!kbuf)
+ return NULL;
+
+ *kbuf = *kbuf_orig;
+
+ return kbuf;
+}
+
/** kbuffer_free - free an allocated kbuffer
* @kbuf: The kbuffer to free
*
--
2.42.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 5/6] kbuffer: Add kbuffer_subbuffer() API
2023-12-24 19:15 [PATCH 0/6] libtraceevent/kbuffer: Add more kbuffer APIs Steven Rostedt
` (3 preceding siblings ...)
2023-12-24 19:16 ` [PATCH 4/6] kbuffer: Add kbuffer_dup() Steven Rostedt
@ 2023-12-24 19:16 ` Steven Rostedt
2023-12-24 19:16 ` [PATCH 6/6] kbuffer: Add kbuffer_refresh() API Steven Rostedt
5 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2023-12-24 19:16 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Steven Rostedt (Google)
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>
Add a way to retrieve the last loaded subbuffer to the kbuffer.
The kbuffer_subbuffer() will return a pointer to the last loaded subbuffer or
NULL if none was ever loaded.
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
Documentation/libtraceevent-kbuffer-create.txt | 11 ++++++++++-
Documentation/libtraceevent.txt | 1 +
include/traceevent/kbuffer.h | 1 +
src/kbuffer-parse.c | 11 +++++++++++
4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/Documentation/libtraceevent-kbuffer-create.txt b/Documentation/libtraceevent-kbuffer-create.txt
index 7279dbe56b01..0dca31432455 100644
--- a/Documentation/libtraceevent-kbuffer-create.txt
+++ b/Documentation/libtraceevent-kbuffer-create.txt
@@ -3,7 +3,8 @@ libtraceevent(3)
NAME
----
-kbuffer_alloc, kbuffer_dup, kbuffer_free, kbuffer_load_subbuffer, kbuffer_subbuffer_size, kbuffer_start_of_data - Creating of kbuffer element to parse
+kbuffer_alloc, kbuffer_dup, kbuffer_free, kbuffer_load_subbuffer, kbuffer_subbuffer,
+kbuffer_subbuffer_size, kbuffer_start_of_data - Creating of kbuffer element to parse
the Linux kernel tracing ring buffer
SYNOPSIS
@@ -33,6 +34,7 @@ void *kbuffer_free*(struct kbuffer pass:[*]_kbuf_);
int *kbuffer_load_subbuffer*(struct kbuffer pass:[*]_kbuf_, void pass:[*]_subbuffer_);
int *kbuffer_subbuffer_size*(struct kbuffer pass:[*]_kbuf);
int *kbuffer_start_of_data*(struct kbuffer pass:[*]_kbuf_);
+void pass:[*]*kbuffer_subbuffer*(struct kbuffer pass:[*]_kbuf);
--
DESCRIPTION
@@ -79,6 +81,10 @@ on the sub-buffer. It does not return the size of the sub-buffer itself.
The *kbuffer_start_of_data()* function returns the offset of where the actual
data load of the sub-buffer begins.
+The *kbuffer_subbuffer()* function returns the pointer to the currently loaded
+subbuffer. That is, the last subbuffer that was loaded by *kbuffer_load_subbuffer()*.
+If no subbuffer was loaded NULL is returned.
+
RETURN VALUE
------------
*kbuffer_alloc()* returns an allocated kbuffer descriptor or NULL on error.
@@ -92,6 +98,9 @@ of the last event is located.
*kbuffer_start_of_data()* returns the offset of where the data begins on the
sub-buffer loaded in _kbuf_.
+*kbuffer_subbuffer()* returns the last loaded subbuffer to _kbuf_ that was loaded
+by *kbuffer_load_subbuffer()* or NULL if none was loaded.
+
EXAMPLE
-------
[source,c]
diff --git a/Documentation/libtraceevent.txt b/Documentation/libtraceevent.txt
index 8b63982e541e..253c9ea810aa 100644
--- a/Documentation/libtraceevent.txt
+++ b/Documentation/libtraceevent.txt
@@ -185,6 +185,7 @@ kbuffer parsing:
void *kbuffer_free*(struct kbuffer pass:[*]_kbuf_);
int *kbuffer_load_subbuffer*(struct kbuffer pass:[*]_kbuf_, void pass:[*]_subbuffer_);
int *kbuffer_subbuffer_size*(struct kbuffer pass:[*]_kbuf);
+ void pass:[*]*kbuffer_subbuffer*(struct kbuffer pass:[*]_kbuf);
int *kbuffer_start_of_data*(struct kbuffer pass:[*]_kbuf_);
unsigned long long *kbuffer_timestamp*(struct kbuffer pass:[*]_kbuf_);
unsigned long long *kbuffer_subbuf_timestamp*(struct kbuffer pass:[*]_kbuf_, void pass:[*]_subbuf_);
diff --git a/include/traceevent/kbuffer.h b/include/traceevent/kbuffer.h
index 7086e0303e5c..624517ed334b 100644
--- a/include/traceevent/kbuffer.h
+++ b/include/traceevent/kbuffer.h
@@ -52,6 +52,7 @@ int kbuffer_curr_size(struct kbuffer *kbuf);
int kbuffer_event_size(struct kbuffer *kbuf);
int kbuffer_missed_events(struct kbuffer *kbuf);
int kbuffer_subbuffer_size(struct kbuffer *kbuf);
+void *kbuffer_subbuffer(struct kbuffer *kbuf);
void kbuffer_set_old_format(struct kbuffer *kbuf);
int kbuffer_start_of_data(struct kbuffer *kbuf);
diff --git a/src/kbuffer-parse.c b/src/kbuffer-parse.c
index b117094856bc..b218d1fc9679 100644
--- a/src/kbuffer-parse.c
+++ b/src/kbuffer-parse.c
@@ -747,6 +747,17 @@ int kbuffer_subbuffer_size(struct kbuffer *kbuf)
return kbuf->size;
}
+/**
+ * kbuffer_subbuffer - the currently loaded subbuffer
+ * @kbuf: The kbuffer to read from
+ *
+ * Returns the currently loaded subbuffer.
+ */
+void *kbuffer_subbuffer(struct kbuffer *kbuf)
+{
+ return kbuf->subbuffer;
+}
+
/**
* kbuffer_curr_index - Return the index of the record
* @kbuf: The kbuffer to read from
--
2.42.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 6/6] kbuffer: Add kbuffer_refresh() API
2023-12-24 19:15 [PATCH 0/6] libtraceevent/kbuffer: Add more kbuffer APIs Steven Rostedt
` (4 preceding siblings ...)
2023-12-24 19:16 ` [PATCH 5/6] kbuffer: Add kbuffer_subbuffer() API Steven Rostedt
@ 2023-12-24 19:16 ` Steven Rostedt
5 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2023-12-24 19:16 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Steven Rostedt (Google)
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>
Add a way to refresh the current size of the loaded subbuffer of the
kbuffer. This is needed if the loaded subbuffer has a writer on it and it
needs to update for new events that have been written.
Note, no memory barriers are used here and that would be required by the
application.
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
.../libtraceevent-kbuffer-create.txt | 15 ++++++++++++--
Documentation/libtraceevent.txt | 1 +
include/traceevent/kbuffer.h | 1 +
src/kbuffer-parse.c | 20 +++++++++++++++++++
4 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/Documentation/libtraceevent-kbuffer-create.txt b/Documentation/libtraceevent-kbuffer-create.txt
index 0dca31432455..6f89de914f39 100644
--- a/Documentation/libtraceevent-kbuffer-create.txt
+++ b/Documentation/libtraceevent-kbuffer-create.txt
@@ -4,7 +4,7 @@ libtraceevent(3)
NAME
----
kbuffer_alloc, kbuffer_dup, kbuffer_free, kbuffer_load_subbuffer, kbuffer_subbuffer,
-kbuffer_subbuffer_size, kbuffer_start_of_data - Creating of kbuffer element to parse
+kbuffer_refresh, kbuffer_subbuffer_size, kbuffer_start_of_data - Creating of kbuffer element to parse
the Linux kernel tracing ring buffer
SYNOPSIS
@@ -32,7 +32,8 @@ struct kbuffer pass:[*]*kbuffer_alloc*(enum kbuffer_long_size _size_, enum kbuff
struct kbuffer pass:[*]*kbuffer_dup*(struct kbuffer pass:[*]_kbuf_);
void *kbuffer_free*(struct kbuffer pass:[*]_kbuf_);
int *kbuffer_load_subbuffer*(struct kbuffer pass:[*]_kbuf_, void pass:[*]_subbuffer_);
-int *kbuffer_subbuffer_size*(struct kbuffer pass:[*]_kbuf);
+int *kbuffer_subbuffer_size*(struct kbuffer pass:[*]_kbuf_);
+int *kbuffer_refresh*(struct kbuffer pass:[*]_kbuf_);
int *kbuffer_start_of_data*(struct kbuffer pass:[*]_kbuf_);
void pass:[*]*kbuffer_subbuffer*(struct kbuffer pass:[*]_kbuf);
--
@@ -78,6 +79,13 @@ is what kbuffer uses to walk the events.
The *kbuffer_subbuffer_size()* returns the location of the end of the last event
on the sub-buffer. It does not return the size of the sub-buffer itself.
+The *kbuffer_refresh()* is to be used if more writes were done on the loaded kbuffer
+where the size of the kbuffer needs to be refreshed to be able to read the new
+events that were written since the last *kbuffer_load_subbuffer()* was called on it.
+
+Note, no memory barriers are implemented with this function and any synchronization
+with the writer is the responsibility of the application.
+
The *kbuffer_start_of_data()* function returns the offset of where the actual
data load of the sub-buffer begins.
@@ -101,6 +109,9 @@ sub-buffer loaded in _kbuf_.
*kbuffer_subbuffer()* returns the last loaded subbuffer to _kbuf_ that was loaded
by *kbuffer_load_subbuffer()* or NULL if none was loaded.
+*kbuffer_refresh()* returns 0 on success and -1 if _kbuf_ is NULL or it does not
+have a subbuffer loaded via *kbuffer_load_subbuffer()*.
+
EXAMPLE
-------
[source,c]
diff --git a/Documentation/libtraceevent.txt b/Documentation/libtraceevent.txt
index 253c9ea810aa..d1aef40804e3 100644
--- a/Documentation/libtraceevent.txt
+++ b/Documentation/libtraceevent.txt
@@ -186,6 +186,7 @@ kbuffer parsing:
int *kbuffer_load_subbuffer*(struct kbuffer pass:[*]_kbuf_, void pass:[*]_subbuffer_);
int *kbuffer_subbuffer_size*(struct kbuffer pass:[*]_kbuf);
void pass:[*]*kbuffer_subbuffer*(struct kbuffer pass:[*]_kbuf);
+ int *kbuffer_refresh*(struct kbuffer pass:[*]_kbuf_);
int *kbuffer_start_of_data*(struct kbuffer pass:[*]_kbuf_);
unsigned long long *kbuffer_timestamp*(struct kbuffer pass:[*]_kbuf_);
unsigned long long *kbuffer_subbuf_timestamp*(struct kbuffer pass:[*]_kbuf_, void pass:[*]_subbuf_);
diff --git a/include/traceevent/kbuffer.h b/include/traceevent/kbuffer.h
index 624517ed334b..31a8c62d7a61 100644
--- a/include/traceevent/kbuffer.h
+++ b/include/traceevent/kbuffer.h
@@ -34,6 +34,7 @@ struct kbuffer *kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian e
struct kbuffer *kbuffer_dup(struct kbuffer *kbuf);
void kbuffer_free(struct kbuffer *kbuf);
int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer);
+int kbuffer_refresh(struct kbuffer *kbuf);
void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts);
void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts);
unsigned long long kbuffer_timestamp(struct kbuffer *kbuf);
diff --git a/src/kbuffer-parse.c b/src/kbuffer-parse.c
index b218d1fc9679..d43fe5d972fd 100644
--- a/src/kbuffer-parse.c
+++ b/src/kbuffer-parse.c
@@ -299,6 +299,26 @@ void kbuffer_free(struct kbuffer *kbuf)
free(kbuf);
}
+/**
+ * kbuffer_refresh - update the meta data from the subbuffer
+ * @kbuf; The kbuffer to update
+ *
+ * If the loaded subbuffer changed its meta data (the commit)
+ * then update the pointers for it.
+ */
+int kbuffer_refresh(struct kbuffer *kbuf)
+{
+ unsigned long long flags;
+
+ if (!kbuf || !kbuf->subbuffer)
+ return -1;
+
+ flags = read_long(kbuf, kbuf->subbuffer + 8);
+ kbuf->size = (unsigned int)flags & COMMIT_MASK;
+
+ return 0;
+}
+
static unsigned int type4host(struct kbuffer *kbuf,
unsigned int type_len_ts)
{
--
2.42.0
^ permalink raw reply related [flat|nested] 7+ messages in thread