# Pre12 Final Report

Date: 2026-08-13

## Conclusion and scope

Pre12 is complete for its deliberately limited scope. The final result is
**PASS** for the planned static review, both FreeBSD KLD build configurations,
KLD load/status/unload, and the ordinary Plain/LZ4/LZMA QEMU smoke cases.

This PASS is not a claim of complete EROFS feature validation. No feature
test, `test_all.py`, new fixture, ZSTD data test, DEFLATE data test, ACL runtime
test, explicit-extent test, or multi-device test was run. The included changes
were selected as low-side-effect maintenance work and did not require a full
feature suite after their static proofs and final build/smoke matrix. Deferred
behavior work remains unresolved and is listed below.

The validated device-under-test identity is:

| Identity | Value |
| --- | --- |
| Commit | `a55e42a117e504f6ece49be3c2a2d81603031ea3` |
| `repo-pre-12` tree | `9161671bd0e855faa52c37e24fe8efcd6ddd71e0` |
| `repo-pre-12/src` tree | `d63c45c7872dcf9dd84007c8883cf9fbe0f9467d` |
| Source archive SHA-256 | `bb7e7f0383be29102475575e130e0b19a48452d20520c94059dc6ef128d0c7ce` |

## Goals

Pre12 continued the staged effort to reduce unnecessary maintenance
differences from Linux EROFS without importing Linux-only memory, I/O, device,
or concurrency models into FreeBSD. Its concrete scope was nine core batches
and one conditional maintenance closeout:

1. Use existing semantic scalar aliases where their width and signedness are
   exactly equivalent.
2. Use FreeBSD unaligned little-endian readers for raw on-disk bytes.
3. Use the FreeBSD POSIX.1e ACL mode conversion facility.
4. Introduce a Linux-comparable private compression header.
5. Remove an unreachable ZSTD lower-bound condition.
6. Align codec descriptor ownership while preserving FreeBSD behavior.
7. Align exact macro vocabulary and remove one zero-consumer alias.
8. Align one xattr helper's file order through a byte-identical block move.
9. Remove include duplication introduced by the compression-header work.
10. Review Makefile readability and make no change when no useful grouping
    was found.

The work explicitly excluded broad file reordering, catch-all style cleanup,
Linux page/folio/bio/workqueue infrastructure, and behavior changes requiring
specialized feature fixtures.

## Batch results

| Batch | Commit | Result and summary |
| --- | --- | --- |
| 01 | `bb28c47bdf4de777febde05ebb333c420ea1e9b9` | Replaced the planned NID, block-number, and byte-offset declarations with existing equal-width unsigned `erofs_nid_t`, `erofs_blk_t`, and `erofs_off_t` aliases. Field order, layout, ABI width, expressions, on-disk types, and control flow were unchanged. |
| 02 | `76a655788538f2270626cff1ca91b8c47700d536` | Replaced exactly three potentially unaligned typed loads with `le16dec`/`le32dec` in xattr, inode, and block-map decoding. |
| 03 | `35bde15f5242f84a6343cc9e96519fcce4eeca90` | Replaced three manual ACL mode shifts with `acl_posix1e_mode_to_perm` for owner, group, and other entries. |
| 04 | `b591751f90e62bc0ec54d3f34c724f698c99813d` | Added `src/compress.h` for private decompressor request, descriptor, and backend declarations; public entry points and runtime enum remained in `internal.h`. |
| 05 | `aaa3c5db40745ee558e6fcf6375d60e044217df9` | Removed only the unreachable `zstd_windowlog + 10 < 10` subcondition; the upper bound, zero-output check, disabled stub, errno behavior, and resource handling remained unchanged. |
| 06 | `6748d58f7e15927321f44a83d81a6c697c1185ae` | Moved LZMA, DEFLATE, and ZSTD descriptors into their backends, kept LZ4 and plain transforms central, and changed the central descriptor table to the pointer table `z_erofs_decomp`. All six normalized descriptor tuples and indices remained unchanged. |
| 07 | `292da21bd9288cac4a8b280bb67970c8b9058550` | Renamed `EROFS_ALL_SUPPORTED_INCOMPAT` to Linux's `EROFS_ALL_FEATURE_INCOMPAT` at its definition and sole source use, and removed zero-consumer `EROFS_CHUNK_FORMAT_INDEXES_FLAG`. |
| 08 | `0be5642d917104f1904bcfadaea803c9845c7a5c` | Moved the complete `erofs_listxattr_foreach` static function block before `erofs_getxattr_foreach`; the block SHA-256 remained `0541c211f78a19f39caeebdafe73bdd0a7064e996686a7b45c9c651160ed98ae`. |
| 09 | `e5315489eb5ed08884d5d5f2645264067e36838e` | Removed five direct `internal.h` includes made redundant by `compress.h`; declaration visibility and the acyclic include graph were preserved. |
| 10 | `a55e42a117e504f6ece49be3c2a2d81603031ea3` | Conditional Makefile readability closeout: honest no-op. The source list and Makefile remained byte-for-byte unchanged because no non-redundant grouping comment was justified. |

