# Pre9 LZMA cache review resolution

This document records the follow-up to commit `61f4709`, which cached one
decoded LZMA extent per vnode.

## Findings addressed

- The cache is now one entry in `struct erofs_mount`, rather than one entry in
  every `struct erofs_node`. Retained decoded memory is bounded by one extent
  per mounted filesystem, with the number of mounts controlled by mount
  privileges. Keeping many ordinary file descriptors open cannot create more
  cache entries.
- Cache initialization is performed in `erofs_mountfs()` immediately after
  mount allocation. `erofs_sb_free()` destroys it on every mount failure path
  and after successful `vflush()` during unmount. Node reclaim no longer owns
  cache cleanup.
- `EROFS_MAP_META` is an explicit ineligibility condition. Metadata-backed
  tailpacking therefore remains on its existing read path.
- `packed_inode` and `metabox_en` are explicit ineligibility conditions. The
  mount-private backing objects cannot populate or consume the user-data
  cache.
- The cache type and helper names are now `erofs_zextent_cache` and
  `z_erofs_extent_cache_*`, distinguishing decoded extents from Linux's
  managed compressed-page cache names.
- The key retains the existing physical/logical extent fields, device id,
  flags, and algorithm, and adds the stable inode `nid`. The `data` pointer is
  the validity bit, so NID zero is not treated as an empty key.

## Copy bound and concurrency

`z_erofs_read_uio()` limits each output request to `MAXPHYS`. The generic
`z_erofs_read_data()` API can receive a larger request, so cache eligibility
rejects any request whose mapped portion exceeds `MAXPHYS`. Both cache helper
entry points also contain `KASSERT(len <= MAXPHYS)` checks. The largest copy
performed while holding `z_extent_cache_lock` is therefore `MAXPHYS`; the
12 MiB `Z_EROFS_PCLUSTER_MAX_DSIZE` limit remains an on-disk decoded-extent
allocation bound, not a mutex-copy bound.

Allocation, compressed reads, and decompression happen outside the mutex. A
cache hit copies while holding the mutex, and a miss publishes and copies
under the same mutex before the previous allocation is freed. Concurrent
misses may decode duplicate extents and may replace one another, but pointer
access and replacement remain serialized. A refcounted immutable cache entry
was deliberately not introduced in this first stage.

## Resource tradeoff

The per-mount entry is intentionally a small first-stage design. It removes
the unbounded-per-open-vnode retention introduced by `61f4709`, but it can
thrash when many files are read concurrently on one mount. Retention lasts
until unmount, and the retained allocation is capped by the existing EROFS
format constant `Z_EROFS_PCLUSTER_MAX_DSIZE` (12 MiB). A FreeBSD shrinker or
pressure callback is deferred; adding one would require a broader memory
accounting and lifecycle design than this corrective commit.

## Validation scope

This correction is statically validated only. QEMU validation remains
required for complete SHA-256 reads, same-file concurrent reads, close/reopen,
unmount cleanup, metadata tailpacking, and memory-pressure behavior. The
existing Pre9 manual test report predates this correction and must not be
reported as runtime validation of this commit.
