[PATCH 0/2] perf mmap: Fix replayed and skipped records

From: Paul Moses

Date: Tue Oct 20 2026 - 13:39:41 EST


perf_mmap__push() can copy through one producer head but save an earlier
head in prev, causing the next drain to write the same records again.

The race duplicates a small fraction of samples but reproduced in most
runs. Across 20 unpatched runs on two source baselines, each containing
500,000 unique samples:
- Replay occurred in 15 of 20 runs; five had no duplicates.
- Affected runs contained 14–53 duplicate samples each,
representing 0.0028–0.0106% of their 500,000 unique samples.
- The longest replay duplicated a block of 53 consecutive
timestamped records byte-for-byte.
- Overall, 485 duplicate samples were recorded alongside
10 million unique samples (0.00485%).

The patched builds had no duplicates in the corresponding 20 runs.

The second issue is that perf_mmap__read_done() advances the forward
cursor to the producer head even when unread records remain. perf kvm
stat live processes at most 25 records per mmap pass before calling
read_done(), so it can skip the remaining records without a race.

In three runs without patch 2, perf kvm stat live reported 111,894,
6,433, and 6,838 intervals against roughly 200,600 independently
counted KVM exits per run. With patch 2, the reported counts were
within 1–3 intervals of the independent counts. Separate cursor tracing
confirmed that read_done() advanced past unread records without the
fix and preserved the consumed cursor with it.

Paul Moses (2):
perf mmap: Use the head selected by read_init
perf mmap: Preserve the consumed cursor in forward mode

tools/lib/perf/mmap.c | 2 +-
tools/perf/util/mmap.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)

--
2.56.GIT