Batch 10 is not counted among the nine core source workflows. Batch 09 did
produce a precise cleanup diff, while Batch 10 records the required review
without manufacturing source churn.

## Static review

The final static review found no source-blocking issue. In particular, it did
not find a regression in declaration/definition matching, include ownership or
graph shape, descriptor indices and callback ownership, errno paths, resource
release, in-memory ABI/layout, endian decoding, ACL construction, macro values,
or the byte-identical xattr function move.

The important proofs were:

- The three semantic scalar aliases are direct unsigned 64-bit aliases; the
  approved substitutions preserve size, alignment, signedness, structure
  layout, parameter representation, and arithmetic width.
- The three `le16dec`/`le32dec` inputs are raw little-endian disk bytes of the
  required length; the decoded values are equivalent while avoiding typed
  unaligned loads.
- ACL owner/group/other conversion was exhaustively compared across modes
  `0000` through `0777`: `1536/1536` tag/mode combinations were equivalent,
  with zero mismatches.
- The compression include graph remained acyclic and each migrated or private
  symbol retained one authoritative declaration/definition relationship.
- The six codec descriptor tuples, indices, names, config callbacks,
  decompress callbacks, and ZSTD conditional ownership remained equivalent.
- The removed ZSTD lower bound is unreachable because the field is `uint8_t`;
  its promoted value plus 10 cannot be less than 10.
- Macro expressions and values were unchanged, and the deleted chunk-format
  alias had no source, build, documentation-interface, or preprocessor
  consumer in the target tree.
- The moved xattr function block retained its exact SHA-256 and conditional
  context.

The Batch 06 record originally used wording that could imply an actual
`WITH_ZSTDIO=0` build had already occurred during that batch. It has been
corrected to state that only the static conditional path was validated then.
Final validation subsequently built both configurations successfully.

## KLD build matrix

The valid final run used FreeBSD `15.0-RELEASE-p8`, amd64, with `/usr/src/sys`
and the in-tree FreeBSD ZSTD headers present. The extracted source archive
matched SHA-256
`bb7e7f0383be29102475575e130e0b19a48452d20520c94059dc6ef128d0c7ce`.

For each configuration, the guest executed:

```sh
timeout -k 10s 120s make "WITH_ZSTDIO=<0-or-1>" clean
timeout -k 10s 600s make "WITH_ZSTDIO=<0-or-1>"
```

| Configuration | Clean exit | Build exit | Module SHA-256 |
| --- | ---: | ---: | --- |
| `WITH_ZSTDIO=0` | 0 | 0 | `96dc276c6c3f68943e68a144cc2ea138ffc215b62c7392cad9688ec45c9fc2fb` |
| `WITH_ZSTDIO=1` | 0 | 0 | `4d879c0b7ebc653e915a3e41863f74d6d5b5f18aa81c5178579368048d1b6ee3` |

The enabled build compiled `decompressor_zstd.c` with `-DZSTDIO` and linked
`erofs.ko`. These builds prove both compile-time configurations close and link;
they do not prove ZSTD or DEFLATE data-path correctness.

## KLD and smoke results

The valid run loaded the `WITH_ZSTDIO=1` artifact under the standard module
name `erofs.ko`.

| Check | Result |
| --- | --- |
| `kldload` | exit 0 |
| `kldstat -n erofs.ko` | present as `erofs.ko`, module id 5 |
| Loaded module SHA-256 | `4d879c0b7ebc653e915a3e41863f74d6d5b5f18aa81c5178579368048d1b6ee3` |
| `kldunload erofs.ko` | exit 0 |
| Post-unload `kldstat` | module absent, as expected |

All ordinary read cases matched their complete expected hashes:

