# repo22 Final Review WIP Manual Test Report Started: 2026-08-09 01:24 UTC Completed: 2026-08-09 03:33 UTC Parent commit: `9a3604fba32cfe2ff263d954d80fe588f99db88f` Guest: FreeBSD 15.0-RELEASE-p8 amd64, QEMU TCG Linux reference: `/work/dev-src-linux/fs/erofs` FreeBSD reference: `/work/dev-freebsd-releng` ## Scope This run reviews and validates four final correctness findings: - Linux-compatible 48-bit superblock union selection; - rejection of extended inode sizes above FreeBSD `OFF_MAX`; - bounded reads from multi-GiB explicit extent holes; - 64-bit directory block-search indexes. No CI work, binary fixture, guest overlay, build object, or raw VM artifact is part of the intended commit. ## Result | Test | Result | Evidence | |---|---|---| | TC150 48-bit fallback root | PASS | Real FreeBSD mount, root read, inode and `df` | | TC151 size above `OFF_MAX` | PASS | Six direct failures, rc 1, syscall errno 97 | | TC152 bounded extent hole | PASS | Two pread/mmap probes, stable active allocation | | TC153 large directory index | SHELVED | Host fixture reproducible; kernel run incomplete | TC153 is deliberately not marked PASS. See `issues/TC153-large-directory-block-index-validation.md`. ## Source Review Linux `super.c` initializes `blocks_lo` and uses `rb.blocks_hi` only inside `48BIT && rootnid_8b`. repo22 now decodes blocks and root NID together under that same selector. FreeBSD exposes signed `off_t` pager and vnode interfaces bounded by `OFF_MAX`; repo22 rejects a larger decoded inode before vnode/pager setup. The extent-hole path now zeroes only the current requested span in `z_erofs_do_read()` instead of allocating the complete logical extent. The directory block search now uses 64-bit bounds and a checked block-offset multiplication. The within-block search remains 32-bit, matching the validated block-sized domain. ## Build Results Commands: ```sh EROFS_ZSTDIO=0 ./build.sh EROFS_ZSTDIO=1 ./build.sh nm -u build/erofs.ko git diff --check -- repo-community/repo22 ``` | Configuration | Module SHA256 | Result | |---|---|---| | `EROFS_ZSTDIO=0` | `65bc19d53a2a7f0525bfacadb441dab37ee318f5f5b4c62b5ecd1b5090fe46d2` | PASS | | `EROFS_ZSTDIO=1` | `d46ca4dfc858deaf4840fad8b8589b16d4b71b34afa96dc7acf1255890c5cef7` | PASS | Both freestanding builds completed. Neither module had an unresolved `bcmp` reference. The ZSTDIO-enabled module was transferred to the guest, loaded as KLD ID 7, and unloaded after testing. ## Fixture Evidence | Fixture | SHA256 | |---|---| | `fallback-48bit-root2.erofs` | `bed3be4dfb8499d4e794b03eddd5b9cda95bc8e5571ae7d765c4852ece0d95a3` | | `extended-size-bit63.erofs` | `e4a0f550168f1a2911603863d0074d474e61adc787c14c0278c83a060643ee38` | | `extent-hole-5g.erofs` | `50014a24493918247e36511ad34a2fe8ab47ae09ea46d7fd62a1bed445a6c65f` | | `large-dir-intmax.erofs` | `0f90d3d57adbbbd946e41b225c1f6c464915c6abb0b13478ec9b2a318def1f72` | The TC153 hash is host generator evidence only. ## TC150 The fixture encoded `rootnid_2b=36`, `rootnid_8b=0`, `blocks_lo=1`, and the 48-bit incompat bit. The 4 KiB image mounted on `/dev/md0` and produced: ```text content=48-bit fallback root sha256=d361f537492113ca93cfbf91c06ebc06e2b8b695d8b6e63ad3666013eaa029f0 root inode=36 df total=4 one-KiB blocks ``` This proves the union was not shifted into a high block count. It does not replace the large-provider TC010 test. ## TC151 The fixture used extended inode NID 40 at byte 1280 with `i_size=0x8000000000000000`. The image mounted, but every access to `big.dat` failed before open or pager setup: | Access | Attempts | Direct rc | `truss` result | |---|---:|---:|---| | `stat` | 2 | 1, 1 | `fstatat ... ERR#97` | | `cat` | 2 | 1, 1 | `openat ... ERR#97` | | `mmap_fault` | 2 | 1, 1 | `openat ... ERR#97` | All six errors were `Integrity check failed`. No file descriptor reached the read or mmap phase. ## TC152 The mounted file size was `5368713216` bytes. The native helper probed offset `3221225472` with a one-byte pread and one-page private mmap: ```text attempt 1: PASS, real 0.03 s attempt 2: PASS, real 0.02 s ``` The `erofs` malloc row was `3` active allocations and `768` active bytes both before and after. The cumulative allocation counter moved from 89 to 95, as expected for temporary request buffers; active memory did not scale with the 5 GiB hole. ## TC153 The first 4096-byte fixture was Layout 2 and failed before the target namei path. A second 65536-byte base with 400 entries was still Layout 2. The tracked generator now converts the directory to Layout 0 by moving its complete data to appended blocks and produced a 90112-byte patched image with raw block 16, 22 image blocks, and the hash listed above. The corrected fixture was not executed in the FreeBSD kernel during this run. TC153 remains SHELVED, and the complete attempt history and acceptance criteria are in its issue document. ## Cleanup The qualified rerun used dmesg line count 123 before and after. It ended with: ```text EROFS mounts: 0 md providers: none EROFS modules: 0 ``` An earlier unqualified probe encountered a preloaded differently named EROFS KLD and a `truss` exit-status ambiguity. It was discarded. The qualified run first unloaded that KLD, loaded the exact module hash above, captured direct command exit codes separately from syscall traces, and then cleaned up. ## Deferred Issues - `issues/TC153-large-directory-block-index-validation.md` - `issues/TC010-48bit-statfs-large-provider.md` - `issues/extent-metadata-fixture-unavailable.md` The raw guest transcripts remain untracked under `/work/build`. This report, the deterministic generator, and source/test documentation are the tracked evidence.