From nobody Sun May 24 22:35:50 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 7C70C403EA4; Wed, 20 May 2026 18:49:58 +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=1779303002; cv=none; b=SP+vDud2uSBQhz3u6E70tFw+8a6eronPwNhVfAg8LlduN9/sCJjo0KKcgsBi2HiFp94moq5lQ6G2DdwXEdhEWV/HSZS28pH/7j6Sh8p00AoddJ2Bia5BX+Or0enCMg0YhWGwCC1fFTvQprMzuzMsRAUZVdvvu3jTVNkUyOfjfeM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779303002; c=relaxed/simple; bh=Esvh+IpuqKCjEwaasRA3vxjoPJheFxicV0WeUZTY9tM=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=nWs34D2fX76ikf4XHDZj0C8R4AktgWHmPeoJbsV7RUUHfMb2SGs2m/+qfAHKFhCsScMnKxkFQqyMemDs4van21Fukknk2snnzTAboGJnjaa1pwtMTXCclMHY7/AuuhGbU0+4vc9hJm62CAi0jIKTLwCnUq+RFRUTclUgMn2nxwI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Hv7Px66x; 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="Hv7Px66x" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 959371F0089A; Wed, 20 May 2026 18:49:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779302997; bh=8FdY2yfPfChMtwk9luqkFOvle1crq3KfeaHIzsWjnD8=; h=Date:From:To:Cc:Subject:References; b=Hv7Px66xhUr51akQ2Ak+vXs6YwLfefYfGwEYddX4KdmOCwRyKYMxPir1Vm2CudybJ MDCepAQrb62LE5gQm49VR5sPUUMrICE0oryAdZKYQasJ/LWaTlQPxmO0IAH+1AbQxM SlA6Mwi3M4q88hVRkWh0A1Sf7F2G6gGUDPz0U2Viik1dsqkNrGiqrWRBfiR/FzlcCh r4P10uMaFK9Y0wxhZYYHxYDE2oSbZ9ETJs8kThrjaDI/aK50HrsYYei6L5wJK/03GC XdJJpvDamrqJ2Bp0vbuU6/dx5RzrUtAjqwYox5ANT6X4anEBvEk76kOm0BPWP79Zj5 rYhJwVDvFO+Xw== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wPlzl-00000004qQq-0qOu; Wed, 20 May 2026 14:50:17 -0400 Message-ID: <20260520185017.044376275@kernel.org> User-Agent: quilt/0.69 Date: Wed, 20 May 2026 14:49:39 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Catalin Marinas , Will Deacon , Ian Rogers Subject: [PATCH v20 01/10] ring-buffer: Skip invalid sub-buffers when validating persistent ring buffer References: <20260520184938.749337513@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. Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 116 ++++++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 46 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 4c0cf6ac0161..97ef702655f5 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) { @@ -5635,8 +5655,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; @@ -5648,11 +5669,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; } --=20 2.53.0 From nobody Sun May 24 22:35:50 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 792CE403E92; Wed, 20 May 2026 18:49:58 +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=1779303003; cv=none; b=KXgrBmdiR7Mt8LdD6EPQH25T7cZYXiOmLzlEKFgoeEYzFxLW/g91oOwAoyshQKW2vuM+GawzcMqN9gc2qpBcwWh/fuw+x5Q2DOGsRFc6HngLE458ztR1B6kP64XCciLF4kwK/QoGVIty35v1NuaAEG+3ZWYpdIfAV325LqTwfz4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779303003; c=relaxed/simple; bh=dTfWW0EGfppg5wQA5TLVkE+qRLXWKwOSDXCU2P5YglU=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=G9fAVnPYZBAll8Mqtrc8E/ESewzDrD/ztysZOAFGpQAHiS6I14vJe4zqqKdMTWHc0TH+mEYKtZzku/LPuYjzRBwaqSsBpY7jUTGIvWKOEv8sHNmyPrdFD1UPGoQZke+5PS9WDHHk9u31WqqQOaHyzFVpHaHJjSf3rnx+RLBls5U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=o21BohyJ; 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="o21BohyJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CD27B1F0089C; Wed, 20 May 2026 18:49:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779302997; bh=Tz4o0IPUFGlacSMFrrih4D6KtT8s8pgNnzQswDMjuFw=; h=Date:From:To:Cc:Subject:References; b=o21BohyJrRyyPHVrnJINDVCyPm5k2nGToOEhCaWvaJ3FegCDxsuuvuPmT+yU5TuNT Xup/6XhB/sOS1i8x6OmXgzY9Rr29vbRNr8LiV0zBafKHFEUmnApugA/ao/VLT9pfqQ VPKE14xYmwz27aVNXj9qVeEEoIKdBxT61uPgFSOplKzdkRfhl6mZqY/qnsvdMy93IF Zry9YGUGaeyVusr87jK3jheky85O3ghBpBtfLiPJi19bqe6+7JCyNS1I5ro+jxyFAx 9aK4npNhIPGSZCSHgu9ZW3UyWnD3hkJF7B21cvfj+1XOn2hDU/ev5zFZSJ/5jv4/EG x3YGkJFZlIsxQ== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wPlzl-00000004qRK-1d8L; Wed, 20 May 2026 14:50:17 -0400 Message-ID: <20260520185017.219342323@kernel.org> User-Agent: quilt/0.69 Date: Wed, 20 May 2026 14:49:40 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Catalin Marinas , Will Deacon , Ian Rogers Subject: [PATCH v20 02/10] ring-buffer: Skip invalid sub-buffers when rewinding persistent ring buffer References: <20260520184938.749337513@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. Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 102 +++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 39 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 97ef702655f5..dca27ed6a3a1 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 */ @@ -1915,25 +1936,29 @@ 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); + goto skip_rewind; + } + 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; - /* - * 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 +1971,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 +2053,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 +2062,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 +2075,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 +2103,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 Sun May 24 22:35:50 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 7914D3FCB27; Wed, 20 May 2026 18:49:58 +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=1779303002; cv=none; b=aoFEilB2A3HNNplN9l0l/cy7V9DOVCF3n3VFxrJ2gUToNZF137vkz3D/oLjkEfREXY6vZBMom3YFRCwdtqRvAM2YHtMg/JYLwfy9K8g6BZLdBRvxCclp5DevDDy0nnXyEd7fSNz/n4qJhVPHEA6j2FV99dQlTezzKZZqem4/cOs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779303002; c=relaxed/simple; bh=j6aav4uC8PRI45cHwcHaJJN76oR3obz5YqJIVWeOP74=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=uV9AlF/9HzOvwdlGn0x+s2fa68fX6nxW4JI2GrRMHh9XKlO9ooc7JQSQaSIETj3rAXQ89l3y9ThnnRItmrmGmDCa7wVjVLffvUeldEd77fq0t60YXMd2kEq8zHzCWL7FwfLsm5cOHdu6YRsSZ8aiemKUp0Ln6Fo7qo9A+8IpAy8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Q9ej5+fF; 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="Q9ej5+fF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 080511F0089B; Wed, 20 May 2026 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779302998; bh=fJlundH3mC+rSYNjlNxiCzbQLfr+Nqwx+hUjeanTfKM=; h=Date:From:To:Cc:Subject:References; b=Q9ej5+fFKg0bmc1FbiSdJZ/crEGdN1RRMA8AYrTPG3Huvh4LuoJCMHFL5sp+lt3s0 6GboJqlnWNDCNwTOp5gRcDIJz4uswPOsoihSsx324QBQSLcihqG57g/mVA6RRaW+AT 49HLQSgufvBABLQeMKQByAL/c+QQbFbqraL4+9t4Dt5JbSRGrsgtmDGbPvTxQyfy8G c/T549OCrJUi1vaWLZ9P77SRDwgsPjCdDancBS5lAHSG2itNSUFsZ3VyFIEOa2A2mI 1GEx9WIPLa3cwoolCazJPs/T6PSTnShs3xWHHfBSwynNQaNJcmJh0S9AprGmxmN+pS mE9yBHrctoa8Q== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wPlzl-00000004qRp-2Ol6; Wed, 20 May 2026 14:50:17 -0400 Message-ID: <20260520185017.411525220@kernel.org> User-Agent: quilt/0.69 Date: Wed, 20 May 2026 14:49:41 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Catalin Marinas , Will Deacon , Ian Rogers Subject: [PATCH v20 03/10] ring-buffer: Add persistent ring buffer invalid-page inject test References: <20260520184938.749337513@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) 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 dca27ed6a3a1..ce645ca8425d 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 @@ -2094,6 +2098,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: @@ -2574,12 +2593,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 Sun May 24 22:35:50 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 AEA08407CC2; Wed, 20 May 2026 18:49:59 +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=1779303003; cv=none; b=ikXzCI04cAdqe2/iDDIcl2fHAQ7eyLYdINCM1oY0e0rH1YvtW4AX84Wyj4mIzV7u9OKejOdW8EsWoEt3ElYA7Nhj8+RWW/2MGDwZyDo9VzzhkDo+OTIL2ZT3WdaIspi//+ZF4MAUhwAxE33P8Vri+QJj38UeV2J8U6Uk9F1ychY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779303003; c=relaxed/simple; bh=z5SVxvOPWouWAEsykNXiPrhwQD4I2e6zBCMpbO6NQ9A=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=tcDxdO4J8mUX1sauIcaTRkh9vFpXUiUlmkaVJoC2z253LtoKzNcm6gOA4jgYmfGHcHyyUWhjzLVue6u4wXJeNpOSMJmDUUEdhu5VWrqozu/0Zdu5TWDMWW6L8Gf9r21qdVJIizIPmfbBiiuf0B/msqffWk+ZDrv56wE0fW371lo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ozSb5z9q; 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="ozSb5z9q" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1BF1C1F00896; Wed, 20 May 2026 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779302998; bh=+qxY6XO6xH+KHvQWKy6geEKa64zKIpoMCS+55NWFVSc=; h=Date:From:To:Cc:Subject:References; b=ozSb5z9q16eUCBHQB6MbRFTNnaxfl/aNu8zF1u4eFQD0k0p/rz3LQnVg2ezUINV08 Se0JfWZd/eXjEbvPKD4B2u0sZCGN6M/kyhQZneP4uYyRPOdkKj14oKp+DuZiXhaKKZ SXfXtrwkPBAYHnGAMEmFH/CkwVcrAPCyX7B90/XoGH6MSS3+tRA9QtV5F9FNZLj6F7 eX/Ywb5DTfnQVpHBBaEm2LrAdpWNPbZvOZ+kWBV7E71oCBipETqV9ITVoOQPW2KJon rxOJZTSwBBmAM1mnon9Z1DBzXWAjuA2eWI985d/RltgDIMOjK3vCUduUwSLPRnpZJq izxLZllN+jNDA== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wPlzl-00000004qSK-32du; Wed, 20 May 2026 14:50:17 -0400 Message-ID: <20260520185017.589985000@kernel.org> User-Agent: quilt/0.69 Date: Wed, 20 May 2026 14:49:42 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Catalin Marinas , Will Deacon , Ian Rogers Subject: [PATCH v20 04/10] ring-buffer: Show commit numbers in buffer_meta file References: <20260520184938.749337513@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) 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 ce645ca8425d..695398d72fbb 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -2224,6 +2224,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", @@ -2236,7 +2237,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 Sun May 24 22:35:50 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 B6B82402453; Wed, 20 May 2026 18:50:01 +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=1779303007; cv=none; b=pGA3m1W6EL2eExfOoCrVQRw0G58saO3p2grlBaTDkeiPUfPxafu95wS7EEsho9eGKK6Am9zL7M+9kocRW/6/G7Daop1vZO1CLzi4WMdLWVCA685XKW53fOPmUX8fYkhJvurBK/nbb2L9d3gOxYu1k12xDO1FDcD8Q+NTM3MsdPg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779303007; c=relaxed/simple; bh=b11s2AvDB+fIYqA5HC3PF5oz2tqHO/2f5Od9WenRkXg=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=poQUJ2PPjg1LNIwsA1pMiU0geuQ9jRrYfDMqZ8MNIYCey2br8nD/L7vlBgezSD2erwvEz8Pqb8IaQI8RBYGYxB4FQJIkMPgbcu49tuN/Nk+GXyc5hejIjxtc0Bfpz0cymtsIYJG3yvVa6XYu6MuZS2NGj8Kv0yNhQQKSXzfqBng= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UlsugH9o; 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="UlsugH9o" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4BE771F00897; Wed, 20 May 2026 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779302998; bh=Y9lpcbBcztVGamz9VXZGLkQV5l9j+VEU2Ro5/J9ikFk=; h=Date:From:To:Cc:Subject:References; b=UlsugH9odcFQnWDZWBKAoWQbPvKsTWWW4gBhtqWIo5GSHoIHwna8717H498IeqXRv Q+6agqyja+g0NFc1u9iJWZmdCzHkHVr2ej9gg6jY12Jadwb0VhfyMoNmyfjgUOS9s8 h2HhzmLu2RcziHvlVXVTuyKeckdvf5+WbofhRYzOPf+RB/P0QnP3WZ9uQZRGJUSuvi LJTgDh86UJ0mQbDEG/IBJObxZ22gYtifYKyGS/m48tfa6aMH5syGWu/jJSz2gFtAi+ 292zM6D1u/ewlr7/KdbuqkkmEikiTYG/wyQYR8XBFAUO5j/oJgmU+fz6Fq8R9KsDG7 BivHh+CAEnwmQ== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wPlzl-00000004qSo-3gGb; Wed, 20 May 2026 14:50:17 -0400 Message-ID: <20260520185017.743458353@kernel.org> User-Agent: quilt/0.69 Date: Wed, 20 May 2026 14:49:43 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Catalin Marinas , Will Deacon , Ian Rogers Subject: [PATCH v20 05/10] ring-buffer: Cleanup persistent ring buffer validation References: <20260520184938.749337513@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(). Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 198 ++++++++++++++++++++----------------- 1 file changed, 107 insertions(+), 91 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 695398d72fbb..3f1dd75ba332 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,16 +1930,94 @@ 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 }; int ret; - u64 ts; int i; =20 if (!meta || !meta->head_buffer) @@ -1941,25 +2027,16 @@ 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); goto skip_rewind; } - 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 /* * Try to rewind the head so that we can read the pages which are already @@ -1983,19 +2060,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); @@ -2009,43 +2074,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; } @@ -2057,7 +2086,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)) { @@ -2066,21 +2095,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; } @@ -2091,25 +2107,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 Sun May 24 22:35:50 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 A926A407CE5; Wed, 20 May 2026 18:50:01 +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=1779303005; cv=none; b=rp7eoiUMh4EdCVU27xOzbKSIyAqPY5/wGk5s3EIEHD1F0++LiM+eXlU4t10IXRQgTQXp5fXorozcMJvlTjetkdqDfgbyo0ap6LAfHvSED/DYk83E0TGrDCkWHBsEkJ+kuNqbg0Z9rMU2FQnyOar5GQBJyHSFwj6UyVLTwt11sXw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779303005; c=relaxed/simple; bh=237y143rt9ohSS5C+B6Dsa69odeWboQixAM0TEVE7PE=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=PYv4gwWaHKH3Ef6kxwuhGXfU834BgT42Nymn6LCoMx4lZJEidmrlfl/noO/x5q4K3fJqITULcCL2g6XWMk4H1yQouPpCydhtoq6ZHhcyTVmXXi8SmZ8o0hujiYUproaS3hJpaUiWfmxnlJ1MzHmRIzxmXZDJp6oPkgJ/5AxD6Qo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iM/RjzQ8; 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="iM/RjzQ8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 65A7B1F00898; Wed, 20 May 2026 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779302998; bh=8Yjvq5TvG9GBl9+NXOWM3pKDy3mAu51MshgIlAiL+5o=; h=Date:From:To:Cc:Subject:References; b=iM/RjzQ8CQYv7eTLlyaZdl5IJgSIZieM21CCFb2HqREiSJEFPGnk3Dj6jUCnj6akV X5nLBM8CYDGo3ZdEe8TAUwrYLNoujHwXOdU5NUiNEeHofgMCRyouZBz9h8pTwaMZj9 YCfmtwIkEkc+QFPNlPW5sesOlG0v1gbHVkmhmvVRbs20rXR7yo1xLNOJVATP1/wS48 abEETov+zT/Fn8UpN7tou1wd4R82FamrelGSIa2m4t9UMvLpnnMPDagUuW+YttHQO4 fpCP/UhLc1VT36mNvDQDb5tQrZcNjc0qWZI43BvNAHLdMCAsjgdtAzN6QIx5xXqA95 +2wDXPv+AByKg== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wPlzm-00000004qTJ-08kx; Wed, 20 May 2026 14:50:18 -0400 Message-ID: <20260520185017.895814309@kernel.org> User-Agent: quilt/0.69 Date: Wed, 20 May 2026 14:49:44 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Catalin Marinas , Will Deacon , Ian Rogers Subject: [PATCH v20 06/10] ring-buffer: Cleanup buffer_data_page related code References: <20260520184938.749337513@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. 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 3f1dd75ba332..c6c2f92bfc24 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 @@ -2138,12 +2147,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 @@ -2203,7 +2212,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; } } @@ -2255,7 +2264,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; } @@ -2646,7 +2655,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 /* @@ -2658,7 +2667,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 @@ -4187,8 +4196,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 @@ -4560,7 +4568,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) { @@ -4568,12 +4576,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 @@ -4623,7 +4631,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)) \ @@ -4639,16 +4647,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 */ @@ -4659,7 +4667,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 /* @@ -4668,7 +4676,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", @@ -6456,7 +6464,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 @@ -6941,7 +6949,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) { @@ -6966,8 +6974,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]) @@ -6987,15 +6995,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); @@ -7040,7 +7048,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; @@ -7066,8 +7074,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); @@ -7133,7 +7141,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 @@ -7149,9 +7157,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; @@ -7161,13 +7169,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, @@ -7175,12 +7183,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 */ @@ -7189,19 +7197,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; } @@ -7832,7 +7840,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, @@ -7840,18 +7848,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 Sun May 24 22:35:50 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 AFB153FCB0C; Wed, 20 May 2026 18:50:02 +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=1779303005; cv=none; b=eNyDUXEV85AACMNEquMUrxBdzyqrDihgWPHBBM1b5ShOBhlUoMzN93d4UKY7QTer9egX9dc7RPn9+BIGj6g+KBQuehvKjig0oFct6i9DM4DNAyuytrTQ2I1fMiiViMLLOv9GK0RFGOJuwNZpDx26GnXdqcEMU7SLT/ZuTNpjjZQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779303005; c=relaxed/simple; bh=7cStp9iAFCfzNIMOS1aeqeiXWQXiHMpbhyTbXVbKyF4=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=lyAFGda58s06QHlvC7mUyspRGTimsCJh9n7NSwFs/RC17iqa2DD7xWaiu9Vv+dWIMGcFggQFp5USpdaUkMsckVusmR+aosGbuhUngkg1tm7tvU7SmBf79V1PUFPAA5mnQ3Vo7WPJIz/49gHBarem+J9VX/MA4EwRy8saqtJHs38= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=U+N5UzLG; 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="U+N5UzLG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9EB3A1F00893; Wed, 20 May 2026 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779302998; bh=U/nH3wN6/B7CzarRELedI5Kh63j9KxKoMaDk29Z7PXA=; h=Date:From:To:Cc:Subject:References; b=U+N5UzLGp+lpgwVNcOqmB0liFqRHLkFo0rar4H1Y4ElTReCJVenHhT2gCGv7Da3jv h6wZfRwDASeikjoexq7/P7/W3gBEKMdhI3uEl8/RGq0loVsghtedXgIXw+i6GCXdfM 2Po7m5vRbXYi108DP/Pt2iHOSAlwTmW16pp+3l5cO2kgAwQqw4TtZ8XpqAfAe19k/9 RDkNC7ybuFMSFN+OnyU591GDChe+3XfggWM1SzZmRZWWoO/iJaVoP5CImDaqC7J3kJ QcazbGVg6x5d+sorrgu8AYCJVH+Gs9qXesogTC9gyqtjUls7gvJDcKefzSUpwj7LQP jCdL1iiCEE0HA== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wPlzm-00000004qTo-0jiZ; Wed, 20 May 2026 14:50:18 -0400 Message-ID: <20260520185018.051228084@kernel.org> User-Agent: quilt/0.69 Date: Wed, 20 May 2026 14:49:45 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Catalin Marinas , Will Deacon , Ian Rogers Subject: [PATCH v20 07/10] ring-buffer: Skip invalid sub-buffers for iterator References: <20260520184938.749337513@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 On bootup if the persistent ring buffer finds an invalid sub-buffer, it only invalidates the invalid sub-buffer and continues. Several sub-buffers may be invalid and this can cause the iterator to loop more than 3 times looking for a new event. If that happens, then it returns NULL. Having a NULL return early can confuse the iterator looking for the next event, and may show events out of order. Have the same logic for the consuming read for the iterator that will allow the loop to find the next event to happen the number of sub-buffers and not just 3. Fixes: **TBD** ring-buffer: Skip invalid sub-buffers when validating persis= tent ring buffer Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index c6c2f92bfc24..bda53a2d2159 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -6103,12 +6103,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 @@ -6131,7 +6133,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 Sun May 24 22:35:50 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 B70F4405C4C; Wed, 20 May 2026 18:50:02 +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=1779303006; cv=none; b=Sd7uApHdyseKLZsRVWTqcn9Clgjrt8oBnMVfFI8YsyL6P2VCV9nkXz3yw3Ux93FpiICt5Ufsp5eyKNe7wFNSm5BBg82amtSQfPcNA4soTJFaN8RtbFaZwaDkwWKEK6kl4qRGGADByVEi2hIFv4EXPzPWrmOjYSg8tSnkRK9qANw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779303006; c=relaxed/simple; bh=orwZGuCKw0NsE3QkTxl6aFwhdSbPRfB9i4ivuNAhiNk=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=sz3pOJgeCV8Qj/kI5yw3SkAUiKX/Bown1ujPx70ogVDmrKizsMAqp3hXZrTahUJmeGkmlMXbpkZ1ilxkSxjBvv7HWRf/fPs+8WlPRxcoCe1YdnfdJr5J5TXUlBWRsS7ljMSNVwjWqsE6l4OCa5Nf7U5lTVVL2iM8HwN7AhbLcPM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FHfe4zHI; 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="FHfe4zHI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B5DCF1F00894; Wed, 20 May 2026 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779302998; bh=aj+Fvwl35GqnHrspv/MiQnGTGssIabZz3jXzeH8ZwbA=; h=Date:From:To:Cc:Subject:References; b=FHfe4zHIOs+543bn85sA5+iUkZ32595ia2NQQf70mHTCAPok8+5Eb9ShJWgjV43+U S266ltOEshcWLeva3fT8oPTdqC980XaiL0jJUKHwxrbGFX1gnEauL+q2iep3v24rXE qhZ5YRHmzpkAVgW6I6vUkfVJna9FI5UjkjZEAiZ9lIwGA2pj3/QrtxGOsyXhrwNqRt r1WSM00jZbIRFJYTqyIfeec5Xlj+xTZTI/BGXJKi8ltshf7PWOnN69Sjkx0cPnRifJ J1PAx2Bmodsxv5H/bA1qJnMU73th/HzTzNpdhzI2XtkWe5cYVTakrqVrHfve6YMsL7 j1JLjAlDhctTQ== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wPlzm-00000004qUI-1Jth; Wed, 20 May 2026 14:50:18 -0400 Message-ID: <20260520185018.193087991@kernel.org> User-Agent: quilt/0.69 Date: Wed, 20 May 2026 14:49:46 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Catalin Marinas , Will Deacon , Ian Rogers Subject: [PATCH v20 08/10] ring-buffer: Have dropped subbuffers be persistent across reboots References: <20260520184938.749337513@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. Signed-off-by: Steven Rostedt Reviewed-by: Masami Hiramatsu (Google) --- 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 bda53a2d2159..ae5c645b59c9 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 { @@ -3444,7 +3444,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 */ @@ -3473,7 +3473,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; @@ -5643,7 +5643,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 @@ -5836,6 +5836,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 Sun May 24 22:35:50 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 2A1BE408029; Wed, 20 May 2026 18:50:05 +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=1779303010; cv=none; b=asSWNLcvno7ND8ZXA0aQIDXB20Z4VqpUHp+1tuMoctq0o1TIlzUj1yVg08PbZtnVzpZ+zOLibKoXA68YT5sXg2qZ2MBheQU7I4ns2hSGu7cDovdd5vJbTmQ7PkmJscxQiZjRr7FTSktw/qDlZ4X6vB5GVlf7JjiQE3ki8Pe5mMM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779303010; c=relaxed/simple; bh=4LM7UGpkPPAdz6wFC2u10s6cEMpiVQpG/yXlU12QIHI=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=culWmPvp/TxC6/gkI8vkqqU7GjScwKlrTfl4ULCve6Z3+YpZZujBYMXMGGvLv8dHO7Ea4ylzzUMiNLrp5dIXr4iyOXUpuIhbvskNNV1tBBM4F2bucfqroAUT2Qn/iZc91IM7RwB5hk5Zu0dtseCJSzeDJ/4x7iUiTCRBFR8r55k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=b6tz7FKf; 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="b6tz7FKf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D73531F0089D; Wed, 20 May 2026 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779302998; bh=m8JZiNzYpcke5wsPufmn0LZJyXNKSLN47iJA5IjJPlI=; h=Date:From:To:Cc:Subject:References; b=b6tz7FKfpQ6eIeRfi2LmNsw3fbufCTqu9CYOaxONdYd8oieH63AN3rqY8rOS7h+H2 lsZQo7WeftJp1tKUEESdpiIZoG7Og67Dj8d8U8aXiDVDm3F3fIgn4zKszD/jReSAqc evCXWn8ssbfMnmtCuddV68d4x7BKdSd6FDbkx8qb8ni4Ziwa0fPlhqM1BWVAggYY5w yJzQBKSIik4ceCtDyNHbwoDRdwRi9S0crRTyungwtr2zSJVqWth7YvEBE4NMcNmSkK C8/iLAGjsfbu+juzDX+vQ9QQB/oJ+AGoXoqoazXxBDKoY31F8gGolKHB4Xz9rva9UN M+UOiwnrq9jJA== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wPlzm-00000004qUn-1tUc; Wed, 20 May 2026 14:50:18 -0400 Message-ID: <20260520185018.332045380@kernel.org> User-Agent: quilt/0.69 Date: Wed, 20 May 2026 14:49:47 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Catalin Marinas , Will Deacon , Ian Rogers Subject: [PATCH v20 09/10] ring-buffer: Show persistent buffer dropped events in trace file References: <20260520184938.749337513@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 Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index ae5c645b59c9..9cdbee171cdc 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -3518,6 +3518,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; @@ -5579,6 +5582,7 @@ static void rb_iter_reset(struct ring_buffer_iter *it= er) iter->head_page =3D cpu_buffer->reader_page; iter->head =3D cpu_buffer->reader_page->read; iter->next_event =3D iter->head; + iter->missed_events =3D 0; =20 iter->cache_reader_page =3D iter->head_page; iter->cache_read =3D cpu_buffer->read; @@ -7053,7 +7057,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; @@ -7179,6 +7183,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, @@ -7196,10 +7202,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 Sun May 24 22:35:50 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 9AEC4407CD8; Wed, 20 May 2026 18:50:06 +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=1779303010; cv=none; b=u7c0t3fDo79uqJ+PpaquO6HDhRTTNWubkVWH2rZJucYWAIf80b4zF6zVa4wtBq/GMtDF9hG5TWBKW+yPqjREU4UWGGBhKXx7UuvwczJdjYrb/dXOauSRTsdRjpA7/k9KXF9Bv2hegLanIg41Tx25LwOzPlWmltAW5JiAsXBLPJY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779303010; c=relaxed/simple; bh=+QjRjOIYSxwOhZM9tWkY+qyaunWJj+bbW8RN3AD9sYY=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=nThzYIDVxEioaQZotUYyDks6P4o3ENPXHrX1uvSTVTcbGzdSyLTIeKd+saJavr5PxmAOzIjAlz2077sqDqyUaTUbfPI6caYxnUKVx7Mb1JCqaSM9l4T5mMeaiAOb9PF414mSdzlNrwsxCkbadwwvfQnpyI0w3Qboc5P6lXkhlmA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZUnKIgwb; 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="ZUnKIgwb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 05B461F0089F; Wed, 20 May 2026 18:49:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779302999; bh=jygDceG30LUq+hbqus2XeFHvbPtOFQakWAqYsRXmO/k=; h=Date:From:To:Cc:Subject:References; b=ZUnKIgwbzwLbDGQp78LIep0m697U9ZzxtGobybxEy9rTKWIadU8MllJy0Mp3Ylke9 mRphhWEzgjS0io6XVokeEZHWKoDTqacv+bMiEQl7cHZ/sxhEG2SJMBa5xg7IMEj42v LERXYwOKi/wG+HRCSfy1k74hmiEH2FxBHic5dKrFg6LQQ//oNz+JOns8GVknVqui9U sPZaHYNI4syBr2Ed+6mpaURkPIQDJS55DMBVYBJo1b67KdlzlOSfnsH+RkX9KIqoyZ A5C7fiLsGK6yLriDeeEbp792j22VEzFqzjtw80PM94mAiywbRE+VAgxGq3hUUPrwxU kbNnnq1c6C8mw== Received: from rostedt by gandalf with local (Exim 4.99.2) (envelope-from ) id 1wPlzm-00000004qVJ-2UWl; Wed, 20 May 2026 14:50:18 -0400 Message-ID: <20260520185018.470465795@kernel.org> User-Agent: quilt/0.69 Date: Wed, 20 May 2026 14:49:48 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mathieu Desnoyers , Catalin Marinas , Will Deacon , Ian Rogers Subject: [PATCH v20 10/10] ring-buffer: Show persistent buffer dropped events in trace_pipe file References: <20260520184938.749337513@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) Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 57 +++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 9cdbee171cdc..f42d2176b92c 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -5794,6 +5794,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 @@ -5894,6 +5895,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 @@ -5958,6 +5962,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; } @@ -7059,6 +7065,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; @@ -7094,7 +7101,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; @@ -7108,13 +7116,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 @@ -7123,19 +7132,23 @@ 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) { + printk("MISSED\n"); + flags =3D RB_MISSED_EVENTS; } + /* save the current timestamp, since the user will need it */ save_timestamp =3D cpu_buffer->read_stamp; =20 @@ -7147,25 +7160,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 */ @@ -7197,7 +7210,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 */ @@ -7207,11 +7220,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); } @@ -7219,8 +7232,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