From nobody Mon Jun 8 10:56:13 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 E670833985A for ; Fri, 29 May 2026 13:21:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060915; cv=none; b=EGhFU74nhqEtIqp6kqid52ZcBdlL1rrGlIO51uQZhqeFSXU3t/u+h0cR+rYvyOG/J17GpMNpN6wv9hA/4yTL2tchsfBN/x89u/cCPYMRvrMUKXQEmDdUo+AeeVT6O7a1ifbsjlWwMrbWt0xNjcZgjT//WLAEJJRTHkSFvrmVhz8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060915; c=relaxed/simple; bh=LwjFmzNew0DCxlBUtT20h5GEm4v6A+wrlZGoZRTZ69Q=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=RBc5Hme3IeQyYlS9ctLZkDVfFh1a7QmoDtHWWzgQxpS9ruiFXHSmW+CfRWvLouE/0nq4kcqKMCRBV6DGie6qiIrsI6tEOydpQjpAfApa8f0hT4VnKbMjSgjg4PxdWPHq2K5ia1ziJEAONKU6+Z2LncF3Tc0IGfDfAqvMgOFi2fI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EOiyt38A; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EOiyt38A" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B69911F00899; Fri, 29 May 2026 13:21:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780060913; bh=ZxLphBAAu2sYpkbaS2YgliSATY9IblOd8QAjOzW+g4I=; h=Date:From:To:Cc:Subject:References; b=EOiyt38Ai2tksHfFr9cZZcjyc6DMN+WAKFD+A+l31apgDJKm+JqfGYE/jA3taZYOB pWYqAMsZUh+2QrsS3v+OYvnR2UjKNplpm7xfG93Zl+yx0DQE2TC8h3adB3rNwiTr6h XscPBfxpV44feITS45wYoPAqLKYhir6NL3kWum3r9jP6x7O+8hS3KJP0RnA9cLXuog vgFxQS1zAhuW5wKPI0+sYuhYxFwgpd9fYsIxvrxUPrUMRHoIN+SXvaecWUk+Iew9Ui 0f33MaR3zNwsILkVXeTPwndmPhaS2neGet66c1r0t+AGQU+BPWwJPTnIaosmwtQwz9 ejZXixbrqc9Jg== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wSxAW-0000000ASS5-3fxR; Fri, 29 May 2026 09:22:32 -0400 Message-ID: <20260529132232.736240646@kernel.org> User-Agent: quilt/0.69 Date: Fri, 29 May 2026 09:22:13 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [for-next][PATCH 1/9] ring-buffer: Skip invalid sub-buffers when validating persistent ring buffer References: <20260529132212.153072686@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Masami Hiramatsu (Google)" Skip invalid sub-buffers when validating the persistent ring buffer instead of discarding the entire ring buffer. Only skipped buffers are invalidated (cleared). If the cache data in memory fails to be synchronized during a reboot, the persistent ring buffer may become partially corrupted, but other sub-buffers may still contain readable event data. Only discard the subbuffers that are found to be corrupted. Link: https://lore.kernel.org/all/20260520185018.051228084@kernel.org/ Link: https://patch.msgid.link/20260522171050.914418536@kernel.org Signed-off-by: Masami Hiramatsu (Google) [SDR: Fixed max_loops in rb_iter_peek() as well ] Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 120 ++++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 47 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 7b07d2004cc6..6afd8ea5081a 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -370,6 +370,12 @@ static __always_inline unsigned int rb_page_commit(str= uct buffer_page *bpage) return local_read(&bpage->page->commit); } =20 +/* Size is determined by what has been committed */ +static __always_inline unsigned int rb_page_size(struct buffer_page *bpage) +{ + return rb_page_commit(bpage) & ~RB_MISSED_MASK; +} + static void free_buffer_page(struct buffer_page *bpage) { /* Range pages are not to be freed */ @@ -1762,7 +1768,6 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cpu_= meta *meta, int cpu, unsigned long *subbuf_mask) { int subbuf_size =3D PAGE_SIZE; - struct buffer_data_page *subbuf; unsigned long buffers_start; unsigned long buffers_end; int i; @@ -1770,6 +1775,11 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cpu= _meta *meta, int cpu, if (!subbuf_mask) return false; =20 + if (meta->subbuf_size !=3D PAGE_SIZE) { + pr_info("Ring buffer boot meta [%d] invalid subbuf_size\n", cpu); + return false; + } + buffers_start =3D meta->first_buffer; buffers_end =3D meta->first_buffer + (subbuf_size * meta->nr_subbufs); =20 @@ -1786,11 +1796,12 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cp= u_meta *meta, int cpu, return false; } =20 - subbuf =3D rb_subbufs_from_meta(meta); - bitmap_clear(subbuf_mask, 0, meta->nr_subbufs); =20 - /* Is the meta buffers and the subbufs themselves have correct data? */ + /* + * Ensure the meta::buffers array has correct data. The data in each subb= ufs + * are checked later in rb_meta_validate_events(). + */ for (i =3D 0; i < meta->nr_subbufs; i++) { if (meta->buffers[i] < 0 || meta->buffers[i] >=3D meta->nr_subbufs) { @@ -1798,18 +1809,12 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cp= u_meta *meta, int cpu, return false; } =20 - if ((unsigned)local_read(&subbuf->commit) > subbuf_size) { - pr_info("Ring buffer boot meta [%d] buffer invalid commit\n", cpu); - return false; - } - if (test_bit(meta->buffers[i], subbuf_mask)) { pr_info("Ring buffer boot meta [%d] array has duplicates\n", cpu); return false; } =20 set_bit(meta->buffers[i], subbuf_mask); - subbuf =3D (void *)subbuf + subbuf_size; } =20 return true; @@ -1873,13 +1878,22 @@ static int rb_read_data_buffer(struct buffer_data_p= age *dpage, int tail, int cpu return events; } =20 -static int rb_validate_buffer(struct buffer_data_page *dpage, int cpu) +static int rb_validate_buffer(struct buffer_data_page *dpage, int cpu, + struct ring_buffer_cpu_meta *meta) { unsigned long long ts; + unsigned long tail; u64 delta; - int tail; =20 - tail =3D local_read(&dpage->commit); + /* + * When a sub-buffer is recovered from a read, the commit value may + * have RB_MISSED_* bits set, as these bits are reset on reuse. + * Even after clearing these bits, a commit value greater than the + * subbuf_size is considered invalid. + */ + tail =3D local_read(&dpage->commit) & ~RB_MISSED_MASK; + if (tail > meta->subbuf_size - BUF_PAGE_HDR_SIZE) + return -1; return rb_read_data_buffer(dpage, tail, cpu, &ts, &delta); } =20 @@ -1890,6 +1904,7 @@ static void rb_meta_validate_events(struct ring_buffe= r_per_cpu *cpu_buffer) struct buffer_page *head_page, *orig_head, *orig_reader; unsigned long entry_bytes =3D 0; unsigned long entries =3D 0; + int discarded =3D 0; int ret; u64 ts; int i; @@ -1901,14 +1916,19 @@ static void rb_meta_validate_events(struct ring_buf= fer_per_cpu *cpu_buffer) orig_reader =3D cpu_buffer->reader_page; =20 /* Do the reader page first */ - ret =3D rb_validate_buffer(orig_reader->page, cpu_buffer->cpu); + ret =3D rb_validate_buffer(orig_reader->page, cpu_buffer->cpu, meta); if (ret < 0) { - pr_info("Ring buffer reader page is invalid\n"); - goto invalid; + pr_info("Ring buffer meta [%d] invalid reader page detected\n", + cpu_buffer->cpu); + discarded++; + /* Instead of discard whole ring buffer, discard only this sub-buffer. */ + local_set(&orig_reader->entries, 0); + local_set(&orig_reader->page->commit, 0); + } else { + entries +=3D ret; + entry_bytes +=3D rb_page_size(orig_reader); + local_set(&orig_reader->entries, ret); } - entries +=3D ret; - entry_bytes +=3D local_read(&orig_reader->page->commit); - local_set(&orig_reader->entries, ret); =20 ts =3D head_page->page->time_stamp; =20 @@ -1936,7 +1956,7 @@ static void rb_meta_validate_events(struct ring_buffe= r_per_cpu *cpu_buffer) break; =20 /* Stop rewind if the page is invalid. */ - ret =3D rb_validate_buffer(head_page->page, cpu_buffer->cpu); + ret =3D rb_validate_buffer(head_page->page, cpu_buffer->cpu, meta); if (ret < 0) break; =20 @@ -1945,7 +1965,7 @@ static void rb_meta_validate_events(struct ring_buffe= r_per_cpu *cpu_buffer) if (ret) local_inc(&cpu_buffer->pages_touched); entries +=3D ret; - entry_bytes +=3D rb_page_commit(head_page); + entry_bytes +=3D rb_page_size(head_page); } if (i) pr_info("Ring buffer [%d] rewound %d pages\n", cpu_buffer->cpu, i); @@ -2015,21 +2035,24 @@ static void rb_meta_validate_events(struct ring_buf= fer_per_cpu *cpu_buffer) if (head_page =3D=3D orig_reader) continue; =20 - ret =3D rb_validate_buffer(head_page->page, cpu_buffer->cpu); + ret =3D rb_validate_buffer(head_page->page, cpu_buffer->cpu, meta); if (ret < 0) { - pr_info("Ring buffer meta [%d] invalid buffer page\n", - cpu_buffer->cpu); - goto invalid; - } - - /* If the buffer has content, update pages_touched */ - if (ret) - local_inc(&cpu_buffer->pages_touched); - - entries +=3D ret; - entry_bytes +=3D local_read(&head_page->page->commit); - local_set(&head_page->entries, ret); + if (!discarded) + pr_info("Ring buffer meta [%d] invalid buffer page detected\n", + cpu_buffer->cpu); + discarded++; + /* Instead of discard whole ring buffer, discard only this sub-buffer. = */ + local_set(&head_page->entries, 0); + local_set(&head_page->page->commit, 0); + } else { + /* If the buffer has content, update pages_touched */ + if (ret) + local_inc(&cpu_buffer->pages_touched); =20 + entries +=3D ret; + entry_bytes +=3D rb_page_size(head_page); + local_set(&head_page->entries, ret); + } if (head_page =3D=3D cpu_buffer->commit_page) break; } @@ -2043,7 +2066,10 @@ static void rb_meta_validate_events(struct ring_buff= er_per_cpu *cpu_buffer) local_set(&cpu_buffer->entries, entries); local_set(&cpu_buffer->entries_bytes, entry_bytes); =20 - pr_info("Ring buffer meta [%d] is from previous boot!\n", cpu_buffer->cpu= ); + pr_info("Ring buffer meta [%d] is from previous boot!", cpu_buffer->cpu); + if (discarded) + pr_cont(" (%d pages discarded)", discarded); + pr_cont("\n"); return; =20 invalid: @@ -3330,12 +3356,6 @@ rb_iter_head_event(struct ring_buffer_iter *iter) return NULL; } =20 -/* Size is determined by what has been committed */ -static __always_inline unsigned rb_page_size(struct buffer_page *bpage) -{ - return rb_page_commit(bpage) & ~RB_MISSED_MASK; -} - static __always_inline unsigned rb_commit_index(struct ring_buffer_per_cpu *cpu_buffer) { @@ -5636,8 +5656,9 @@ __rb_get_reader_page_from_remote(struct ring_buffer_p= er_cpu *cpu_buffer) static struct buffer_page * __rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) { - struct buffer_page *reader =3D NULL; + int max_loops =3D cpu_buffer->ring_meta ? cpu_buffer->nr_pages : 3; unsigned long bsize =3D READ_ONCE(cpu_buffer->buffer->subbuf_size); + struct buffer_page *reader =3D NULL; unsigned long overwrite; unsigned long flags; int nr_loops =3D 0; @@ -5649,11 +5670,14 @@ __rb_get_reader_page(struct ring_buffer_per_cpu *cp= u_buffer) again: /* * This should normally only loop twice. But because the - * start of the reader inserts an empty page, it causes - * a case where we will loop three times. There should be no - * reason to loop four times (that I know of). + * start of the reader inserts an empty page, it causes a + * case where we will loop three times. There should be no + * reason to loop four times unless the ring buffer is a + * recovered persistent ring buffer. For persistent ring buffers, + * invalid pages are reset during recovery, so there may be more + * than 3 contiguous pages can be empty, but less than nr_pages. */ - if (RB_WARN_ON(cpu_buffer, ++nr_loops > 3)) { + if (RB_WARN_ON(cpu_buffer, ++nr_loops > max_loops)) { reader =3D NULL; goto out; } @@ -5950,12 +5974,14 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) struct ring_buffer_per_cpu *cpu_buffer; struct ring_buffer_event *event; int nr_loops =3D 0; + int max_loops; =20 if (ts) *ts =3D 0; =20 cpu_buffer =3D iter->cpu_buffer; buffer =3D cpu_buffer->buffer; + max_loops =3D cpu_buffer->ring_meta ? cpu_buffer->nr_pages : 3; =20 /* * Check if someone performed a consuming read to the buffer @@ -5978,7 +6004,7 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) * the ring buffer with an active write as the consumer is. * Do not warn if the three failures is reached. */ - if (++nr_loops > 3) + if (++nr_loops > max_loops) return NULL; =20 if (rb_per_cpu_empty(cpu_buffer)) --=20 2.53.0 From nobody Mon Jun 8 10:56:13 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 2878E332EAC for ; Fri, 29 May 2026 13:21:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060916; cv=none; b=faZjyy/2NCzqO1iewkBsa/tskcYwKHMDJExFDBOe+I+MJj86O4jsH7B9yBsnCwepX5qnTMGz/VzqqghhlecUFSLH1Jf65zXsiHsgvRanax4jtCNP1WFboUs1YW3PljjoLNzLsA6R2ukeTKz8TlZgFB6AZjOnuDK8dsv+hrqXcME= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060916; c=relaxed/simple; bh=ePT7i7NxirMM4gvfakarNQ0ofbTqD3YWQr0uJTLkfdc=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=h5DriMluWPUBAqrmMJ3QBZLLzfTLpOvydYuKNseTjwx7UYCcQxVQGA/SnaqKunXj7tN5TQK3HNlfMrI9JxYpyYQYpyeTSNtgPJAjUqpF8VHfWb6TFSjM9urnZwgTYHaEx4Mh9IFSY77KVCZ9fENVCrzvdysodIp2s2BmSbmC6ow= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GxcVc43R; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GxcVc43R" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D10EA1F0089A; Fri, 29 May 2026 13:21:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780060913; bh=XcQyvZUY1rflis5kRNvf9iUBptHQQ/MfdOzpFk7d+gw=; h=Date:From:To:Cc:Subject:References; b=GxcVc43R2CSXJAw/GXZ0C4ErKGw/F9i4c5gDXIF5fnKdmKUs8rkvV5vnfpRko8k5k a8+jma0n0OEoJvZa1QqqX1beuCqLXxKnTPhG/bPhSEOMUZ70blF8kBKMoNRa8PvK19 Kh+Ax/8Y7TEjxLcJUH/LvShziLU+JsHqTa05DJxUKI25k2J6qO8MZPp6/0SugfCDfH wEdZmrfTcu/MfQsbHeNQWhc4P0MmHBlS8lrydVj//kAH+Z6RN5XLoIr2VLMUn8fU5k 3J1N84T8cFSx2qg3QPqe1EN9GfHgPfQ1DHJxLT450NH1kKHh8HqJT4kHXjZpgP8AL/ 2p5dMFseJRDZQ== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wSxAX-0000000ASSZ-09cY; Fri, 29 May 2026 09:22:33 -0400 Message-ID: <20260529132232.893005040@kernel.org> User-Agent: quilt/0.69 Date: Fri, 29 May 2026 09:22:14 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [for-next][PATCH 2/9] ring-buffer: Skip invalid sub-buffers when rewinding persistent ring buffer References: <20260529132212.153072686@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Masami Hiramatsu (Google)" Skip invalid sub-buffers when rewinding the persistent ring buffer instead of stopping the rewinding the ring buffer. The skipped buffers are cleared. To ensure the rewinding stops at the unused page, this also clears buffer_data_page::time_stamp when tracing resets the buffer. This allows us to identify unused pages and empty pages. Link: https://patch.msgid.link/20260522171051.091265852@kernel.org Signed-off-by: Masami Hiramatsu (Google) [ SDR: Have reader_page still get evaluated if header_page fails ] Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 107 ++++++++++++++++++++++++------------- 1 file changed, 69 insertions(+), 38 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 6afd8ea5081a..c10cf4ba91d6 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -363,6 +363,7 @@ struct buffer_page { static void rb_init_page(struct buffer_data_page *bpage) { local_set(&bpage->commit, 0); + bpage->time_stamp =3D 0; } =20 static __always_inline unsigned int rb_page_commit(struct buffer_page *bpa= ge) @@ -1878,12 +1879,14 @@ static int rb_read_data_buffer(struct buffer_data_p= age *dpage, int tail, int cpu return events; } =20 -static int rb_validate_buffer(struct buffer_data_page *dpage, int cpu, - struct ring_buffer_cpu_meta *meta) +static int rb_validate_buffer(struct buffer_page *bpage, int cpu, + struct ring_buffer_cpu_meta *meta, u64 prev_ts, u64 next_ts) { + struct buffer_data_page *dpage =3D bpage->page; unsigned long long ts; unsigned long tail; u64 delta; + int ret; =20 /* * When a sub-buffer is recovered from a read, the commit value may @@ -1892,9 +1895,27 @@ static int rb_validate_buffer(struct buffer_data_pag= e *dpage, int cpu, * subbuf_size is considered invalid. */ tail =3D local_read(&dpage->commit) & ~RB_MISSED_MASK; - if (tail > meta->subbuf_size - BUF_PAGE_HDR_SIZE) - return -1; - return rb_read_data_buffer(dpage, tail, cpu, &ts, &delta); + if (tail <=3D meta->subbuf_size - BUF_PAGE_HDR_SIZE) + ret =3D rb_read_data_buffer(dpage, tail, cpu, &ts, &delta); + else + ret =3D -1; + + /* + * The timestamp must be greater than @prev_ts and smaller than @next_ts. + * Since this function works in both forward (verify) and reverse (unwind) + * loop, we don't know both @prev_ts and @next_ts at the same time. + * So use the known boundary as the boundary. + */ + if (ret < 0 || (prev_ts && prev_ts > ts) || (next_ts && ts > next_ts)) { + local_set(&bpage->entries, 0); + local_set(&dpage->commit, 0); + dpage->time_stamp =3D prev_ts ? prev_ts : next_ts; + ret =3D -1; + } else { + local_set(&bpage->entries, ret); + } + + return ret; } =20 /* If the meta data has been validated, now validate the events */ @@ -1905,6 +1926,7 @@ static void rb_meta_validate_events(struct ring_buffe= r_per_cpu *cpu_buffer) unsigned long entry_bytes =3D 0; unsigned long entries =3D 0; int discarded =3D 0; + bool skip =3D false; int ret; u64 ts; int i; @@ -1915,25 +1937,35 @@ static void rb_meta_validate_events(struct ring_buf= fer_per_cpu *cpu_buffer) orig_head =3D head_page =3D cpu_buffer->head_page; orig_reader =3D cpu_buffer->reader_page; =20 - /* Do the reader page first */ - ret =3D rb_validate_buffer(orig_reader->page, cpu_buffer->cpu, meta); + /* Do the head page first */ + ret =3D rb_validate_buffer(head_page, cpu_buffer->cpu, meta, 0, 0); + if (ret < 0) { + pr_info("Ring buffer meta [%d] invalid head page detected\n", + cpu_buffer->cpu); + /* Don't bother rewinding */ + skip =3D true; + ts =3D 0; + } else { + ts =3D head_page->page->time_stamp; + } + + /* Do the reader page - reader must be previous to head. */ + ret =3D rb_validate_buffer(orig_reader, cpu_buffer->cpu, meta, 0, ts); if (ret < 0) { pr_info("Ring buffer meta [%d] invalid reader page detected\n", cpu_buffer->cpu); discarded++; - /* Instead of discard whole ring buffer, discard only this sub-buffer. */ - local_set(&orig_reader->entries, 0); - local_set(&orig_reader->page->commit, 0); } else { entries +=3D ret; entry_bytes +=3D rb_page_size(orig_reader); - local_set(&orig_reader->entries, ret); + ts =3D orig_reader->page->time_stamp; } =20 - ts =3D head_page->page->time_stamp; + if (skip) + goto skip_rewind; =20 /* - * Try to rewind the head so that we can read the pages which already + * Try to rewind the head so that we can read the pages which are already * read in the previous boot. */ if (head_page =3D=3D cpu_buffer->tail_page) @@ -1946,26 +1978,27 @@ static void rb_meta_validate_events(struct ring_buf= fer_per_cpu *cpu_buffer) if (head_page =3D=3D cpu_buffer->tail_page) break; =20 - /* Ensure the page has older data than head. */ - if (ts < head_page->page->time_stamp) + /* Rewind until unused page (no timestamp, no commit). */ + if (!head_page->page->time_stamp && rb_page_commit(head_page) =3D=3D 0) break; =20 - ts =3D head_page->page->time_stamp; - /* Ensure the page has correct timestamp and some data. */ - if (!ts || rb_page_commit(head_page) =3D=3D 0) - break; - - /* Stop rewind if the page is invalid. */ - ret =3D rb_validate_buffer(head_page->page, cpu_buffer->cpu, meta); - if (ret < 0) - break; - - /* Recover the number of entries and update stats. */ - local_set(&head_page->entries, ret); - if (ret) - local_inc(&cpu_buffer->pages_touched); - entries +=3D ret; - entry_bytes +=3D rb_page_size(head_page); + /* + * Skip if the page is invalid, or its timestamp is newer than the + * previous valid page. + */ + ret =3D rb_validate_buffer(head_page, cpu_buffer->cpu, meta, 0, ts); + if (ret < 0) { + if (!discarded) + pr_info("Ring buffer meta [%d] invalid buffer page detected\n", + cpu_buffer->cpu); + discarded++; + } else { + entries +=3D ret; + entry_bytes +=3D rb_page_size(head_page); + if (ret > 0) + local_inc(&cpu_buffer->pages_touched); + ts =3D head_page->page->time_stamp; + } } if (i) pr_info("Ring buffer [%d] rewound %d pages\n", cpu_buffer->cpu, i); @@ -2027,6 +2060,7 @@ static void rb_meta_validate_events(struct ring_buffe= r_per_cpu *cpu_buffer) /* Nothing more to do, the only page is the reader page */ goto done; } + ts =3D head_page->page->time_stamp; =20 /* Iterate until finding the commit page */ for (i =3D 0; i < meta->nr_subbufs + 1; i++, rb_inc_page(&head_page)) { @@ -2035,15 +2069,12 @@ static void rb_meta_validate_events(struct ring_buf= fer_per_cpu *cpu_buffer) if (head_page =3D=3D orig_reader) continue; =20 - ret =3D rb_validate_buffer(head_page->page, cpu_buffer->cpu, meta); + ret =3D rb_validate_buffer(head_page, cpu_buffer->cpu, meta, ts, 0); if (ret < 0) { if (!discarded) pr_info("Ring buffer meta [%d] invalid buffer page detected\n", cpu_buffer->cpu); discarded++; - /* Instead of discard whole ring buffer, discard only this sub-buffer. = */ - local_set(&head_page->entries, 0); - local_set(&head_page->page->commit, 0); } else { /* If the buffer has content, update pages_touched */ if (ret) @@ -2051,7 +2082,7 @@ static void rb_meta_validate_events(struct ring_buffe= r_per_cpu *cpu_buffer) =20 entries +=3D ret; entry_bytes +=3D rb_page_size(head_page); - local_set(&head_page->entries, ret); + ts =3D head_page->page->time_stamp; } if (head_page =3D=3D cpu_buffer->commit_page) break; @@ -2079,12 +2110,12 @@ static void rb_meta_validate_events(struct ring_buf= fer_per_cpu *cpu_buffer) =20 /* Reset the reader page */ local_set(&cpu_buffer->reader_page->entries, 0); - local_set(&cpu_buffer->reader_page->page->commit, 0); + rb_init_page(cpu_buffer->reader_page->page); =20 /* Reset all the subbuffers */ for (i =3D 0; i < meta->nr_subbufs - 1; i++, rb_inc_page(&head_page)) { local_set(&head_page->entries, 0); - local_set(&head_page->page->commit, 0); + rb_init_page(head_page->page); } } =20 --=20 2.53.0 From nobody Mon Jun 8 10:56:13 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 3AD1D33A029 for ; Fri, 29 May 2026 13:21:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060915; cv=none; b=Da1+fLUC294FZec5rFPwmVz/7EzMdC0OESZPci1Wo1HKa6kzxrMYGdLcQEfaA4BUHYo1PXYK3ZY/c4NGw3cYQix1khs6Di56nqa4j11itw+k9q4d9rEcbOU3aL2BFNNM4PycEPkM1oAngmf9T2yHmhSrQ+RocZX49o2xogrNDTQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060915; c=relaxed/simple; bh=y4k3Ml5s97CJSPXHH9LJ3EyMr4dzr5oJxirG4qRgPmQ=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=O2ITaJOppr25rChvV+bJeU817zJkKUSSWQ8hMTI46j2o2Z17F8Bcot0RjqtD9Jwrg3oY2RwHQ624yfBNPgbJUqRbmcbc0fIuwnjB0x+uq7iPbgrJhyHy8VAZf2EdqbXqgBnzAr1wKdnTMDzgbS8fxmCio49HdRnpDGCQl3Dz2Wk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lPa/zXq0; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lPa/zXq0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1122E1F0089D; Fri, 29 May 2026 13:21:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780060914; bh=ESvwqTLBTp9WQpPFokIQlPuQbyIZWLDphaGjjY72dTw=; h=Date:From:To:Cc:Subject:References; b=lPa/zXq0k8H6vHsy5QvyEErBZWaFqjAKna5xRcEvEbnVDK7Rkmmi3iqakak76u63M Ywc0QeshYs+6srzbeLxW7sfOpRBqiAAXS9nalNJuQmI8ciR8PKsmMjY8vuJ9tY9Vn9 oPkv6gEZXws6iL5CG2jXy/lb9dSJ6hPE0hV1UkcvaVujgi/d18huFrg01bmqLYIMEh 1BY5V289Xef/yK3WSWgKN8Cu2R+DXf86vpdOv4hIaYWb3d2EHCvYVTveJ1ZaJqK0lC KThI3Nphotf6ySx7lQz4yA/yXjIWZh6iUoVT5hjwS5jby5ZITWhCq2bhgg/fISpxaF /ja2KBoUCAtWA== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wSxAX-0000000AST3-0oj9; Fri, 29 May 2026 09:22:33 -0400 Message-ID: <20260529132233.054154166@kernel.org> User-Agent: quilt/0.69 Date: Fri, 29 May 2026 09:22:15 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [for-next][PATCH 3/9] ring-buffer: Add persistent ring buffer invalid-page inject test References: <20260529132212.153072686@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Masami Hiramatsu (Google)" Add a self-corrupting test for the persistent ring buffer. This will inject an erroneous value to some sub-buffer pages (where the index is even or multiples of 5) in the persistent ring buffer when the kernel panics, and checks whether the number of detected invalid pages and the total entry_bytes are the same as the recorded values after reboot. This ensures that the kernel can correctly recover a partially corrupted persistent ring buffer after a reboot or panic. The test only runs on the persistent ring buffer whose name is "ptracingtest". The user has to fill it with events before a kernel panic. To run the test, enable CONFIG_RING_BUFFER_PERSISTENT_INJECT and add the following kernel cmdline: reserve_mem=3D20M:2M:trace trace_instance=3Dptracingtest^traceoff@trace panic=3D1 Run the following commands after the 1st boot: cd /sys/kernel/tracing/instances/ptracingtest echo 1 > tracing_on echo 1 > events/enable sleep 3 echo c > /proc/sysrq-trigger After panic message, the kernel will reboot and run the verification on the persistent ring buffer, e.g. Ring buffer meta [2] invalid buffer page detected Ring buffer meta [2] is from previous boot! (318 pages discarded) Ring buffer testing [2] invalid pages: PASSED (318/318) Ring buffer testing [2] entry_bytes: PASSED (1300476/1300476) Link: https://patch.msgid.link/20260522171051.260140328@kernel.org Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- include/linux/ring_buffer.h | 1 + kernel/trace/Kconfig | 34 ++++++++++++++++ kernel/trace/ring_buffer.c | 79 +++++++++++++++++++++++++++++++++++++ kernel/trace/trace.c | 4 ++ 4 files changed, 118 insertions(+) diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index 994f52b34344..0670742b2d60 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h @@ -238,6 +238,7 @@ int ring_buffer_subbuf_size_get(struct trace_buffer *bu= ffer); =20 enum ring_buffer_flags { RB_FL_OVERWRITE =3D 1 << 0, + RB_FL_TESTING =3D 1 << 1, }; =20 #ifdef CONFIG_RING_BUFFER diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index e130da35808f..084f34dc6c9f 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -1202,6 +1202,40 @@ config RING_BUFFER_VALIDATE_TIME_DELTAS Only say Y if you understand what this does, and you still want it enabled. Otherwise say N =20 +config RING_BUFFER_PERSISTENT_INJECT + bool "Enable persistent ring buffer error injection test" + depends on RING_BUFFER + help + This option will have the kernel check if the persistent ring + buffer is named "ptracingtest". and if so, it will corrupt some + of its pages on a kernel panic. This is used to test if the + persistent ring buffer can recover from some of its sub-buffers + being corrupted. + To use this, boot a kernel with a "ptracingtest" persistent + ring buffer, e.g. + + reserve_mem=3D20M:2M:trace trace_instance=3Dptracingtest@trace panic= =3D1 + + And after the 1st boot, run the following commands: + + cd /sys/kernel/tracing/instances/ptracingtest + echo 1 > events/enable + echo 1 > tracing_on + sleep 3 + echo c > /proc/sysrq-trigger + + After the panic message, the kernel will reboot and will show + the test results in the console output. + + Note that events for the test ring buffer needs to be enabled + prior to crashing the kernel so that the ring buffer has content + that the test will corrupt. + As the test will corrupt events in the "ptracingtest" persistent + ring buffer, it should not be used for any other purpose other + than this test. + + If unsure, say N + config MMIOTRACE_TEST tristate "Test module for mmiotrace" depends on MMIOTRACE && m diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index c10cf4ba91d6..dc603d9c9414 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -64,6 +64,10 @@ struct ring_buffer_cpu_meta { unsigned long commit_buffer; __u32 subbuf_size; __u32 nr_subbufs; +#ifdef CONFIG_RING_BUFFER_PERSISTENT_INJECT + __u32 nr_invalid; + __u32 entry_bytes; +#endif int buffers[]; }; =20 @@ -2101,6 +2105,21 @@ static void rb_meta_validate_events(struct ring_buff= er_per_cpu *cpu_buffer) if (discarded) pr_cont(" (%d pages discarded)", discarded); pr_cont("\n"); + +#ifdef CONFIG_RING_BUFFER_PERSISTENT_INJECT + if (meta->nr_invalid) + pr_warn("Ring buffer testing [%d] invalid pages: %s (%d/%d)\n", + cpu_buffer->cpu, + (discarded =3D=3D meta->nr_invalid) ? "PASSED" : "FAILED", + discarded, meta->nr_invalid); + if (meta->entry_bytes) + pr_warn("Ring buffer testing [%d] entry_bytes: %s (%ld/%ld)\n", + cpu_buffer->cpu, + (entry_bytes =3D=3D meta->entry_bytes) ? "PASSED" : "FAILED", + (long)entry_bytes, (long)meta->entry_bytes); + meta->nr_invalid =3D 0; + meta->entry_bytes =3D 0; +#endif return; =20 invalid: @@ -2581,12 +2600,72 @@ static void rb_free_cpu_buffer(struct ring_buffer_p= er_cpu *cpu_buffer) kfree(cpu_buffer); } =20 +#ifdef CONFIG_RING_BUFFER_PERSISTENT_INJECT +static void rb_test_inject_invalid_pages(struct trace_buffer *buffer) +{ + struct ring_buffer_per_cpu *cpu_buffer; + struct ring_buffer_cpu_meta *meta; + struct buffer_data_page *dpage; + unsigned long entry_bytes =3D 0; + unsigned long ptr; + int subbuf_size; + int invalid =3D 0; + int cpu; + int i; + + if (!(buffer->flags & RB_FL_TESTING)) + return; + + guard(preempt)(); + cpu =3D smp_processor_id(); + + cpu_buffer =3D buffer->buffers[cpu]; + if (!cpu_buffer) + return; + meta =3D cpu_buffer->ring_meta; + if (!meta) + return; + + ptr =3D (unsigned long)rb_subbufs_from_meta(meta); + subbuf_size =3D meta->subbuf_size; + + for (i =3D 0; i < meta->nr_subbufs; i++) { + unsigned long idx =3D meta->buffers[i]; + + dpage =3D (void *)(ptr + idx * subbuf_size); + /* Skip unused pages */ + if (!local_read(&dpage->commit)) + continue; + + /* + * Invalidate even pages or multiples of 5. This will cause 3 + * contiguous invalidated(empty) pages. + */ + if (!(i & 0x1) || !(i % 5)) { + local_add(subbuf_size + 1, &dpage->commit); + invalid++; + } else { + /* Count total commit bytes. */ + entry_bytes +=3D local_read(&dpage->commit) & ~RB_MISSED_MASK; + } + } + + pr_info("Inject invalidated %d pages on CPU%d, total size: %ld\n", + invalid, cpu, (long)entry_bytes); + meta->nr_invalid =3D invalid; + meta->entry_bytes =3D entry_bytes; +} +#else /* !CONFIG_RING_BUFFER_PERSISTENT_INJECT */ +#define rb_test_inject_invalid_pages(buffer) do { } while (0) +#endif + /* Stop recording on a persistent buffer and flush cache if needed. */ static int rb_flush_buffer_cb(struct notifier_block *nb, unsigned long eve= nt, void *data) { struct trace_buffer *buffer =3D container_of(nb, struct trace_buffer, flu= sh_nb); =20 ring_buffer_record_off(buffer); + rb_test_inject_invalid_pages(buffer); arch_ring_buffer_flush_range(buffer->range_addr_start, buffer->range_addr= _end); return NOTIFY_DONE; } diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 6eb4d3097a4d..4573f65d68ce 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -8383,6 +8383,8 @@ static void setup_trace_scratch(struct trace_array *t= r, memset(tscratch, 0, size); } =20 +#define TRACE_TEST_PTRACING_NAME "ptracingtest" + int allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf= , int size) { enum ring_buffer_flags rb_flags; @@ -8394,6 +8396,8 @@ int allocate_trace_buffer(struct trace_array *tr, str= uct array_buffer *buf, int buf->tr =3D tr; =20 if (tr->range_addr_start && tr->range_addr_size) { + if (tr->name && !strcmp(tr->name, TRACE_TEST_PTRACING_NAME)) + rb_flags |=3D RB_FL_TESTING; /* Add scratch buffer to handle 128 modules */ buf->buffer =3D ring_buffer_alloc_range(size, rb_flags, 0, tr->range_addr_start, --=20 2.53.0 From nobody Mon Jun 8 10:56:13 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 4AB8A33A6F7 for ; Fri, 29 May 2026 13:21:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060915; cv=none; b=TSXUTB3ey++MHU81UpveHN0Znvwa6/e7uNA5hqy2PbDTwbOv0nN5ydhnjRJDugbGEHYalsAUgYeUgzX1Pb6qY5XmyLhfbdj0M82IqAPpVGUJbFF2DCIxAe2hvFBtXyVqTB/Qwx1QfMnuIdU/vaf5q7ik3qfm0S8XBDCLYAC57DI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060915; c=relaxed/simple; bh=BdhVLZAGn/Xoq0otFpQ/VPCnXQmsIJ//8Jy21NsDxtk=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=pbQEMXxnLNxjtrwlcA5xS52MhNiymDSmBjdOkFPPR1RcP+SoFddlAscmWiAavAxGaEpzYju2b1axSKNXhRg32eJEvj+sgD0xoDsYwRK11JMQZg8ByVj9GQV4UKNkc/c1SDIOaiPjePoC2Z1AscBwLRTTH0mpO3av1DG/SEhhk1w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YS5yW8iE; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YS5yW8iE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3088C1F00893; Fri, 29 May 2026 13:21:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780060914; bh=Tef/5B7KZAYAbHQk40WNyTK9xVr9XoHaLXSdmc9TxMc=; h=Date:From:To:Cc:Subject:References; b=YS5yW8iECG1FTKTbCxLfMoqXgmf12b9FXJPyB1X6Ayg6EEptpZwEvrTeWTX021JgW IUMortipZtvmInAhlhawb15ZkymD2H06FqY7jyd/o1lk0xEsmU/xEOmYDzmrlAcI7T H8NUPGHoMKRAwJys2LRSHgTDrP6R66Cg2reJt9xep5Tl/77BGVO1q0ULxYn1LIQAFY 5rRbv1+Mxg28MXiIuOwz4gdUjomwTrxqaDnSRCVXPvTVEwTIaOimCsG6I3IqxYBiMS NVMb1AeMx7DwWzjbP7MPDbJptXQze1ftQND68sFVKV5l8Iapk/j7H0rFACQ7tbqhXt 7p+t6ZS6N5twA== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wSxAX-0000000ASTX-1U71; Fri, 29 May 2026 09:22:33 -0400 Message-ID: <20260529132233.213694284@kernel.org> User-Agent: quilt/0.69 Date: Fri, 29 May 2026 09:22:16 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [for-next][PATCH 4/9] ring-buffer: Show commit numbers in buffer_meta file References: <20260529132212.153072686@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Masami Hiramatsu (Google)" In addition to the index number, show the commit numbers of each data page in the per_cpu buffer_meta file. This is useful for understanding the current status of the persistent ring buffer. (Note that this file is shown only for persistent ring buffer and its backup instance) Link: https://patch.msgid.link/20260522171051.424411323@kernel.org Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index dc603d9c9414..88e613e78632 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -2231,6 +2231,7 @@ static int rbm_show(struct seq_file *m, void *v) struct ring_buffer_per_cpu *cpu_buffer =3D m->private; struct ring_buffer_cpu_meta *meta =3D cpu_buffer->ring_meta; unsigned long val =3D (unsigned long)v; + struct buffer_data_page *dpage; =20 if (val =3D=3D 1) { seq_printf(m, "head_buffer: %d\n", @@ -2243,7 +2244,9 @@ static int rbm_show(struct seq_file *m, void *v) } =20 val -=3D 2; - seq_printf(m, "buffer[%ld]: %d\n", val, meta->buffers[val]); + dpage =3D rb_range_buffer(cpu_buffer, val); + seq_printf(m, "buffer[%ld]: %d (commit: %ld)\n", + val, meta->buffers[val], dpage ? local_read(&dpage->commit) : -1); =20 return 0; } --=20 2.53.0 From nobody Mon Jun 8 10:56:13 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 E857633AD8A for ; Fri, 29 May 2026 13:21:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060916; cv=none; b=rUBqZnjEwBRYzJZPtk/DXgTkER60AedxPmV0UPCN0V5dLOGaxoeTGrjJqx3PphnNMTis11id3xSY0DYGGyi+FQLLcUyn2io7ZWHoTAGE5/phk7EwMYsiEVVi4eToU6aNvkk+Ig5Q5p1/+euBdWKpjL7HSfIKFjfUxmoUwRiv7uI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060916; c=relaxed/simple; bh=nMXpH80CJ6IwDWugKDn3K1kZTOjT27h9ALRCUgn1mTw=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=FiW6koHRuxr/8n2/WRpv2eIBtgzbopZT0XNS1aJCP31+7s2kzIC94VrIjD7wxuxIrxG7hJEJemLwLbFImtUINTY6ZGLgnHqgYt2rba9eQti6xBZrJX0mBwYBk0HUCAXlQKRueW+aRxM1c9vBO7KnVXuPf+xTjtw7pXxt66FgIfM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=C0OHW38F; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="C0OHW38F" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 501BD1F0089B; Fri, 29 May 2026 13:21:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780060914; bh=XyucF8EbUzpCHXPXKjuFYnp1GSUdy2i3wEH3fvMx2Ek=; h=Date:From:To:Cc:Subject:References; b=C0OHW38FYn0aSZCmFtBOmhUjQJEsN5WQzO2ehHUt0kCYSlyOJY3j8cxifTAkirhzU gZ39tqB5qT0wxp/j2f9tsJEyutjXZ+i9IckyDz9kJLVZqKq81aancyE+PcDUoe6++i quYD4GkGQbdhzuceMV9WTFAdFSz4aJnyCTbCDu0mKjHyxZKf14bmQiXfU5qUiRBSto st6tINLEdcVybvmpCOcEy2nVDC91GepxwqLBWrlIrYnJKuRVSCEeJmel9u2BGf1jfl nB54NqaMM6qe1rdDYEvrTJsSDgqyrZ2JRSnSOij/wlT82jHm32kqlN9+LmuvHpeNSf Xf+69fsG4A+Kw== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wSxAX-0000000ASU1-2842; Fri, 29 May 2026 09:22:33 -0400 Message-ID: <20260529132233.374157005@kernel.org> User-Agent: quilt/0.69 Date: Fri, 29 May 2026 09:22:17 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [for-next][PATCH 5/9] ring-buffer: Cleanup persistent ring buffer validation References: <20260529132212.153072686@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Masami Hiramatsu (Google)" Cleanup rb_meta_validate_events() function to make it easier to read. This includes the following cleanups: - Introduce rb_validatation_state to hold working variables in validation. - Move repleated validation state updates into rb_validate_buffer(). - Move reader_page injection code outside of rb_meta_validate_events(). Link: https://patch.msgid.link/20260522171051.577231395@kernel.org Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 200 ++++++++++++++++++++----------------- 1 file changed, 108 insertions(+), 92 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 88e613e78632..73f453ba12ce 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -1883,8 +1883,16 @@ static int rb_read_data_buffer(struct buffer_data_pa= ge *dpage, int tail, int cpu return events; } =20 -static int rb_validate_buffer(struct buffer_page *bpage, int cpu, - struct ring_buffer_cpu_meta *meta, u64 prev_ts, u64 next_ts) +struct rb_validation_state { + unsigned long entries; + unsigned long entry_bytes; + int discarded; + u64 ts; +}; + +static int __rb_validate_buffer(struct buffer_page *bpage, int cpu, + struct ring_buffer_cpu_meta *meta, + u64 prev_ts, u64 next_ts) { struct buffer_data_page *dpage =3D bpage->page; unsigned long long ts; @@ -1922,17 +1930,95 @@ static int rb_validate_buffer(struct buffer_page *b= page, int cpu, return ret; } =20 +/** + * rb_validate_buffer - validates a single buffer page and updates the sta= te. + * @bpage: buffer page to validate + * @cpu_buffer: cpu_buffer this page belongs to + * @meta: meta of the cpu_buffer + * @state: validation state + * @prev_ts: previous buffer's timestamp (optional) + * @next_ts: next buffer's timestamp (optional) + * + * If the page is invalid (wrong event length or timestamp), it increments= the + * discarded counter and warns it. Otherwise, it updates the validation st= ate. + */ +static void rb_validate_buffer(struct buffer_page *bpage, + struct ring_buffer_per_cpu *cpu_buffer, + struct ring_buffer_cpu_meta *meta, + struct rb_validation_state *state, + u64 prev_ts, u64 next_ts) +{ + int ret; + + ret =3D __rb_validate_buffer(bpage, cpu_buffer->cpu, meta, prev_ts, next_= ts); + if (ret < 0) { + if (!state->discarded) + pr_info("Ring buffer meta [%d] invalid buffer page detected\n", + cpu_buffer->cpu); + state->discarded++; + } else { + /* If the buffer has content, update pages_touched */ + if (ret) + local_inc(&cpu_buffer->pages_touched); + + state->entries +=3D ret; + state->entry_bytes +=3D rb_page_size(bpage); + state->ts =3D bpage->page->time_stamp; + } +} + +static void rb_meta_inject_reader_page(struct ring_buffer_per_cpu *cpu_buf= fer, + struct ring_buffer_cpu_meta *meta, + struct buffer_page *orig_head, + struct buffer_page *head_page) +{ + struct buffer_page *bpage =3D orig_head; + int i; + + rb_dec_page(&bpage); + /* + * Insert the reader_page before the original head page. + * Since the list encode RB_PAGE flags, general list + * operations should be avoided. + */ + cpu_buffer->reader_page->list.next =3D &orig_head->list; + cpu_buffer->reader_page->list.prev =3D orig_head->list.prev; + orig_head->list.prev =3D &cpu_buffer->reader_page->list; + bpage->list.next =3D &cpu_buffer->reader_page->list; + + /* Make the head_page the reader page */ + cpu_buffer->reader_page =3D head_page; + bpage =3D head_page; + rb_inc_page(&head_page); + head_page->list.prev =3D bpage->list.prev; + rb_dec_page(&bpage); + bpage->list.next =3D &head_page->list; + rb_set_list_to_head(&bpage->list); + cpu_buffer->pages =3D &head_page->list; + + cpu_buffer->head_page =3D head_page; + meta->head_buffer =3D (unsigned long)head_page->page; + + /* Reset all the indexes */ + bpage =3D cpu_buffer->reader_page; + meta->buffers[0] =3D rb_meta_subbuf_idx(meta, bpage->page); + bpage->id =3D 0; + + for (i =3D 1, bpage =3D head_page; i < meta->nr_subbufs; + i++, rb_inc_page(&bpage)) { + meta->buffers[i] =3D rb_meta_subbuf_idx(meta, bpage->page); + bpage->id =3D i; + } +} + /* If the meta data has been validated, now validate the events */ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) { struct ring_buffer_cpu_meta *meta =3D cpu_buffer->ring_meta; struct buffer_page *head_page, *orig_head, *orig_reader; - unsigned long entry_bytes =3D 0; - unsigned long entries =3D 0; - int discarded =3D 0; + struct rb_validation_state state =3D { 0 }; bool skip =3D false; int ret; - u64 ts; int i; =20 if (!meta || !meta->head_buffer) @@ -1942,28 +2028,19 @@ static void rb_meta_validate_events(struct ring_buf= fer_per_cpu *cpu_buffer) orig_reader =3D cpu_buffer->reader_page; =20 /* Do the head page first */ - ret =3D rb_validate_buffer(head_page, cpu_buffer->cpu, meta, 0, 0); + ret =3D __rb_validate_buffer(head_page, cpu_buffer->cpu, meta, 0, 0); if (ret < 0) { pr_info("Ring buffer meta [%d] invalid head page detected\n", cpu_buffer->cpu); /* Don't bother rewinding */ skip =3D true; - ts =3D 0; + state.ts =3D 0; } else { - ts =3D head_page->page->time_stamp; + state.ts =3D head_page->page->time_stamp; } =20 /* Do the reader page - reader must be previous to head. */ - ret =3D rb_validate_buffer(orig_reader, cpu_buffer->cpu, meta, 0, ts); - if (ret < 0) { - pr_info("Ring buffer meta [%d] invalid reader page detected\n", - cpu_buffer->cpu); - discarded++; - } else { - entries +=3D ret; - entry_bytes +=3D rb_page_size(orig_reader); - ts =3D orig_reader->page->time_stamp; - } + rb_validate_buffer(orig_reader, cpu_buffer, meta, &state, 0, state.ts); =20 if (skip) goto skip_rewind; @@ -1990,19 +2067,7 @@ static void rb_meta_validate_events(struct ring_buff= er_per_cpu *cpu_buffer) * Skip if the page is invalid, or its timestamp is newer than the * previous valid page. */ - ret =3D rb_validate_buffer(head_page, cpu_buffer->cpu, meta, 0, ts); - if (ret < 0) { - if (!discarded) - pr_info("Ring buffer meta [%d] invalid buffer page detected\n", - cpu_buffer->cpu); - discarded++; - } else { - entries +=3D ret; - entry_bytes +=3D rb_page_size(head_page); - if (ret > 0) - local_inc(&cpu_buffer->pages_touched); - ts =3D head_page->page->time_stamp; - } + rb_validate_buffer(head_page, cpu_buffer, meta, &state, 0, state.ts); } if (i) pr_info("Ring buffer [%d] rewound %d pages\n", cpu_buffer->cpu, i); @@ -2016,43 +2081,7 @@ static void rb_meta_validate_events(struct ring_buff= er_per_cpu *cpu_buffer) * into the location just before the original head page. */ if (head_page !=3D orig_head) { - struct buffer_page *bpage =3D orig_head; - - rb_dec_page(&bpage); - /* - * Insert the reader_page before the original head page. - * Since the list encode RB_PAGE flags, general list - * operations should be avoided. - */ - cpu_buffer->reader_page->list.next =3D &orig_head->list; - cpu_buffer->reader_page->list.prev =3D orig_head->list.prev; - orig_head->list.prev =3D &cpu_buffer->reader_page->list; - bpage->list.next =3D &cpu_buffer->reader_page->list; - - /* Make the head_page the reader page */ - cpu_buffer->reader_page =3D head_page; - bpage =3D head_page; - rb_inc_page(&head_page); - head_page->list.prev =3D bpage->list.prev; - rb_dec_page(&bpage); - bpage->list.next =3D &head_page->list; - rb_set_list_to_head(&bpage->list); - cpu_buffer->pages =3D &head_page->list; - - cpu_buffer->head_page =3D head_page; - meta->head_buffer =3D (unsigned long)head_page->page; - - /* Reset all the indexes */ - bpage =3D cpu_buffer->reader_page; - meta->buffers[0] =3D rb_meta_subbuf_idx(meta, bpage->page); - bpage->id =3D 0; - - for (i =3D 1, bpage =3D head_page; i < meta->nr_subbufs; - i++, rb_inc_page(&bpage)) { - meta->buffers[i] =3D rb_meta_subbuf_idx(meta, bpage->page); - bpage->id =3D i; - } - + rb_meta_inject_reader_page(cpu_buffer, meta, orig_head, head_page); /* We'll restart verifying from orig_head */ head_page =3D orig_head; } @@ -2064,7 +2093,7 @@ static void rb_meta_validate_events(struct ring_buffe= r_per_cpu *cpu_buffer) /* Nothing more to do, the only page is the reader page */ goto done; } - ts =3D head_page->page->time_stamp; + state.ts =3D head_page->page->time_stamp; =20 /* Iterate until finding the commit page */ for (i =3D 0; i < meta->nr_subbufs + 1; i++, rb_inc_page(&head_page)) { @@ -2073,21 +2102,8 @@ static void rb_meta_validate_events(struct ring_buff= er_per_cpu *cpu_buffer) if (head_page =3D=3D orig_reader) continue; =20 - ret =3D rb_validate_buffer(head_page, cpu_buffer->cpu, meta, ts, 0); - if (ret < 0) { - if (!discarded) - pr_info("Ring buffer meta [%d] invalid buffer page detected\n", - cpu_buffer->cpu); - discarded++; - } else { - /* If the buffer has content, update pages_touched */ - if (ret) - local_inc(&cpu_buffer->pages_touched); + rb_validate_buffer(head_page, cpu_buffer, meta, &state, state.ts, 0); =20 - entries +=3D ret; - entry_bytes +=3D rb_page_size(head_page); - ts =3D head_page->page->time_stamp; - } if (head_page =3D=3D cpu_buffer->commit_page) break; } @@ -2098,25 +2114,25 @@ static void rb_meta_validate_events(struct ring_buf= fer_per_cpu *cpu_buffer) goto invalid; } done: - local_set(&cpu_buffer->entries, entries); - local_set(&cpu_buffer->entries_bytes, entry_bytes); + local_set(&cpu_buffer->entries, state.entries); + local_set(&cpu_buffer->entries_bytes, state.entry_bytes); =20 pr_info("Ring buffer meta [%d] is from previous boot!", cpu_buffer->cpu); - if (discarded) - pr_cont(" (%d pages discarded)", discarded); + if (state.discarded) + pr_cont(" (%d pages discarded)", state.discarded); pr_cont("\n"); =20 #ifdef CONFIG_RING_BUFFER_PERSISTENT_INJECT if (meta->nr_invalid) pr_warn("Ring buffer testing [%d] invalid pages: %s (%d/%d)\n", cpu_buffer->cpu, - (discarded =3D=3D meta->nr_invalid) ? "PASSED" : "FAILED", - discarded, meta->nr_invalid); + (state.discarded =3D=3D meta->nr_invalid) ? "PASSED" : "FAILED", + state.discarded, meta->nr_invalid); if (meta->entry_bytes) pr_warn("Ring buffer testing [%d] entry_bytes: %s (%ld/%ld)\n", cpu_buffer->cpu, - (entry_bytes =3D=3D meta->entry_bytes) ? "PASSED" : "FAILED", - (long)entry_bytes, (long)meta->entry_bytes); + (state.entry_bytes =3D=3D meta->entry_bytes) ? "PASSED" : "FAILED", + (long)state.entry_bytes, (long)meta->entry_bytes); meta->nr_invalid =3D 0; meta->entry_bytes =3D 0; #endif --=20 2.53.0 From nobody Mon Jun 8 10:56:13 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 E84E833AD82 for ; Fri, 29 May 2026 13:21:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060918; cv=none; b=PvgweZf1QxxG4CivIz3BfkfpwWlu8bQnlwogPRYq/L2iA18CPchOhlSNT8CJmc4HKke5n82916x5YghKO7DN2kIedGyAfneF1uBwHfjAr1i0S1JqoTqiAiH6xKdlAt9dk4fmn/Bb5yFyi70LFHpkF6YtOurTHwBzHOCj7kHH9Fw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060918; c=relaxed/simple; bh=rNpVNAI1Lbkibl9XTvgiUEkTs5bj9wu2mvGTA5TlhPc=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=AUDIb9cTKsqTo1s2KXAlWxZBAEXKYsGWQMe2aqY2S1EtCrX/Wdg7GvO/knbUYrf7to6XEZwLElQaEg0pnC0x8QK1AzfS3GE08KGymPf8SvJUDIp70MWpfJ1GyEE3anG53SZn54Zni0qOOgybylQ9+R3rkG4hAL8wKbTUmg5XlD4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=n30F6PKD; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="n30F6PKD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7DB481F0089F; Fri, 29 May 2026 13:21:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780060914; bh=fUtR0sCUCiU9sTS3VH8p/HCs76MNk35bsU8khHpD9nw=; h=Date:From:To:Cc:Subject:References; b=n30F6PKDFh5DVTbZYqYkQ8SH2i/gdG1yRY4U9EOA8IHwNUMp4nIlMHhk8FH6aCpNF kNmyo/euUa5tB+vZAamBMBsNcPaIkasnZsPp/RLtP9y3vKx63V1k4o8Ajx5E0OBxci CCUaK46yDTbQzgAxKMNcSSaJQTidDRTYiDQC5x6k6g/s+Tz2qzcWZG0MqaG/lU4tNg UeIjqC+tAleje51U+wa/d+ywllj5xXCQbiv2WLAHgFb4i/5GUFA/EZonHwsZw6Vvpx 89djVdtEVp3xv0VH+6MOC0GA397Yyp/eiHMH8lgX0mfcfu1+199Dg+595HwuRVAWa+ jBXYQWg7JjYBg== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wSxAX-0000000ASUW-2lXw; Fri, 29 May 2026 09:22:33 -0400 Message-ID: <20260529132233.527701640@kernel.org> User-Agent: quilt/0.69 Date: Fri, 29 May 2026 09:22:18 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [for-next][PATCH 6/9] ring-buffer: Cleanup buffer_data_page related code References: <20260529132212.153072686@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Masami Hiramatsu (Google)" Code cleanup related to buffer_data_page for readability, which includes: - Introduce rb_data_page_commit() and rb_data_page_size() - Use 'dpage' for buffer_data_page, instead of 'bpage' because 'bpage' is used for buffer_page. Link: https://patch.msgid.link/20260522171051.722645963@kernel.org Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 112 ++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 52 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 73f453ba12ce..fd4a8dc5484e 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -364,21 +364,30 @@ struct buffer_page { #define RB_WRITE_MASK 0xfffff #define RB_WRITE_INTCNT (1 << 20) =20 -static void rb_init_page(struct buffer_data_page *bpage) +static void rb_init_data_page(struct buffer_data_page *bpage) { local_set(&bpage->commit, 0); bpage->time_stamp =3D 0; } =20 +static __always_inline long rb_data_page_commit(struct buffer_data_page *d= page) +{ + return local_read(&dpage->commit); +} + +static __always_inline long rb_data_page_size(struct buffer_data_page *dpa= ge) +{ + return rb_data_page_commit(dpage) & ~RB_MISSED_MASK; +} + static __always_inline unsigned int rb_page_commit(struct buffer_page *bpa= ge) { - return local_read(&bpage->page->commit); + return rb_data_page_commit(bpage->page); } =20 -/* Size is determined by what has been committed */ static __always_inline unsigned int rb_page_size(struct buffer_page *bpage) { - return rb_page_commit(bpage) & ~RB_MISSED_MASK; + return rb_data_page_size(bpage->page); } =20 static void free_buffer_page(struct buffer_page *bpage) @@ -419,7 +428,7 @@ static struct buffer_data_page *alloc_cpu_data(int cpu,= int order) return NULL; =20 dpage =3D page_address(page); - rb_init_page(dpage); + rb_init_data_page(dpage); =20 return dpage; } @@ -659,7 +668,7 @@ static void verify_event(struct ring_buffer_per_cpu *cp= u_buffer, do { if (page =3D=3D tail_page || WARN_ON_ONCE(stop++ > 100)) done =3D true; - commit =3D local_read(&page->page->commit); + commit =3D rb_page_commit(page); write =3D local_read(&page->write); if (addr >=3D (unsigned long)&page->page->data[commit] && addr < (unsigned long)&page->page->data[write]) @@ -1906,7 +1915,7 @@ static int __rb_validate_buffer(struct buffer_page *b= page, int cpu, * Even after clearing these bits, a commit value greater than the * subbuf_size is considered invalid. */ - tail =3D local_read(&dpage->commit) & ~RB_MISSED_MASK; + tail =3D rb_data_page_size(dpage); if (tail <=3D meta->subbuf_size - BUF_PAGE_HDR_SIZE) ret =3D rb_read_data_buffer(dpage, tail, cpu, &ts, &delta); else @@ -2145,12 +2154,12 @@ static void rb_meta_validate_events(struct ring_buf= fer_per_cpu *cpu_buffer) =20 /* Reset the reader page */ local_set(&cpu_buffer->reader_page->entries, 0); - rb_init_page(cpu_buffer->reader_page->page); + rb_init_data_page(cpu_buffer->reader_page->page); =20 /* Reset all the subbuffers */ for (i =3D 0; i < meta->nr_subbufs - 1; i++, rb_inc_page(&head_page)) { local_set(&head_page->entries, 0); - rb_init_page(head_page->page); + rb_init_data_page(head_page->page); } } =20 @@ -2210,7 +2219,7 @@ static void rb_range_meta_init(struct trace_buffer *b= uffer, int nr_pages, int sc */ for (i =3D 0; i < meta->nr_subbufs; i++) { meta->buffers[i] =3D i; - rb_init_page(subbuf); + rb_init_data_page(subbuf); subbuf +=3D meta->subbuf_size; } } @@ -2262,7 +2271,7 @@ static int rbm_show(struct seq_file *m, void *v) val -=3D 2; dpage =3D rb_range_buffer(cpu_buffer, val); seq_printf(m, "buffer[%ld]: %d (commit: %ld)\n", - val, meta->buffers[val], dpage ? local_read(&dpage->commit) : -1); + val, meta->buffers[val], dpage ? rb_data_page_commit(dpage) : -1); =20 return 0; } @@ -2653,7 +2662,7 @@ static void rb_test_inject_invalid_pages(struct trace= _buffer *buffer) =20 dpage =3D (void *)(ptr + idx * subbuf_size); /* Skip unused pages */ - if (!local_read(&dpage->commit)) + if (!rb_data_page_commit(dpage)) continue; =20 /* @@ -2665,7 +2674,7 @@ static void rb_test_inject_invalid_pages(struct trace= _buffer *buffer) invalid++; } else { /* Count total commit bytes. */ - entry_bytes +=3D local_read(&dpage->commit) & ~RB_MISSED_MASK; + entry_bytes +=3D rb_data_page_size(dpage); } } =20 @@ -4194,8 +4203,7 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cp= u_buffer) local_set(&cpu_buffer->commit_page->page->commit, rb_page_write(cpu_buffer->commit_page)); RB_WARN_ON(cpu_buffer, - local_read(&cpu_buffer->commit_page->page->commit) & - ~RB_WRITE_MASK); + rb_page_commit(cpu_buffer->commit_page) & ~RB_WRITE_MASK); barrier(); } =20 @@ -4567,7 +4575,7 @@ static const char *show_interrupt_level(void) return show_irq_str(level); } =20 -static void dump_buffer_page(struct buffer_data_page *bpage, +static void dump_buffer_page(struct buffer_data_page *dpage, struct rb_event_info *info, unsigned long tail) { @@ -4575,12 +4583,12 @@ static void dump_buffer_page(struct buffer_data_pag= e *bpage, u64 ts, delta; int e; =20 - ts =3D bpage->time_stamp; + ts =3D dpage->time_stamp; pr_warn(" [%lld] PAGE TIME STAMP\n", ts); =20 for (e =3D 0; e < tail; e +=3D rb_event_length(event)) { =20 - event =3D (struct ring_buffer_event *)(bpage->data + e); + event =3D (struct ring_buffer_event *)(dpage->data + e); =20 switch (event->type_len) { =20 @@ -4630,7 +4638,7 @@ static atomic_t ts_dump; } \ atomic_inc(&cpu_buffer->record_disabled); \ pr_warn(fmt, ##__VA_ARGS__); \ - dump_buffer_page(bpage, info, tail); \ + dump_buffer_page(dpage, info, tail); \ atomic_dec(&ts_dump); \ /* There's some cases in boot up that this can happen */ \ if (WARN_ON_ONCE(system_state !=3D SYSTEM_BOOTING)) \ @@ -4646,16 +4654,16 @@ static void check_buffer(struct ring_buffer_per_cpu= *cpu_buffer, struct rb_event_info *info, unsigned long tail) { - struct buffer_data_page *bpage; + struct buffer_data_page *dpage; u64 ts, delta; bool full =3D false; int ret; =20 - bpage =3D info->tail_page->page; + dpage =3D info->tail_page->page; =20 if (tail =3D=3D CHECK_FULL_PAGE) { full =3D true; - tail =3D local_read(&bpage->commit); + tail =3D rb_data_page_commit(dpage); } else if (info->add_timestamp & (RB_ADD_STAMP_FORCE | RB_ADD_STAMP_ABSOLUTE)) { /* Ignore events with absolute time stamps */ @@ -4666,7 +4674,7 @@ static void check_buffer(struct ring_buffer_per_cpu *= cpu_buffer, * Do not check the first event (skip possible extends too). * Also do not check if previous events have not been committed. */ - if (tail <=3D 8 || tail > local_read(&bpage->commit)) + if (tail <=3D 8 || tail > rb_data_page_commit(dpage)) return; =20 /* @@ -4675,7 +4683,7 @@ static void check_buffer(struct ring_buffer_per_cpu *= cpu_buffer, if (atomic_inc_return(this_cpu_ptr(&checking)) !=3D 1) goto out; =20 - ret =3D rb_read_data_buffer(bpage, tail, cpu_buffer->cpu, &ts, &delta); + ret =3D rb_read_data_buffer(dpage, tail, cpu_buffer->cpu, &ts, &delta); if (ret < 0) { if (delta < ts) { buffer_warn_return("[CPU: %d]ABSOLUTE TIME WENT BACKWARDS: last ts: %ll= d absolute ts: %lld clock:%pS\n", @@ -6466,7 +6474,7 @@ static void rb_clear_buffer_page(struct buffer_page *= page) { local_set(&page->write, 0); local_set(&page->entries, 0); - rb_init_page(page->page); + rb_init_data_page(page->page); page->read =3D 0; } =20 @@ -6951,7 +6959,7 @@ ring_buffer_alloc_read_page(struct trace_buffer *buff= er, int cpu) local_irq_restore(flags); =20 if (bpage->data) { - rb_init_page(bpage->data); + rb_init_data_page(bpage->data); } else { bpage->data =3D alloc_cpu_data(cpu, cpu_buffer->buffer->subbuf_order); if (!bpage->data) { @@ -6976,8 +6984,8 @@ void ring_buffer_free_read_page(struct trace_buffer *= buffer, int cpu, struct buffer_data_read_page *data_page) { struct ring_buffer_per_cpu *cpu_buffer; - struct buffer_data_page *bpage =3D data_page->data; - struct page *page =3D virt_to_page(bpage); + struct buffer_data_page *dpage =3D data_page->data; + struct page *page =3D virt_to_page(dpage); unsigned long flags; =20 if (!buffer || !buffer->buffers || !buffer->buffers[cpu]) @@ -6997,15 +7005,15 @@ void ring_buffer_free_read_page(struct trace_buffer= *buffer, int cpu, arch_spin_lock(&cpu_buffer->lock); =20 if (!cpu_buffer->free_page) { - cpu_buffer->free_page =3D bpage; - bpage =3D NULL; + cpu_buffer->free_page =3D dpage; + dpage =3D NULL; } =20 arch_spin_unlock(&cpu_buffer->lock); local_irq_restore(flags); =20 out: - free_pages((unsigned long)bpage, data_page->order); + free_pages((unsigned long)dpage, data_page->order); kfree(data_page); } EXPORT_SYMBOL_GPL(ring_buffer_free_read_page); @@ -7050,7 +7058,7 @@ int ring_buffer_read_page(struct trace_buffer *buffer, { struct ring_buffer_per_cpu *cpu_buffer =3D buffer->buffers[cpu]; struct ring_buffer_event *event; - struct buffer_data_page *bpage; + struct buffer_data_page *dpage; struct buffer_page *reader; unsigned long missed_events; unsigned int commit; @@ -7076,8 +7084,8 @@ int ring_buffer_read_page(struct trace_buffer *buffer, if (data_page->order !=3D buffer->subbuf_order) return -1; =20 - bpage =3D data_page->data; - if (!bpage) + dpage =3D data_page->data; + if (!dpage) return -1; =20 guard(raw_spinlock_irqsave)(&cpu_buffer->reader_lock); @@ -7143,7 +7151,7 @@ int ring_buffer_read_page(struct trace_buffer *buffer, * We have already ensured there's enough space if this * is a time extend. */ size =3D rb_event_length(event); - memcpy(bpage->data + pos, rpage->data + rpos, size); + memcpy(dpage->data + pos, rpage->data + rpos, size); =20 len -=3D size; =20 @@ -7159,9 +7167,9 @@ int ring_buffer_read_page(struct trace_buffer *buffer, size =3D rb_event_ts_length(event); } while (len >=3D size); =20 - /* update bpage */ - local_set(&bpage->commit, pos); - bpage->time_stamp =3D save_timestamp; + /* update dpage */ + local_set(&dpage->commit, pos); + dpage->time_stamp =3D save_timestamp; =20 /* we copied everything to the beginning */ read =3D 0; @@ -7171,13 +7179,13 @@ int ring_buffer_read_page(struct trace_buffer *buff= er, cpu_buffer->read_bytes +=3D rb_page_size(reader); =20 /* swap the pages */ - rb_init_page(bpage); - bpage =3D reader->page; + rb_init_data_page(dpage); + dpage =3D reader->page; reader->page =3D data_page->data; local_set(&reader->write, 0); local_set(&reader->entries, 0); reader->read =3D 0; - data_page->data =3D bpage; + data_page->data =3D dpage; =20 /* * Use the real_end for the data size, @@ -7185,12 +7193,12 @@ int ring_buffer_read_page(struct trace_buffer *buff= er, * on the page. */ if (reader->real_end) - local_set(&bpage->commit, reader->real_end); + local_set(&dpage->commit, reader->real_end); } =20 cpu_buffer->lost_events =3D 0; =20 - commit =3D local_read(&bpage->commit); + commit =3D rb_data_page_commit(dpage); /* * Set a flag in the commit field if we lost events */ @@ -7199,19 +7207,19 @@ int ring_buffer_read_page(struct trace_buffer *buff= er, * missed events, then record it there. */ if (buffer->subbuf_size - commit >=3D sizeof(missed_events)) { - memcpy(&bpage->data[commit], &missed_events, + memcpy(&dpage->data[commit], &missed_events, sizeof(missed_events)); - local_add(RB_MISSED_STORED, &bpage->commit); + local_add(RB_MISSED_STORED, &dpage->commit); commit +=3D sizeof(missed_events); } - local_add(RB_MISSED_EVENTS, &bpage->commit); + local_add(RB_MISSED_EVENTS, &dpage->commit); } =20 /* * This page may be off to user land. Zero it out here. */ if (commit < buffer->subbuf_size) - memset(&bpage->data[commit], 0, buffer->subbuf_size - commit); + memset(&dpage->data[commit], 0, buffer->subbuf_size - commit); =20 return read; } @@ -7842,7 +7850,7 @@ int ring_buffer_map_get_reader(struct trace_buffer *b= uffer, int cpu) =20 if (missed_events) { if (cpu_buffer->reader_page !=3D cpu_buffer->commit_page) { - struct buffer_data_page *bpage =3D reader->page; + struct buffer_data_page *dpage =3D reader->page; unsigned int commit; /* * Use the real_end for the data size, @@ -7850,18 +7858,18 @@ int ring_buffer_map_get_reader(struct trace_buffer = *buffer, int cpu) * on the page. */ if (reader->real_end) - local_set(&bpage->commit, reader->real_end); + local_set(&dpage->commit, reader->real_end); /* * If there is room at the end of the page to save the * missed events, then record it there. */ commit =3D rb_page_size(reader); if (buffer->subbuf_size - commit >=3D sizeof(missed_events)) { - memcpy(&bpage->data[commit], &missed_events, + memcpy(&dpage->data[commit], &missed_events, sizeof(missed_events)); - local_add(RB_MISSED_STORED, &bpage->commit); + local_add(RB_MISSED_STORED, &dpage->commit); } - local_add(RB_MISSED_EVENTS, &bpage->commit); + local_add(RB_MISSED_EVENTS, &dpage->commit); } else if (!WARN_ONCE(cpu_buffer->reader_page =3D=3D cpu_buffer->tail_pa= ge, "Reader on commit with %ld missed events", missed_events)) { --=20 2.53.0 From nobody Mon Jun 8 10:56:13 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 76AE233B6CB for ; Fri, 29 May 2026 13:21:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060917; cv=none; b=XGCMv4WH/GE1P8h94xcm7QzCBImJdMxKuQN8WImsXpLbmwtjffQJjzSKBxN1YmWVNEEM3+PYRtKbA6RpjOdoWjOHYS8uyrJTMgx09pSPVq/AudQnOeFc7rW8epNcq+5innDiwpKoQMd5SvFbyUp2vLzBJzXhDSDiZ1eNQnJcWEQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060917; c=relaxed/simple; bh=x+o/DOLZlj7Bwmu0EoamwBQaf6CHwB47o9OMscTjeJs=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=RIbI5Md0stbT6GTzCdipopJIAf7sqwYHdDTp7sHOSAVjf+uAM1eh6UnnmSHOfG3haw1n738utsFdT7LaTu5XVudneeOL0vGII3dm86QJ97sPSDYwsad8OolAmxhgg8c5/2UD2MKhy/XUNPunkmP2WOcVU9dYStGpmb9Yv9j6Idw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Rbg1cctO; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Rbg1cctO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B1B501F008A1; Fri, 29 May 2026 13:21:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780060914; bh=Lp86shnKnsqoyJ3siQmlvokVG/F4xvoHMgWz1Rxtio8=; h=Date:From:To:Cc:Subject:References; b=Rbg1cctO5b1eamk1ayo3rePP+nkqpGtp5fUSoChhAAetB35jRaBaakEesZ69pjyWf tWYJ04BTMpQnXrip5pNpWu0MJnJYS1SV3vJYI747bAtOgagVkw3/AbHQnGlXIwnspi yME/GNcDTo5eT1WyVfakKRfED2VgqvBe5QqVR6971WBY903ZZ/JYV86kHTt+kzjzHK uulux+5fR+1q2P7/9oYjUubQv/VyNuFBDYScaivK8ZBovAPvXDpCtwBsYdL5pZdY3b bV7dyIr0C89MNO7wksJ4Gmou6gbdHT92lVjzT9JSLBgH05sCRh2Oyl4/Hbm1KgAd7A LCQX1VwwdEUlw== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wSxAX-0000000ASV0-3R4k; Fri, 29 May 2026 09:22:33 -0400 Message-ID: <20260529132233.679624644@kernel.org> User-Agent: quilt/0.69 Date: Fri, 29 May 2026 09:22:19 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [for-next][PATCH 7/9] ring-buffer: Have dropped subbuffers be persistent across reboots References: <20260529132212.153072686@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Steven Rostedt When the persistent ring buffer detects a corrupted subbuffer, it will zero its size and report dropped pages in the dmesg, then it continues normally. But if a reboot happens without clearing or restarting tracing on the persistent ring buffer, the next boot will show no pages are dropped. If the persistent ring buffer is still the same, then it should still report dropped pages so the user knows that the buffer has missing events. Add the RB_MISSED_EVENTS flag to the commit value of the subbuffer so that the next boot will still show that pages were dropped. Link: https://patch.msgid.link/20260522171051.860780286@kernel.org Reviewed-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index fd4a8dc5484e..db72969aefa9 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -1915,7 +1915,7 @@ static int __rb_validate_buffer(struct buffer_page *b= page, int cpu, * Even after clearing these bits, a commit value greater than the * subbuf_size is considered invalid. */ - tail =3D rb_data_page_size(dpage); + tail =3D rb_data_page_commit(dpage); if (tail <=3D meta->subbuf_size - BUF_PAGE_HDR_SIZE) ret =3D rb_read_data_buffer(dpage, tail, cpu, &ts, &delta); else @@ -1929,7 +1929,7 @@ static int __rb_validate_buffer(struct buffer_page *b= page, int cpu, */ if (ret < 0 || (prev_ts && prev_ts > ts) || (next_ts && ts > next_ts)) { local_set(&bpage->entries, 0); - local_set(&dpage->commit, 0); + local_set(&dpage->commit, RB_MISSED_EVENTS); dpage->time_stamp =3D prev_ts ? prev_ts : next_ts; ret =3D -1; } else { @@ -3451,7 +3451,7 @@ rb_iter_head_event(struct ring_buffer_iter *iter) * is a mb(), which will synchronize with the rmb here. * (see rb_tail_page_update() and __rb_reserve_next()) */ - commit =3D rb_page_commit(iter_head_page); + commit =3D rb_page_size(iter_head_page); smp_rmb(); =20 /* An event needs to be at least 8 bytes in size */ @@ -3480,7 +3480,7 @@ rb_iter_head_event(struct ring_buffer_iter *iter) =20 /* Make sure the page didn't change since we read this */ if (iter->page_stamp !=3D iter_head_page->page->time_stamp || - commit > rb_page_commit(iter_head_page)) + commit > rb_page_size(iter_head_page)) goto reset; =20 iter->next_event =3D iter->head + length; @@ -5651,7 +5651,7 @@ int ring_buffer_iter_empty(struct ring_buffer_iter *i= ter) * (see rb_tail_page_update()) */ smp_rmb(); - commit =3D rb_page_commit(commit_page); + commit =3D rb_page_size(commit_page); /* We want to make sure that the commit page doesn't change */ smp_rmb(); =20 @@ -5844,6 +5844,7 @@ __rb_get_reader_page(struct ring_buffer_per_cpu *cpu_= buffer) */ local_set(&cpu_buffer->reader_page->write, 0); local_set(&cpu_buffer->reader_page->entries, 0); + rb_init_data_page(cpu_buffer->reader_page->page); cpu_buffer->reader_page->real_end =3D 0; =20 spin: --=20 2.53.0 From nobody Mon Jun 8 10:56:13 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 76A5333B6C9 for ; Fri, 29 May 2026 13:21:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060916; cv=none; b=SXS2CPsWeMJN641C0XpnxX6Oi2SnOTfoMV6MiOH9rRbAXjWlDhtpqc3ivFTGLhWvdnvp23Tw39VR98ER0hP5qWRiBJAorLp1tE5ptWnG/wWympxq3qkDYrKjbD007X1fE6GapYNRMY0uJaYYJhVKqqFGOevQ9whCXgIwU4iA0Zw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060916; c=relaxed/simple; bh=vaYwWYoX8vnhHhT+iv/ODlKBPqrEHdlD24XqXQ9YSG0=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=tv4Wh9d6A+Mp7jBa11tPpr8YCtDABMqmGna6dtzXB5N3QzbYWbQHpEaFLFsoVlH9cgFmFWpb4U5ubNFFz5KgY4qgnoqZrFHUtNlA5NNx9+J5DaUj6MeBrFVJBz/x//00y0pBgTJiotGkqheMTS80z2POfmwXLbfUyE9OXFWjdiY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=f84/IQ0Q; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="f84/IQ0Q" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CAFEC1F008A0; Fri, 29 May 2026 13:21:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780060914; bh=02dfIMvm1t9MxLIH3+le/fMg8wx4LGDjXuv+Av5ztj0=; h=Date:From:To:Cc:Subject:References; b=f84/IQ0QqkuBR9bMCCclCiloV+3NNbfCNezbG12t/DVdtxDlSRWgd11Qm8V0JlKmm Q3+4RRZ+ZFzdhTSlw5bOOhBVPYTEigatGBaG9Mijh5Z2xyc/hnw3vzCSvTRx4rsYpB iK5/YFlwR2K0aW7AycxjcFpjkBDKT9/s4PghMIV+CD/npnMYxRSh9Y9g0ZAiMUP4TT kDs6/H0sO7dyEV5XX02HWI4mwcMfGGUjOw6RzI1SPQjzcb6/1cPwCdJyneEs5wsqOo 4uW1mfLDrwKcwHJUGbIbXxu6MZvZcuyCR2MK4iCdvEbv5F2ba+2woUgd8oYdYfeXKq JbGALFp1E7NLQ== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wSxAX-0000000ASVX-44xA; Fri, 29 May 2026 09:22:33 -0400 Message-ID: <20260529132233.836743076@kernel.org> User-Agent: quilt/0.69 Date: Fri, 29 May 2026 09:22:20 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [for-next][PATCH 8/9] ring-buffer: Show persistent buffer dropped events in trace file References: <20260529132212.153072686@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Steven Rostedt When the persistent ring buffer is validated on boot up, if a subbuffer is deemed invalid, it resets the buffer and continues. Currently, these lost events are not shown in the trace file output. Have the trace iterator look for subbuffers that have the RB_MISSED_EVENTS set and set the iter->missed_events flag when it is detected. This will then have the trace file shows "LOST EVENTS" when it reads across a subbuffer that was corrupted and invalidated. For example: <...>-1016 [005] ...1. 6230.660403: preempt_disable: caller=3D__mod_me= mcg_state+0x1c8/0x200 parent=3D__mod_memcg_state+0x1c8/0x200 CPU:5 [LOST EVENTS] <...>-1016 [005] ..... 6230.660673: kmem_cache_alloc: call_site=3D__an= on_vma_prepare+0x1ad/0x1e0 ptr=3D000000006e40294c name=3Danon_vma bytes_req= =3D200 bytes_alloc=3D208 gfp_flags=3DGFP_KERNEL node=3D-1 accounted=3Dtrue Link: https://patch.msgid.link/20260522171052.006276604@kernel.org Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index db72969aefa9..988915f035c7 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -3525,6 +3525,9 @@ static void rb_inc_iter(struct ring_buffer_iter *iter) else rb_inc_page(&iter->head_page); =20 + if (rb_page_commit(iter->head_page) & RB_MISSED_EVENTS) + iter->missed_events =3D -1; + iter->page_stamp =3D iter->read_stamp =3D iter->head_page->page->time_sta= mp; iter->head =3D 0; iter->next_event =3D 0; @@ -7061,7 +7064,7 @@ int ring_buffer_read_page(struct trace_buffer *buffer, struct ring_buffer_event *event; struct buffer_data_page *dpage; struct buffer_page *reader; - unsigned long missed_events; + long missed_events; unsigned int commit; unsigned int read; u64 save_timestamp; @@ -7187,6 +7190,8 @@ int ring_buffer_read_page(struct trace_buffer *buffer, local_set(&reader->entries, 0); reader->read =3D 0; data_page->data =3D dpage; + if (!missed_events && rb_data_page_commit(dpage) & RB_MISSED_EVENTS) + missed_events =3D -1; =20 /* * Use the real_end for the data size, @@ -7204,10 +7209,12 @@ int ring_buffer_read_page(struct trace_buffer *buff= er, * Set a flag in the commit field if we lost events */ if (missed_events) { - /* If there is room at the end of the page to save the + /* + * If there is room at the end of the page to save the * missed events, then record it there. */ - if (buffer->subbuf_size - commit >=3D sizeof(missed_events)) { + if (missed_events > 0 && + buffer->subbuf_size - commit >=3D sizeof(missed_events)) { memcpy(&dpage->data[commit], &missed_events, sizeof(missed_events)); local_add(RB_MISSED_STORED, &dpage->commit); --=20 2.53.0 From nobody Mon Jun 8 10:56:13 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 B68A733B6ED for ; Fri, 29 May 2026 13:21:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060917; cv=none; b=Ec+XTRzcdIcV2wcHBZzpuzXBNTolLz7kpePbQzohBSfQase1XpI1AZ1OVn/DQeUkc/+eqnaYg7tNh1dv+eP7jx453SFvd90dgT65jtHL/DG1ya1SnzXxTEkBrc0HFlIPVide2al/QppwqbjXnw/I4Zv5o+i38Q3MwkXUasl4BfU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780060917; c=relaxed/simple; bh=h6oTqbUvk735yAvF0IyZ2ruDJpJ1rQ4s1pOqtLvWGNY=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=LKzwt+dK7VJ9l8MIMih6OFnvY2+thtS10M0UuSrNMkvxMTHVF/6SojSU2bu7UyWN0w35/Py/XGZgj37iAUOjwMkwFWOgXF8oCzKuz9jh2HufkqV/VMYicgMpMUZBkyAM+Sl6DXnpwgCfiv8YyOT0+FMdzK507834F2LzjUytlEw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oiD+31R+; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oiD+31R+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EF2F31F00898; Fri, 29 May 2026 13:21:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780060915; bh=G4Mj0i9rfh5+WjlhoL+WuQMoGlRRfT0PtrJ9bdcvu/U=; h=Date:From:To:Cc:Subject:References; b=oiD+31R+evQB56LSC5F/6p7bEgwY5icFfKmfqwnv6/t0s1jHXjYfUS5c2TMZZ0hF4 +EjMXS+tzXnbT7Y+uu3oOIoZrKXGIOMIrTP+V4CHrqO5j59qqGYhkS0N4nnCV4lGFF Gs2h36Yv0NQZF76xEAjLk3woQutI0CJuz1NKOu2KauMK4Lb1Jrup1ngFm2xRJ8QlWt lD6VnlOQ0cv4D0RUzRtUVkgCnrPVIDiQC1y4KoTIys6Vib/m6B8KteXkAwCs369mUz m1TZG6RVmcP1diHCk6oeXkMPRImHbRX42KEr3zZA+OqCzd/zQbxHUDYgSK+5p9/uNR 5NLYxkrguovqA== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wSxAY-0000000ASW1-0W5C; Fri, 29 May 2026 09:22:34 -0400 Message-ID: <20260529132233.989753362@kernel.org> User-Agent: quilt/0.69 Date: Fri, 29 May 2026 09:22:21 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [for-next][PATCH 9/9] ring-buffer: Show persistent buffer dropped events in trace_pipe file References: <20260529132212.153072686@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Steven Rostedt When the persistent ring buffer is validated on boot up, if a subbuffer is deemed invalid, it resets the buffer and continues. Have the code preserve the RB_MISSED_EVENTS flag in the commit portion of the subbuffer header and pass that back so that the trace_pipe file can show the missed events like the trace file does. For example: <...>-1242 [005] d.... 4429.120116: page_fault_user: address=3D0x7ff= aebb6e728 ip=3D0x7ffaeb9d4960 error_code=3D0x7 <...>-1242 [005] ..... 4429.120124: mm_page_alloc: page=3D0000000005= 5254f3 pfn=3D0x1373bd order=3D0 migratetype=3D1 gfp_flags=3DGFP_HIGHUSER_MO= VABLE|__GFP_COMP <...>-1242 [005] d..2. 4429.120132: tlb_flush: pages:1 reason:local = MM shootdown (3) CPU:5 [LOST EVENTS] <...>-1242 [005] d.... 4429.120661: page_fault_user: address=3D0x55b= a7c2d0944 ip=3D0x55ba7c20cd02 error_code=3D0x7 <...>-1242 [005] ..... 4429.120669: mm_page_alloc: page=3D0000000005= a02500 pfn=3D0x12b6e4 order=3D0 migratetype=3D1 gfp_flags=3DGFP_HIGHUSER_MO= VABLE|__GFP_COMP <...>-1242 [005] d..2. 4429.120680: tlb_flush: pages:1 reason:local = MM shootdown (3) Link: https://patch.msgid.link/20260522171052.156419479@kernel.org Reviewed-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 56 +++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 988915f035c7..910f6b3adf74 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -5801,6 +5801,7 @@ __rb_get_reader_page(struct ring_buffer_per_cpu *cpu_= buffer) struct buffer_page *reader =3D NULL; unsigned long overwrite; unsigned long flags; + int missed_events =3D 0; int nr_loops =3D 0; bool ret; =20 @@ -5901,6 +5902,9 @@ __rb_get_reader_page(struct ring_buffer_per_cpu *cpu_= buffer) if (!ret) goto spin; =20 + if (rb_page_commit(reader) & RB_MISSED_EVENTS) + missed_events =3D -1; + if (cpu_buffer->ring_meta) rb_update_meta_reader(cpu_buffer, reader); =20 @@ -5965,6 +5969,8 @@ __rb_get_reader_page(struct ring_buffer_per_cpu *cpu_= buffer) */ smp_rmb(); =20 + if (!cpu_buffer->lost_events) + cpu_buffer->lost_events =3D missed_events; =20 return reader; } @@ -7066,6 +7072,7 @@ int ring_buffer_read_page(struct trace_buffer *buffer, struct buffer_page *reader; long missed_events; unsigned int commit; + unsigned int size; unsigned int read; u64 save_timestamp; bool force_memcpy; @@ -7101,7 +7108,8 @@ int ring_buffer_read_page(struct trace_buffer *buffer, event =3D rb_reader_event(cpu_buffer); =20 read =3D reader->read; - commit =3D rb_page_size(reader); + commit =3D rb_page_commit(reader); + size =3D rb_page_size(reader); =20 /* Check if any events were dropped */ missed_events =3D cpu_buffer->lost_events; @@ -7115,13 +7123,14 @@ int ring_buffer_read_page(struct trace_buffer *buff= er, * we must copy the data from the page to the buffer. * Otherwise, we can simply swap the page with the one passed in. */ - if (read || (len < (commit - read)) || + if (read || (len < (size - read)) || cpu_buffer->reader_page =3D=3D cpu_buffer->commit_page || force_memcpy) { struct buffer_data_page *rpage =3D cpu_buffer->reader_page->page; unsigned int rpos =3D read; unsigned int pos =3D 0; - unsigned int size; + unsigned int event_size; + unsigned int flags =3D 0; =20 /* * If a full page is expected, this can still be returned @@ -7130,19 +7139,22 @@ int ring_buffer_read_page(struct trace_buffer *buff= er, * the reader page. */ if (full && - (!read || (len < (commit - read)) || + (!read || (len < (size - read)) || cpu_buffer->reader_page =3D=3D cpu_buffer->commit_page)) return -1; =20 - if (len > (commit - read)) - len =3D (commit - read); + if (len > (size - read)) + len =3D (size - read); =20 /* Always keep the time extend and data together */ - size =3D rb_event_ts_length(event); + event_size =3D rb_event_ts_length(event); =20 - if (len < size) + if (len < event_size) return -1; =20 + if (commit & RB_MISSED_EVENTS) + flags =3D RB_MISSED_EVENTS; + /* save the current timestamp, since the user will need it */ save_timestamp =3D cpu_buffer->read_stamp; =20 @@ -7154,25 +7166,25 @@ int ring_buffer_read_page(struct trace_buffer *buff= er, * one or two events. * We have already ensured there's enough space if this * is a time extend. */ - size =3D rb_event_length(event); - memcpy(dpage->data + pos, rpage->data + rpos, size); + event_size =3D rb_event_length(event); + memcpy(dpage->data + pos, rpage->data + rpos, event_size); =20 - len -=3D size; + len -=3D event_size; =20 rb_advance_reader(cpu_buffer); rpos =3D reader->read; - pos +=3D size; + pos +=3D event_size; =20 - if (rpos >=3D commit) + if (rpos >=3D event_size) break; =20 event =3D rb_reader_event(cpu_buffer); /* Always keep the time extend and data together */ - size =3D rb_event_ts_length(event); - } while (len >=3D size); + event_size =3D rb_event_ts_length(event); + } while (len >=3D event_size); =20 /* update dpage */ - local_set(&dpage->commit, pos); + local_set(&dpage->commit, pos | flags); dpage->time_stamp =3D save_timestamp; =20 /* we copied everything to the beginning */ @@ -7204,7 +7216,7 @@ int ring_buffer_read_page(struct trace_buffer *buffer, =20 cpu_buffer->lost_events =3D 0; =20 - commit =3D rb_data_page_commit(dpage); + size =3D rb_data_page_size(dpage); /* * Set a flag in the commit field if we lost events */ @@ -7214,11 +7226,11 @@ int ring_buffer_read_page(struct trace_buffer *buff= er, * missed events, then record it there. */ if (missed_events > 0 && - buffer->subbuf_size - commit >=3D sizeof(missed_events)) { - memcpy(&dpage->data[commit], &missed_events, + buffer->subbuf_size - size >=3D sizeof(missed_events)) { + memcpy(&dpage->data[size], &missed_events, sizeof(missed_events)); local_add(RB_MISSED_STORED, &dpage->commit); - commit +=3D sizeof(missed_events); + size +=3D sizeof(missed_events); } local_add(RB_MISSED_EVENTS, &dpage->commit); } @@ -7226,8 +7238,8 @@ int ring_buffer_read_page(struct trace_buffer *buffer, /* * This page may be off to user land. Zero it out here. */ - if (commit < buffer->subbuf_size) - memset(&dpage->data[commit], 0, buffer->subbuf_size - commit); + if (size < buffer->subbuf_size) + memset(&dpage->data[size], 0, buffer->subbuf_size - size); =20 return read; } --=20 2.53.0