update
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
# P15-005 Stage0 Decision
|
||||
|
||||
Status: `GO` for B06.
|
||||
|
||||
The authoritative baseline replay used commit
|
||||
`edf098905a34de764185e72fc7e92d7b8f4e7285`. The gate extracts and compiles
|
||||
the current FreeBSD `data.c` and `zmap.c` producer bodies instead of replaying
|
||||
an arithmetic model. Fourteen frozen cases cover plain, inline, hole, chunk,
|
||||
48-bit multidevice, compressed explicit extents, fragment, partial-reference,
|
||||
post-EOF, bounds, overflow, short-read, and post-acquire error behavior. Every
|
||||
field in `(m_la,m_pa,m_llen,m_plen,m_deviceid,m_flags,errno,acquire_count,
|
||||
release_count)` matched the independently frozen record oracle.
|
||||
|
||||
The ownership oracle freezes 27 audited function bodies and 22 success,
|
||||
validation-error, provider-error/short-read, transfer, and release paths across
|
||||
plain data, compressed data/config, xattr, inode, superblock, and map consumers.
|
||||
It also pins the corresponding Linux source hashes and `erofs_buf` acquire/put
|
||||
semantic anchors. Candidate replay must satisfy the predeclared per-function
|
||||
object/put/raw-buffer contract and execute the actual FreeBSD helper through
|
||||
primary-image, metabox, error, overflow, idempotent-put, and null-callback paths.
|
||||
|
||||
The supplied prep remains correctly classified `BLOCKED`: its static scan uses
|
||||
obsolete `erofs_mount`/`erofs_node` text anchors and its Python map model does
|
||||
not execute DUT code. `P15-005.sh` and `P15-005-input.json` close those gaps on
|
||||
the current BASE. Evidence is in
|
||||
`planning/pre15/evidence/20260814T145546Z-G02-P15-005/`.
|
||||
|
||||
QEMU and the full feature suite were not run. G02 for P15-005 is a host/source
|
||||
gate, and its candidate contract does not require either. This GO authorizes
|
||||
B06 only; it does not authorize P15-006 or any B07 map-object change.
|
||||
|
||||
## B06 completion
|
||||
|
||||
B06 commit `1b1f904a674c21eed3ee29ca7df93c44429ac8d5` replayed the same
|
||||
corpus and oracle with `object_mode=true`, `oracle_equal=true`, 14/14 tuples,
|
||||
22/22 ownership paths, and five actual helper lifecycle paths. D, the B06 host
|
||||
case, and both FreeBSD KLD configurations pass. Seven frozen FreeBSD raw I/O
|
||||
and GEOM lifecycle functions are unchanged, and the pre-B07 map object hash is
|
||||
unchanged. This completes the B06 dependency and unlocks B07a for its own
|
||||
separate gated batch; it does not pre-approve a B07 implementation.
|
||||
@@ -0,0 +1,60 @@
|
||||
# P15-006 Stage0 Decision
|
||||
|
||||
Status: `GO`; B07a is complete.
|
||||
|
||||
The authoritative baseline replay used commit
|
||||
`6673f51152a5195a8a8903aa801f820abce7936e`. This decision is independent of
|
||||
the earlier P15-005 GO: P15-006 has its own corpus, model digest, source
|
||||
extractors, byte encoding, and decision record.
|
||||
|
||||
The frozen corpus contains 80 map tuples and 13 device-resolution cases. The
|
||||
map tuples comprise 50 plain/inline/chunk producer cases and 30 compressed
|
||||
explicit-extent cases. They cover plain and inline boundaries, holes, raw
|
||||
32-bit chunks, indexed 32-bit chunks, indexed 48-bit chunks, masked and
|
||||
nonzero device IDs, all four explicit extent record sizes, fragments, partial
|
||||
references, exact and post EOF, provider/metabox bounds, checked arithmetic
|
||||
overflow, invalid formats and algorithms, and errors both before and after
|
||||
metadata acquisition. The device cases separately exercise primary,
|
||||
multidevice, flat-device, unified-address, missing-provider, range, and
|
||||
overflow behavior without changing GEOM ownership.
|
||||
|
||||
Expected records are produced by an independent arithmetic and on-disk record
|
||||
decoder whose frozen SHA256 is
|
||||
`effcf0b6cc6a6e916eae89a14ad52d7b96273a453556647b6eabf2926fcb4abb`.
|
||||
The gate separately extracts the real `data.c` and `zmap.c` producer bodies
|
||||
from the frozen BASE, compiles them with `-Werror`, and compares every
|
||||
`m_la`, `m_pa`, `m_llen`, `m_plen`, `m_deviceid`, `m_flags`,
|
||||
`m_algorithmformat`, positive errno, acquire count, and release count. It
|
||||
also packs those fields with fixed layout `<QQQQH2xIiiII`; the baseline tuple
|
||||
bytes have SHA256
|
||||
`8d3fec7ccbdfb7f7c851a494b6ecad02b8a019247bd9486188f8d37c169faedd`.
|
||||
Two complete baseline replays produced byte-identical tuple, device, and
|
||||
result files.
|
||||
|
||||
Protected hashes freeze the existing plain/chunk and compressed producers,
|
||||
metadata acquire/put paths, physical I/O path, and device/GEOM mapping bodies.
|
||||
The candidate replay additionally requires FULL and COMPACT dispatch to pass
|
||||
all five map flag bits and all tuple fields through the new adapter. Every
|
||||
observed acquisition is balanced: the baseline contains 41 paths at 0:0, 30
|
||||
at 1:1, seven at 2:2, and two at 3:3. All successful non-EOF mappings have a
|
||||
positive `m_llen`; Pre13 H07 remains closed.
|
||||
|
||||
This closes the specific Pre13 H01 oracle gaps for chunk, multidevice, bounds,
|
||||
and overflow rather than reusing the old 26 plain/inline/hole tuples. The
|
||||
supplied G02 prep remains a non-authoritative prototype and was not used as
|
||||
the tuple source.
|
||||
|
||||
The B07a implementation is commit
|
||||
`141b11f0d847a63a47b6c6143e4c2913a1147a0f`. Its authoritative host run
|
||||
replayed all 80 tuples and 13 device cases against the frozen oracle. The
|
||||
4,480-byte tuple streams are byte-identical with SHA256
|
||||
`8d3fec7ccbdfb7f7c851a494b6ecad02b8a019247bd9486188f8d37c169faedd`;
|
||||
FULL and COMPACT dispatch preserve every tuple field and all five map flag
|
||||
bits. D and both K2 configurations pass, with no global or undefined symbol
|
||||
delta from B06.
|
||||
|
||||
QEMU and the full feature suite were not run. The final plan requires host
|
||||
tuple replay, D, and K2 for B07a; it does not require a B07a QEMU fixture.
|
||||
B07b is now dependency-unblocked for a separate batch. B07c remains blocked
|
||||
on B07b, and B08 remains blocked on B07c. This decision neither implements
|
||||
nor pre-accepts any of those later batches.
|
||||
@@ -0,0 +1,102 @@
|
||||
# P15-019 Stage0 Decision
|
||||
|
||||
Status: `GO`. G03 authorizes B16 for P15-019 only. P15-046 remains the B01
|
||||
test-only legacy xattr prefix fallback contract; it neither changes this
|
||||
decision nor authorizes any exact-header or xattr behavior change.
|
||||
|
||||
The decision is bound to DUT BASE
|
||||
`d645feb720c7022d2138d2a62eb72c022eb75351`, FreeBSD source HEAD
|
||||
`106727738dcfb6c001b46f25363b91cece970085`, erofs-utils source HEAD
|
||||
`7db78788b000999e2de88decd2ba90654f26171c`, and
|
||||
`mkfs.erofs (erofs-utils) 1.8.6`.
|
||||
|
||||
## Authoritative Run
|
||||
|
||||
The gate ran from `/work/erofs-freebsd-pre/repo-pre-15` as:
|
||||
|
||||
```sh
|
||||
umask 077
|
||||
timeout -k 10 240 tests/pre15/gates/P15-019.sh \
|
||||
--base d645feb720c7022d2138d2a62eb72c022eb75351 \
|
||||
--output /work/erofs-freebsd-pre-evidence/pre15/\
|
||||
20260815T093800Z-G03-P15-019-umask-fix/gate-output
|
||||
```
|
||||
|
||||
It returned zero with `GO`. The authoritative hashes are:
|
||||
|
||||
- gate script: `afa20cbd28ca9dfc8064596a312248756ed7cde54398efb5ef713818cc04ea54`
|
||||
- gate input: `291bf12838981ef650e16bbf7381eaa9b2921de957e97dec46e6a573750a19b8`
|
||||
- result: `bb52e1a88cb09554a51432ec545ed98d5509a529832141ed0ce83b0c336be5bb`
|
||||
- cases: `0c12cdce8b3ed37e85f349af0715a728d4acabbb758451fb65546dd9836066b5`
|
||||
- fixture manifest/set: `5e99e5ad9112508991e78ae6e65928973d6b0da78285a059894bed06010cf373`
|
||||
- semantics: `090e6b0cd5eaa197f17da12daf29f30bd8f337d3d4ae2f0f4f5819ad41e906f9`
|
||||
- cleanup: `8e3b52610ee1492262494d00c48bf66ea04d313ab9ac1ef27565fa0e607b9a97`
|
||||
|
||||
An additional independent replay from `umask 077` produced the same result,
|
||||
cases, fixture manifest, semantics, and cleanup hashes byte for byte. The gate
|
||||
sets `umask 022` internally because erofs-utils records the packed fragment
|
||||
inode's source mode; this makes the fixture set independent of its caller.
|
||||
|
||||
## Real EROFS Fixture Oracle
|
||||
|
||||
The gate creates 35 deterministic EROFS images and seven external chunk blobs
|
||||
in owned output. Nothing is committed as an image, blob, binary, or KLD. Each
|
||||
of the five required storage paths has these seven cases:
|
||||
|
||||
- normal short target;
|
||||
- normal 1,024-byte `MAXPATHLEN` target;
|
||||
- zero-byte target;
|
||||
- embedded NUL at the first, middle, and last byte;
|
||||
- 1,025-byte over-limit target.
|
||||
|
||||
Inline positives are native mkfs symlinks. Plain, chunk, compact compressed
|
||||
ztailpacking, and whole-file fragment cases start as real mkfs regular-file
|
||||
carriers because the host cannot create a symlink containing NUL and mkfs does
|
||||
not select those layouts for symlinks. The transform changes only inode mode,
|
||||
the root dirent type, and, for empty cases, inode size, then recomputes the real
|
||||
EROFS checksum. Chunk data remains on a real `--blobdev`; fragment data remains
|
||||
in the real packed inode. Changed-byte offsets are recorded for every case.
|
||||
|
||||
The independent Python parser reads the superblock, checksum span, inode,
|
||||
dirent, layout, and target bytes directly. It resolves chunk indexes and the
|
||||
external blob, decodes compact inline-pcluster raw LZ4 without a DUT helper,
|
||||
and resolves the whole-fragment offset through the packed inode. It does not
|
||||
compile, call, or inject values into any DUT internal function. `dump.erofs`
|
||||
is only a layout/type cross-check. All legal targets also pass
|
||||
`fsck.erofs --extract` and reproduce the exact source bytes.
|
||||
|
||||
The independent decision model returns positive FreeBSD `EINTEGRITY` (97) for
|
||||
empty or embedded-NUL targets, positive `ENAMETOOLONG` (63) before target I/O
|
||||
for size greater than `MAXPATHLEN`, and success for exact non-NUL bytes. No
|
||||
trailing NUL is required. All 35 expected results match, so every layout has a
|
||||
bounded positive and negative oracle as required by G03.
|
||||
|
||||
## Linux and FreeBSD Semantics
|
||||
|
||||
Linux `erofs_fill_symlink()` validates only flat-inline fast symlinks while
|
||||
building `i_link`; it uses `kmemdup_nul()`/`strlen()` and returns negative
|
||||
`-EFSCORRUPTED`. Non-inline Linux symlinks use `page_get_link`. That page/cache
|
||||
shape is not a FreeBSD implementation contract.
|
||||
|
||||
FreeBSD enters through `VOP_READLINK` on a vnode and currently streams through
|
||||
`erofs_readlink_target`, the common map/read path, GEOM or the compressed
|
||||
backing path, and `uiomove`. It has no Linux `i_link` or page-get-link path and
|
||||
uses positive errno. B16 must therefore validate the complete immutable target
|
||||
before any `uiomove`, use the existing layout-specific map/read machinery, and
|
||||
keep the scan bounded by `MAXPATHLEN=1024`.
|
||||
|
||||
The 1,024-byte case is a successful `readlink(2)` byte target. Pathname follow
|
||||
may still return `ENAMETOOLONG` when that target plus the remaining pathname
|
||||
exceeds FreeBSD's namei buffer; that VFS result is distinct from the on-disk
|
||||
target validator. The 1,025-byte inode is rejected by B16 before target I/O.
|
||||
|
||||
## Scope and Cleanup
|
||||
|
||||
The gate did not modify `src/**`, build a KLD, start QEMU, or run a feature
|
||||
suite. It observed but did not signal or otherwise alter protected PID 26318,
|
||||
port 9222, or `/work/debug-qemu/local/vm-freebsd-build.qcow2.bp`; their recorded
|
||||
identity was unchanged before and after the run. Owned temporary source and
|
||||
extract directories were removed, with zero leftovers.
|
||||
|
||||
B16 may now modify only its planned source/test write set and must pass the
|
||||
specified host TC166, D, zstdio0 build, and targeted TC166 QEMU acceptance.
|
||||
@@ -0,0 +1,93 @@
|
||||
# P15-021 Stage0 Decision
|
||||
|
||||
Status: `GO`. B19b source is authorized; B19a remains `STOP-NO-SOURCE`.
|
||||
|
||||
P15-021 is the xattr Bloom fast-negative candidate. The gate uses a real,
|
||||
byte-reproducible EROFS image generated by `mkfs.erofs` 1.8.6, an independent
|
||||
on-disk parser, a temporary file-local `erofs_xxh32` prototype, frozen Linux
|
||||
format/use-site anchors, and five cold provider-metadata-read samples. It does
|
||||
not link a prototype into the DUT KLD and does not modify `src/**`.
|
||||
|
||||
The required matrix is hit, proven miss, collision false positive, unknown
|
||||
filter format, feature off, malformed shared-count metadata, malformed shared
|
||||
ID metadata, positive FreeBSD errno, 64-worker replay, one million generated
|
||||
names without a false negative, and owned cleanup. Unknown formats and feature
|
||||
off must scan. A collision must scan. Structural corruption reached before or
|
||||
during the scan must remain `EINTEGRITY` rather than becoming `ENOATTR`.
|
||||
|
||||
The gate command is:
|
||||
|
||||
```sh
|
||||
timeout -k 10 240 tests/pre15/gates/P15-021.sh \
|
||||
--base 666e52f710363df07f7c93919eb835d41092d011 \
|
||||
--output OUTPUT
|
||||
```
|
||||
|
||||
## Frozen Identity
|
||||
|
||||
The gate BASE is `666e52f710363df07f7c93919eb835d41092d011`.
|
||||
`P15-021-input.json` freezes the three DUT source files, Linux `erofs_fs.h` and
|
||||
`xattr.c`, FreeBSD 15 source HEAD
|
||||
`106727738dcfb6c001b46f25363b91cece970085`, erofs-utils HEAD
|
||||
`7db78788b000999e2de88decd2ba90654f26171c`, host tools, format constants,
|
||||
thresholds, seven endian/seed vectors, one million generated names, 64 workers,
|
||||
and the exact gate/source write sets. FreeBSD has no public xxh32 API; its only
|
||||
copies are private Zstd/OpenZFS sources, so the authorized implementation is
|
||||
file-local and namespaced as `erofs_xxh32`.
|
||||
|
||||
The generated prototype source SHA256 is
|
||||
`3fe1a7a64ce4386d74f5f49455fe8bef2a2ee55a03eb72593a89d4dec70c1b4b`.
|
||||
Its temporary host binary SHA256 is
|
||||
`9910baed4d018a0257f38377bb48857a3205ee42d9f0ff279db71e63e5ba695b`;
|
||||
the binary is evidence only, is not committed, and is never linked into the DUT
|
||||
KLD.
|
||||
|
||||
## Fixture And Oracle
|
||||
|
||||
`mkfs.erofs` 1.8.6 generated the filter-bearing image twice from 64 peers and
|
||||
one target with eight shared user xattrs. The two images were byte-identical;
|
||||
the valid fixture SHA256 is
|
||||
`b06b7c4c30adb3684d11505edf815dc0a395c03f6a95120b3150361008a182cb`.
|
||||
The independent parser handles multi-block directories and separately decodes
|
||||
inode xattr headers, inline entries, shared IDs, and shared entries. Legal
|
||||
valid, unknown-reserved, and feature-off images pass `fsck.erofs`.
|
||||
|
||||
The seven-case matrix passes: present hit, proven miss, collision false
|
||||
positive, unknown filter, feature off, malformed shared count, and out-of-range
|
||||
shared ID. Miss alone takes the fast-negative. Hit and collision perform the
|
||||
complete scan; unknown format and feature off perform the unchanged complete
|
||||
scan. Corrupt header/shared metadata returns positive FreeBSD `EINTEGRITY=97`,
|
||||
while valid absence returns positive `ENOATTR=87`.
|
||||
|
||||
The candidate implementation, independent Python xxh32, system libxxhash, and
|
||||
the frozen Linux seed/endianness vectors agree. One million deterministic random
|
||||
names across EROFS indexes 1/2/3/4/6 produce no candidate/oracle difference and
|
||||
no false negative in 1,024 constructed valid filters. Sixty-four workers
|
||||
complete 1,280 mixed lookups with identical bytes/errno.
|
||||
|
||||
## Benefit And Decision
|
||||
|
||||
Five cold samples of 200 real-fixture misses each are stable. Baseline metadata
|
||||
read calls are `3400,3400,3400,3400,3400`; candidate calls are
|
||||
`400,400,400,400,400`, an 88.235 percent reduction. Baseline cold unique
|
||||
provider blocks are `400,400,400,400,400`; candidate blocks are
|
||||
`200,200,200,200,200`, a 50 percent reduction. Both exceed the mandatory 25
|
||||
percent threshold. The model counts the extra header/shared-ID reads on
|
||||
positive and collision paths and therefore does not hide their overhead.
|
||||
|
||||
G03 is `GO` for P15-021. Only a proven negative may bypass the full scan; all
|
||||
other outcomes retain the current FreeBSD extattr namespace, VOP transfer,
|
||||
positive errno, metadata buffer ownership, and lock-free immutable lookup
|
||||
behavior. Linux supplies the format/hash comparison, not FreeBSD vnode/cache or
|
||||
locking semantics.
|
||||
|
||||
Attempt 1 stopped at the fixed-vector check because five hexadecimal hashes
|
||||
were transcribed to incorrect decimal JSON values. Python and libxxhash agreed
|
||||
on the hexadecimal values and bits; the input-only correction was replayed
|
||||
under a new output directory. Attempts 2 and 3 then produced identical semantic
|
||||
results and fixture hashes. Attempt 3 evidence is retained at
|
||||
`/work/pre15-evidence/20260815T-P15-021-G03-attempt-3`; its `SHA256SUMS` digest
|
||||
is `b81fe1b94048dbc3d17c62c95aba6a5de9e068e2a15639ca55ea60fe5a251e07`.
|
||||
No QEMU or full feature suite was run for the Stage0 decision. Source remained
|
||||
unchanged, owned temporary files/processes are zero, and protected PID 26318,
|
||||
port 9222, and the base bp were untouched.
|
||||
@@ -0,0 +1,87 @@
|
||||
# P15-022 Stage0 Decision
|
||||
|
||||
Status: `GO`. B19a source is authorized.
|
||||
|
||||
P15-022 is the G03/G05 xattr-cache candidate. The old decision was not treated
|
||||
as terminal because its multi-block path parser stopped before producing a
|
||||
P15-022 result and G05 had zero samples. The repaired gate completed both
|
||||
mandatory branches before source implementation.
|
||||
|
||||
## Frozen Identity
|
||||
|
||||
The replay base is `50a4e84d0da33592a81361e0294b7feb5bbd3ffa`.
|
||||
`P15-022-input.json` freezes the current DUT/Linux source, exact-ABI FreeBSD
|
||||
source `/work/dev-freebsd-releng` at
|
||||
`106727738dcfb6c001b46f25363b91cece970085`, host tools, B17 assets, B19a
|
||||
generator/oracle/model assets, a 1 MiB mount budget, a 64 KiB per-vnode body
|
||||
limit, 64 workers, five samples per variant, and the unchanged 25 percent
|
||||
provider-metadata-read threshold.
|
||||
|
||||
## Oracle Repair And G03
|
||||
|
||||
The B19a oracle now reads every logical directory block, including a short
|
||||
final block, and validates name offsets, embedded NUL rules, strict in-block
|
||||
ordering, strict adjacent-block ordering, stable entry order, duplicate
|
||||
resolution, and missing-path classification. Its self-controls cover target
|
||||
lookup after a block boundary, duplicate within/across blocks, duplicate
|
||||
resolution, missing target, backwards boundary, and an invalid name range.
|
||||
|
||||
The real fixture retains 64 long-named peers and one target. It has 2 root
|
||||
directory blocks, 68 entries, and resolves `target.bin` in block 1 after the
|
||||
`peer-047`/`peer-048` boundary. The target contains both one inline xattr and
|
||||
one shared xattr. Valid, corrupt shared-count, corrupt shared-ID, and corrupt
|
||||
inline-name fixtures are independently checked with positive FreeBSD errno.
|
||||
|
||||
G03 completed twice on byte-reproducible images. The existing B17 oracle also
|
||||
replayed twice with all 10 legal and 15 damaged images passing and frozen
|
||||
fixture-set SHA256
|
||||
`d821aeb36de37ae40b817b91f8169e585721c33a3a9e59098cdfbcbfff74e364`.
|
||||
|
||||
## G05 Result
|
||||
|
||||
The same image, host, operations, warmup, loops, and sample order were used for
|
||||
both variants. Five raw samples per variant are retained; no failed sample was
|
||||
filtered. Baseline provider metadata reads were
|
||||
`1400,1400,1400,1400,1400`; candidate reads were
|
||||
`800,800,800,800,800`. Median reduction is `42.857142857142854%` for both
|
||||
instrumented calls and provider block reads, above the unchanged `25.0%` gate.
|
||||
|
||||
The focused cache model passes 64-worker one-owner publication, identical
|
||||
waiter bytes and typed failure, failed initialization without a half-published
|
||||
body, the 64 KiB entry limit, exact 1 MiB budget exhaustion fallback, invalidation,
|
||||
inflight close, reclaim, and zero resident bytes after cleanup. The decision
|
||||
is `GO`; source modification is now authorized only within the B19a write set.
|
||||
|
||||
## Evidence And Scope
|
||||
|
||||
Evidence is retained under
|
||||
`planning/pre15/evidence/20260817T171814Z-B19a/`. `GATE-attempt1` preserves the
|
||||
runner failure caused by the missing sample directory. `GATE-attempt2` is the
|
||||
authoritative GO replay with raw fixtures, oracle reports, cache-model output,
|
||||
sample JSON, aggregate TSV, commands, and cleanup manifest.
|
||||
|
||||
The authorized source/test write set is:
|
||||
|
||||
```text
|
||||
repo-pre-15/src/erofs_vnops.c
|
||||
repo-pre-15/src/inode.c
|
||||
repo-pre-15/src/internal.h
|
||||
repo-pre-15/src/xattr.c
|
||||
repo-pre-15/tests/pre15/cases/B19a-xattr-cache.sh
|
||||
repo-pre-15/tests/pre15/fixtures/B19a-*
|
||||
```
|
||||
|
||||
No QEMU or production source was touched by this Stage0 gate. B36 and all
|
||||
other execution units remain out of scope.
|
||||
|
||||
## B19a Acceptance Addendum
|
||||
|
||||
B19a subsequently implemented the authorized per-vnode xattr body/shared-ID
|
||||
cache within the declared write set. The focused FreeBSD 15.0-RELEASE-p8
|
||||
exact-ABI run passed first, concurrent, and repeated xattr reads; symmetric
|
||||
`EINTEGRITY` results for all three damaged images; normal and forced unmount;
|
||||
cache invalidation and reclaim; KLD unload; guest mount/md cleanup; target and
|
||||
runner cleanup; and an empty dmesg delta. The runner retained the original
|
||||
1200-second case deadline, focused command timeouts, 64 KiB body limit, 1 MiB
|
||||
mount budget, and 25 percent G05 threshold. The final evidence is under
|
||||
`planning/pre15/evidence/20260817T193130Z-B19a-final/`.
|
||||
@@ -0,0 +1,43 @@
|
||||
# P15-027 Stage0 Decision
|
||||
|
||||
Status: `STOP`. B36 is `STOP-NO-SOURCE`.
|
||||
|
||||
G07 is evaluated per architecture against frozen BASE
|
||||
`4683579dabc57b0c9aaf5762e13ecc2a0ec3f8f9`. The mandatory audit set is
|
||||
arm64, riscv64, and i386. i386 is the real FreeBSD 32-bit target: the
|
||||
available FreeBSD source contains its machine headers and the pinned Clang
|
||||
toolchain contains the x86 backend. Source/toolchain availability is not
|
||||
native runtime evidence.
|
||||
|
||||
The inventory-first gate finds no declared same-architecture FreeBSD runtime
|
||||
for arm64, riscv64, or i386. The host is Linux/x86_64. An emulator binary,
|
||||
x86_64 guest, Linux execution, cross compilation, static layout output, or a
|
||||
runtime from another candidate cannot satisfy this condition. Missing native
|
||||
runtime is a per-architecture `STOP`, not `INFRA_BLOCKED`, and no architecture
|
||||
can borrow another architecture's result.
|
||||
|
||||
Because cross-only results cannot change any current decision, dual
|
||||
`WITH_ZSTDIO=0/1` KMOD builds and layout/unaligned/endian probes are
|
||||
`NOT_RUN` for all three architectures. The gate still verifies the frozen
|
||||
EROFS source tree, selected planning and probe hashes, FreeBSD source identity
|
||||
and architecture headers, compiler identity and target backends, and exact
|
||||
input-recorded Makefile relaxation. That patch is applied only to an owned
|
||||
temporary Makefile copy. The production `src/Makefile` remains byte-identical
|
||||
to BASE and retains the amd64-only error.
|
||||
|
||||
For a future rerun, each architecture has an independent native runner slot.
|
||||
A declaration must pass a bounded preflight reporting matching FreeBSD
|
||||
`uname -s`, architecture-specific `uname -m` and `uname -p`, and cleanup.
|
||||
Only then does the gate create a frozen temporary source copy, apply the sole
|
||||
recorded Makefile patch, build both KMOD configurations, record sizes and
|
||||
`nm -u`, and compile the layout and unaligned little-endian probes. The same
|
||||
runner must then load and unload both exact module hashes and record Plain,
|
||||
LZ4, LZMA, and Zstd reads. It must also prove running-kernel `options ZSTDIO`
|
||||
capability and exact disabled `EOPNOTSUPP`. Every operation carries argv,
|
||||
deadline, exit, target marker, cleanup, stdout/stderr, and hashes. A candidate
|
||||
is GO only when its own cross and native records both pass.
|
||||
|
||||
This decision does not authorize any B36 allowlist entry. No production
|
||||
source, B36 case, B36 probe, QEMU run, K build, feature suite, or smoke suite
|
||||
is created or run. Protected PID 26318, port 9222, and the shared base image
|
||||
are outside the gate and are not addressed.
|
||||
@@ -0,0 +1,51 @@
|
||||
# P15-030 Stage0 Decision
|
||||
|
||||
Status: `STOP`. B37a is `STOP-NO-SOURCE`.
|
||||
|
||||
G08 is replayed against frozen BASE
|
||||
`3e1d26a53eef30ecadc3407444d214feac861cb4`. P15-030 may proceed only if all
|
||||
four conditions pass: an existing diagnostic or operational consumer, bounded
|
||||
atomic counters, a FreeBSD 15 native `sysctl_ctx` lifecycle that closes every
|
||||
required teardown path, and a stable privileged-read ABI that leaks no
|
||||
unauthenticated metadata.
|
||||
|
||||
The consumer condition is evaluated first because no prototype can create its
|
||||
own justification. The bounded inventory covers all 3,206 tracked paths under
|
||||
`repo-pre-15` and `planning/pre15` at BASE, without reading
|
||||
`planning/pre15/introduction.md` or treating this addendum as evidence. It
|
||||
finds 54 broad sysctl/sysfs references: 31 planning or audit records, one
|
||||
historical evidence record, 19 test-only paths, and three project reports or
|
||||
documents. There are zero production or operations paths and zero qualifying
|
||||
consumer declarations.
|
||||
|
||||
A qualifying future declaration must use schema
|
||||
`pre15-p15-030-consumer-v1`, identify a versioned diagnostic or operational
|
||||
consumer in production use, name its owner, workflow, deployment reference,
|
||||
privileged-read access mode, and consumed signals, and bind a tracked non-test
|
||||
implementation by path and SHA-256. The implementation must actually invoke
|
||||
sysctl and reference each declared signal. A hypothetical future user, Linux
|
||||
sysfs analogy, generic observability value, test script, or gate prototype is
|
||||
rejected. If a declaration appears, this STOP-only run refuses false GO and
|
||||
requires the FreeBSD 15 native lifecycle prototype before source authorization.
|
||||
|
||||
The first condition is `STOP`, so the bounded atomic-counter prototype,
|
||||
FreeBSD 15 parse-failure/normal-unmount/forced-unmount/delayed-handler/
|
||||
`sysctl_ctx_free`-failure lifecycle work, and permissions/ABI/leak probes are
|
||||
all `NOT_RUN`. No host model is reported as native evidence and no prototype,
|
||||
KLD, QEMU process, feature test, or smoke test is built or run.
|
||||
|
||||
P15-068 and B37b also close as `STOP` / `STOP-NO-SOURCE` because the plan
|
||||
explicitly requires the P15-030 transport. This is capability dependency
|
||||
closure, not an independent decision about UUID or volume-label formatting.
|
||||
The identity oracle is `NOT_RUN`; no P15-068 gate addendum and no second sysctl
|
||||
lifecycle are created.
|
||||
|
||||
The committed replay evidence is recorded under
|
||||
`planning/pre15/evidence/20260816T041649Z-G08-P15-030/`. The gate owns one
|
||||
temporary directory, uses a 60-second internal timeout plus the recorded outer
|
||||
timeout, records argv, scope/source/addendum hashes, result, and cleanup, and
|
||||
rejects an existing output directory.
|
||||
|
||||
No production source, B37a/B37b case, fixture, or empty commit is created.
|
||||
Protected PID 26318, port 9222, and the immutable base image are outside the
|
||||
gate and are not addressed or hashed.
|
||||
@@ -0,0 +1,45 @@
|
||||
# P15-031 Stage0 Decision
|
||||
|
||||
Status: `STOP`. B38 is `STOP-NO-SOURCE`.
|
||||
|
||||
G08 is replayed against frozen BASE
|
||||
`0f696ad1e2c6628022d02ce52d07eb66704769dd`. P15-031 may proceed only if all
|
||||
five conditions pass: an existing project diagnostic consumer that has
|
||||
actually captured the complete predeclared mount/map/vget/xattr/decode/cache
|
||||
schema through FreeBSD DTrace/SDT or a justified KTR path; no pointer,
|
||||
credential, or unauthenticated metadata leakage; an owned-temp FreeBSD 15
|
||||
prototype with exact fields/counts and closed failure/detach/unload lifecycle;
|
||||
disabled `WITH_ZSTDIO=0/1` builds with no new undefined symbols; and a 10-run
|
||||
hot-path median regression of at most 3% with retained interleaved controls.
|
||||
|
||||
The consumer condition is evaluated first because neither a gate prototype nor
|
||||
a proposed B38 test can create its own project need. The bounded inventory
|
||||
covers all 3,243 tracked paths under `repo-pre-15` and `planning/pre15` at
|
||||
BASE, without reading `planning/pre15/introduction.md` or treating this
|
||||
addendum as evidence. It finds 33 native-tracing references: 16 planning or
|
||||
audit records, three historical evidence files, 10 test-only paths, and four
|
||||
reports or documents. There are zero production/operations paths, zero
|
||||
consumer manifests, and zero qualifying consumers.
|
||||
|
||||
A future declaration uses schema `pre15-p15-031-consumer-v1` under
|
||||
`repo-pre-15/diagnostics/`. It binds a versioned production implementation and
|
||||
actual FreeBSD 15 capture by path and SHA-256, identifies owner/workflow/
|
||||
deployment, records privileged access and DTrace/SDT or justified KTR
|
||||
transport, binds the complete event-schema hash, and records a positive count
|
||||
for every event. The gate rejects a hypothetical maintainer, Linux
|
||||
tracepoints, generic usefulness, a proposed test, its own prototype, or merely
|
||||
installed `dtrace`. If an approved declaration appears, this STOP-only version
|
||||
refuses false GO and requires the remaining native prototype, privacy, build,
|
||||
and benchmark stages before source authorization.
|
||||
|
||||
The first condition is `STOP`, so privacy execution, prototype generation,
|
||||
`WITH_ZSTDIO=0/1` builds, undefined-symbol comparison, the 10-run benchmark,
|
||||
D/H/K0/K1, targeted QEMU TC178, full feature, and smoke are all `NOT_RUN`.
|
||||
The gate's seven decision controls prove that GO is emitted only when all five
|
||||
conditions are `PASS`; no benchmark samples or later-stage metrics are
|
||||
fabricated.
|
||||
|
||||
No `src/erofs_trace.h`, trace callsite, `src/Makefile` change,
|
||||
`tests/pre15/cases/B38-trace.sh`, source commit, or empty commit is created.
|
||||
Protected PID 26318, port 9222, and the immutable base image are outside this
|
||||
STOP path and are not addressed or hashed.
|
||||
@@ -0,0 +1,106 @@
|
||||
# P15-032 / G09 vnode-backed image gate
|
||||
|
||||
## Decision rule
|
||||
|
||||
This gate is source-preparatory only. It does not link its model into EROFS and
|
||||
does not authorize B39 merely because a declared state sequence looks safe. It
|
||||
pins and extracts the relevant FreeBSD 15 vnode, pager, mount, GEOM, md(4),
|
||||
nullfs, unionfs, tarfs, and deadfs contracts, compiles an owned-temporary C
|
||||
lifecycle model generated from `P15-032-input.json`, and rejects adversarial
|
||||
false-GO mutations.
|
||||
|
||||
The runner exits with:
|
||||
|
||||
* `0`: gate GO;
|
||||
* `10`: gate STOP;
|
||||
* `20` or another nonzero value: runner failure;
|
||||
* `124`: absolute gate timeout.
|
||||
|
||||
All phases have absolute deadlines. The generated C source and its output are
|
||||
copied into the requested evidence directory; the temporary executable is
|
||||
removed by the runner trap.
|
||||
|
||||
## Closeable local vnode contract
|
||||
|
||||
The pinned FreeBSD sources support a coherent local lifecycle:
|
||||
|
||||
1. Use an explicit `vnode:/absolute/path` tag; GEOM remains explicit or legacy
|
||||
GEOM syntax. A mount and all `device.N` sources use one backend kind.
|
||||
2. Resolve with `namei`, require `VREG`, retain vnode identity with
|
||||
`vn_open_vnode(FREAD)`, retain the mounter credential with `crhold`, and use
|
||||
that credential for every source `VOP_READ`.
|
||||
3. Apply `VOP_SET_TEXT` before first I/O. The default write-count contract
|
||||
rejects existing or later writers with `ETXTBSY`; retain a size snapshot and
|
||||
convert a short source read into `EIO`. Rename or pathname replacement does
|
||||
not change the held vnode identity.
|
||||
4. Read synchronously into `UIO_SYSSPACE` under a source range lock and source
|
||||
vnode lock. FreeBSD's old vnode-pager fallback drops the VM object write
|
||||
lock before `VOP_READ`, so no user-buffer pager fault is introduced by this
|
||||
read shape.
|
||||
5. Register the source mount with `vfs_register_upper_from_vp` before first I/O.
|
||||
On unmount, reject new I/O, drain delayed and in-flight completions, `vflush`,
|
||||
unregister the upper mount, unset text, close the vnode, release the held
|
||||
credential, and then release the final mount-private reference. A forced
|
||||
dead source returns `ENXIO` rather than silently changing identity.
|
||||
6. Keep GEOM open/read/close and vnode open/read/close as disjoint tagged-union
|
||||
branches. This preserves the existing GEOM and multidevice behavior.
|
||||
|
||||
The generated model checks this order and independently removes each local
|
||||
invariant to ensure that every mutation is rejected.
|
||||
|
||||
## Blocking FreeBSD contract
|
||||
|
||||
The required pre-I/O self and ancestor check is transitive across VFS and GEOM,
|
||||
not only across pathname aliases:
|
||||
|
||||
```
|
||||
regular source vnode
|
||||
-> source filesystem
|
||||
-> md(4) GEOM provider
|
||||
-> md_s.s_vnode.vnode
|
||||
-> another filesystem vnode
|
||||
```
|
||||
|
||||
The final identity edge is not available through a generic, identity-preserving
|
||||
FreeBSD API:
|
||||
|
||||
* `VOP_GETLOWVNODE` exposes vnode-stack aliases such as nullfs and unionfs, but
|
||||
it does not traverse a filesystem's GEOM storage dependency.
|
||||
* `vfs_register_upper_from_vp` pins the immediate source vnode mount and orders
|
||||
its unmount, but it does not register hidden GEOM-to-vnode backing edges.
|
||||
* `md(4)` stores the held backing vnode in the private `struct md_s` defined in
|
||||
`md.c`. Its GEOM object exposes only `void *softc`; dump configuration exposes
|
||||
a pathname, not a held vnode identity.
|
||||
* Re-resolving that pathname fails the rename/replace invariant. Casting
|
||||
`g_geom.softc` to a copied private `struct md_s` is an undocumented,
|
||||
class-specific dependency and does not cover other filesystem-private or
|
||||
GEOM-private file-backed providers.
|
||||
|
||||
Consequently a visible-only oracle can approve all vnode, credential, pager,
|
||||
resize, and unmount checks while missing the hidden backing-vnode ancestor. The
|
||||
gate includes that case as an adversarial false-GO control. There is no sound
|
||||
place to return the required single cycle errno (`EDEADLK`) because the cycle
|
||||
identity cannot first be discovered.
|
||||
|
||||
## Result
|
||||
|
||||
`P15-032` is **STOP** and B39 is **STOP-NO-SOURCE**. Recursive I/O and its lock
|
||||
graph cannot be statically excluded for the requested regular-file source
|
||||
surface using documented generic FreeBSD interfaces. A safe future GO needs a
|
||||
new kernel dependency API that returns and pins transitive backing vnode
|
||||
identities, or an explicitly narrower feature contract whose permitted source
|
||||
filesystems have no hidden storage dependencies. Neither change is in B39's
|
||||
authorized write set.
|
||||
|
||||
Run from the repository root:
|
||||
|
||||
```sh
|
||||
repo-pre-15/tests/pre15/gates/P15-032.sh \
|
||||
--base bd5a09054e5cf89efd4db82aadb051f20b06ebf7 \
|
||||
--freebsd-src /work/build/freebsd-src \
|
||||
--output /absolute/owned/output/path
|
||||
```
|
||||
|
||||
No EROFS source, Makefile, feature documentation, B39 case, or B39 fixture is
|
||||
modified by this STOP addendum. D, H, K, Q, TC006, TC179, TC184, smoke, and the
|
||||
full feature suite are not run at the gate stage.
|
||||
@@ -0,0 +1,85 @@
|
||||
# P15-038 Stage0 Decision
|
||||
|
||||
Status: `GO`. B33 is authorized.
|
||||
|
||||
The authoritative frozen-BASE run is
|
||||
`planning/pre15/evidence/20260816T021736Z-G05-P15-038/` against
|
||||
`5d6755649a369498a9b257bb2d1d1e3496d5135e`. Its state model, hard-budget
|
||||
accounting, real codec oracle, eviction check, and owned cleanup all pass.
|
||||
|
||||
The gate compares the current LZMA-only admission policy with a test-only,
|
||||
codec-neutral single-entry decoded cache. Both variants execute the same 1,024
|
||||
deterministic random 4 KiB logical reads against the same 256 KiB payload for
|
||||
each of LZ4, LZMA, Deflate, and Zstd. Each variant has exactly five cold-cache
|
||||
samples; no sample may be discarded. The helper uses the frozen host
|
||||
liblz4/liblzma/zlib/libzstd libraries and performs real compression and full
|
||||
decode work. It contains no synthetic sleep.
|
||||
|
||||
This is an independent host codec-cost oracle. It can prove avoided codec work
|
||||
and byte correctness, but it is not guest vnode latency evidence and must not
|
||||
be reported as such. Provider I/O, map lookup, VOP dispatch, and guest kernel
|
||||
scheduling are outside its scope.
|
||||
|
||||
The state model preserves B32's exact key, one-owner, waiter, typed-failure,
|
||||
retry, and no-cache fallback rules. It additionally freezes mount-cache then
|
||||
global-budget lock order, reservation-before-decode accounting, codec-neutral
|
||||
work/size admission, disabled policy, global exhaustion, ready eviction,
|
||||
inflight reclaim refusal, successful reclaim, unmount drain, and key reuse.
|
||||
Reserved plus resident decoded bytes are charged to the same hard budget.
|
||||
|
||||
G05 is GO only if the state model closes, all current/candidate hashes match,
|
||||
eviction-before/after SHA-256 matches, every candidate sample stays within the
|
||||
fixed budget, and at least two codecs improve median latency by 10 percent or
|
||||
more. Any missing sample, correctness mismatch, lifecycle gap, or budget
|
||||
overflow is STOP for P15-038 only.
|
||||
|
||||
## Result
|
||||
|
||||
All five current and five candidate samples are retained for each codec. The
|
||||
median current/candidate latencies and improvements are:
|
||||
|
||||
| Codec | Current median | Candidate median | Improvement |
|
||||
|---|---:|---:|---:|
|
||||
| LZ4 | 44,988,337 ns | 6,583,335 ns | 85.367% |
|
||||
| LZMA | 7,278,779 ns | 7,286,634 ns | -0.108% |
|
||||
| Deflate | 186,791,959 ns | 6,102,297 ns | 96.733% |
|
||||
| Zstd | 20,355,035 ns | 6,236,635 ns | 69.361% |
|
||||
|
||||
Three codecs exceed the required 10 percent threshold. LZMA is the expected
|
||||
control because both current and candidate policies admit it; its negative
|
||||
0.108 percent delta is retained and is not excluded or rewritten.
|
||||
|
||||
Every candidate sample charges exactly 262,144 resident bytes against the
|
||||
262,144-byte mount budget. The state model reaches the 524,288-byte global
|
||||
limit with two mounts, proves a third mount's synchronous no-cache fallback,
|
||||
reclaims one reservation, retries successfully, and returns to zero bytes.
|
||||
It also passes 16-thread success and typed-failure waves, ready eviction,
|
||||
inflight reclaim refusal, key reuse, policy disable, low-work/oversize bypass,
|
||||
and unmount drain. The real Deflate decode before and after eviction has
|
||||
SHA-256 `5d3c21088380524a78c52b067d47a93117c5385464c5dfc83e8de598119511bb`.
|
||||
|
||||
No QEMU process was started by this pre-source gate. No guest vnode latency is
|
||||
claimed. No production source, B32 correctness path, B32 QEMU runner, protected
|
||||
PID 26318, port 9222, or shared base image was touched. B33 may now execute its
|
||||
exact write set and acceptance matrix.
|
||||
|
||||
## B33 Execution
|
||||
|
||||
B33 source/test commit `bc56f830918b76029871b60cca2e53992de70a2e`
|
||||
implements codec-neutral decoded-work/size admission with fixed hard mount and
|
||||
global budgets, loader configuration/disable controls, four-codec accounting,
|
||||
FreeBSD `vm_lowmem` reclaim, eviction, unmount release, and synchronous
|
||||
no-cache fallback. It changes only `src/internal.h` and `src/zdata.c` in the
|
||||
production tree and preserves the B32 key/inflight/failure contract.
|
||||
|
||||
D, authoritative H `20260816T025825Z-host-B33-cache-policy-1393732-0`, and
|
||||
FreeBSD 15 cross-KLD builds with zstdio0 and zstdio1 pass. The final H-tested
|
||||
seven-path source/test tree is byte-identical to the committed tree. Q
|
||||
TC168-cache-inflight is `INFRA_BLOCKED`: guest SSH was not ready at the exact
|
||||
absolute 300-second deadline, so no guest source, case target, KLD load, vnode
|
||||
latency, or guest PASS is claimed. Owned PID 1389807, overlay, and port 33537
|
||||
were cleaned; the protected process, port, and base metadata are unchanged.
|
||||
|
||||
The Q attempt predates the final replacement-order and policy-bypass-accounting
|
||||
changes and did not reach the DUT. Full correspondence details and exact hashes
|
||||
are in `planning/pre15/evidence/20260816T023315Z-B33/VERDICT.md`.
|
||||
@@ -0,0 +1,44 @@
|
||||
# P15-045 Stage0 Decision
|
||||
|
||||
Status: `STOP`. B35 is `STOP-NO-SOURCE`.
|
||||
|
||||
G07 is replayed against frozen BASE
|
||||
`13974efc00c31d8c13c8dccb7c65a82adafcbff6`. Its first mandatory condition
|
||||
is a concrete, versioned support/deployment manifest in existing project
|
||||
evidence that identifies deployment targets and explicitly requires Zstd to
|
||||
be enabled by default. General codec availability, prior Zstd test success,
|
||||
Linux defaults, and maintainer preference are intentionally nonqualifying.
|
||||
|
||||
The gate inventories every tracked path in the frozen
|
||||
`planning/pre15/evidence` tree (tree object
|
||||
`3ecce7a124d153638853ab5d897126c769125309`, 2,560 paths), locates every text
|
||||
record containing Zstd/Zstandard, and reviews records with deployment,
|
||||
support, manifest, policy, default, or requirement signals. It accepts either
|
||||
a structured JSON manifest or explicit text manifest headers, but requires a
|
||||
manifest kind, version, nonempty deployment/support targets, and an
|
||||
affirmative Zstd-default requirement together. The replay finds 596 Zstd text
|
||||
records and 206 demand-signal candidates; no record meets that contract.
|
||||
|
||||
The missing deployment-demand prerequisite determines STOP before runtime or
|
||||
build work. The disabled exact-`EOPNOTSUPP` runtime check, enabled real Zstd
|
||||
EROFS read, FreeBSD kernel `ZSTDIO` symbol/capability check, and KLD size delta
|
||||
measurement are therefore `NOT_RUN`; none is reported as PASS. In particular,
|
||||
the gate does not claim or attempt to load a generic dependency KLD. A
|
||||
false-GO guard requires every G07 condition to be PASS.
|
||||
|
||||
The frozen source is checked only to preserve the current policy boundary:
|
||||
`src/Makefile` contains exactly one `WITH_ZSTDIO?= 0` default, the disabled
|
||||
stub returns `EOPNOTSUPP`, and the documentation names kernel
|
||||
`options ZSTDIO`. These are static observations, not substitutes for the
|
||||
runtime conditions omitted after the prerequisite STOP.
|
||||
|
||||
The committed replay evidence is recorded under
|
||||
`planning/pre15/evidence/20260816T033449Z-G07-P15-045/`. The gate owns one
|
||||
temporary directory, uses a 90-second internal absolute timeout plus the
|
||||
recorded outer timeout, records argv, source/candidate hashes, exit status,
|
||||
and cleanup, and rejects an existing output directory.
|
||||
|
||||
No production source, B35 case, B35 fixture, QEMU process, full feature suite,
|
||||
or smoke suite is run or changed. Protected PID 26318, port 9222, and the
|
||||
shared base image are outside the gate. The supported policy remains opt-in
|
||||
`WITH_ZSTDIO=1`, with default `WITH_ZSTDIO?=0`.
|
||||
@@ -0,0 +1,74 @@
|
||||
# P15-052 Stage0 Decision
|
||||
|
||||
Status: `STOP`. B20 is complete as `STOP-NO-SOURCE`; B21 was not started.
|
||||
|
||||
The authoritative G06 replay uses frozen BASE
|
||||
`ca7bb4fe6b33e4a1bdf423801134b0ed6bda86dd`. It verifies the exact current
|
||||
FreeBSD and Linux source hashes, the FreeBSD amd64 `PAGE_SHIFT=12` contract,
|
||||
signed 64-bit `off_t`, and GEOM's `off_t mediasize` before evaluating every
|
||||
listed branch.
|
||||
|
||||
## Exact Branch Result
|
||||
|
||||
All twelve proposed on-disk arithmetic branches have unique source sites, but
|
||||
none has a target marker reachable from one validated on-disk field mutation.
|
||||
The current source text returns positive `EOVERFLOW` at those defensive sites;
|
||||
the proposed mapping would be positive `EINTEGRITY`. Linux has no matching
|
||||
checked branches in these functions, so its relevant semantic mapping is
|
||||
negative `-EFSCORRUPTED`, not a textual negative copy of the FreeBSD return.
|
||||
|
||||
The decisive counterexample to the supplied READY prototype is
|
||||
`xattr.metadata.header_add`. The prototype directly mutates the local
|
||||
`aligned_off` value. The real helper first rejects input above
|
||||
`UINT64_MAX - 3`, then rounds to four bytes. The greatest surviving aligned
|
||||
offset is therefore `UINT64_MAX - 3`; adding the two-byte header cannot
|
||||
overflow. The named branch cannot be independently reached.
|
||||
|
||||
The other prototype vectors likewise inject values outside current provenance:
|
||||
mounted image bytes are bounded by GEOM's signed `off_t mediasize`; inode size
|
||||
is bounded by `OFF_MAX`; decoded physical blocks are at most 48 bits;
|
||||
`blkszbits` is at most 12; prefix start and shared IDs are 32-bit. These bounds
|
||||
prevent each proposed shift, add, alignment, and index overflow before the
|
||||
listed target.
|
||||
|
||||
## Preserved Semantics
|
||||
|
||||
The replay separately freezes corruption, unsupported, provider I/O, EOF, and
|
||||
short-read behavior. Disk/backing range contradictions remain positive
|
||||
`EINTEGRITY`; exact zero-length EOF remains success; provider `EIO` and media
|
||||
`ENXIO` remain exact; unsupported xattr layout remains positive
|
||||
`EOPNOTSUPP`; allocation remains positive `ENOMEM` and outside B20. Linux
|
||||
counterparts retain negative errno or `PTR_ERR` propagation.
|
||||
|
||||
The nominal `erofs_xattr_read_backing()` `off > INT64_MAX` positive
|
||||
`EOVERFLOW` site is also not reachable for a mounted primary provider: the
|
||||
preceding range check requires `off <= backing_size`, while mount validation
|
||||
requires `backing_size <= INT64_MAX`. This site remains unchanged because a
|
||||
STOP decision has no source diff.
|
||||
|
||||
## Atomic Decision
|
||||
|
||||
G06 requires every listed branch to be independently reachable. One missing
|
||||
branch stops all of P15-052; this replay finds twelve missing target markers.
|
||||
No `data.c` or `xattr.c` errno is changed, no B20 case/fixture is created, and
|
||||
no candidate replay or QEMU run can cure a host-proven reachability failure.
|
||||
The full feature suite was not run.
|
||||
|
||||
The authoritative command was:
|
||||
|
||||
```sh
|
||||
timeout -k 10 240 tests/pre15/gates/P15-052.sh \
|
||||
--base ca7bb4fe6b33e4a1bdf423801134b0ed6bda86dd \
|
||||
--output OWNED_OUTPUT
|
||||
```
|
||||
|
||||
It exited 1 because a valid gate `STOP` is not `GO`. Two fresh output
|
||||
directories were byte-identical. The initial replay produced result SHA256
|
||||
`37280545d8ef5a6b87c7b9d536939513a1bbac8e4e4b2389e84f5ca77e1aa522`,
|
||||
branch-ledger SHA256
|
||||
`8024a2cb6b43bd10fbcf446cf8cf44de37f1f9d6df25718c641cb9db4c257169`,
|
||||
and preservation-ledger SHA256
|
||||
`d17e05b8df43ea5173bed6e58d7431b37a7a9c4a143e07717b543efcb54ecc66`.
|
||||
|
||||
B21 is not authorized because the execution request requires B20 PASS before
|
||||
B21. Wave16 is therefore not ready from this serial chain.
|
||||
@@ -0,0 +1,13 @@
|
||||
# P15-057 Stage0 Decision
|
||||
|
||||
Status: `GO`; B17 is complete.
|
||||
|
||||
The B17 fixture gate contains 25 reproducible EROFS images and independently
|
||||
freezes all legal results and damaged positive FreeBSD errnos. The source
|
||||
commit `433cf4ec66478b65b291ec5b21a0bf6d806bd14f` preserves the raw xattr filter
|
||||
feature declaration, saves its reserved byte, and gates the current filter
|
||||
format only at the ACL use site. Reserved values 0, 1, and 255 and feature
|
||||
present/absent combinations pass host and minimal FreeBSD 15 QEMU replay.
|
||||
|
||||
Evidence is in `planning/pre15/evidence/20260814T203439Z-B17/`. This decision
|
||||
does not authorize the separate cache, Bloom, or ordering batches.
|
||||
@@ -0,0 +1,13 @@
|
||||
# P15-058 Stage0 Decision
|
||||
|
||||
Status: `GO`; B17 is complete.
|
||||
|
||||
The B17 corpus separately covers inline names, shared names, and long-prefix
|
||||
infixes containing embedded NUL, with independently frozen `EINTEGRITY` (97)
|
||||
reject points. It also covers legal ACL empty-suffix names and short/long
|
||||
name-index failures. Source commit
|
||||
`433cf4ec66478b65b291ec5b21a0bf6d806bd14f` rejects only the length-delimited
|
||||
embedded-NUL formats and retains the FreeBSD namespace and extattr ABI.
|
||||
|
||||
Evidence is in `planning/pre15/evidence/20260814T203439Z-B17/`. This decision
|
||||
does not include xattr cache, Bloom, or call-order changes.
|
||||
@@ -0,0 +1,89 @@
|
||||
# P15-062 Stage0 Decision
|
||||
|
||||
Status: `STOP`. B26 is `STOP-NO-SOURCE`; no production source, B26 case, or
|
||||
B26 fixture is authorized.
|
||||
|
||||
The decision is bound to DUT BASE
|
||||
`205a90465edb64e83ba44aaacac9bedad4cbe905`, FreeBSD source HEAD
|
||||
`106727738dcfb6c001b46f25363b91cece970085`, and exact upstream erofs-utils
|
||||
commits for v1.4, v1.7, and v1.8.6. The authoritative gate evidence and final
|
||||
script/input hashes are recorded below and in the G04 evidence commit.
|
||||
|
||||
The later B26 terminal review is recorded at
|
||||
`planning/pre15/evidence/20260817T-B26-terminal-review/VERDICT.md`.
|
||||
It retains `STOP_NO_SOURCE / NOT_TESTED` and adds secondary
|
||||
`TERMINAL_REVIEWED_NO_SOURCE`. It found the historical zero-tail shape to be
|
||||
reproducible, but did not establish that trailing zeros are format-mandated or
|
||||
that current FreeBSD rejects them.
|
||||
|
||||
## Authoritative Run
|
||||
|
||||
The gate ran from `/work/erofs-freebsd-pre` as:
|
||||
|
||||
```sh
|
||||
timeout -k 10 240 repo-pre-15/tests/pre15/gates/P15-062.sh \
|
||||
--base 205a90465edb64e83ba44aaacac9bedad4cbe905 \
|
||||
--output planning/pre15/evidence/20260815T062257Z-G04-P15-062/gate-output
|
||||
```
|
||||
|
||||
It returned the gate-defined STOP exit status 1. Evidence is rooted at
|
||||
`planning/pre15/evidence/20260815T062257Z-G04-P15-062/`. The authoritative
|
||||
script SHA-256 is
|
||||
`6af503f1612eb42410f91a54fdc37481bae86a4419232c9de48c08bfa7ecee5d` and
|
||||
the input SHA-256 is
|
||||
`390202738ac006aba2514d27d3b0a19a0123a009601a26cac3b560a3dff388e5`.
|
||||
The result SHA-256 is
|
||||
`597466203edcaee6d163651a6d6a05e49dff24f39201234911f9753b29eebbe0`.
|
||||
|
||||
## Decision Rule
|
||||
|
||||
G04 permits P15-062 only if every normative and historical full LZ4 input uses
|
||||
the same exact-consumption rule. The B26 review found that the old fsck
|
||||
acceptance path uses `LZ4_decompress_safe_partial()` for legacy/no-0padding
|
||||
images, so that acceptance does not prove full physical consumption or format
|
||||
legality. The format sources contain no stored compressed-stream length or
|
||||
general trailing-zero rule. The current FreeBSD decoder accepts an all-zero
|
||||
remainder and rejects nonzero remainder bytes; no implementation defect was
|
||||
demonstrated.
|
||||
|
||||
## Reproducible Corpus
|
||||
|
||||
The gate builds three upstream mkfs generations from exact commits in an owned
|
||||
temporary directory. Each version twice generates the same fixed-time,
|
||||
fixed-UUID, root-owned, xattr-free legacy LZ4 image from the same deterministic
|
||||
1 MiB file. Matching `fsck.erofs --extract` accepts each image. The image,
|
||||
source, build tree, and binaries remain temporary and are not committed.
|
||||
|
||||
The independent parser reconstructs the complete file from two physical
|
||||
pclusters. The final extent has `m_plen=4096`, but its raw LZ4 stream reaches
|
||||
9,670 decoded bytes after consuming 48 bytes; the remaining 4,048 bytes are
|
||||
zero. This shape is byte-reproducible in v1.4, v1.7, and v1.8.6. The current
|
||||
FreeBSD decoder accepts the whole input and liblz4 accepts the 48-byte exact
|
||||
stream but rejects the block-sized input. The zero-tail shape is therefore a
|
||||
historical tool-compatible candidate, not a proven format-legal fixture.
|
||||
|
||||
## Partial and Corruption Controls
|
||||
|
||||
A separate v1.8.6 `-Ededupe` image contains two real noncompact
|
||||
`Z_EROFS_LI_PARTIAL_REF` records that share an LZ4 pcluster. The independent
|
||||
parser, liblz4 partial API, and frozen DUT callback agree on the 4,096- and
|
||||
5,594-byte prefixes. Corruption beginning after the 4,096-byte request remains
|
||||
undetected by that partial read but causes the same fixture's full decode to
|
||||
return positive `EINTEGRITY` (97), as required by G04. Truncation and nonzero
|
||||
tail controls also return 97; all output guards remain unchanged.
|
||||
|
||||
Production `zdata.c` ownership anchors show that metadata/physical input is
|
||||
released after every decoder return, failed decoded output is freed, and only
|
||||
successful output is published. The decoder itself allocates and owns no
|
||||
buffers. The gate's owned build/image directory is removed, and it does not
|
||||
start QEMU or touch protected PID 26318, port 9222, or the shared base image.
|
||||
|
||||
## Consequence
|
||||
|
||||
P15-062 remains STOP for Pre15 because B26 has no authorized production source,
|
||||
case, or fixture. `src/decompressor_lz4.c`,
|
||||
`tests/pre15/cases/B26-lz4-input.sh`, and `tests/pre15/fixtures/B26-*` remain
|
||||
unchanged or absent as applicable. B26 acceptance D, exact-ABI build, TC167
|
||||
QEMU, and the full feature suite are not run because no implementation error
|
||||
was demonstrated. The secondary B26 status is
|
||||
`TERMINAL_REVIEWED_NO_SOURCE`.
|
||||
@@ -0,0 +1,75 @@
|
||||
# P15-076 Stage0 Decision
|
||||
|
||||
Status: `STOP`. B29 is `STOP-NO-SOURCE`.
|
||||
|
||||
The gate is bound to frozen DUT BASE
|
||||
`3e9bc3f03ba9c39c38cc40f2f08eb6e769557f55` and FreeBSD source HEAD
|
||||
`106727738dcfb6c001b46f25363b91cece970085`. Three host attempts are retained:
|
||||
|
||||
- `20260815T170841Z-G05-P15-076`: `RUNNER_FAIL`, FreeBSD headers shadowed
|
||||
glibc headers during host compilation.
|
||||
- `20260815T170931Z-G05-P15-076`: `RUNNER_FAIL`, the Deflate oracle compared
|
||||
one selected extent with the complete source payload.
|
||||
- `20260815T171051Z-G05-P15-076`: the runner returned 0, but final review
|
||||
rejects its local `GO` because mandatory state-model conditions are not
|
||||
closed.
|
||||
|
||||
## Last Attempt Command
|
||||
|
||||
```sh
|
||||
timeout -k 10 240 repo-pre-15/tests/pre15/gates/P15-076.sh \
|
||||
--base 3e9bc3f03ba9c39c38cc40f2f08eb6e769557f55 \
|
||||
--output planning/pre15/evidence/20260815T171051Z-G05-P15-076/gate-output
|
||||
```
|
||||
|
||||
The command returned 0 in three seconds. The gate script SHA-256 is
|
||||
`1d2cc18de150c8bdeb4fa8d284ab345f9ec4249c2ba1b50e1badbe7f942b42dc`,
|
||||
the input SHA-256 is
|
||||
`30497cf86785c367dcd4a3d6889ba6a6302f6f133d68e4af31d984a1031e0058`,
|
||||
and the result SHA-256 is
|
||||
`ac007afc4ad5a97bb1561888105c67612d3eea5427f77c54a858bede4c86e0a3`.
|
||||
|
||||
## Benefit Result
|
||||
|
||||
The last attempt regenerates the frozen B28 EROFS fixtures in owned temporary
|
||||
storage and decodes the exact selected LZMA, Deflate, and Zstd extents. Input,
|
||||
expected output, and output buffers are outside the tracked allocator region.
|
||||
Baseline creates and destroys a context per decode; the prototype resets one
|
||||
context across 64 exact decodes. Seven samples are retained per mode.
|
||||
|
||||
| Codec | Baseline events | Reused events | Reduction | Measured peak |
|
||||
|---|---:|---:|---:|---:|
|
||||
| LZMA | 128 | 2 | 98.4375% | 28,504 B |
|
||||
| Deflate | 256 | 4 | 98.4375% | 39,928 B |
|
||||
| Zstd | 128 | 2 | 98.4375% | 95,992 B |
|
||||
|
||||
All tracked baseline backend allocator events are context lifecycle events, so
|
||||
the measured share is 100 percent and passes the 10 percent threshold. All
|
||||
three event reductions pass the 25 percent threshold. Exact output and
|
||||
balanced allocation/free counts pass. CPU remains diagnostic: Deflate is
|
||||
1.30 percent faster, LZMA is 10.20 percent slower, and Zstd is 15.35 percent
|
||||
faster by median per-decode time; the LZMA regression is retained.
|
||||
|
||||
## STOP Review
|
||||
|
||||
G05 requires both the benefit threshold and a complete pre-source state model.
|
||||
The retained runner does not establish a hard memory limit: its 329,616-byte
|
||||
mount and 2,636,928-byte global calculations use peaks from representative
|
||||
streams. In particular, its Zstd prototype sets `ZSTD_d_windowLogMax` to 16,
|
||||
while the frozen DUT accepts values through 20. The measured 95,992-byte Zstd
|
||||
peak therefore is not a hard bound for the production-supported range. LZMA is
|
||||
also sampled with a 65,536-byte dictionary while the DUT accepts up to 8 MiB.
|
||||
|
||||
The state model also does not execute a global-exhaustion transition. It sets
|
||||
`global_owned` and `mount_owned` to the mount limit of two and selects fresh
|
||||
allocation because the mount is full; the independent global limit of 16 is
|
||||
never reached. Text describing global exhaustion cannot replace that missing
|
||||
assertion. Therefore the hard-cap and global-exhaustion requirements are not
|
||||
closed, and the runner-local `GO` cannot authorize source work.
|
||||
|
||||
No threshold, sample, or result is changed to force a decision. Per G05, one
|
||||
failed mandatory condition makes P15-076 `STOP`; B29 is recorded
|
||||
`STOP-NO-SOURCE`. No production `src/**`, B29 case, fixture, or helper was
|
||||
changed. B29 H/K/Q acceptance, QEMU, and the full feature suite were not run.
|
||||
The hard-timeout D check passed. Owned temporary cleanup passed; protected PID
|
||||
26318, port 9222, and the shared base image were untouched.
|
||||
@@ -0,0 +1,95 @@
|
||||
# P15-081 Stage0 Decision
|
||||
|
||||
Status: `GO`. B11 is authorized; no production source was modified by this
|
||||
decision.
|
||||
|
||||
The authoritative G11 replay uses frozen B25 BASE
|
||||
`e2e3fb86b6fffcb01d6fd29c17dd95628ad070de`, FreeBSD source HEAD
|
||||
`106727738dcfb6c001b46f25363b91cece970085`, and
|
||||
`mkfs.erofs (erofs-utils) 1.8.6`. The gate script and input SHA256 values are
|
||||
`6215a3005214ba8d25dacd63e039320a0c63308d2334b5faff99a3927cad7d2e`
|
||||
and `a887fad56927545adb48462b770100d1e64b22b32554ed8ffad14c72b8febfc3`.
|
||||
|
||||
## Real Disk and Normal Entrypoint
|
||||
|
||||
The gate independently materializes a deterministic source tree containing
|
||||
regular, directory, character-device, block-device, FIFO, socket, symlink,
|
||||
and two hardlink names. It invokes mkfs twice with fixed UUID, time, ownership,
|
||||
worker count, xattr policy, and inline-data policy. It also fixes and restores
|
||||
the process umask and explicitly sets every source-node mode. Complete
|
||||
replays under outer umask `022` and `077`, including both seed generations in
|
||||
each replay, are byte-identical.
|
||||
|
||||
The gate parses the actual superblock, checksum range, root inode, inline root
|
||||
directory, 12-byte dirents, NIDs, and compact inode modes without using DUT
|
||||
helpers. Every derived image changes one real dirent byte and recomputes the
|
||||
superblock CRC32C. `dump.erofs --ls --path=/` observes the mutated on-disk
|
||||
`file_type`, while `dump.erofs --path=/NAME` reaches the same NID and reports
|
||||
the inode kind from its mode. This gives 13 normal namespace resolutions from
|
||||
real disk fields: eight known mismatches and five forward-compatibility cases.
|
||||
|
||||
All eight known mismatches are checksum-valid, fsck-clean images and yield
|
||||
positive FreeBSD `EINTEGRITY` in the independent candidate oracle. Type zero,
|
||||
nonzero dirent reserved bytes, and out-of-range type 8/255 remain accepted by
|
||||
the DUT policy and candidate oracle. erofs-utils fsck separately rejects 8/255;
|
||||
the evidence records that as `policy-reject` rather than falsely claiming
|
||||
fsck-clean. P15-093 already freezes the FreeBSD behavior for these extension
|
||||
values as `DT_UNKNOWN`, so fsck's stricter userspace policy does not override
|
||||
the G11 compatibility boundary.
|
||||
|
||||
## Cache and Lock Boundary
|
||||
|
||||
`regular` and `regular-hard` are different namespace keys with the same real
|
||||
NID. The first normal lookup can instantiate the vnode; the second name misses
|
||||
that namecache key and reaches the existing `erofs_vget()` path, whose frozen
|
||||
body checks `vfs_hash_get()` before inode decode. Mutating only the second
|
||||
dirent to known directory type therefore provides the required cached-vnode
|
||||
trigger without adding a readdir-time vget.
|
||||
|
||||
The generated candidate patch adds no lock, vget, hash, or recursive lookup
|
||||
call. It reads immutable `vtype` after the existing child lookup, returns
|
||||
positive `EINTEGRITY` for a known mismatch, drops the locked child with
|
||||
`vput()`, and runs before `a_vpp` and namecache publication. Dotdot's existing
|
||||
`vn_vget_ino()` path explicitly bypasses the validator because root `..` can
|
||||
return the directory vnode itself; this preserves its parent-lock contract.
|
||||
The parent/child lock order, readdir cookies, and VFS/VOP entrypoints are
|
||||
unchanged. Readdir still contains no vnode lookup.
|
||||
|
||||
Linux supplies the format mapping: EROFS file type values match generic Linux
|
||||
`FT_*`, and Linux readdir maps those values with `fs_ftype_to_dtype()`. The
|
||||
candidate aligns that known-type mapping while retaining FreeBSD vnode types,
|
||||
the FreeBSD 15 `__enum_uint8(vtype)` ABI type, positive errno, VFS locks, and
|
||||
forward handling for unknown values.
|
||||
|
||||
## Replay Result
|
||||
|
||||
The authoritative command was:
|
||||
|
||||
```sh
|
||||
timeout -k 10 240 tests/pre15/gates/P15-081.sh \
|
||||
--base e2e3fb86b6fffcb01d6fd29c17dd95628ad070de \
|
||||
--output OWNED_OUTPUT
|
||||
```
|
||||
|
||||
It exits zero with `GO`: 14 generated images, eight known-match records
|
||||
including the hardlink alias, eight known mismatches, five compatibility
|
||||
cases, 13 normal entrypoint observations, one cached-vnode sequence, and 21
|
||||
compiled prototype records. Two fresh output directories are byte-identical. The fixture-set
|
||||
SHA256 is
|
||||
`b562a7e42e139b16f3ce399d585aa7c373a66aa478a084bfed67b2b2aa9f2bd3`.
|
||||
|
||||
Key immutable evidence SHA256 values are:
|
||||
|
||||
- `result.json`: `4ec8e053c60ae75ae2fc4580a3d820a0452cf519f6b85376953135e18a7ec0ec`
|
||||
- `oracle.json`: `932e558d3ead05572f38c89635bb10cae45393e42028031f81dfc7a56f2093f6`
|
||||
- `lock-ledger.json`: `e8c2e6ba797fbcc83d832af6583d3f74f344750f6897111e7fe501130e577c13`
|
||||
- `fixture-index.json`: `1a46b8ebfec16109c5d193001dc650a1b56000045e5d9e1e9b145fe7c5df9a16`
|
||||
- `candidate.patch`: `427097da9304f5bedb770be8cab5f589706d316fb18a152ca16cb9d0663713fd`
|
||||
- `prototype.c`: `1a295d18830c61a9708d465c3b1e415efb3ff8276100e4e32139bfa715195d8b`
|
||||
- `normal-entry.tsv`: `b2841448068f70633ed0c02d901177a639cfed150f0e1c58977cc6c7b1e7313e`
|
||||
- `SHA256SUMS`: `36b486617920b04ca87e88016e2fc0f519cda3a5f99dc675c9a89549615a02e3`
|
||||
|
||||
QEMU and the full feature suite were not run for this pre-source gate. The
|
||||
gate uses host-created real EROFS images, independent binary parsing, normal
|
||||
userspace namespace resolution, frozen DUT/FreeBSD control flow, and a
|
||||
compiled prototype that is not linked into the DUT KLD.
|
||||
@@ -0,0 +1,101 @@
|
||||
# P15-083 Stage0 Decision
|
||||
|
||||
Status: `GO`. G04 authorizes B27 for all three non-LZ4 codecs. The source batch
|
||||
must preserve the exact policies below and may not import the P15-062 LZ4 STOP
|
||||
rule.
|
||||
|
||||
The gate is bound to DUT BASE
|
||||
`68bbe94c44e35d53cec8ab55d007f40b01cf0502`, FreeBSD source HEAD
|
||||
`106727738dcfb6c001b46f25363b91cece970085`, erofs-utils 1.8.6, liblzma
|
||||
5.8.1, zlib 1.3.1, and libzstd 1.5.7.
|
||||
|
||||
## Authoritative Run
|
||||
|
||||
The gate ran from `/work/erofs-freebsd-pre` as:
|
||||
|
||||
```sh
|
||||
timeout -k 10 240 repo-pre-15/tests/pre15/gates/P15-083.sh \
|
||||
--base 68bbe94c44e35d53cec8ab55d007f40b01cf0502 \
|
||||
--output planning/pre15/evidence/20260815T142600Z-G04-P15-083/gate-output
|
||||
```
|
||||
|
||||
It returned 0 and recorded `GO`. Evidence is rooted at
|
||||
`planning/pre15/evidence/20260815T142600Z-G04-P15-083/`. The authoritative
|
||||
script SHA-256 is
|
||||
`6847541266b0668ad12442ffb54b67a772a29ed8ebe6fba0e1e25214db16b2c2`, the
|
||||
input SHA-256 is
|
||||
`b3c71b4ae03c6f9511246813952aab3178a1451433ece96f04562ec7cc6c1d1e`, and
|
||||
the result SHA-256 is
|
||||
`b9431b3819d64cdf940dff05ce7bc0e0bdf44c3ec647c90592052af5f7b3e544`.
|
||||
|
||||
## Decision Rule
|
||||
|
||||
P15-083 is GO only if LZMA, Deflate, and Zstd each have a reproducible real
|
||||
EROFS fixture, an independent consumed-byte oracle, and a codec-specific policy
|
||||
that distinguishes EROFS leading zero padding from unread nonzero bytes. Any
|
||||
missing codec oracle, legal image rejected by the proposed full-stream policy,
|
||||
or inability to distinguish trailing garbage makes the whole candidate STOP.
|
||||
|
||||
## Reproducible Corpus
|
||||
|
||||
erofs-utils 1.8.6 twice generates each fixed-time, fixed-UUID, root-owned,
|
||||
xattr-free image from the same 151,552-byte source. Matching fsck extraction
|
||||
reconstructs the complete source. The image hashes are:
|
||||
|
||||
| Codec | Image SHA-256 | Selected real extent | Leading zero padding | Stream |
|
||||
|---|---|---:|---:|---:|
|
||||
| LZMA | `c26cf15844fe45a21a746bacbad2ef551c683bb9b2538de7a7eced37d8eadff9` | 4,096 + 4,096 | 3,556 | 540 |
|
||||
| Deflate | `39455150c3e999bb7ae6c36402c15a408a5679726b6d099e7d121e009ef43af6` | 28,672 + 4,096 | 1,479 | 2,617 |
|
||||
| Zstd | `b905803f0e08500cc3c6cfe07a95fe027859165acae19ca8865856af256f32ca` | 4,096 + 4,096 | 1,092 | 3,004 |
|
||||
|
||||
The leading zero bytes are legal EROFS pcluster padding. They are removed by
|
||||
the common dispatch before the codec callback, matching Linux
|
||||
`z_erofs_fixup_insize()`. Every remaining legal stream reaches the format end,
|
||||
consumes every byte, reproduces the selected logical extent, and leaves its
|
||||
output guards intact.
|
||||
|
||||
## Per-Codec Policy
|
||||
|
||||
- Deflate: a full raw stream must reach `Z_STREAM_END` with no unread input.
|
||||
The independent zlib decoder consumes 2,617 of 2,625 bytes after an 8-byte
|
||||
nonzero tail and reproduces the output. fsck also accepts that mutation, as
|
||||
does the Linux streaming loop when output is already full, but the bytes are
|
||||
not EROFS leading padding and no mkfs fixture emits them. The audited FreeBSD
|
||||
full policy rejects them with positive `EINTEGRITY` (97).
|
||||
- LZMA: MicroLZMA stores no end marker and requires an exact compressed size.
|
||||
The legal 540-byte stream consumes all bytes. Adding the same tail produces
|
||||
liblzma status 9 after consuming 540 of 548 bytes; fsck rejects it and the
|
||||
FreeBSD policy returns 97.
|
||||
- Zstd: exactly one frame must finish with no unread input. The library finds
|
||||
frame end after 3,004 of 3,012 bytes with the tail present; fsck rejects the
|
||||
source-size mismatch and the FreeBSD policy returns 97. A concatenated or
|
||||
skippable second frame is not EROFS pcluster padding.
|
||||
|
||||
This is deliberately codec-specific. It aligns Linux's non-LZ4 leading-padding
|
||||
placement and stream completion semantics without copying the Linux wrappers'
|
||||
implicit unread-byte acceptance into the FreeBSD provider path.
|
||||
|
||||
## Partial, Corruption, and Cleanup
|
||||
|
||||
The independent libraries decode real-stream prefixes that match the full
|
||||
slice: Deflate produces 3,587 bytes after consuming 715, LZMA produces 4,096
|
||||
after consuming 352, and Zstd produces 4,096 after consuming 1,457. Replacing
|
||||
the final 64 stream bytes with zero begins strictly after each partial
|
||||
consumption boundary. The same partial request still succeeds and matches;
|
||||
full decode and fsck both fail for all three codecs, with the audited FreeBSD
|
||||
policy mapping the full failure to 97. Removing the final compressed byte also
|
||||
returns 97 for all three.
|
||||
|
||||
Every library path reports cleanup complete and unchanged guards. Frozen
|
||||
`zdata.c` releases metadata or physical input after the callback, frees failed
|
||||
decoded output, and publishes only successful output. The owned temporary tree
|
||||
was removed. QEMU, protected PID 26318, port 9222, and the shared base image
|
||||
were not touched. The full feature suite was not run.
|
||||
|
||||
## Consequence
|
||||
|
||||
B27 may now make these three existing policies explicit in the exact planned
|
||||
write set and add TC176 host/QEMU coverage. It must preserve positive FreeBSD
|
||||
errno, optional Zstd ABI, provider/GEOM ownership, input release, failed-output
|
||||
free, and successful-output lifetime. The generated images, extracted files,
|
||||
oracle source, and oracle binary remain temporary and are not committed.
|
||||
@@ -0,0 +1,147 @@
|
||||
# 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:
|
||||
|
||||
```sh
|
||||
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/`.
|
||||
@@ -0,0 +1,95 @@
|
||||
# P15-087 Stage0 Decision
|
||||
|
||||
Status: `STOP`. B12 is `STOP-NO-SOURCE`; no production source, B12 case, or
|
||||
B12 fixture is authorized.
|
||||
|
||||
The final decision uses frozen DUT BASE
|
||||
`c7d692acf9166f5c5e42335db2de64f0793ba8a2`, FreeBSD source HEAD
|
||||
`106727738dcfb6c001b46f25363b91cece970085`, and
|
||||
`mkfs.erofs (erofs-utils) 1.8.6`. The final gate script and input SHA256 values
|
||||
are `349720b900ad2288153c9830f5f5ee84b8da707c06ffabcbd8e3e7a7e89f9e2a`
|
||||
and `cb3aaa6c780c7b1efbd7c339f2b2da2ed8bf38d3ba32229dc17996807fd00787`.
|
||||
|
||||
## Workload and Independent Oracle
|
||||
|
||||
The gate deterministically creates 18,000 long-name regular files. Since
|
||||
erofs-utils tailpacks the root directory even with `-E noinline_data`, the
|
||||
generator moves the final 1,456-byte tail into one appended contiguous block,
|
||||
changes only the root layout from flat-inline to flat-plain, increments the
|
||||
superblock block count, and recomputes CRC32C. A second generation is
|
||||
byte-identical and `fsck.erofs -d0` exits zero.
|
||||
|
||||
The independent parser does not call DUT code. It verifies a 3,880,368-byte
|
||||
flat-plain directory at physical block 282, covering 948 contiguous 4 KiB
|
||||
blocks and 18,002 entries. Its expected final cookie is 3,880,368 and its
|
||||
record FNV64 is `427bb414efa99dc0`; the random offset is 1,937,408. The fixture
|
||||
SHA256 is `3ecc5b706dd43b734c7e14a648a2bed2fb97a9f7963d4db703d15de81dc07a9d`.
|
||||
The immutable `oracle.json` SHA256 is
|
||||
`f247bbe5029301265342ff2098fcbd463a25e4752608826cbc1126d6620ef5d6`.
|
||||
|
||||
The generated prototype patch SHA256 is
|
||||
`33b25131a611eec9c8731e88e4c258dfc92fe5897dd6781b6c95414a846dd2d1`.
|
||||
Static extraction proves that it calls `breadn` only on the mapped backing
|
||||
`devvp`, does not call `breadn` on the EROFS directory vnode, caps the window
|
||||
at exactly 1 MiB, gates readahead on an offset-zero sequential readdir, and
|
||||
adds no VM entrypoint, vnode lock, GEOM ownership operation, `cluster_read`,
|
||||
or errno token. The `semantic-ledger.json` SHA256 is
|
||||
`d26dbc37f4f34f65d07745a1b8069217d18545436d7f16f24e775e8c2db1a6b3`.
|
||||
This closes the static design boundary but cannot replace runtime proof.
|
||||
|
||||
## Quantitative Decision
|
||||
|
||||
| Required G11 measurement | Required | Valid result | Decision |
|
||||
|---|---:|---:|---|
|
||||
| Cold sequential runs | 5 baseline + 5 prototype | 0 + 0 | FAIL: no median |
|
||||
| Median latency improvement | at least 10% | not measurable | FAIL |
|
||||
| Extra provider reads | at most 25% | not measurable | FAIL |
|
||||
| Readahead window | at most 1 MiB | 1 MiB static cap | PASS |
|
||||
| Random seek readahead | zero | 0 valid runtime samples | FAIL: not verified |
|
||||
| Hash/cookie equality | exact independent oracle | 0 valid runtime samples | FAIL: not verified |
|
||||
|
||||
No run produced `runs.tsv`; therefore no latency, read-transfer, random-no-op,
|
||||
or runtime hash/cookie value is claimed. It would be dishonest to infer GO
|
||||
from the static prototype, from QEMU startup, or from build progress. Because
|
||||
the workload could not be measured credibly and repeatably, G11's explicit
|
||||
rule requires low-confidence STOP even though the 1 MiB static bound passes.
|
||||
|
||||
## Replay Ledger
|
||||
|
||||
The authoritative command shape was:
|
||||
|
||||
```sh
|
||||
timeout -k 30 1200 tests/pre15/gates/P15-087.sh \
|
||||
--base c7d692acf9166f5c5e42335db2de64f0793ba8a2 \
|
||||
--output OWNED_OUTPUT
|
||||
```
|
||||
|
||||
Existing evidence was retained long enough to hash and reconcile before
|
||||
repository cleanup:
|
||||
|
||||
| Run ID | Result before any benchmark sample |
|
||||
|---|---|
|
||||
| `20260815T044720Z-G11-P15-087` | Superseded generator STOP: mkfs root remained flat-inline |
|
||||
| `20260815T044924Z-G11-P15-087` | `INFRA_BLOCKED`: 12 boot-time providers exceeded SSH deadline |
|
||||
| `20260815T045505Z-G11-P15-087` | `INFRA_BLOCKED`: FreeBSD did not enumerate PCI-hotplugged virtio-blk devices |
|
||||
| `20260815T050003Z-G11-P15-087` | `INFRA_BLOCKED`: guest benchmark declaration error |
|
||||
| `20260815T050520Z-G11-P15-087` | `INFRA_BLOCKED`: baseline KLD load did not reach workload |
|
||||
| `20260815T051933Z-G11-P15-087` | `INFRA_BLOCKED`: phased baseline KLD load did not reach workload |
|
||||
| `20260815T053543Z-G11-P15-087` | `INFRA_BLOCKED`: exact-basename baseline KLD load did not reach workload |
|
||||
| `20260815T054540Z-G11-P15-087` | Aborted on instruction; owned process group terminated and audited |
|
||||
|
||||
Each completed QEMU ownership record reports that the owned port was free
|
||||
after cleanup, protected PID 26318 retained the same identity, protected port
|
||||
9222 was not used, and `/work/build/vm-freebsd-build.qcow2.bp` retained inode,
|
||||
size, mtime, and ctime. The interrupted run used owned PID 1172175 and port
|
||||
49845; both were absent after targeted process-group cleanup. Final process
|
||||
audit found only protected QEMU PID 26318.
|
||||
|
||||
## Semantic and Batch Consequences
|
||||
|
||||
Runtime preservation of FreeBSD vnode, VM, locking, GEOM, errno, hash, and
|
||||
cookie behavior was not established. Correctness may not depend on
|
||||
readahead, so static plausibility is insufficient. P15-087 is STOP for Pre15,
|
||||
B12 remains absent, and no host feature case, K0 build, TC183 QEMU acceptance,
|
||||
or full feature suite is run. Rollback is the single gate decision commit;
|
||||
there is no source commit to revert.
|
||||
@@ -0,0 +1,142 @@
|
||||
# P15-092 Stage0 Decision
|
||||
|
||||
Status: `STOP`. B15 is `STOP-NO-SOURCE`; terminal static review status is
|
||||
`TERMINAL_REVIEWED_NO_SOURCE`. No production source, B15 case, or B15 fixture
|
||||
was created. Historical acceptance remains `NOT_TESTED`.
|
||||
|
||||
P15-092 is the G11 zero-nlink candidate. The frozen BASE is
|
||||
`b22dae8dc634c68db4ea89dccade91350614c139`, the FreeBSD source HEAD is
|
||||
`106727738dcfb6c001b46f25363b91cece970085`, the erofs-utils source HEAD is
|
||||
`7db78788b000999e2de88decd2ba90654f26171c`, and the generator is
|
||||
`mkfs.erofs (erofs-utils) 1.8.6`. Linux EROFS identity is frozen by the three
|
||||
source hashes in `P15-092-input.json` and the Pre15 semantic audit hash ledger.
|
||||
|
||||
The final gate script and input SHA256 values are
|
||||
`5943b85864da9095174ef51d1eed032ec6f0a1766c6465cb9660ea20cbd46b1e`
|
||||
and `0a6f6c76185644d3f5525a98429a310027556ef3cf7ebb43abb912f92e052bde`.
|
||||
|
||||
## Real Disk Oracle
|
||||
|
||||
The gate creates the same deterministic source tree twice in forced compact
|
||||
form and twice in forced extended form. It uses fixed UUID, timestamp, worker
|
||||
count, xattr policy, and inline-data policy. Both complete host output trees
|
||||
are byte-identical.
|
||||
|
||||
An independent parser reads the real superblock, checksum span, metadata block,
|
||||
root NID, directory entries, compact `i_nb.nlink`, extended `i_nlink`, and the
|
||||
compact `EROFS_I_NLINK_1_BIT` rule. It then materializes seven images:
|
||||
|
||||
- compact and extended positive seeds;
|
||||
- namespace-reachable compact, extended, and directory inodes with nlink zero;
|
||||
- a root inode with nlink zero;
|
||||
- an unreachable inode with nlink zero, whose former name is redirected to a
|
||||
real hardlink NID and whose replacement link count is corrected to three.
|
||||
|
||||
Every derived image has a recomputed valid EROFS CRC32C. `dump.erofs --path`
|
||||
resolves the actual directory edge and NID; no DUT helper or internal value
|
||||
injection is used. All seven images, including all three namespace-reachable
|
||||
zero-nlink images, pass `fsck.erofs -d0` with no error marker. The fixture-set
|
||||
SHA256 is `99897d4fd81da015bdaa66a5dfdbf3f42e9e830882c0d8c979e691fa9209ee7a`.
|
||||
|
||||
Key deterministic host evidence SHA256 values are:
|
||||
|
||||
- `host-result.json`: `59a27e9389e2771c921d689f6b76caeb858f0fd28487a933529153727aac12e8`
|
||||
- `disk-records.json`: `44bf0355dc5b34e93ec6868db9f9049de32500591b048a9016bf46aed9609485`
|
||||
- `boundary.json`: `985df1236c6dd2016d6cb244b71578d36bd4cd10aa273b60a92d5bb6d24d5b60`
|
||||
- `format-semantics.json`: `88efc1d7814103c044b36ff4dc3cac1dfa4da79f3d8955c682d1a60d9bfd9fcf`
|
||||
- `fixture-index.json`: `4d2b69bcc31709ecb96cfafb41f5db8ffcc97215c3290cfa476d0b6c7fc27886`
|
||||
- `source-anchors.json`: `ef9e6871d5fe1a3a6113f1172340269da4ea0c1692003aad0b0fee06ec4deb42`
|
||||
|
||||
## Linux and FreeBSD Semantics
|
||||
|
||||
Linux EROFS calls `set_nlink()` with the compact or extended disk value and has
|
||||
no zero-nlink rejection in inode decode or super initialization. This is an
|
||||
inode/link-count behavior, not a FreeBSD vnode publication rule. Linux and
|
||||
FreeBSD both permit a live unlinked inode/vnode with link count zero; the
|
||||
FreeBSD VM code explicitly treats `va_nlink == 0` as an unlinked mapping case.
|
||||
|
||||
The FreeBSD EROFS adapter has three distinct entry semantics:
|
||||
|
||||
1. `erofs_lookup()` owns a non-dot namespace edge and calls `erofs_vget()`.
|
||||
2. `.vfs_vget = erofs_vget` is the raw NID entry used by VFS/root callers.
|
||||
3. `erofs_fhtovp()` calls raw `VFS_VGET` and then maps `nlink == 0` to `ESTALE`.
|
||||
|
||||
Therefore Linux's direct `set_nlink()` behavior does not authorize either a
|
||||
global FreeBSD rejection or a namespace-only rejection. The latter would be a
|
||||
new FreeBSD validator policy, and the disk/fsck corpus supplies no format-level
|
||||
rule requiring it.
|
||||
|
||||
## Publication Boundary
|
||||
|
||||
B09 moved the vnode constructor to `src/erofs_vnops.c`, but the frozen B15
|
||||
write set is only `src/namei.c` and `src/inode.c`. `erofs_vget()` inserts the
|
||||
constructing vnode in the hash, decodes the inode, marks it
|
||||
`VSTATE_CONSTRUCTED`, and only then returns to `erofs_lookup()`.
|
||||
|
||||
A post-`erofs_vget()` check in `namei.c` is therefore too late to reject before
|
||||
vnode publication. `vput()` alone does not perform the required `vgone`
|
||||
cleanup. An unconditional `vgone()` cannot preserve an already cached vnode
|
||||
obtained through raw `VFS_VGET`, because `erofs_vget()` does not return a
|
||||
created-versus-hit indicator. Pre-reading through `erofs_read_inode()` would
|
||||
duplicate complete inode decode and metadata I/O on every cold namespace
|
||||
lookup, then decode the same inode again in `erofs_vget()`.
|
||||
|
||||
The four failed GO requirements are consequently:
|
||||
|
||||
- no format or cross-kernel rule requires reachable zero-nlink rejection;
|
||||
- rejection before vnode publication is unavailable within the exact B15
|
||||
write set;
|
||||
- post-publication cleanup cannot preserve cached raw VGET semantics;
|
||||
- pre-reading would duplicate full inode decode for a low-value validator.
|
||||
|
||||
Namespace and raw entrypoints are distinguishable, and the orphan needs no
|
||||
mount-wide scan, but those two facts do not outweigh the failed safety,
|
||||
compatibility, and cost requirements. P15-092 is therefore STOP rather than a
|
||||
partial or expanded-write-set implementation.
|
||||
|
||||
## Replay and Infrastructure
|
||||
|
||||
The authoritative deterministic host command was run twice:
|
||||
|
||||
```sh
|
||||
timeout -k 10 240 tests/pre15/gates/P15-092.sh \
|
||||
--base b22dae8dc634c68db4ea89dccade91350614c139 \
|
||||
--output OWNED_OUTPUT --host-only
|
||||
```
|
||||
|
||||
Both runs exit `22` with `STOP` and have byte-identical host output trees.
|
||||
|
||||
One supplemental isolated runtime attempt used the standalone
|
||||
`/work/debug-qemu/local/vm/freebsd-build-runtime.qcow2`, not the protected base
|
||||
bp, with a fresh overlay, random port, exact baseline KLD, 180-second boot
|
||||
deadline, 60-second guest command deadlines, 900-second inner timeout, and
|
||||
1200-second outer timeout. Run
|
||||
`20260815T083854Z-qemu-P15-092-gate-runtime-1219662-0` was
|
||||
`INFRA_BLOCKED`: guest SSH did not become ready before the boot deadline, so no
|
||||
runtime vnode result is claimed. The run used only PID `1219981` and port
|
||||
`49795`; it did not own PID `26318`, port `9222`, or the protected base bp.
|
||||
|
||||
Cleanup is `PASS`: the owned QEMU PID stopped, port `49795` is free, the
|
||||
overlay and case temp were removed, and the standalone base SHA256 remained
|
||||
`ae09f47aef43cfd016049610e86bcf2073fdf70430961bcdb94662facac9f046`.
|
||||
The runtime manifest and cleanup SHA256 values are
|
||||
`2e9a4220dc86c5d8fa465e77e6d81e5e36c0f26338b70d71a84881af8fc02cb9`
|
||||
and `0a499d8fa3397f73998c6c3c3ae9dfc9070f61267a86361ba96d1e8bc64cb392`.
|
||||
|
||||
Because the reproducible host gate already fails mandatory GO conditions, the
|
||||
runtime infrastructure block does not defer or weaken the STOP decision. It is
|
||||
reported separately and was not retried with another long-running VM. B15,
|
||||
TC021, TC025, TC182, K0, and B15 acceptance QEMU are `NOT_RUN` by the mandatory
|
||||
STOP-NO-SOURCE rule. The full feature suite was not run.
|
||||
|
||||
## Terminal Static Review
|
||||
|
||||
The 2026-08-17 review rechecked the current `repo-pre-15`, Linux EROFS
|
||||
implementation, P15-092 plan, frozen write set, and post-STOP history. It
|
||||
found no format or cross-kernel requirement for namespace zero-nlink
|
||||
rejection, no new B15 consumer or test target, and no safe implementation
|
||||
entry within the frozen write set. The detailed evidence is
|
||||
`planning/pre15/evidence/20260817T-B15-terminal-review/VERDICT.md`.
|
||||
|
||||
The terminal review does not convert the historical STOP or acceptance state:
|
||||
`STOP_NO_SOURCE` and `NOT_TESTED` remain the authoritative historical values.
|
||||
@@ -0,0 +1,62 @@
|
||||
# Pre15 Stage0 Execution Evidence
|
||||
|
||||
## Scope
|
||||
|
||||
B01 establishes the only Pre15 runner interface and the evidence contract used
|
||||
by later gates, builds, directed tests, and smoke runs. It does not modify
|
||||
`src/**`, run the full feature suite, or convert host parser results into KLD
|
||||
runtime claims.
|
||||
|
||||
## Entrypoints
|
||||
|
||||
```sh
|
||||
timeout -k 10 240 tests/pre15/run-host.sh CASE
|
||||
timeout -k 30 1200 tests/pre15/run-build.sh zstdio0
|
||||
timeout -k 30 1200 tests/pre15/run-build.sh zstdio1
|
||||
timeout -k 30 1200 tests/pre15/run-qemu.sh CASE
|
||||
timeout -k 30 1500 tests/pre15/run-smoke.sh final-four-codec
|
||||
```
|
||||
|
||||
Cases are discovered as exact files under `tests/pre15/cases/`; no shared case
|
||||
registry or historical result runner is consulted. `run-build.sh` reports a
|
||||
Linux invocation as `INFRA_BLOCKED` because `build.sh` requires a native
|
||||
FreeBSD host.
|
||||
|
||||
## Evidence
|
||||
|
||||
Set `PRE15_EVIDENCE_ROOT` to a new evidence parent. Every invocation creates a
|
||||
unique run directory and never overwrites an earlier run. `manifest.json`
|
||||
conforms to `tests/pre15/EVIDENCE-SCHEMA.json` and records exact argv, DUT and
|
||||
source identities, worktree diff hash, fixture/module hashes, timestamps,
|
||||
deadline, exit code, target marker, status, cleanup, and raw-output paths.
|
||||
|
||||
The only case statuses are `PASS`, `DUT_FAIL`, `RUNNER_FAIL`,
|
||||
`INFRA_BLOCKED`, `STOP`, and `NOT_RUN`. A nonzero guest command without a target
|
||||
marker is not a DUT failure. Cleanup failure always changes the run to
|
||||
`RUNNER_FAIL`.
|
||||
|
||||
## Ownership
|
||||
|
||||
The runner records each owned process, path, forwarded port, SSH ControlMaster,
|
||||
guest mount, md unit, loaded EROFS KLD, and base image before use. Cleanup runs
|
||||
in reverse order and refuses to remove paths outside the current run directory.
|
||||
QEMU always writes to a fresh overlay. The base image is read-only input for the
|
||||
runner and its SHA256 must remain unchanged.
|
||||
|
||||
Mount, md, and KLD cleanup applies only to resources explicitly registered by
|
||||
the current run. Kernel ZSTDIO is a kernel option, not an unloadable dependency.
|
||||
|
||||
## B01 Controls
|
||||
|
||||
- `B01-runner-selftest`: known-good, target-marked DUT mismatch, pre-target
|
||||
command failure, SSH failure, QEMU early exit, timeout, owned PID cleanup, and
|
||||
deliberate cleanup-boundary failure.
|
||||
- `B01-g3-equivalence`: verifies the two archived script identities, compares
|
||||
their source/artifact inventories with the stable helper, and repeats stable
|
||||
generation.
|
||||
- `TC162-xattr-legacy`: verifies checksum-valid legacy primary, explicit plain,
|
||||
packed, and metabox prefix carriers plus exact single-field `EINTEGRITY`
|
||||
negatives.
|
||||
|
||||
The authoritative B01 and initial gate verdicts are recorded under
|
||||
`planning/pre15/evidence/` after execution from a committed B01 tree.
|
||||
@@ -0,0 +1,101 @@
|
||||
# Phase 0: B-ZSTD-001 Remediation
|
||||
|
||||
Status: `FIXED_STATICALLY`; runtime corruption-tail verification remains
|
||||
`NOT_TESTED` in this remediation pass.
|
||||
|
||||
## Problem
|
||||
|
||||
Strict audit item B-ZSTD-001 / BUG-ZSTD-035 found that ordinary ZSTD extents
|
||||
advertised subextent support. A prefix or middle read could therefore decode
|
||||
only the requested output and accept `z_erofs_zstd_finish()` without checking
|
||||
the remaining compressed stream. Corruption after the requested range could be
|
||||
skipped.
|
||||
|
||||
P15-086 already authorizes partial ordinary reads only for LZ4, LZMA, and
|
||||
Deflate. Its ZSTD result is `FULL_FALLBACK` because the partial candidate used
|
||||
more temporary memory than full decode.
|
||||
|
||||
## Call Graph
|
||||
|
||||
For an ordinary mapped compressed read:
|
||||
|
||||
1. `z_erofs_do_read()` calls `z_erofs_decode_length()` with `mapoff` and
|
||||
`want`.
|
||||
2. `z_erofs_decode_length()` sets `partial=true` and `decoded_len=mapoff+want`
|
||||
when the descriptor reports `supports_subextent` and the request ends before
|
||||
the extent.
|
||||
3. `z_erofs_decode_extent()` passes that length and mode to
|
||||
`z_erofs_decompress()`.
|
||||
4. `z_erofs_zstd_decompress()` fills the shortened output and calls
|
||||
`z_erofs_zstd_finish()`.
|
||||
5. `z_erofs_zstd_finish()` intentionally permits partial decoding without
|
||||
requiring stream end. That behavior remains necessary for the separately
|
||||
defined `EROFS_MAP_PARTIAL_REF` bounded-prefix path.
|
||||
|
||||
The smallest correct policy fix is to stop ordinary ZSTD reads at step 2:
|
||||
ZSTD now advertises `.supports_subextent = 0`. `z_erofs_decode_length()` then
|
||||
selects the full extent for ordinary prefix and middle reads. The explicit
|
||||
`EROFS_MAP_PARTIAL_REF` branch still sets `partial=true` and remains unchanged.
|
||||
|
||||
## Changes
|
||||
|
||||
- Set the ZSTD descriptor capability to false in
|
||||
`src/decompressor_zstd.c`; no finish validation was weakened or bypassed.
|
||||
- Updated B27 assertions to preserve ZSTD partial-reference completion while
|
||||
requiring ordinary ZSTD full fallback.
|
||||
- Updated B28 source and extracted-policy assertions, host report, and QEMU
|
||||
corruption decision so ZSTD is `FULL_FALLBACK`; LZ4/LZMA/Deflate policy is
|
||||
unchanged.
|
||||
|
||||
## Verification
|
||||
|
||||
Commands and actual results:
|
||||
|
||||
- `git diff --check`: `PASS`.
|
||||
- `sh -n repo-pre-15/tests/pre15/cases/B27-stream-tail.sh` and
|
||||
`sh -n repo-pre-15/tests/pre15/cases/B28-partial.sh`: `PASS`.
|
||||
- `PRE15_EVIDENCE_ROOT=/tmp/erofs-phase0-b28-20260818-r2 timeout -k 10 600
|
||||
repo-pre-15/tests/pre15/run-host.sh B28-partial`: `PASS`; cleanup `PASS`,
|
||||
target reached. Evidence:
|
||||
`/tmp/erofs-phase0-b28-20260818-r2/20260818T070848Z-host-B28-partial-1780769-0/`.
|
||||
The source audit reports `zstd=false`, ZSTD in `current_full_fallback`,
|
||||
`current_partial=[deflate,lz4,lzma]`, and partial-reference preserved.
|
||||
- `PRE15_EVIDENCE_ROOT=/tmp/erofs-phase0-b27-20260818 timeout -k 10 600
|
||||
repo-pre-15/tests/pre15/run-host.sh B27-stream-tail`: `RUNNER_FAIL`, cleanup
|
||||
`PASS`; the pre-existing B29 Deflate context-pool delta fails B27's frozen
|
||||
exact-transform audit before the completion harness. This is not claimed as
|
||||
ZSTD runtime evidence.
|
||||
- P15-086 frozen gate result and policy were inspected, not rerun; its existing
|
||||
recorded decision remains ZSTD `FULL_FALLBACK`.
|
||||
|
||||
The B28 host case generated and compared real EROFS fixtures and ran the
|
||||
descriptor/decode-length source audit, but did not load a FreeBSD KLD or read
|
||||
an image through the kernel. No full feature suite was run.
|
||||
|
||||
## Not Tested
|
||||
|
||||
`NOT_TESTED`: a real FreeBSD runtime read of an EROFS ZSTD image whose stream
|
||||
is corrupted after an ordinary prefix or middle request. The required runtime
|
||||
threshold is that the short ordinary read returns positive `EINTEGRITY` (97),
|
||||
matching full fallback, while a valid ordinary prefix/middle/tail read matches
|
||||
the source bytes.
|
||||
|
||||
`NOT_TESTED`: runtime confirmation that `EROFS_MAP_PARTIAL_REF` retains its
|
||||
bounded-prefix semantics on a real image after this policy change.
|
||||
|
||||
## Risk
|
||||
|
||||
Ordinary ZSTD prefix and middle reads now decode the complete extent. This may
|
||||
increase CPU or temporary output work relative to the previously incorrect
|
||||
partial path, but it restores corruption visibility and matches P15-086 policy.
|
||||
The changed tests do not alter test fixtures, image bytes, test environment, or
|
||||
finish-error behavior.
|
||||
|
||||
## Runtime Gate
|
||||
|
||||
Before claiming Phase 0 runtime closure, run the existing focused B28 runtime
|
||||
case with ZSTD enabled and verify valid prefix, middle, and tail reads, an
|
||||
after-request-range corruption case returning `EINTEGRITY`, full corruption
|
||||
returning `EINTEGRITY`, and the real partial-reference case. Record separate
|
||||
`PASS`, `INFRA_BLOCKED`, or `NOT_TESTED` results; do not infer runtime behavior
|
||||
from the extracted C harness.
|
||||
Reference in New Issue
Block a user