update
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user