8.4 KiB
Pre9 controlled manual QEMU evidence audit
Date: 2026-08-13
Scope and evidence status
This report audits the already completed manual run at
/work/tests-dev/temp/pre9-manual-20260813-run3/. No QEMU test was rerun.
The long-lived guard VM (PID 26318, host port 9222) was not touched.
The automated TC004 implementation remains PENDING_FIX/BLOCKED in
/work/tests-dev/fix-todo/tc004-automation.md. Run3 is a manual substitute;
it is not evidence that TC004 automation passes.
Run history:
- Run1: infrastructure failure; no retained result directory is available.
- Run2:
INFRA. Guest SSH authentication failed for Pre7 and Pre8, then the host runner was interrupted while preparing Pre9. It produced no DUT result. - Run3: valid manual run. All three DUTs built, loaded, mounted, executed the bounded probes, produced a live SHA stack sample, and cleaned up.
Verdict
| Question | Verdict | Evidence |
|---|---|---|
| 4 KiB, 16 KiB, 64 KiB and 1 MiB single-syscall read correctness | PASS | Every version returned the requested byte count, errno=0, matched the source-range SHA-256, exited zero, and has exactly one target-file pread() in truss. |
First 1 MiB sequential dd read |
PASS | Every version returned zero and copied 1 MiB within the 20-second bound. This is a bounded smoke check, not proof of one 1 MiB kernel read. |
| Full-file SHA correctness | BLOCKED | No version retained a hash or an exit status for the background SHA. sha_after is empty and process disappearance is not correctness evidence. |
| Full-file read liveness/performance | FAIL | After an eight-second observation delay, SHA was still running in the LZMA decode path and had advanced only about 1.0-1.25 MiB. This is unacceptable for the 8 MiB smoke fixture and reproduces across all three versions. |
| Pre7 to Pre8/Pre9 regression attribution | PASS: no Pre9 regression demonstrated | Pre8 and Pre9 have the same src tree and identical KLD hash. Pre7 has a different source tree/KLD but shows the same symptom and stack. The evidence attributes the issue to shared behavior, not a Pre9-only change. |
Overall verdict: PARTIAL. Bounded reads are correct, but the full-file correctness verdict is blocked and full-file liveness fails.
Runner semantics audit
The runner creates a fresh qcow2 overlay per version over the read-only base,
archives the selected repository subtree, builds the KLD in the guest, mounts
the same LZMA fixture, and runs four probes. Each probe invokes a C program that
contains one target-file pread() and writes the returned bytes to a file.
The runner then hashes that file and compares it with bytes read from the
uncompressed source fixture.
Important field meanings:
commit: Git tree object for the version directory at the enclosing repo HEAD. It is not a standalone commit ID.src_tree: Git tree object for that version'ssrcdirectory.probes[].elapsed: host wall time for the complete SSH command, including SSH and truss overhead. It is not pure kernel decompression time.metadata.hash_match: equality between the mounted output-range hash and the uncompressed source-range hash.signal=0: runner shorthand for probe return code zero. It is not a signal collected throughwaitpid().dd_1m: a userspacedd bs=1m count=1result. It does not establish the size or count of VOP/kernel reads.sha_pid: PID printed after starting a backgroundsha256command.diagnostic_sample: process table, kernel stack, descriptor offset, mount, md device and dmesg captured after an unconditional eight-second sleep.sha_after: process status followed bysha.outandsha.err. Empty output means neither a process row nor captured SHA/error output was available.status=PARTIAL: runner-generated fallback when any bounded probe succeeds. It does not mean full SHA correctness passed.
The full SHA was not run under timeout. The runner waited eight seconds,
sampled it, sent TERM, slept two seconds, then attempted KILL, and finally read
the output files. No start/end timestamp or exit status was recorded. Therefore
the exact SHA lifetime is unknown; the only defensible timing statement is that
it was still active approximately eight seconds after launch.
sha_after contains only ,state=,command= for all versions. The subsequent
KILL reports No such process. This establishes only that the sampled PID no
longer existed after TERM plus the two-second delay. It does not distinguish a
successful completion from TERM handling, and the absent sha.out means no
hash can be validated. Process disappearance must not be reported as PASS.
Controlled identities and setup
The common fixture hashes were:
- Image:
32107a084b27362a093768b88746c37c2e99a74b9f1301a9d4046988479defe9 - Source:
ddda39737f0f6093e828a032ec161511fefbb1fa361bc6cbffdbc91e48e4c461
| Version | Repository tree | src tree |
KLD SHA-256 | Build/load/mount |
|---|---|---|---|---|
| Pre7 | b8f9af2cd55225c4348b79ff5910ae6fc83cd517 |
dc203534d7b5721905f8538026e4c59346106020 |
33a52f2f16a94afda0501d305b238678b96c71e420d4b8bbcbeec6ffcdf1aae5 |
PASS/PASS/PASS |
| Pre8 | 1e24c992a5b071e6fdabfdc42d342b6ed5a91cf5 |
cbf93a19df8d1ce2fb66e2aeb7276a4ea6d4dcc2 |
348cb1f5a91d47e1412747d285c795c49375a61a66cfb3d35d22f38ecfde6ea0 |
PASS/PASS/PASS |
| Pre9 | dc0c01157b5c925684bd77c57ed6703904af7453 |
cbf93a19df8d1ce2fb66e2aeb7276a4ea6d4dcc2 |
348cb1f5a91d47e1412747d285c795c49375a61a66cfb3d35d22f38ecfde6ea0 |
PASS/PASS/PASS |
Pre8 and Pre9 are runtime-identical for this test according to both the source tree and the produced KLD hash.
Single-syscall probes
All probes used offset zero. Times below include SSH/truss overhead.
| Version | Length | Returned | Hash match | Elapsed | Exactly one target pread() |
|---|---|---|---|---|---|
| Pre7 | 4 KiB | 4 KiB | yes | 1.299 s | yes |
| Pre7 | 16 KiB | 16 KiB | yes | 1.291 s | yes |
| Pre7 | 64 KiB | 64 KiB | yes | 1.438 s | yes |
| Pre7 | 1 MiB | 1 MiB | yes | 1.432 s | yes |
| Pre8 | 4 KiB | 4 KiB | yes | 1.216 s | yes |
| Pre8 | 16 KiB | 16 KiB | yes | 1.327 s | yes |
| Pre8 | 64 KiB | 64 KiB | yes | 1.430 s | yes |
| Pre8 | 1 MiB | 1 MiB | yes | 1.442 s | yes |
| Pre9 | 4 KiB | 4 KiB | yes | 1.791 s | yes |
| Pre9 | 16 KiB | 16 KiB | yes | 1.341 s | yes |
| Pre9 | 64 KiB | 64 KiB | yes | 1.374 s | yes |
| Pre9 | 1 MiB | 1 MiB | yes | 1.737 s | yes |
The target-file truss lines are preserved in
pre9-manual-evidence/probe-summary.txt. Dynamic-loader pread() calls are
not counted as target-file calls.
The 1 MiB dd results were:
- Pre7: 1 MiB in 0.195526 s.
- Pre8: 1 MiB in 0.179484 s.
- Pre9: 1 MiB in 0.367417 s.
These values are not stable enough for version performance ranking, but all three bounded operations completed.
Full SHA sample
| Version | State at sample | File offset | Kernel stack | Final hash |
|---|---|---|---|---|
| Pre7 | running (RC) |
1,245,184 | lzma2_lzma -> erofs_xz_dec_microlzma_run -> lzma_decompress -> z_erofs_decompress -> z_erofs_do_read -> z_erofs_read_uio |
absent |
| Pre8 | running (RC) |
1,150,976 | same | absent |
| Pre9 | running (RC) |
1,044,480 | same | absent |
The stack is direct evidence of active CPU-side decompression, not an EROFS
lock wait. It does not by itself prove why decompression is slow. Combined with
the static review, the leading explanation remains repeated full mapped-extent
decompression as z_erofs_read_uio() segments reads at MAXPHYS. There is no
direct evidence here of an XZ infinite loop or an EROFS lock deadlock.
Infrastructure integrity and cleanup
The base image SHA-256 before and after run3 was identical and matched the expected value:
67f359621f23a1d745f0889370cbb99a096cee3e99a0b2f3bb18fc7a91bf6fef
For each version, umount, mdconfig -d and kldunload returned zero. Each
QEMU PID was no longer alive and each overlay was deleted. The run3 result set
therefore supports successful test-VM cleanup. This report does not infer the
state of the unrelated long-lived guard VM and did not inspect or modify it.
Required follow-up
A supplemental manual test is still required if full-file correctness must be
closed. It should run one full SHA with an explicit wall-clock deadline, record
start/end timestamps and exit status, capture sha.out before cleanup, compare
the hash to the source fixture, and separately record whether TERM/KILL was
used. Until then, full-file SHA correctness remains BLOCKED.