From: "Masami Hiramatsu (Google)" <[email protected]> [ Upstream commit eb3bd277b37cd435d26a44a40d8f7c87ff16feb6 ]
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/[email protected]/ Link: https://patch.msgid.link/[email protected] Signed-off-by: Masami Hiramatsu (Google) <[email protected]> [SDR: Fixed max_loops in rb_iter_peek() as well ] Signed-off-by: Steven Rostedt <[email protected]> Signed-off-by: Sasha Levin <[email protected]> --- LLM Generated explanations, may be completely bogus: # Stable Backport Analysis: ring-buffer persistent validation fix **Local tree:** `v6.18.44` (Linux 6.18.44) --- ## PHASE 1: COMMIT MESSAGE FORENSICS ### Step 1.1: Subject line **Record:** `[ring-buffer]` `[skip]` — Skip invalid sub-buffers when validating persistent ring buffer during boot recovery. ### Step 1.2: Tags **Record:** - `Link:` https://lore.kernel.org/all/[email protected]/ - `Link:` https://patch.msgid.link/[email protected] - `Signed-off-by:` Masami Hiramatsu (Google) <[email protected]> - `Signed-off-by:` Steven Rostedt <[email protected]> (with note: "Fixed max_loops in rb_iter_peek() as well") - No `Fixes:`, `Reported-by:`, `Cc: stable`, `Tested-by:`, or `Reviewed- by:` tags - Notable: subsystem maintainer (Rostedt) amended and signed off ### Step 1.3: Body analysis **Record:** - **Bug:** After reboot, persistent ring buffer validation treats any single corrupted sub-buffer as fatal and discards the entire buffer. - **Symptom:** Valid trace events from previous boot (especially post- crash traces) are lost when only some sub-buffers are bad. - **Root cause:** Cache may not fully sync across reboot; partial corruption is realistic. Current code in `rb_cpu_meta_valid()` and `rb_meta_validate_events()` rejects the whole buffer on first bad sub- buffer. - **Version info:** None in message. ### Step 1.4: Hidden bug fix detection **Record:** Yes — described as validation improvement, but it fixes real data-loss and reader-loop failures (`RB_WARN_ON` when >3 empty pages after recovery). --- ## PHASE 2: DIFF ANALYSIS ### Step 2.1: Inventory **Record:** - **File:** `kernel/trace/ring_buffer.c` only (~73 insertions, ~47 deletions) - **Functions modified:** `rb_cpu_meta_valid()`, `rb_validate_buffer()`, `rb_meta_validate_events()`, `rb_get_reader_page()`, `rb_iter_peek()`; relocates `rb_page_size()` earlier - **Scope:** Single-file surgical fix in persistent ring-buffer recovery path ### Step 2.2: Code flow changes **Record:** | Hunk | Before → After | |------|----------------| | `rb_cpu_meta_valid()` | Rejects entire meta if any subbuf `commit > PAGE_SIZE` → only validates meta array structure; adds `subbuf_size != PAGE_SIZE` check | | `rb_validate_buffer()` | Uses raw `commit` → masks `RB_MISSED_MASK`, bounds-checks against `meta->subbuf_size` | | `rb_meta_validate_events()` | `goto invalid` on first bad page → clear only that sub-buffer, continue; track `discarded` count | | `rb_get_reader_page()` / `rb_iter_peek()` | `max_loops = 3` hardcoded → `max_loops = nr_pages` for persistent buffers | | `rb_page_size()` | Moved earlier so validation code can use masked commit size | ### Step 2.3: Bug mechanism **Record:** - **Category:** Logic/correctness fix + secondary loop-limit bug - **Mechanism:** Overly aggressive all-or-nothing validation discards recoverable trace data; after per-page discard, multiple consecutive empty pages exceed the hardcoded loop limit of 3, triggering `RB_WARN_ON` and breaking trace reads ### Step 2.4: Fix quality **Record:** Fix is minimal, obviously correct, and low regression risk. Invalidates only proven-bad pages; still falls back to full discard on structural failures (e.g., commit page not found). Rostedt's `max_loops` addition addresses a real follow-on failure. --- ## PHASE 3: GIT HISTORY INVESTIGATION ### Step 3.1: Blame **Record:** - Aggressive per-subbuf commit check introduced in `c76883f18e59b7` ("ring-buffer: Add test if range of boot buffer is valid", 2024-06-14) - `goto invalid` on bad buffer page in `rb_meta_validate_events()` dates to `5f3b6e839f3ceb` (2024-06-12) - Persistent ring buffer metadata added in `4009cc31e7813` (2025-03-05) — present in this tree ### Step 3.2: Fixes: tag **Record:** N/A — no `Fixes:` tag in commit message. ### Step 3.3: Related file history **Record:** Multiple persistent ring-buffer fixes already in this 6.18.y tree: - `ca296d32ece38` — rewind persistent ring buffer on reboot - `b6925774dd15d` — fix per-subbuf entries - `2bc60c175568e` — flush/stop on panic - This fix (`009124508d96f` / upstream `eb3bd277b37cd`) is **not** yet in HEAD ### Step 3.4: Author context **Record:** Masami Hiramatsu is the primary persistent ring-buffer author; Steven Rostedt is trace/ring-buffer maintainer. Both have multiple related commits in this file. ### Step 3.5: Dependencies **Record:** Standalone for the validation path. Companion commit `8a4563881fa3d` ("Skip invalid sub-buffers when rewinding persistent ring buffer", patch 2/9 in v21 series) addresses a related rewind path but is separate. This commit includes its own `max_loops` fixes and applies independently. --- ## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH ### Step 4.1: Original discussion **Record:** - `b4 dig -c 009124508d96f` matched: **[PATCH v21 1/9]** at https://patch.msgid.link/[email protected] - Lore URLs blocked by bot protection (Anubis) — could not read thread content directly ### Step 4.2: Reviewers **Record:** `b4 dig -w` CC list includes Steven Rostedt, linux-trace- kernel, Mathieu Desnoyers, Mark Rutland, Andrew Morton — appropriate maintainer/reviewer coverage. ### Step 4.3: Bug report **Record:** No external bug report or syzbot link. Bug rationale is in commit message (cache sync failure across reboot). ### Step 4.4: Series context **Record:** Part of v21 9-patch series; this is patch 1/9. Companion rewinding fix exists separately. Validation fix is self-contained. ### Step 4.5: Stable list history **Record:** UNVERIFIED — could not search lore stable list due to bot protection. However, multiple prior persistent ring-buffer fixes are already present in this 6.18.y tree. --- ## PHASE 5: CODE SEMANTIC ANALYSIS ### Step 5.1: Key functions **Record:** `rb_cpu_meta_valid()`, `rb_validate_buffer()`, `rb_meta_validate_events()`, `rb_get_reader_page()`, `rb_iter_peek()` ### Step 5.2: Callers **Record:** - `rb_meta_validate_events()` called from ring buffer CPU init at line 2399 during `range_addr_start` (persistent/reserved-memory) buffer setup - `rb_get_reader_page()` → `rb_buffer_peek()` → `ring_buffer_consume()` / trace reading paths - `rb_iter_peek()` → `ring_buffer_iter_peek()` — non-consuming trace reads ### Step 5.3: Callees **Record:** `rb_read_data_buffer()`, `local_read/set`, `rb_page_commit()`, `RB_WARN_ON()`, page list operations ### Step 5.4: Reachability **Record:** Triggered at boot when persistent tracing instance is configured via reserved memory / boot parameters (`trace.c` maps boot instances via `reserve_mem_find_by_name()`). Affects crash/post-mortem tracing users, not all kernels — but reachable on every boot for configured systems. ### Step 5.5: Similar patterns **Record:** Same "skip invalid sub-buffer instead of aborting" pattern exists in companion rewinding patch (not yet in tree). Consistent with incremental recovery approach used elsewhere in persistent ring-buffer series. --- ## PHASE 6: CROSS-REFERENCE AGAINST LOCAL TREE (v6.18.44) ### Step 6.1: Buggy code present? **Record:** **YES.** Current tree still has: - `rb_cpu_meta_valid()` commit check at lines 1795–1797 that rejects entire meta - `rb_meta_validate_events()` `goto invalid` on first bad page at lines 2012–2016 - `rb_get_reader_page()` / `rb_iter_peek()` hardcoded `nr_loops > 3` ### Step 6.2: Backport complications **Record:** Expected **clean apply**. `rb_page_size()` already exists at line 3247; patch relocates it earlier (trivial). Function names match (`rb_get_reader_page`, not `__rb_get_reader_page`). ### Step 6.3: Related fixes already present? **Record:** Prior persistent ring-buffer fixes are in tree, but **not** this validation-granularity fix or the companion rewinding fix. --- ## PHASE 7: SUBSYSTEM CONTEXT ### Step 7.1: Subsystem criticality **Record:** `kernel/trace/` — IMPORTANT subsystem. Persistent ring buffer is a debugging/crash-analysis feature, not core VFS/net, but critical for post-crash trace retention. ### Step 7.2: Activity **Record:** Actively developed — 10+ persistent ring-buffer commits in recent `ring_buffer.c` history on this branch. --- ## PHASE 8: IMPACT AND RISK ### Step 8.1: Who is affected **Record:** Users with persistent/reserved-memory tracing configured (boot params, DT `reserve_mem`, crash analysis setups). Config-specific, not universal. ### Step 8.2: Trigger conditions **Record:** Reboot with partially unsynchronized persistent ring-buffer memory (unclean shutdown, crash, power loss). Realistic for the feature's intended use case. ### Step 8.3: Failure severity **Record:** - **Without fix:** Total loss of previous-boot trace data when any single sub-buffer is corrupt; `RB_WARN_ON` / failed reads when multiple cleared pages exist after recovery - **Severity:** MEDIUM-HIGH for affected users (defeats purpose of persistent tracing); LOW for systems without persistent tracing ### Step 8.4: Risk-benefit **Record:** - **Benefit:** Recovers partial crash traces; prevents false `RB_WARN_ON` on read path — high value for persistent tracing users - **Risk:** Very low — only clears proven-invalid pages; structural failures still trigger full discard - **Ratio:** Favorable --- ## PHASE 9: FINAL SYNTHESIS ### Step 9.1: Evidence summary **FOR backport:** - Real bug with verified presence in v6.18.44 - Causes loss of recoverable crash-trace data - Secondary `RB_WARN_ON`/read failure after recovery - Small, single-file, maintainer-reviewed fix - Consistent with other persistent ring-buffer fixes already in this stable line - Applies cleanly to this tree **AGAINST backport:** - Niche feature (persistent tracing only) - Not a general security/crash issue for all users - Companion rewinding patch may also be desirable for complete coverage **Unresolved:** Lore thread content and stable-list discussion (bot- blocked). ### Step 9.2: Stable rules checklist 1. Obviously correct and tested? **PASS** — logic is clear; maintainer signed off; no Tested-by but tracing selftest series exists 2. Fixes real bug affecting users? **PASS** — data loss on boot recovery for persistent tracing 3. Important issue? **PASS** — trace data loss + `RB_WARN_ON` on read path for crash-analysis users 4. Small and contained? **PASS** — ~120 lines, one file 5. No new features/APIs? **PASS** 6. Can apply to local tree? **PASS** — code exists, patch should apply cleanly ### Step 9.3: Exception categories **Record:** None (not a quirk/DT/build/docs fix — a correctness bug fix in existing feature). ### Step 9.4: Decision rationale This commit fixes a real correctness bug in the persistent ring buffer recovery path present in Linux 6.18.44. When memory is partially corrupted across reboot (the exact scenario persistent tracing is designed for), the current code throws away **all** trace data because of **one** bad sub-buffer. The fix surgically invalidates only corrupted pages and adjusts reader/iterator loop limits so recovered buffers remain readable. The change is small, reviewed by the trace maintainer, and follows the same pattern as other persistent ring-buffer fixes already accepted into this stable series. **Note:** Consider also backporting the companion patch `ring-buffer: Skip invalid sub-buffers when rewinding persistent ring buffer` for the rewind path, but this validation commit is independently valuable. --- ## Verification - [Phase 1] `git show 009124508d96f`: parsed subject, body, tags; no Fixes/Reported-by/Cc:stable - [Phase 2] `git show 009124508d96f -- kernel/trace/ring_buffer.c`: full diff analyzed; 1 file, 5 functions - [Phase 3] `git describe HEAD`: v6.18.44 - [Phase 3] `git merge-base --is-ancestor 009124508d96f HEAD`: exit 1 — fix NOT in tree - [Phase 3] `git merge-base --is-ancestor 4009cc31e7813 HEAD`: exit 0 — persistent ring buffer feature IS in tree - [Phase 3] `git blame -L 1795,1816,2012,2017 kernel/trace/ring_buffer.c`: buggy code from c76883f18e59b7 / 5f3b6e839f3ceb - [Phase 3] `git log --oneline -20 -- kernel/trace/ring_buffer.c`: multiple prior persistent ring-buffer fixes in tree - [Phase 3] `git merge-base --is-ancestor 8a4563881fa3d HEAD`: exit 1 — companion rewinding fix not in tree - [Phase 4] `b4 dig -c 009124508d96f`: found [PATCH v21 1/9] at patch.msgid.link/[email protected] - [Phase 4] `b4 dig -c 009124508d96f -w`: CC list includes Rostedt, Desnoyers, linux-trace-kernel - [Phase 4] WebFetch lore/patch.msgid.link URLs: BLOCKED by Anubis bot protection - [Phase 5] Read `ring_buffer.c` lines 1754–2057, 2399, 3247, 5421–5765: confirmed buggy code paths and call sites - [Phase 5] Grep `rb_meta_validate_events`, `rb_get_reader_page`, `rb_iter_peek`: traced callers - [Phase 5] Read `trace.c` lines 11137–11165: persistent boot instance via `reserve_mem_find_by_name()` - [Phase 6] Grep `rb_validate_buffer(head_page->page, cpu_buffer->cpu)` without meta param: confirms pre-fix code in tree - [Phase 6] Grep `nr_loops > 3` in reader/iter paths: confirms hardcoded limit in tree - [Phase 8] Failure mode: total trace data discard + RB_WARN_ON on read; severity MEDIUM-HIGH for persistent tracing users **YES****Result:** Backport analysis for `ring-buffer: Skip invalid sub- buffers when validating persistent ring buffer` on **v6.18.44** — **YES**. The fix belongs in this tree: the buggy all-or-nothing validation is still present, persistent ring-buffer support is in-tree, and the patch is a small, maintainer-reviewed correctness fix for crash-trace recovery after reboot. **Worth noting:** It’s patch **1/9** in the v21 series. The companion **rewinding** fix (`Skip invalid sub-buffers when rewinding persistent ring buffer`) isn’t in this tree yet and may be worth evaluating separately for full coverage. 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 fefa16e51e0ef..631d42281f5b3 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -396,6 +396,12 @@ static __always_inline unsigned int rb_page_commit(struct buffer_page *bpage) return local_read(&bpage->page->commit); } +/* 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 */ @@ -1756,7 +1762,6 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu, unsigned long *subbuf_mask) { int subbuf_size = PAGE_SIZE; - struct buffer_data_page *subbuf; unsigned long buffers_start; unsigned long buffers_end; int i; @@ -1764,6 +1769,11 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu, if (!subbuf_mask) return false; + if (meta->subbuf_size != PAGE_SIZE) { + pr_info("Ring buffer boot meta [%d] invalid subbuf_size\n", cpu); + return false; + } + buffers_start = meta->first_buffer; buffers_end = meta->first_buffer + (subbuf_size * meta->nr_subbufs); @@ -1780,11 +1790,12 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu, return false; } - subbuf = rb_subbufs_from_meta(meta); - bitmap_clear(subbuf_mask, 0, meta->nr_subbufs); - /* Is the meta buffers and the subbufs themselves have correct data? */ + /* + * Ensure the meta::buffers array has correct data. The data in each subbufs + * are checked later in rb_meta_validate_events(). + */ for (i = 0; i < meta->nr_subbufs; i++) { if (meta->buffers[i] < 0 || meta->buffers[i] >= meta->nr_subbufs) { @@ -1792,18 +1803,12 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu, return false; } - 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; } set_bit(meta->buffers[i], subbuf_mask); - subbuf = (void *)subbuf + subbuf_size; } return true; @@ -1867,13 +1872,22 @@ static int rb_read_data_buffer(struct buffer_data_page *dpage, int tail, int cpu return events; } -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; - tail = 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 = 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); } @@ -1884,6 +1898,7 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) struct buffer_page *head_page, *orig_head, *orig_reader; unsigned long entry_bytes = 0; unsigned long entries = 0; + int discarded = 0; int ret; u64 ts; int i; @@ -1895,14 +1910,19 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) orig_reader = cpu_buffer->reader_page; /* Do the reader page first */ - ret = rb_validate_buffer(orig_reader->page, cpu_buffer->cpu); + ret = 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 += ret; + entry_bytes += rb_page_size(orig_reader); + local_set(&orig_reader->entries, ret); } - entries += ret; - entry_bytes += local_read(&orig_reader->page->commit); - local_set(&orig_reader->entries, ret); ts = head_page->page->time_stamp; @@ -1930,7 +1950,7 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) break; /* Stop rewind if the page is invalid. */ - ret = rb_validate_buffer(head_page->page, cpu_buffer->cpu); + ret = rb_validate_buffer(head_page->page, cpu_buffer->cpu, meta); if (ret < 0) break; @@ -1939,7 +1959,7 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) if (ret) local_inc(&cpu_buffer->pages_touched); entries += ret; - entry_bytes += rb_page_commit(head_page); + entry_bytes += rb_page_size(head_page); } if (i) pr_info("Ring buffer [%d] rewound %d pages\n", cpu_buffer->cpu, i); @@ -2009,21 +2029,24 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) if (head_page == orig_reader) continue; - ret = rb_validate_buffer(head_page->page, cpu_buffer->cpu); + ret = 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 += ret; - entry_bytes += 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); + entries += ret; + entry_bytes += rb_page_size(head_page); + local_set(&head_page->entries, ret); + } if (head_page == cpu_buffer->commit_page) break; } @@ -2037,7 +2060,10 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) local_set(&cpu_buffer->entries, entries); local_set(&cpu_buffer->entries_bytes, entry_bytes); - 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; invalid: @@ -3243,12 +3269,6 @@ rb_iter_head_event(struct ring_buffer_iter *iter) return NULL; } -/* 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) { @@ -5421,8 +5441,9 @@ rb_update_iter_read_stamp(struct ring_buffer_iter *iter, static struct buffer_page * rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) { - struct buffer_page *reader = NULL; + int max_loops = cpu_buffer->ring_meta ? cpu_buffer->nr_pages : 3; unsigned long bsize = READ_ONCE(cpu_buffer->buffer->subbuf_size); + struct buffer_page *reader = NULL; unsigned long overwrite; unsigned long flags; int nr_loops = 0; @@ -5434,11 +5455,14 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_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 = NULL; goto out; } @@ -5728,12 +5752,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 = 0; + int max_loops; if (ts) *ts = 0; cpu_buffer = iter->cpu_buffer; buffer = cpu_buffer->buffer; + max_loops = cpu_buffer->ring_meta ? cpu_buffer->nr_pages : 3; /* * Check if someone performed a consuming read to the buffer @@ -5756,7 +5782,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; if (rb_per_cpu_empty(cpu_buffer)) -- 2.53.0
