From patchwork Sun Dec 24 19:15:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13504406 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DAE25D2E2 for ; Sun, 24 Dec 2023 19:17:04 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 60CC5C433C8; Sun, 24 Dec 2023 19:17:04 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.97) (envelope-from ) id 1rHTzL-00000004VxG-38q4; Sun, 24 Dec 2023 14:18:15 -0500 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: "Steven Rostedt (Google)" Subject: [PATCH 1/6] libtraceevent: Add tep_get_sub_buffer_commit_offset() Date: Sun, 24 Dec 2023 14:15:58 -0500 Message-ID: <20231224191813.1076074-2-rostedt@goodmis.org> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231224191813.1076074-1-rostedt@goodmis.org> References: <20231224191813.1076074-1-rostedt@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: "Steven Rostedt (Google)" 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) --- 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 From patchwork Sun Dec 24 19:15:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13504408 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E76B5D298 for ; Sun, 24 Dec 2023 19:17:04 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 841F1C433CB; Sun, 24 Dec 2023 19:17:04 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.97) (envelope-from ) id 1rHTzL-00000004VxK-3RTq; Sun, 24 Dec 2023 14:18:15 -0500 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: "Steven Rostedt (Google)" Subject: [PATCH 2/6] libtraceevent: Fix tep_kbuffer() to have kbuf assign long_size Date: Sun, 24 Dec 2023 14:15:59 -0500 Message-ID: <20231224191813.1076074-3-rostedt@goodmis.org> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231224191813.1076074-1-rostedt@goodmis.org> References: <20231224191813.1076074-1-rostedt@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: "Steven Rostedt (Google)" 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) --- 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 From patchwork Sun Dec 24 19:16:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13504409 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E7685D297 for ; Sun, 24 Dec 2023 19:17:04 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 840F2C433C7; Sun, 24 Dec 2023 19:17:04 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.97) (envelope-from ) id 1rHTzL-00000004VxO-3kdD; Sun, 24 Dec 2023 14:18:15 -0500 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: "Steven Rostedt (Google)" Subject: [PATCH 3/6] kbuffer: Add kbuffer_read_buffer() Date: Sun, 24 Dec 2023 14:16:00 -0500 Message-ID: <20231224191813.1076074-4-rostedt@goodmis.org> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231224191813.1076074-1-rostedt@goodmis.org> References: <20231224191813.1076074-1-rostedt@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: "Steven Rostedt (Google)" 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) --- 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; +} From patchwork Sun Dec 24 19:16:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13504410 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E76E1D2F1 for ; Sun, 24 Dec 2023 19:17:04 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8BBBAC433CA; Sun, 24 Dec 2023 19:17:04 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.97) (envelope-from ) id 1rHTzL-00000004VxS-42LU; Sun, 24 Dec 2023 14:18:15 -0500 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: "Steven Rostedt (Google)" Subject: [PATCH 4/6] kbuffer: Add kbuffer_dup() Date: Sun, 24 Dec 2023 14:16:01 -0500 Message-ID: <20231224191813.1076074-5-rostedt@goodmis.org> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231224191813.1076074-1-rostedt@goodmis.org> References: <20231224191813.1076074-1-rostedt@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: "Steven Rostedt (Google)" 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) --- .../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 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 * From patchwork Sun Dec 24 19:16:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13504412 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49765D298 for ; Sun, 24 Dec 2023 19:17:05 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 95E06C433CC; Sun, 24 Dec 2023 19:17:04 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.97) (envelope-from ) id 1rHTzM-00000004VxW-08Ul; Sun, 24 Dec 2023 14:18:16 -0500 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: "Steven Rostedt (Google)" Subject: [PATCH 5/6] kbuffer: Add kbuffer_subbuffer() API Date: Sun, 24 Dec 2023 14:16:02 -0500 Message-ID: <20231224191813.1076074-6-rostedt@goodmis.org> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231224191813.1076074-1-rostedt@goodmis.org> References: <20231224191813.1076074-1-rostedt@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: "Steven Rostedt (Google)" 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) --- 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 From patchwork Sun Dec 24 19:16:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13504411 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4972FD297 for ; Sun, 24 Dec 2023 19:17:05 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C2AA2C433CD; Sun, 24 Dec 2023 19:17:04 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.97) (envelope-from ) id 1rHTzM-00000004Vxa-0QmW; Sun, 24 Dec 2023 14:18:16 -0500 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: "Steven Rostedt (Google)" Subject: [PATCH 6/6] kbuffer: Add kbuffer_refresh() API Date: Sun, 24 Dec 2023 14:16:03 -0500 Message-ID: <20231224191813.1076074-7-rostedt@goodmis.org> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231224191813.1076074-1-rostedt@goodmis.org> References: <20231224191813.1076074-1-rostedt@goodmis.org> Precedence: bulk X-Mailing-List: linux-trace-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: "Steven Rostedt (Google)" 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) --- .../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) {