# 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.