18 KiB
Pre11 Completion and Smoke Report
Status
Pre11 is complete for its approved mechanical maintenance scope.
- Final implementation commit tested:
040fc69025c5031436205c3acd421be1d95fe86b - Final
repo-pre-11tree:f0cca92670c76ab13cc5b9353d5aeb993effa6e2 - Final
repo-pre-11/srctree:c4aac4d69cb25a4b049239d0c1f422dcb89465d6 - Static review:
ACCEPT, with no P0-P3 findings in the included changes - FreeBSD KLD build:
PASS, usingWITH_ZSTDIO=0 - Targeted plain/LZ4/LZMA QEMU smoke:
PASS - Full feature test and
test_all.py:NOT RUN
This report does not claim full feature validation. Pre11 deliberately contains mechanical naming, responsibility, dead-scaffolding, file-layout, and cleanup changes that could be reviewed for behavioral equivalence and then covered by a focused build and smoke run. Behavior changes requiring purpose-built fixtures remain deferred.
Snapshot and Planning
Pre11 was created from the completed Pre10 tree in:
0483dcb41c2a980badb829ff4d17361bd1fec930
snapshot: create repo-pre-11 from repo-pre-10
At the snapshot boundary, repo-pre-10/src and repo-pre-11/src were both:
ec684d8dbd7662070234da1fe947aba48a293db8
The executable Pre11 plan was added in:
9ad1fa0cf8ba251b574da033bf0c9fad83acaa38
docs: add pre11 execution plan
The original plan included several candidates that would have changed visible filesystem behavior. An independent boundary review narrowed the release in:
c89c228ac1817cfd0337905b39247245eaa67f3b
docs: narrow pre11 execution boundaries
The narrowed scope retained only work that could preserve control flow, errno, on-disk interpretation, vnode and GEOM ownership, iterator order, decompressor semantics, and cache lifetime. The following candidates were removed from implementation because honest validation would require targeted feature tests:
- root vnode type rejection;
- zero-length mapping behavior in the UIO reader;
- header-only xattr semantics;
- duplicate or missing
device.Nbehavior; - direct propagation of
vnode_create_vobject()errors; - broad map, inode, directory, and name-lookup interface reshaping.
This narrowing allowed Pre11 to remain a comparatively large maintenance release without mixing low-risk structural alignment with unvalidated semantic changes.
Batch A: Type and Vocabulary Alignment
Commit:
b4e38c9fb15df127470d70bc144404f1f3afa2af
pre11: align mount and device helper vocabulary
Exact changes:
- renamed
struct erofs_mount.block_bitstoblkszbitsacross its consumers; - renamed the private
erofs_fill_map_dev()helper toerofs_fill_from_devinfo(); - added the Batch A implementation report.
Linux-maintenance benefit:
blkszbitsmatches established EROFS vocabulary and makes comparisons with Linux mount geometry code more direct;erofs_fill_from_devinfo()describes the same responsibility as the Linux helper without importing Linux block-device objects into FreeBSD.
BSD invariants retained:
- field type, width, units, expressions, overflow handling, and structure layout were unchanged;
- the helper remained a private FreeBSD device-map field filler;
- GEOM provider selection, range checks, flat-device behavior, errno, and physical I/O remained unchanged;
- no broad or search-driven integer type replacement was performed.
Static checks confirmed 48 intended block_bits replacements, zero remaining
old identifiers, four helper-name replacements, zero stale helper references,
and a source diff containing only the approved identifier changes.
Batch B: Vnode Operation Scaffolding
Commit:
67625d3afebb9142e69b19afd08cdfc1d2adaac5
refactor: clean up vnode operation scaffolding
Exact changes:
- removed the unused
EROFS_MOUNT_XATTR_USERoption bit; - removed the zero-consumer
erofs_node.vnodemember and its only assignment; - grouped VOP declarations and
erofs_vnodeopsinitializers by responsibility; - added the Batch B implementation report.
Linux-maintenance benefit:
- removes misleading compatibility-shaped state that had no consumer;
- presents vnode operations in a responsibility-oriented order that is easier to compare with upstream filesystem responsibilities while retaining the native FreeBSD operation table.
BSD invariants retained:
- no VOP function definition or registration changed;
erofs_vnodeopsretained 24 uniquefield=valueentries;erofs_fifoopsretained 14 unique entries and its original sequence;fifo_specops, vnode locking, hash insertion, reclaim, pager behavior, andvnode_create_vobject()errno translation were unchanged.
The removed symbols had no reads, address consumers, initializer dependencies, offset consumers, or external ABI use.
Batch C: ACL Parsing Responsibilities
Commit:
a86b5cac4d193d131de8870bca4132fdc881f992
erofs: split ACL parsing responsibilities
Exact changes:
- extracted private
erofs_posix_acl_from_xattr()fromerofs_get_acl(); - changed the private mode fallback helper to receive the inode mode directly;
- left xattr acquisition and all FreeBSD VOP/UIO responsibilities in the caller;
- added the Batch C implementation report.
Linux-maintenance benefit:
- separates wire-format ACL parsing from filesystem acquisition and VOP glue, matching the upstream responsibility split more closely;
- gives maintainers a bounded parser to compare without introducing Linux ACL objects, RCU, xattr handlers, or inode lifecycle assumptions.
BSD invariants retained:
- mount-option checks, ACL type validation, default-ACL directory checks,
namespace selection, both
erofs_getxattr()stages, UIO setup, andENOATTRfallback remain inerofs_get_acl(); - parser validation order, positive errno, tag phases, duplicate ID checks,
UINT32_MAXhandling, partial ACL writes, and finalacl_posix1e_check()ordering remain unchanged; - input storage remains caller-owned stack memory, with no new allocation or cleanup path;
erofs_xattr_load_body()and the known header-only xattr behavior were not changed.
Static comparison confirmed equivalent branch, error, phase-transition, and ACL-population behavior.
Batch D: LZ4 Backend File Responsibility
Commit:
e631e33a1b8c053ebcb2d737af33e363cba48b34
erofs: align LZ4 backend file responsibility
Exact changes:
- renamed
src/lz4.ctosrc/decompressor_lz4.c; - updated the Makefile source entry;
- updated current architecture documentation references;
- added the Batch D implementation report.
Linux-maintenance benefit:
- makes the filename communicate that the translation unit is the LZ4 codec
backend beside
decompressor_lzma.c,decompressor_deflate.c, anddecompressor_zstd.c; - reduces unnecessary file-layout differences when maintainers inspect codec implementations across the independent Linux and FreeBSD repositories.
BSD invariants retained:
- Git identified a 100% rename;
- the old and new source blobs are both
2cc19f5eb0c283e12ba0a3a4334b8817a1686888; - function bodies, request ABI, descriptor registration, input/output bounds, partial decode behavior, and error normalization were unchanged;
- historical reports and historical test evidence were not rewritten.
Batch E: Mount Device Argument Cleanup
Commit:
040fc69025c5031436205c3acd421be1d95fe86b
erofs: consolidate mount device argument cleanup
Exact changes:
- consolidated caller-owned copied
device.Nargument release into oneout_argsexit inerofs_mount(); - removed two impossible NULL checks immediately following
M_WAITOK | M_ZEROallocations; - added the Batch E implementation report.
Linux-maintenance benefit:
- makes mount setup ownership and cleanup easier to audit by reducing repeated release sites;
- removes defensive branches that contradict the FreeBSD
M_WAITOKcontract, keeping BSD-specific allocation behavior explicit instead of emulating a nullable Linux allocation path.
BSD invariants retained:
- operation order remains parse, filter, get option, open primary, update I/O size, mount setup, free copied arguments, publish mounted-from, and statfs;
- parse failure still returns before caller ownership exists;
out_argsreleases only copied arguments and never releasesprimary;erofs_mountfs()still takes ownership ofprimaryat entry;erofs_mountfs(),erofs_sb_free(), reverse external-device cleanup, errno, and mount error text are unchanged;- duplicate and missing external-device slot behavior remains deferred.
Static Review
Independent reviews were performed after the individual batches and again over
the complete source range from 0483dcb through 040fc690.
The final review found no P0-P3 issue in the included Pre11 source changes and accepted all five batches. It confirmed:
- the source changes were confined to the approved Batch A-E paths;
- no deferred behavior fix entered the source;
- old identifiers had no stale consumers and new private helpers had unique definitions and expected call counts;
- both VOP vectors retained the same registration mappings;
- ACL acquisition, parsing, fallback, errno, and partial-write behavior were preserved;
- the LZ4 backend was a byte-identical rename and the Makefile contained the new filename once;
- mount cleanup retained error order and GEOM ownership;
- uncompressed mapping interfaces, directory/name lookup, decompressor request ABI, LZMA cache policy, disk structures, and Linux reference sources were not changed;
git diff --checkpassed and the implementation worktree was clean before runtime validation.
The final source delta from the snapshot contains 202 insertions and 188 deletions across ten source paths, including the 100% LZ4 file rename. Much of that textual delta is identifier replacement, declaration/vector reordering, or moved ACL parser code rather than new behavior.
First Smoke Attempt: Infrastructure Failure
Evidence directory:
/work/tests-dev/temp/pre11-smoke-final-20260813T122923Z
Result: FAIL, specifically an infrastructure failure before DUT transfer or
execution.
The guest reached FreeBSD and two SSH identity probes succeeded, but the first runner opened an SSH ControlMaster using a detached invocation. The open command returned success and created the control socket, then the master terminated or lost its connection before the immediate health check. The check failed with:
Control socket connect(.../control.sock): Connection refused
The test stopped before source transfer, KLD build, module load, or any EROFS mount. Therefore this attempt is not a PASS, but it is also not evidence of a Pre11 build or driver failure. Its source archive SHA was:
5bbffb101364f350fe1a3771b6f018bc10a68785d8c55cc2a186273a074e9182
The owned QEMU stopped, port 10043 was released, its overlay was removed, the
base image remained unchanged, and the retained guard VM remained reachable.
The run's cleanup status was nonzero only because closing the already-dead
ControlMaster returned an error.
Corrected Smoke Retry
Evidence directory:
/work/tests-dev/temp/pre11-smoke-retry-final-20260813T124214Z
Result: PASS.
The retry used an SSH master process in normal foreground mode but launched it
in the runner shell background, without ssh -f. The runner captured the real
master PID, repeatedly required both kill -0 and ssh -O check to succeed,
and refused to transfer sources unless the master remained alive. Long build
work ran inside the guest with a completion sentinel, so one long SSH command
was not treated as the build lifetime.
Tested identities:
commit: 040fc69025c5031436205c3acd421be1d95fe86b
repo-pre-11 tree: f0cca92670c76ab13cc5b9353d5aeb993effa6e2
src tree: c4aac4d69cb25a4b049239d0c1f422dcb89465d6
source archive: 179b80365c26295770afab58f1209ae3fffd73182ada0bcf97ea027904f781e9
guest: FreeBSD 15.0-RELEASE-p8
The archive hashes differ between attempts because separately generated gzip archives are not required to be byte-reproducible. Both identity files name the same committed repository and source trees; only the passing retry is used as runtime evidence.
Build and Module Lifecycle
The committed repo-pre-11 archive was transferred to the disposable guest,
validated there, extracted, and built with:
make WITH_ZSTDIO=0
Results:
- guest build return code:
0; erofs.koSHA256:77ce41bff5cb7d7c934dd9dba20ba06c20b660ad15ebfc4210f86f6473dffbf7;kldload /root/pre11-smoke/erofs.ko: success;kldstat -n erofs: success, reportingerofs.koloaded;- all smoke mounts and md providers were released;
kldunload erofs: success;- the post-unload
kldstat -n erofscheck confirmed the module was absent.
WITH_ZSTDIO=1 was not built and is not claimed as tested.
Smoke Cases
Each case used an independently attached vnode-backed md provider, required a
successful EROFS mount to be visible in mount -p, computed the complete target
file hash, then unmounted and detached the provider before the next case.
| Case | Target SHA256 | Elapsed | Provider | Result |
|---|---|---|---|---|
| Plain | 056f8f7585667dc695e2edf936deaf84cfee0f88671ba6cd5be22ce890763433 |
0 s | md70 |
PASS |
| LZ4 | 3ff012b76087c4da65ce0b69813a76f47ea367e95782edf8b8cd6cd3ec4d1880 |
5 s | md71 |
PASS |
| LZMA | ddda39737f0f6093e828a032ec161511fefbb1fa361bc6cbffdbc91e48e4c461 |
2 s | md72 |
PASS |
The LZMA case hashed the complete file. No timeout, mount failure, hash mismatch, unmount failure, or md detach failure occurred.
Kernel Messages and Cleanup
The runner captured dmesg before loading the module and after all smoke cases.
The delta contained no EROFS error, decompression failure, panic, or assertion;
the suspect-output file is empty.
Cleanup evidence records:
qemu_stopped=1
port_released=1
overlay_removed=1
base_mode_after=444
base_sha_after=67f359621f23a1d745f0889370cbb99a096cee3e99a0b2f3bb18fc7a91bf6fef
guard_unchanged_and_reachable=1
body_rc=0
cleanup_rc=0
The test owned only port 10044, its QEMU PID, its ControlMaster PID, and its
overlay. All were closed or removed. The permanent base image was never booted
directly and retained mode 0444 and its original SHA256. The retained guard VM
PID 26318 kept start time 1102996924, an identical command line, and a
reachable forwarded SSH port at 9222.
Feature-Test Decision
No feature test and no test_all.py run was performed.
That decision is appropriate for the included Pre11 scope because:
- Batch A changed only private identifiers;
- Batch B removed proven dead state and reordered designated VOP initializers without changing their mappings;
- Batch C mechanically moved parser statements while retaining inputs, outputs, writes, error order, and ownership;
- Batch D was a byte-identical file rename;
- Batch E consolidated one caller-owned cleanup action and removed checks that
cannot be reached after
M_WAITOKallocation.
Static equivalence review plus the FreeBSD build and plain/LZ4/LZMA smoke is sufficient evidence for these changes. It is not sufficient for the deferred behavior changes below, and this report does not claim otherwise.
Deferred Behavior and Required Targeted Tests
Non-directory root
The current root path does not add a new rejection for a root NID that resolves to a non-directory vnode. A future fix requires a purpose-built image and checks for mount errno, vnode release, mount error text, and complete cleanup.
Zero-length internal run
The uncompressed UIO reader's existing run_len == 0 behavior was not changed.
A future fix requires a corrupt mapping fixture that reaches a zero-length run
while the request remains inside the file, with exact comparison to the
contiguous-buffer path and expected EINTEGRITY.
Header-only xattr
The existing behavior for an ibody containing only the xattr header was not changed. Targeted coverage must distinguish zero and nonzero shared counts, name filters, get/list results, ACL mode fallback, and corruption results.
Duplicate or missing device slots
device.N slot parsing behavior and diagnostics were not changed. Future tests
must cover duplicate, out-of-order, missing, excessive, and malformed slots,
flat and non-flat device tables, exact errno and mount error text, and GEOM
cleanup.
insmntque() race closure
The earlier ownership fix remains accepted by static lifecycle review but is not runtime-closed by ordinary smoke. A dedicated mount/unmount or forced unmount race must stress vnode creation and inspect panic, use-after-free, lock, reference, and cleanup behavior.
Explicit mapped extent fixtures
Positive payload fixtures are still unavailable for explicit mapped extent records of 4, 8, 16, and 32 bytes. No restructuring or coverage claim should be made until validated mappings and file hashes exist.
vnode_create_vobject() errno
Pre11 intentionally retains the current conversion of a nonzero
vnode_create_vobject() result to ENOMEM. Direct propagation is a visible
behavior change and requires controlled pager failure or fault injection that
verifies the caller-visible errno and vnode state.
Final Conclusion
Pre11 completed all five narrowed maintenance batches, passed independent static review, built successfully as a FreeBSD KLD, and passed the required plain, LZ4, and full-file LZMA smoke. The first smoke attempt was correctly classified as an infrastructure failure before DUT transfer or build; the corrected retry provides the runtime evidence.
Pre11 improves cross-repository maintainability without replacing native FreeBSD vnode, GEOM, UIO, pager, ACL, or synchronous decompression contracts. Full feature validation remains outside this release and must not be inferred from the targeted smoke result.