Files
erofs-freebsd-out-tree/docs/pre15-stage0/P15-086.md
T
2026-08-18 09:20:44 +02:00

7.8 KiB

P15-086 Stage0 Decision

Status: GO. G04 and G05 authorize B28 partial subextent decoding for LZ4, LZMA, and Deflate. Zstd is not authorized for partial decoding and must use the exact full-decode fallback for ordinary strict subextent reads. Existing partial-reference maps retain their bounded-prefix path. Shifted, interlaced, unknown, and future backends also remain on full fallback unless a new gate authorizes them.

The gate is bound to DUT BASE 6bf5724619be70f805bbe7d1ba77dd70cdced69f, FreeBSD source HEAD 106727738dcfb6c001b46f25363b91cece970085, erofs-utils generations v1.4, v1.7, and v1.8.6 for LZ4, erofs-utils 1.8.6 for the stream codecs, liblz4 1.10.0, liblzma 5.8.1, zlib 1.3.1, and libzstd 1.5.7.

Authoritative Run

The gate ran once from /work/erofs-freebsd-pre as:

timeout -k 10 240 repo-pre-15/tests/pre15/gates/P15-086.sh \
    --base 6bf5724619be70f805bbe7d1ba77dd70cdced69f \
    --output planning/pre15/evidence/20260815T154915Z-G04-G05-P15-086/gate-output

It returned 0 and recorded G04=GO, G05=GO, and B28=AUTHORIZED. Evidence is rooted at planning/pre15/evidence/20260815T154915Z-G04-G05-P15-086/. The authoritative script SHA-256 is 591e407f20a6c8ab5d506329b3bd39ff7bd7f78b66ac86b9db2c45a498b31184, the input SHA-256 is 62f7f505aef846fa85085039b2f47e252e11602e6ef1bf41f56841cdc9089a2a, and the result SHA-256 is 33ef86b73447cd8c8099dc33901b9c4fff6c8ecedda3837d25cac9463a369d4f.

Decision Rule

Each codec is decided independently. A codec is partial-capable only when real, twice-reproduced EROFS input decodes every requested range to the exact full slice, reports a consumed-byte boundary before the end of the stream, leaves guard pages unchanged, preserves positive FreeBSD errno, and reduces peak temporary bytes by at least 20 percent without exceeding the fixed hard budget. Failure of the benefit subgate selects exact full fallback for that codec; an incorrect slice, unbounded memory, missing corruption boundary, or missing oracle stops P15-086.

Reproducible Corpus

All images are fixed-time, fixed-UUID, root-owned, and generated twice with identical bytes. Matching fsck reconstructs every legal source.

Codec Generator Image SHA-256 Logical bytes Physical bytes Leading zero bytes Stream bytes
LZ4 v1.4 8f940673ed9f7e00efc5c0f06d41b2216748ea84256b740751aabff0d632de2b 1,038,906 4,096 0 4,096
LZ4 v1.7 93451e563f4eaf95b2690381074b5dfb3da0257691043c51619fd7d4c68dba7e 1,038,906 4,096 0 4,096
LZ4 v1.8.6 853649c78b159161421a6e833e0c516216382f3e8d135fc80aacd509ddb27b2c 1,038,906 4,096 0 4,096
Deflate 1.8.6 5f98ff39be30b1396be8164e54a8ae80b144d181d5295a640b2e7814406d7a2d 22,878 4,096 1 4,095
LZMA 1.8.6 887d4a9baf629533c8d512177a84ca256a20135157d29a201408534f63230889 151,552 4,096 3,556 540
Zstd 1.8.6 93f6beb46e77187ea8b0fc1ad3a5a1cb565d546d9ce40d51278f26d67187d5fa 151,552 4,096 1,092 3,004

The LZ4 corpus spans all three historical generators required by G04. Stream codec consumption is reported by independent liblzma, zlib, and libzstd decoders after the common EROFS leading-zero padding is removed. LZ4 is checked by an independent raw parser and liblz4 partial/full output.

Hard Budget and Benefit

The fixed input cap is 1 MiB, the decoded-output cap is 12 MiB, and the caller cap is 1 MiB. Codec workspace caps are 0 for LZ4, 512 KiB for Deflate, 9 MiB for LZMA, and 4 MiB for Zstd. These caps cover the frozen format maxima rather than only the selected 4 KiB pclusters.

