All of lore.kernel.org
 help / color / mirror / Atom feed
* EROFS: decompressed page cache returns valid file content from the wrong offset under sustained reclaim
@ 2026-08-28 12:01 Walther, Jens-Uwe
  2026-08-28 13:29 ` Gao Xiang
  0 siblings, 1 reply; 2+ messages in thread
From: Walther, Jens-Uwe @ 2026-08-28 12:01 UTC (permalink / raw)
  To: linux-erofs@lists.ozlabs.org
  Cc: xiang@kernel.org, chao@kernel.org, Walther, Jens-Uwe


[-- Attachment #1.1: Type: text/plain, Size: 5535 bytes --]

Hey folks,

We have two independent occurrences of silent data corruption on EROFS roots, on
two machines run by two different operators, and we cannot reproduce it locally.
The corruption is not random: a contiguous region of a read-only file comes back
containing that same file's own bytes taken from a different offset. Details in
case the pattern is recognisable.

Environment
  EROFS root image built with mkfs.erofs --all-root -z lz4hc,12 -C 262144
  mounted ro, cache_strategy=readaround, dm-verity below with
  restart_on_corruption
  kernels 6.18.38 (case A) and 6.12.95 (case B), x86_64
  8 GiB and 16 GiB machines; swap is zram only (1 GiB, lz4), no disk swap
  failures appeared after 9d5h and 5d16h uptime

Symptom
  A 3,627,816-byte shared library reads back with one contiguous region
  replaced. It has a self-integrity check, which is how it was noticed.
  Everything outside the region is byte-identical to a known-good copy, and the
  region reconstructs 100% from that copy as exactly two contiguous runs taken
  from elsewhere in the same file:

  case A   region 0x239000-0x23afff (8,192 B)
           run 1  at 0x239000  3,694 B  from +16,786
           run 2  at 0x239e6e  4,498 B  from +8,393

  case B   region 0x271d0c-0x273fff (8,948 B)
           run 1  at 0x271d0c  7,436 B  from +17,896
           run 2  at 0x273a18  1,512 B  from +8,948

  In both cases the first shift is exactly twice the second. Neither is a
  multiple of PAGE_SIZE (8,393 = 2*4096 + 201), so this is not a page- or
  folio-level mixup.

Location
  dump.erofs -e places both corrupted ranges and both of their source ranges
  inside a single extent: logical 2,177,202..2,779,162 (601,960 B) decompressed
  from one 262,144-byte pcluster. Nothing sits near an extent boundary. The
  error is therefore produced within one decompression, not by selecting the
  wrong pcluster.

Ruled out
  on-disk corruption - dm-verity reported no error across 15.92 days spanning
    the fault, with restart_on_corruption armed
  a stale mapping - a read() of the file and the process mapping return the same
    wrong bytes, so the page cache itself holds them
  hardware - two operators, different CPU vendors, and the result is structured
  folio migration as the copying agent - migration moves whole pages, the shifts
    are not page-aligned

Conditions
  Both machines were under sustained page-cache reclaim. Case A: 956M
  pgsteal_kswapd and 559M workingset_refault_file over 17.7 days. Case B: 71M
  and 16M over 7.74 days. A comparable machine on the same image with no reclaim
  shows pgscan_kswapd and pgsteal_kswapd exactly 0. Since the only swap is zram,
  clean page cache - i.e. the EROFS image - is the only memory the kernel can
  genuinely free, so all pressure lands on evicting and re-reading these pages.

Geometry in this configuration
  bpftrace on z_erofs_lz4_decompress, same image and mount options, while the
  library was evicted and re-read about a million times:
    rq->inplace_io was 0 for all 963,196 calls
    74.7% had rq->partial_decoding = 1
    inplace_io=1 occurs only when the compressed pages are absent from the
      managed cache; with a warm managed cache we never observed it
  So the failing path is very likely a managed-cache decode, mostly partial.

Not reproduced
  ~33M real decompressions of the same file, same image and mount options, under
  heavier reclaim than either failing machine (66x the pgsteal_kswapd rate, 1.4x
  the pgmigrate_success rate), produced no mismatch. Also tried: 92M single-page
  faults against a purpose-built image with an identical extent map, forced
  compaction, and cache_strategy=disabled. No mismatch in any configuration.

Questions
  1. Is a byte-granular displacement of this shape known in the partial decode
     path with big pclusters - output written at rq->pageofs_out into a
     partially populated rq->out[] set?
  2. Does the first shift being exactly twice the second suggest particular
     index or length arithmetic worth looking at?
  3. Could z_erofs_lz4_prepare_dstpages() or the fillgaps handling place output
     at the wrong offset when only a subset of out[] is requested?
  4. If field data would help, what would you want captured? We have a detector
     running that hashes the file periodically and, when it fires, preserves the
     machine along with the corrupted copy, /proc/vmstat and PSI. We can also
     run additional tracing or a debug patch on affected fleets.


Thank you in advance.

Best regards
Jens-Uwe Walther
Senior Specialist TAM Containers
AWS Enterprise Support
[CKA badge]<https://www.credly.com/badges/b4f55949-4357-4062-93a9-6d0f0f5f3833/linked_in>[CKAD badge]<https://www.credly.com/badges/85b75f03-91d4-4887-8150-cfb9ea39d272> [CKS: Certified Kubernetes Security Specialist] <https://www.credly.com/badges/c26e3b3c-cfc7-46d7-8b7b-7a7a59045c60/>
e: waltju@amazon.com<mailto:waltju@amazon.com> m: +49 152 38870547
[cid:image004.png@01D9D4D4.4DF69060]<http://www.aws.amazon.com/>



Amazon Web Services EMEA SARL
38 avenue John F. Kennedy, L-1855 Luxembourg
Sitz der Gesellschaft: L-1855 Luxemburg
eingetragen im Luxemburgischen Handelsregister unter R.C.S. B186284

Amazon Web Services EMEA SARL, Niederlassung Deutschland
Anni-Albers-Str. 21, D-80807 Muenchen
Sitz der Zweigniederlassung: Muenchen
eingetragen im Handelsregister des Amtsgerichts Muenchen unter HRB 242240
USt-ID DE317013094

[-- Attachment #1.2: Type: text/html, Size: 9952 bytes --]

[-- Attachment #2: image001.png --]
[-- Type: image/png, Size: 5216 bytes --]

[-- Attachment #3: image002.png --]
[-- Type: image/png, Size: 5563 bytes --]

[-- Attachment #4: image003.png --]
[-- Type: image/png, Size: 7022 bytes --]

[-- Attachment #5: image004.png --]
[-- Type: image/png, Size: 3073 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-08-28 13:29 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-28 12:01 EROFS: decompressed page cache returns valid file content from the wrong offset under sustained reclaim Walther, Jens-Uwe
2026-08-28 13:29 ` Gao Xiang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.