| Case | Exit | Expected SHA-256 | Actual SHA-256 | Elapsed |
| --- | ---: | --- | --- | ---: |
| Plain | 0 | `056f8f7585667dc695e2edf936deaf84cfee0f88671ba6cd5be22ce890763433` | `056f8f7585667dc695e2edf936deaf84cfee0f88671ba6cd5be22ce890763433` | 593 ms |
| LZ4 | 0 | `3ff012b76087c4da65ce0b69813a76f47ea367e95782edf8b8cd6cd3ec4d1880` | `3ff012b76087c4da65ce0b69813a76f47ea367e95782edf8b8cd6cd3ec4d1880` | 6822 ms |
| LZMA | 0 | `ddda39737f0f6093e828a032ec161511fefbb1fa361bc6cbffdbc91e48e4c461` | `ddda39737f0f6093e828a032ec161511fefbb1fa361bc6cbffdbc91e48e4c461` | 3418 ms |

The dmesg delta was zero bytes and the suspect-filter output was zero bytes.
No new panic, trap, or EROFS error was observed.

## Evidence and invalid attempts

The only final valid evidence directory is:

```text
/work/tests-dev/temp/pre12-smoke-direct-20260813T165639Z/
```

Its `final-summary.txt`, guest build logs, module hashes, case records, dmesg
files, and cleanup record form the accepted evidence set.

Two earlier infrastructure attempts are explicitly invalid and contribute no
source result and no test pass:

1. `/work/tests-dev/temp/pre12-build-20260813T154900Z/` is **INFRA-FAIL**.
   The SSH password expanded to an empty string, so there were zero successful
   SSH sessions and neither build began. Its QEMU and temporary resources were
   cleaned. This is neither a DUT failure nor a test success.
2. `/work/tests-dev/temp/pre12-final-smoke-20260813T160957Z/` stopped while
   redundantly hashing the 16 GB base image. Five nested Codex CLI sessions
   were discovered and all were terminated or had exited; no QEMU, SSH,
   guest build, KLD action, or smoke case started. Its partial files are not
   test evidence and it is neither a DUT failure nor a test success.

The final accepted run was performed by a single direct execution layer and
did not start a nested agent or Codex process.

One intermediate runner revision attempted to query KLD using the renamed
artifact filename rather than the module's standard name. That was a
test-period runner issue, not a DUT issue. Only the temporary runner copy under
`tests-dev/temp` was corrected: the successful `WITH_ZSTDIO=1` artifact was
copied to `erofs.ko`, then the complete KLD and Plain/LZ4/LZMA sequence was
rerun. No `repo-pre-12` source or build file was modified to make the test
pass.

## Cleanup and repository state

The accepted run completed cleanup successfully:

- Owned QEMU stopped.
- SSH ControlMaster stopped.
- Test port `10048` released.
- Test overlay removed.
- Guest test mounts and `md70`/`md71`/`md72` devices were removed.
- The retained guard QEMU remained unchanged and reachable at PID `26318`,
  port `9222`, with process start ticks `1102996924`.
- The base image remained mode `0444`, size `16515530752` bytes, and mtime
  `1786418212`. Its retained SHA-256 record is
  `67f359621f23a1d745f0889370cbb99a096cee3e99a0b2f3bb18fc7a91bf6fef`;
  the final run intentionally did not repeat the expensive 16 GB hash.
- At validation completion, `HEAD` and `xdm/main` both identified
  `a55e42a117e504f6ece49be3c2a2d81603031ea3`, and the worktree was clean.

This report is documentation-only and does not alter the validated DUT source
tree `d63c45c7872dcf9dd84007c8883cf9fbe0f9467d`.

## Deferred feature work

The following issues remain unresolved and require dedicated behavior design,
fixtures, or feature tests before any future implementation can be accepted:

- inode decode split or rewrite;
- map request interface conversion;
- directory/namei control flow, qstr, cookies, namecache, and lock behavior;
- metadata reader consolidation;
- rejection or handling of a non-directory root;
- `run_len == 0` behavior;
- header-only xattr behavior;
- duplicate or missing `device.N` behavior;
- `insmntque` race closure;
- explicit extent and explicit mapped-extent fixtures;
- `vnode_create_vobject` errno behavior.

No claim is made that these issues were fixed or covered by the ordinary
smoke run. The final PASS is limited to the Pre12 static review, both KLD build
configurations, KLD lifecycle, and the Plain/LZ4/LZMA smoke cases recorded in
the accepted evidence directory.