Codec Workspace full/partial Hard cap Baseline peak Candidate peak Reduction CPU median partial/full Decision
LZ4 v1.8.6 0 / 0 14,680,064 1,047,098 12,288 98.826% 10,688 / 208,150 ns GO
Deflate 39,928 / 39,928 15,204,352 70,998 52,216 26.454% 14,207 / 61,627 ns GO
LZMA 98,992 / 98,992 24,117,248 258,736 111,280 56.991% 21,384 / 80,329 ns GO
Zstd 95,992 / 313,080 18,874,368 255,736 325,368 -27.228% 109,253 / 91,015 ns FULL_FALLBACK

All three LZ4 generations have the same 98.826 percent memory reduction; their partial/full CPU ratios are 4.845, 4.632, and 5.135 percent. The gate collected nine samples of 25 decodes per mode and stopped at that fixed sample count. CPU timings are diagnostic because host scheduling produced visible outliers; the authorization is based on deterministic peak temporary bytes. No noisy CPU sample is used to rescue a codec that misses the 20 percent memory threshold.

Ranges, Corruption, and Errno

Prefix, cross-page, middle, and tail requests all match the corresponding full slice. The tail request reaches the extent end and therefore exercises full fallback. Prefix consumption is 1,032 bytes for LZ4, 805 for Deflate, 352 for LZMA, and 1,457 for Zstd. Corruption begins later at stream offsets 4,032, 4,031, 476, and 2,940 respectively. Every partial prefix remains byte-exact; the same full read and every one-byte truncation return positive EINTEGRITY (97). Real corrupted EROFS images fail matching fsck. All output guards and codec cleanup checks pass.

Partial success is only evidence that the requested slice is correct. It is not reported as verification of bytes after the consumed boundary or of the full extent.

State and Cleanup Model

B28 adds no persistent cache, owner, waiter, pool, or unmount-drain state. A cache hit remains first. A gate-authorized strict subextent miss decodes into a request-local bounded prefix and never publishes a partial cache entry. Full requests, unsupported ordinary strict subextent codecs, shifted/interlaced maps, and arithmetic fallback retain the existing exact full-decode/cache policy. Existing partial-reference maps remain bounded-prefix and cache-ineligible. Failure frees the local output after input release; success publishes no shared partial state. Reclaim, eviction, unmount, and key reuse therefore retain their existing ownership model.

The owned temporary tree was removed and the evidence SHA-256 manifest verifies in full. No QEMU process was started. Protected PID 26318, port 9222, and the shared base image were not touched. The full feature suite was not run.

Consequence

B28 may implement bounded-prefix decode only for LZ4, LZMA, and Deflate in the exact planned write set for ordinary strict subextent reads. Zstd and all non-authorized backends must retain exact full fallback there without returning an unsupported error; existing partial-reference behavior remains unchanged. B28 acceptance owns D, the targeted TC176 host case, both KLD configurations, and strict-timeout TC176 QEMU. It must preserve guards, consumed-byte semantics, positive errno, cache eligibility, provider/GEOM ownership, and cleanup ordering.

B28 Execution Outcome

B28 source/test commit 7a0d7e4a4047ac6d6130a3be5cb677cb94979fe7 has the exact 11-path actual write set. LZ4, LZMA, and Deflate ordinary strict subextent reads decode a bounded prefix; Zstd and non-authorized backends use exact full fallback. Existing partial-reference maps remain bounded-prefix and cache-ineligible.

Final D, targeted host TC176 subset 20260815T163642Z-host-B28-partial-1356298-0, and targeted zstdio0/zstdio1 K2 20260815T163515Z-host-B28-partial-1355895-0 pass. Earlier host and K2 RUNNER_FAIL records are retained with their corrected oracle/build findings. The strict-timeout QEMU run 20260815T163824Z-qemu-B28-partial-1356729-0 is INFRA_BLOCKED because guest SSH did not become ready before the boot deadline; it did not reach the target marker, so no guest TC176 runtime PASS is claimed. Owned cleanup passes, protected PID 26318 and port 9222 were untouched, and the full feature suite was not run. Complete evidence is under planning/pre15/evidence/20260815T161336Z-B28/.