update
This commit is contained in:
+17
-9
@@ -1,10 +1,18 @@
|
|||||||
# Kernel-module build output.
|
|
||||||
/build/
|
|
||||||
|
|
||||||
# Generated manual-test fixtures and captures.
|
i386
|
||||||
/tests/results/manual/*/artifacts/
|
machine
|
||||||
/tests/results/manual/*/fixture/
|
x86
|
||||||
/tests/results/manual/*/repro-artifacts/
|
.cache
|
||||||
/tests/results/manual/*/repro-fixture/
|
|
||||||
/tests/results/manual/*/repro[0-9]-artifacts/
|
export_syms
|
||||||
/tests/results/manual/*/repro[0-9]-fixture/
|
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
|
||||||
|
opt_global.h
|
||||||
|
|
||||||
|
vnode_if.h
|
||||||
|
vnode_if_newproto.h
|
||||||
|
vnode_if_typedef.h
|
||||||
|
|
||||||
|
compile_commands.json
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
# EROFS for FreeBSD
|
|
||||||
|
|
||||||
## Build Kernel Module
|
|
||||||
|
|
||||||
Build on FreeBSD 15 amd64 with a matching FreeBSD source tree. The default
|
|
||||||
source path is `/usr/src`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
WITH_ZSTDIO=0 ./build.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Use `FREEBSD_SRC=/path/to/freebsd-src` when the source tree is elsewhere. The
|
|
||||||
script is a native FreeBSD wrapper around `src/Makefile` and `bsd.kmod.mk`; the
|
|
||||||
Makefile is the authoritative module name, source list, architecture gate, and
|
|
||||||
per-source flag definition. Each run rebuilds `build/obj` and writes
|
|
||||||
`build/erofs.ko`.
|
|
||||||
|
|
||||||
Only `MACHINE_ARCH=amd64` is currently qualified. Other architectures are
|
|
||||||
rejected explicitly instead of inheriting amd64 ABI flags. Build ZSTD support
|
|
||||||
with:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
WITH_ZSTDIO=1 ./build.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
The enabled module references the FreeBSD kernel ZSTD API and therefore
|
|
||||||
requires a running kernel built with `options ZSTDIO`. `WITH_ZSTDIO=0` builds a
|
|
||||||
module without those references and rejects ZSTD-compressed images at mount.
|
|
||||||
|
|
||||||
## Mount
|
|
||||||
|
|
||||||
EROFS is read-only. Mount a single-device image with:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mount -t erofs -o ro /dev/md0 /mnt/erofs
|
|
||||||
```
|
|
||||||
|
|
||||||
For an image with external blob devices, map every one-based on-disk device
|
|
||||||
slot explicitly with `device.<slot>=<provider>`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mount -t erofs -o ro \
|
|
||||||
-o device.2=/dev/md92 \
|
|
||||||
-o device.1=/dev/md91 \
|
|
||||||
/dev/md90 /mnt/erofs
|
|
||||||
```
|
|
||||||
|
|
||||||
Slot names make the mapping independent of option order. Every external slot
|
|
||||||
must be present exactly once; assigning the same GEOM provider to multiple
|
|
||||||
slots is rejected. The same names and values may be passed directly as
|
|
||||||
`nmount(2)` iovec entries.
|
|
||||||
|
|
||||||
There is no repo-local `mount_erofs` binary; FreeBSD's generic `/sbin/mount`
|
|
||||||
frontend passes these distinct option names through to `nmount(2)`. The driver
|
|
||||||
forces every successful mount read-only, so even `-o rw` produces a read-only
|
|
||||||
mount rather than enabling writes.
|
|
||||||
|
|
||||||
If an image has a device table but no `device.<slot>` options are supplied,
|
|
||||||
the primary provider is treated as a Linux-compatible flatdev image. It must
|
|
||||||
contain the external ranges at their declared `uniaddr` block offsets, for
|
|
||||||
example a deterministic concatenation of the primary image and its blobs.
|
|
||||||
|
|
||||||
## Qualified Semantics
|
|
||||||
|
|
||||||
- Compact/extended metadata, Linux device-number decode, plain/inline/chunk
|
|
||||||
data, and LZ4/MicroLZMA/DEFLATE/ZSTD compressed reads.
|
|
||||||
- Inline tails are confined to the inode metadata block and declared image or
|
|
||||||
metabox backing bounds.
|
|
||||||
- Directory lookup/readdir share strict validation while accepting Linux-style
|
|
||||||
nonzero unused bytes after the final name NUL.
|
|
||||||
- Compressed `st_blocks` reflects the inode's on-disk compressed block count;
|
|
||||||
uncompressed and chunk files retain logical block rounding.
|
|
||||||
- FreeBSD 15 local vnode pager sync/async entry points are used for real mmap
|
|
||||||
faults.
|
|
||||||
- NFS export uses full 64-bit NIDs and a generation derived from the
|
|
||||||
superblock seed and inode metadata. Replacing metadata changes the generation
|
|
||||||
and makes old handles stale; a metadata-identical, payload-only replacement
|
|
||||||
is not guaranteed to return `ESTALE`.
|
|
||||||
|
|
||||||
See `docs/features.md` for the bounded feature claim and
|
|
||||||
`tests/results/manual/2026-08-09T1804Z-final-review-independent/manual-test-report.md`
|
|
||||||
for the final-review evidence.
|
|
||||||
|
|
||||||
## Test Fixtures
|
|
||||||
|
|
||||||
`tests/prepare_directory_fixtures.sh` creates the deterministic TC048/141/148
|
|
||||||
directory fixtures. `tests/prepare_error_fixtures.sh` and
|
|
||||||
`tests/erofs_fixture.py` create and self-check the structured TC002/086/087/102
|
|
||||||
and TC112-TC116/119 fixtures. Generated trees, images, overlays, and `build/`
|
|
||||||
outputs are test artifacts and are not committed.
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
|
||||||
FREEBSD_SRC="${FREEBSD_SRC:-/usr/src}"
|
|
||||||
FS_SRC="${SCRIPT_DIR}/src"
|
|
||||||
BUILD_DIR="${SCRIPT_DIR}/build"
|
|
||||||
WORK_DIR="${BUILD_DIR}/obj"
|
|
||||||
MAKE="${MAKE:-make}"
|
|
||||||
WITH_ZSTDIO="${WITH_ZSTDIO:-0}"
|
|
||||||
NM_UNDEF=""
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
[ -z "${NM_UNDEF}" ] || rm -f "${NM_UNDEF}"
|
|
||||||
}
|
|
||||||
|
|
||||||
trap cleanup EXIT
|
|
||||||
trap 'cleanup; exit 1' HUP INT TERM
|
|
||||||
|
|
||||||
fail() {
|
|
||||||
echo "ERROR: $*" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
make_kmod() {
|
|
||||||
MAKEOBJDIR="${WORK_DIR}" "${MAKE}" -C "${FS_SRC}" \
|
|
||||||
SRCTOP="${FREEBSD_SRC}" SYSDIR="${FREEBSD_SRC}/sys" \
|
|
||||||
WITH_ZSTDIO="${WITH_ZSTDIO}" "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
[ "$(uname -s)" = "FreeBSD" ] ||
|
|
||||||
fail "build.sh requires a native FreeBSD build host"
|
|
||||||
[ -d "${FREEBSD_SRC}/sys" ] ||
|
|
||||||
fail "FreeBSD source tree not found: ${FREEBSD_SRC}"
|
|
||||||
[ -d "${FS_SRC}" ] || fail "Source directory not found: ${FS_SRC}"
|
|
||||||
command -v "${MAKE}" >/dev/null 2>&1 || fail "make is required"
|
|
||||||
command -v awk >/dev/null 2>&1 || fail "awk is required"
|
|
||||||
command -v nm >/dev/null 2>&1 || fail "nm is required"
|
|
||||||
[ -f "${FREEBSD_SRC}/sys/tools/vnode_if.awk" ] ||
|
|
||||||
fail "vnode_if.awk not found in ${FREEBSD_SRC}"
|
|
||||||
[ -f "${FREEBSD_SRC}/sys/kern/vnode_if.src" ] ||
|
|
||||||
fail "vnode_if.src not found in ${FREEBSD_SRC}"
|
|
||||||
case "${WITH_ZSTDIO}" in
|
|
||||||
0|1) ;;
|
|
||||||
*) fail "WITH_ZSTDIO must be 0 or 1" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
rm -rf "${WORK_DIR}"
|
|
||||||
mkdir -p "${WORK_DIR}"
|
|
||||||
KMOD="$(make_kmod -V PROG)"
|
|
||||||
[ -n "${KMOD}" ] || fail "src/Makefile did not define a module output"
|
|
||||||
|
|
||||||
echo "==> Building repo22 ${KMOD}"
|
|
||||||
make_kmod all
|
|
||||||
|
|
||||||
[ -f "${WORK_DIR}/${KMOD}" ] || fail "module was not produced"
|
|
||||||
|
|
||||||
NM_UNDEF="$(mktemp "${WORK_DIR}/nm-undef.XXXXXX")" ||
|
|
||||||
fail "could not create nm output file"
|
|
||||||
if ! nm -u "${WORK_DIR}/${KMOD}" >"${NM_UNDEF}"; then
|
|
||||||
fail "nm failed while checking ${KMOD}"
|
|
||||||
fi
|
|
||||||
if ! awk '$NF == "bcmp" { found = 1 } END { exit found }' "${NM_UNDEF}"; then
|
|
||||||
fail "${KMOD} contains an unresolved bcmp reference"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cp -f "${WORK_DIR}/${KMOD}" "${BUILD_DIR}/"
|
|
||||||
echo "==> SUCCESS: ${BUILD_DIR}/${KMOD}"
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# repo22 当前状态报告索引
|
|
||||||
|
|
||||||
- [report-1](report-1/README.md):第一次总体进度报告,保留
|
|
||||||
`573aaab7ee0b47cb6aed7f76c52c68dd4041326b` 创建时的原始内容。
|
|
||||||
- [report-2](report-2/README.md):第二次总体进度报告,按
|
|
||||||
`381349b3847209a67d669264ac54a50a3599915c` 快照汇总正式批次、动态结果、
|
|
||||||
issue、风险和下一步。
|
|
||||||
- [report-3](report-3/README.md):第三次总体进度报告,以
|
|
||||||
`12351cbb0a593474f4fcef68ffc5218d9c99dd46` 为最终验证快照,汇总完成项、
|
|
||||||
160 PASS/1 PARTIAL、独立审查结论、剩余搁置项和后续可选计划。
|
|
||||||
|
|
||||||
后续总体状态报告统一使用 `current/report-N/` 目录。逐项动态证据位于
|
|
||||||
`tests/results/manual/`,问题触发、分析和解决状态位于 `issues/`。
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
# repo22 当前总体进度
|
|
||||||
|
|
||||||
更新时间:2026-08-09 UTC
|
|
||||||
|
|
||||||
状态报告代码基线:`cd0e985b5ac54a4b7acb7042422329ad1729fb3e`
|
|
||||||
|
|
||||||
本报告记录的是上述基线上的阶段性状态。测试结果、问题状态和统计会随后续
|
|
||||||
提交继续更新,不能将本文视为 TC001-TC156 已完成全量回归的声明。
|
|
||||||
|
|
||||||
## 目标与执行范围
|
|
||||||
|
|
||||||
repo22 的目标是在 FreeBSD 15 amd64 上提供只读 EROFS 内核模块,并以可复现
|
|
||||||
fixture、真实 KLD、真实 mount/read/errno 和完整清理证据验证声明的功能边界。
|
|
||||||
|
|
||||||
当前执行约束如下:
|
|
||||||
|
|
||||||
- 只修改和提交 `repo-community/repo22`,fixture、VM overlay、KLD 和原始日志仅
|
|
||||||
放在 `/work/build` 或 guest 临时目录。
|
|
||||||
- 不建设或使用 CI、runner、自动 PASS wrapper;每个 TC 必须逐份对照对应
|
|
||||||
Markdown 手工执行。
|
|
||||||
- host 侧 `mkfs.erofs`、`dump.erofs`、`fsck.erofs` 和静态源码审查只作为 fixture
|
|
||||||
或分析证据,不能替代 FreeBSD 内核动态结果。
|
|
||||||
- 每批测试形成独立 manual report,记录 commit、构建配置、KLD SHA256、guest
|
|
||||||
版本、命令、可观察输出或 errno、fixture hash 和清理状态。
|
|
||||||
- 每批完成后提交并 push 到 `xdm/main`;并行批次若使远端前进,则 fetch、rebase
|
|
||||||
自己的 test-only 提交后正常 push,禁止 force push。
|
|
||||||
|
|
||||||
## 已完成实现与审查
|
|
||||||
|
|
||||||
当前源码已覆盖 superblock、compact/extended inode、plain/inline/chunk 数据、
|
|
||||||
目录/namecache、xattr/ACL/metabox、LZ4/MicroLZMA/DEFLATE/ZSTD、fragment、
|
|
||||||
multi-device、NFS export、pager 和多项 fail-closed 边界检查。功能声明的准确边界
|
|
||||||
以 `docs/features.md` 为准。
|
|
||||||
|
|
||||||
主要 feature 批次包括:
|
|
||||||
|
|
||||||
- `29a215dd`:POSIX ACL 与完整 xattr namespace 集成。
|
|
||||||
- `545d35bd`:xattr、long prefix、shared xattr 和 metabox 边界加固。
|
|
||||||
- `96e22cc`:cold nested namei 与目录结构校验修复。
|
|
||||||
- `4ef680df`、`78182686`:真实 multi-device、slot mapping、flatdev 和 extent
|
|
||||||
映射审查修复。
|
|
||||||
- `2354b448`:NFS export、稳定句柄和相关 vnode 路径。
|
|
||||||
- `c208bf1f`:压缩映射 P0 收口,包括多算法、partial reference 和 extent 路径。
|
|
||||||
- `9a3604fb`:metadata/VFS 语义收口,包括 inline bounds、special `rdev`、pager、
|
|
||||||
namei、NFS generation 和真实压缩占用统计。
|
|
||||||
|
|
||||||
关键收尾与工程对齐提交:
|
|
||||||
|
|
||||||
| Commit | 已完成内容 |
|
|
||||||
|---|---|
|
|
||||||
| `c881f656` | 修复 48-bit superblock union、`OFF_MAX`、大 hole 内存和大目录索引等最终 metadata 边界;建立 TC150-TC153 与三份未决 issue。 |
|
|
||||||
| `4d51ca9e` | 停止跟踪 `build/obj`、生成头和架构 symlink,避免构建产物进入正式提交。 |
|
|
||||||
| `89594551` | 将 KLD 构建布局、源文件命名、架构门控和 `WITH_ZSTDIO` 方式与 FreeBSD/Linux 上游职责对齐。 |
|
|
||||||
| `2f2ac5a8` | 更新 README、architecture、refactoring plan/status,使构建、BSD API 差异和功能边界与源码一致。 |
|
|
||||||
| `077b37ab` | 删除会伪造覆盖或无条件 PASS 的旧 runner/wrapper,加入字段断言的 fixture transformer 与 FreeBSD probe,修订关键 TC 文档。 |
|
|
||||||
| `cd0e985b` | 完成最终 review finding:per-inode NFS generation、显式 extent 物理地址溢出检查、compact/extended timestamp 校验,并直接动态执行 TC154-TC156。 |
|
|
||||||
|
|
||||||
上述工作也包含多轮 code review 和 style review:源文件职责、函数顺序和磁盘 ABI
|
|
||||||
尽量贴近 Linux EROFS;FreeBSD vnode、pager、NFS、GEOM 和 `dev_t` 差异采用
|
|
||||||
FreeBSD 15 原生接口;磁盘长度、加法、移位和 signed/unsigned 转换按 fail-closed
|
|
||||||
原则处理。
|
|
||||||
|
|
||||||
## 已有动态验证
|
|
||||||
|
|
||||||
`tests/results/manual/` 中保留了各 feature 在对应历史 commit 上的真实 FreeBSD 15
|
|
||||||
动态证据。它们证明对应变更批次曾执行内核路径,但不能替代当前 final source 的
|
|
||||||
TC001-TC156 全量重跑。
|
|
||||||
|
|
||||||
| 批次 | 主要动态证据 | 当前解释 |
|
|
||||||
|---|---|---|
|
|
||||||
| 压缩 | compact/full LZ4、legacy full index、partial reference、MicroLZMA、DEFLATE、ZSTD、fragment、ztailpacking 和多种边界 source/hash compare | 历史 feature 证据存在;G5/G6 尚需在本轮 exact KLD 重跑。 |
|
|
||||||
| xattr/ACL/metabox | inline/shared/long-prefix xattr、ACL、metabox carrier 和 corruption errno | 历史 feature 证据存在;G4 尚未启动。 |
|
|
||||||
| directory/namei/pager | cold nested lookup、目录 padding、special `rdev`、真实 mmap/page fault 和 inline bounds | 历史 feature 证据存在;G1/G3 将按当前文档重跑。 |
|
|
||||||
| multi-device | 外部 provider、显式 slot、flatdev、unified address、fragment 和 orphan/error 路径 | 历史 feature 证据存在;G7 尚未启动。 |
|
|
||||||
| NFS | getfh/fhopen、同镜像重挂、同 md 替换、ESTALE、background/stress cleanup | 历史 feature 证据存在;G8 尚未启动。 |
|
|
||||||
| final review | TC150-TC152 动态 PASS;TC153 明确 SHELVED | 结果来自 `c881f656` 前后的 final-review 批次,不是 156 项全量 PASS。 |
|
|
||||||
|
|
||||||
当前 final source `cd0e985b` 的直接动态证据是
|
|
||||||
`tests/results/manual/2026-08-09T0557Z-review-fixes/manual-test-report.md`:
|
|
||||||
|
|
||||||
- FreeBSD 15.0-RELEASE-p8 amd64 上 `WITH_ZSTDIO=0` KLD SHA256 为
|
|
||||||
`d6e755c7a75dd5043b603d58215ae3e7c8f29318b31dc1885aa9bb070d6e57a5`。
|
|
||||||
- `WITH_ZSTDIO=1` KLD SHA256 为
|
|
||||||
`b442f9f05af1d1a76801690c83c9a40ec6fc739adb0663e7dacaf837eeb2ecf3`。
|
|
||||||
- TC154、TC155、TC156 均在该 final source 上直接动态 PASS,分别覆盖 per-inode
|
|
||||||
NFS generation、explicit extent `pa + plen` overflow 和 inode timestamp
|
|
||||||
validation。
|
|
||||||
- 该批结束时 EROFS mount、KLD 和 md provider 均已清理。
|
|
||||||
|
|
||||||
## 本轮八组全量回归
|
|
||||||
|
|
||||||
TC 编号范围为 TC001-TC156,共 156 项。以下集合经计数检查为总数 156、重复 0、
|
|
||||||
遗漏 0。
|
|
||||||
|
|
||||||
| 组 | 精确集合 | 数量 | 当前状态 |
|
|
||||||
|---|---|---:|---|
|
|
||||||
| G1 | TC001, TC007, TC009, TC011-TC014, TC019-TC040, TC147, TC150, TC151 | 32 | 已启动;正在修订文档和确定性 fixture,尚未形成 final-source 32 项结论。 |
|
|
||||||
| G2 | TC002, TC008, TC010, TC015-TC018, TC112-TC116, TC119 | 13 | 已启动;使用独立 worktree/VM,尚未形成 13 项结论。 |
|
|
||||||
| G3 | TC041-TC066, TC141, TC148, TC149, TC153 | 30 | 未启动。 |
|
|
||||||
| G4 | TC005, TC067-TC083, TC117, TC134-TC140, TC142 | 27 | 未启动。 |
|
|
||||||
| G5 | TC003, TC084-TC092 | 10 | 未启动。 |
|
|
||||||
| G6 | TC004, TC102-TC110, TC143-TC146, TC155 | 15 | 未启动。 |
|
|
||||||
| G7 | TC006, TC093-TC101, TC118 | 11 | 未启动。 |
|
|
||||||
| G8 | TC111, TC120-TC133, TC152, TC154, TC156 | 18 | 未启动。 |
|
|
||||||
|
|
||||||
G1/G2 的“已启动”只表示执行代理、工作目录和任务集合已经建立,不表示其中任何
|
|
||||||
TC 已在本轮计为 PASS。G8 中 TC154/TC156、G6 中 TC155 虽已有 `cd0e985b` 直接
|
|
||||||
证据,仍需由对应全量组在最终统计中明确引用或按组要求重跑,不能导致重复计数。
|
|
||||||
|
|
||||||
## 已完成与未完成
|
|
||||||
|
|
||||||
已完成:
|
|
||||||
|
|
||||||
- 核心 feature 实现、针对性 code review、FreeBSD 15 API 对齐和构建布局收口。
|
|
||||||
- 多个历史 feature 批次的真实 KLD 动态验证与清理记录。
|
|
||||||
- 当前 final source 的双配置构建和 TC154-TC156 直接动态验证。
|
|
||||||
- 移除旧 CI 风格 runner/wrapper,建立“逐 Markdown 手工执行”的验收规则。
|
|
||||||
- 三项已知验证缺口均有详细 issue,没有把未执行或环境受限结果标成 PASS。
|
|
||||||
|
|
||||||
未完成:
|
|
||||||
|
|
||||||
- TC001-TC156 在同一 final-source 基线族上的八组全量手工回归与最终汇总。
|
|
||||||
- G1/G2 的文档修订、fixture 固化、exact KLD 执行、逐 TC 报告和 push。
|
|
||||||
- G3-G8 的启动、独立环境分配、执行和结果提交。
|
|
||||||
- TC010 所需 16 TiB 级合格 provider、TC153 大目录内核路径、explicit extent
|
|
||||||
mapped compressed payload 的正向 fixture。
|
|
||||||
|
|
||||||
## Issue 索引
|
|
||||||
|
|
||||||
检查时 `issues/` 只有以下三份已跟踪文档,没有未提交 issue 文件或真实 issue
|
|
||||||
改动,因此本状态提交不修改 `issues/`。
|
|
||||||
|
|
||||||
| Issue | 状态 | 影响 feature | Shelved 原因 |
|
|
||||||
|---|---|---|---|
|
|
||||||
| `issues/TC010-48bit-statfs-large-provider.md` | SHELVED - environment unavailable | 48-bit block count、primary provider size validation、`statfs(2)`/`df` 总量和 root/block union 选择 | 非零 `blocks_hi` 在 4 KiB block 下至少要求 16 TiB GEOM provider;当前 vnode md 流程没有已验证、可安全清理的合格 provider。小 provider 拒绝和 TC150 fallback 都不能替代正向结果。 |
|
|
||||||
| `issues/TC153-large-directory-block-index-validation.md` | SHELVED - kernel validation incomplete | 超大目录二分索引、cold lookup、`EINTEGRITY` 传播和 negative namecache 正确性 | 已有可复现 FLAT_PLAIN fixture,但尚未在 FreeBSD fixed/pre-fix KLD 上完成冷查找对照;host 生成和静态审查不足以计 PASS。 |
|
|
||||||
| `issues/extent-metadata-fixture-unavailable.md` | SHELVED - positive fixture unavailable | explicit compressed extent parser、4/8/16/32-byte record、物理/逻辑高位、binary search、partial reference/fragment 映射 | erofs-utils 1.8.6 和已试 1.9.3 均不生成真实 mapped explicit-record payload。TC152 hole 与 TC155 overflow 只覆盖部分 header/negative 分支,不能替代正向压缩数据读取。 |
|
|
||||||
|
|
||||||
## 风险与依赖
|
|
||||||
|
|
||||||
- 并行组共享远端 `xdm/main`,每批 push 前必须重新 fetch/rebase 并确认没有覆盖其他
|
|
||||||
组的 TC、helper、report 或 issue。
|
|
||||||
- FreeBSD VM、SSH 端口、qcow overlay、md unit 和 mount point 必须按组隔离;任何
|
|
||||||
guest 残留都会污染后续动态证据。
|
|
||||||
- erofs-utils 的格式生成能力限制 explicit extent 等正向 fixture,必要时只能使用
|
|
||||||
字段自检、CRC32C-aware 的 structured transformer,不能手工猜偏移。
|
|
||||||
- 48-bit 大 provider、memory pressure、NFS stress 和性能 TC 对环境容量及稳定性要求
|
|
||||||
较高,环境不足时必须使用 `SHELVED/ISSUE` 或 `ENVIRONMENT-UNAVAILABLE`,不能
|
|
||||||
降低判据。
|
|
||||||
- 历史报告跨多个 commit。最终统计必须只接受对应 exact KLD 的本轮动态结果,或
|
|
||||||
明确标注尚未重跑,禁止把旧 HEAD 结果直接升级为全量 PASS。
|
|
||||||
|
|
||||||
## 下一步
|
|
||||||
|
|
||||||
1. 完成 G1/G2 文档和 fixture 修订,构建各自 exact KLD,逐 TC 手工执行并提交报告。
|
|
||||||
2. 每个先完成的组 fetch/rebase 最新 `xdm/main`,严格 pathspec 提交并正常 push。
|
|
||||||
3. 启动 G3/G4,随后按环境和依赖启动 G5-G8;压缩、multi-device、NFS 使用隔离 VM。
|
|
||||||
4. 对任何 kernel behavior failure 立即停止 PASS 计数,新增或更新有事实依据的 issue。
|
|
||||||
5. 八组结束后汇总 156 项,检查总数、重复、遗漏、KLD/image/source hash 和全部清理
|
|
||||||
证据,再发布 final-source 全量结论。
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
# repo22 当前状态索引
|
|
||||||
|
|
||||||
- [2026-08-09 总体进度](2026-08-09-overall-progress.md):基线
|
|
||||||
`cd0e985b5ac54a4b7acb7042422329ad1729fb3e` 上的实现、历史动态证据、八组
|
|
||||||
全量回归分工、未决 issue、风险和下一步。
|
|
||||||
|
|
||||||
此目录记录阶段性状态;测试结果会随后续 commit 更新。正式逐项证据位于
|
|
||||||
`tests/results/manual/`,未决验证缺口位于 `issues/`。
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
# repo22 第二次总体进度报告
|
|
||||||
|
|
||||||
更新时间:2026-08-09 UTC
|
|
||||||
|
|
||||||
权威统计快照:`381349b3847209a67d669264ac54a50a3599915c`
|
|
||||||
(该提交是当次 `xdm/main` 上完成 G3 报告后的快照)。
|
|
||||||
|
|
||||||
本报告只统计该快照已经提交的实现、正式批次和动态证据。TC060 源码修复与 G5
|
|
||||||
压缩回归正在并行进行,但在形成完整报告并提交前不提前计为 PASS,也不改变下述
|
|
||||||
冻结统计。
|
|
||||||
|
|
||||||
## 总体结论
|
|
||||||
|
|
||||||
- feature 实现、源码 code review、style review、FreeBSD 15 API 对齐和双配置构建
|
|
||||||
布局已经完成阶段性收口。
|
|
||||||
- 正式八组回归中,G1、G2、G3、G4 共执行 103 项:102 PASS,1 项
|
|
||||||
`TC060 KERNEL-FAIL` 正在修复。
|
|
||||||
- final review-fix 阶段还直接动态执行了 TC154-TC156,三项均 PASS。它们是三项
|
|
||||||
额外且不与前述 103 项重叠的 TC,因此当前共有 106 个不同 TC 具备动态结果,
|
|
||||||
其中 105 PASS、1 项待修。
|
|
||||||
- TC154-TC156 已分配给 G8,但先行 PASS 不能重复计入“已完成 G8”,也不能把 G8
|
|
||||||
标成已执行完毕。G8 尚有 TC111、TC131-TC133 未执行。
|
|
||||||
- TC010 与 TC153 已通过真实大 sparse provider 的 FreeBSD 内核路径验证并转为
|
|
||||||
RESOLVED。explicit extent 的 mapped compressed payload 正向 fixture 仍未获得,
|
|
||||||
对应 issue 尚未解决。
|
|
||||||
|
|
||||||
## 实现与审查
|
|
||||||
|
|
||||||
repo22 已完成以下阶段性工程工作:
|
|
||||||
|
|
||||||
- 实现并审查 superblock、compact/extended inode、plain/inline/chunk 数据、目录与
|
|
||||||
namecache、xattr/ACL/metabox、多算法压缩、fragment、multi-device、NFS export、
|
|
||||||
vnode pager 和 fail-closed 元数据边界。
|
|
||||||
- 对照 Linux EROFS 的磁盘 ABI、职责拆分和命名以降低长期维护偏差,同时保持
|
|
||||||
FreeBSD vnode、GEOM、pager、NFS、ACL 和 `dev_t` 语义为行为权威。
|
|
||||||
- 完成 overflow、长度、偏移、移位、signed/unsigned、目录大索引、48-bit union、
|
|
||||||
NFS generation、special vnode 和 timestamp 等多轮独立 code review 修复。
|
|
||||||
- 清理被跟踪的构建产物,统一 FreeBSD KLD 源文件布局、amd64 门控和
|
|
||||||
`WITH_ZSTDIO=0/1` 构建方式;当前构建仍以 kernel `-Werror` 为门槛。
|
|
||||||
- 删除会替代人工判定或无条件给出 PASS 的旧 CI 风格 runner/wrapper,保留可复现
|
|
||||||
fixture transformer 与原生 syscall/probe 工具。当前任务不实现 CI。
|
|
||||||
|
|
||||||
## 正式八组状态
|
|
||||||
|
|
||||||
八组精确集合总计 156 项,彼此无重复、无遗漏。
|
|
||||||
|
|
||||||
| 组 | 精确集合 | 数量 | 快照状态 |
|
|
||||||
|---|---|---:|---|
|
|
||||||
| G1 | TC001, TC007, TC009, TC011-TC014, TC019-TC040, TC147, TC150, TC151 | 32 | 32 PASS,正式批次完成。 |
|
|
||||||
| G2 | TC002, TC008, TC010, TC015-TC018, TC112-TC116, TC119 | 13 | 13 PASS,正式批次完成。 |
|
|
||||||
| G3 | TC041-TC066, TC141, TC148, TC149, TC152, TC153 | 31 | 31 已执行;30 PASS,TC060 KERNEL-FAIL。 |
|
|
||||||
| G4 | TC005, TC067-TC083, TC117, TC134-TC140, TC142 | 27 | 27 PASS,正式批次完成。 |
|
|
||||||
| G5 | TC003, TC004, TC084-TC092, TC102-TC110, TC143-TC146 | 24 | 压缩回归正在进行,尚无正式整组结论。 |
|
|
||||||
| G6 | TC006, TC093-TC101, TC118 | 11 | 尚未执行。 |
|
|
||||||
| G7 | TC120-TC130 | 11 | 尚未执行。 |
|
|
||||||
| G8 | TC111, TC131-TC133, TC154-TC156 | 7 | 正式整组未完成;TC154-TC156 已先行 PASS,TC111、TC131-TC133 尚未执行。 |
|
|
||||||
|
|
||||||
正式批次证据:
|
|
||||||
|
|
||||||
- [G1 报告](../../tests/results/manual/2026-08-09T0710Z-g1/manual-test-report.md)
|
|
||||||
- [G2 报告](../../tests/results/manual/2026-08-09T0710Z-g2/manual-test-report.md)
|
|
||||||
- [G3 报告](../../tests/results/manual/2026-08-09T1059Z-g3/manual-test-report.md)
|
|
||||||
- [G4 报告](../../tests/results/manual/2026-08-09T0839Z-g4/manual-test-report.md)
|
|
||||||
- [review-fix 报告](../../tests/results/manual/2026-08-09T0557Z-review-fixes/manual-test-report.md)
|
|
||||||
|
|
||||||
## 统计口径
|
|
||||||
|
|
||||||
正式批次已执行数为 `32 + 13 + 31 + 27 = 103`;PASS 数为
|
|
||||||
`32 + 13 + 30 + 27 = 102`,另有 TC060 一项 KERNEL-FAIL。
|
|
||||||
|
|
||||||
TC154-TC156 来自 review-fix 阶段的 exact-source FreeBSD 动态运行,并未包含在
|
|
||||||
G1-G4 的 103 项中。因此按“不同 TC 是否已有动态结果”计数,应增加三项,得到
|
|
||||||
106 个 TC 有动态结果、105 PASS、1 待修。按“正式组是否完成”计数时,三项仍属于
|
|
||||||
尚未完成的 G8,不能再次增加 PASS 数或宣称 G8 已完成。
|
|
||||||
|
|
||||||
## 大 Provider 验证
|
|
||||||
|
|
||||||
- TC010 使用逻辑长度 `17592193667072` 字节的 qualified sparse vnode provider,
|
|
||||||
动态挂载了 `blocks_hi=1` 的 48-bit EROFS,并验证 `df` 的 64-bit 总量无截断。
|
|
||||||
issue 已 RESOLVED。
|
|
||||||
- TC153 使用逻辑长度 `8796093091840` 字节的 sparse GEOM provider,令超大
|
|
||||||
FLAT_PLAIN 目录进入 `2147483648` 最终块索引的真实 kernel lookup 路径;固定 KLD
|
|
||||||
在 cold lookup 和 readdir 后均返回 `EINTEGRITY`,没有错误缓存为 `ENOENT`。
|
|
||||||
issue 已 RESOLVED。
|
|
||||||
- explicit extent 已动态覆盖 hole record、header 选择和部分负向分支,但仍缺少
|
|
||||||
mapped compressed payload 以及完整 record variant 的正向读取证据,不能关闭 issue。
|
|
||||||
|
|
||||||
## Issue 索引
|
|
||||||
|
|
||||||
| Issue | 当前状态 | 结论 |
|
|
||||||
|---|---|---|
|
|
||||||
| [TC060 standard pathconf](../../issues/TC060-pathconf-standard-values.md) | OPEN - KERNEL-FAIL | `_PC_NO_TRUNC` 与 `_PC_CHOWN_RESTRICTED` 返回 `EINVAL`;源码修复和复测正在进行。 |
|
|
||||||
| [TC010 48-bit statfs](../../issues/TC010-48bit-statfs-large-provider.md) | RESOLVED - qualified sparse vnode provider validated | qualified 16 TiB 级 sparse provider 已完成真实 mount/statfs/df 验证。 |
|
|
||||||
| [TC153 large directory index](../../issues/TC153-large-directory-block-index-validation.md) | RESOLVED - exact-source kernel validation passed | qualified 多 TiB sparse provider 已完成 exact-source 大索引 kernel lookup 验证。 |
|
|
||||||
| [Explicit extent fixture](../../issues/extent-metadata-fixture-unavailable.md) | SHELVED - positive fixture unavailable | issue 未解决;尚无使用 explicit-record parser 的 mapped compressed payload 正向 fixture。 |
|
|
||||||
|
|
||||||
## 当前风险
|
|
||||||
|
|
||||||
- TC060 是已确认的 FreeBSD kernel behavior failure,修复必须保持 NAME_MAX、PATH_MAX、
|
|
||||||
FILESIZEBITS、LINK_MAX、ACL 查询和未知键 errno 不回归,并完成 mount/md/KLD 清理。
|
|
||||||
- G5 同时覆盖 LZ4、MicroLZMA、DEFLATE、ZSTD、ztailpacking、partial reference、
|
|
||||||
explicit metadata 等多条压缩路径,fixture 资格和 `WITH_ZSTDIO` 配置差异仍是当前
|
|
||||||
最大执行风险。
|
|
||||||
- explicit extent 缺少上游工具可生成的 mapped positive fixture;静态 ABI 对照、
|
|
||||||
hole record 和 malformed case 不能替代真实压缩 payload 读取。
|
|
||||||
- G6 multi-device、G7 边界与压力类测试、G8 NFS/manual 页面仍需隔离 VM、精确 KLD、
|
|
||||||
direct syscall/数据比较和完整清理,历史 feature 报告不能自动升级为本轮结果。
|
|
||||||
- 并行 worktree 共享 `xdm/main`。每次 push 前必须 fetch/rebase,严格 pathspec,禁止
|
|
||||||
force push;guest mount、md、KLD 和临时 provider 残留必须清零。
|
|
||||||
|
|
||||||
## 下一步
|
|
||||||
|
|
||||||
1. 完成 TC060 根因修复,重跑全部 pathconf 键与基础 mount/read smoke,更新 issue
|
|
||||||
和 dated manual report。
|
|
||||||
2. 完成 G5 的 24 项压缩回归,提交 exact KLD、fixture hash、errno/数据比较与清理
|
|
||||||
证据。
|
|
||||||
3. 依次完成 G6 11 项、G7 11 项和 G8 剩余 TC111、TC131-TC133;在 G8 汇总中引用
|
|
||||||
或按要求复跑 TC154-TC156,但禁止重复计数。
|
|
||||||
4. 聚合 `TEST-COVERAGE-MATRIX`,审计 156 项总数、组间重复、遗漏、动态证据来源和
|
|
||||||
未解决 issue。
|
|
||||||
5. 完成最终独立 source review,检查 lock/resource/error path;执行
|
|
||||||
`WITH_ZSTDIO=0/1` 双配置 exact-source build,并做 `xdm/main`、remote/HEAD、
|
|
||||||
tracked clean 和 guest 清理的最终 audit。
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
# repo22 第二次状态报告索引
|
|
||||||
|
|
||||||
- [第二次总体进度报告](2026-08-09-overall-progress.md):以
|
|
||||||
`381349b3847209a67d669264ac54a50a3599915c` 为统计快照,汇总实现与审查、
|
|
||||||
八组回归、动态结果计数、issue、风险和后续工作。
|
|
||||||
|
|
||||||
本目录只记录阶段性总体状态。各 TC 的命令、hash、errno、dmesg 和清理证据以
|
|
||||||
`tests/results/manual/` 中的对应报告为准。
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
# repo22 第三次总体进度报告
|
|
||||||
|
|
||||||
更新时间:2026-08-09 UTC
|
|
||||||
|
|
||||||
权威验证快照:`12351cbb0a593474f4fcef68ffc5218d9c99dd46`
|
|
||||||
|
|
||||||
最终源码基线:`fcc85b93d5f8fd9671686bd68bf3b086c8bd25cf`
|
|
||||||
|
|
||||||
## 总体结论
|
|
||||||
|
|
||||||
本轮要求的 feature 全面验证、FreeBSD/Linux 行为差异审查、code review 和
|
|
||||||
style/可维护性优化已经完成。161 个可执行 Markdown 测试均已执行并形成受控
|
|
||||||
手工证据,最终为 160 PASS、1 PARTIAL、0 FAIL、0 KERNEL-FAIL、0 ENV。
|
|
||||||
|
|
||||||
唯一未完全关闭的是 TC146 的 explicit compressed extent mapped-payload 正向
|
|
||||||
fixture。该问题已按用户授权详细记录并搁置,不是已观察到的 kernel failure,
|
|
||||||
也不影响其他 160 个 TC 的结论。本轮目标因此完成,剩余工作属于已批准搁置项
|
|
||||||
或后续可选增强。
|
|
||||||
|
|
||||||
CI 和自动化 kernel-test harness 不在本轮范围内,未实现也未宣称完成。
|
|
||||||
|
|
||||||
## 已完成内容
|
|
||||||
|
|
||||||
- 完成 TC001-TC161 的规格、执行报告和覆盖矩阵机械审计;TC000 只作为模板。
|
|
||||||
- G1-G8 的 156 个表格行覆盖 TC001-TC156,恰好一次,无重复、无遗漏。
|
|
||||||
- 完成 TC157-TC161 独立回归,覆盖 explicit extent 全局顺序、48-bit compressed
|
|
||||||
block count、special vnode 组合 setattr、dot-omitted `OFF_MAX` cookie 和 `nm`
|
|
||||||
失败传播。
|
|
||||||
- TC010 的 16 TiB-plus statfs、TC060 的 FreeBSD pathconf、TC153 的超大目录索引
|
|
||||||
均已动态验证并转为 RESOLVED。
|
|
||||||
- 完成 superblock、inode、data、directory/namecache、xattr/ACL/metabox、压缩、
|
|
||||||
multi-device、NFS、pager、错误路径和边界算术的多轮独立 review。
|
|
||||||
- 保留 Linux EROFS 的磁盘 ABI、命名、函数顺序和职责拆分作为维护参照,同时以
|
|
||||||
FreeBSD vnode、GEOM、pager、NFS、ACL、`dev_t` 和 errno 语义为行为权威。
|
|
||||||
- 修正 README 的 NFS stale 承诺:generation 来自 superblock seed 和 inode
|
|
||||||
metadata;metadata-identical payload-only replacement 不保证 `ESTALE`。
|
|
||||||
- 清理 repo22 内全部 ignored build/object/image/repro/Python bytecode 产物;最终
|
|
||||||
guest 的 EROFS mount、md、EROFS KLD 和 DTrace KLD 计数均为零。
|
|
||||||
|
|
||||||
## 最终验证统计
|
|
||||||
|
|
||||||
| 状态 | 数量 | 说明 |
|
|
||||||
| --- | ---: | --- |
|
|
||||||
| PASS | 160 | 具备对应 dated manual report 的 FreeBSD 15 手工证据 |
|
|
||||||
| PARTIAL | 1 | TC146;HEAD2/interlaced PASS,explicit mapped payload 未完成 |
|
|
||||||
| FAIL / KERNEL-FAIL | 0 | 无开放 kernel 行为失败 |
|
|
||||||
| ENV | 0 | 无环境阻塞 |
|
|
||||||
| SHELVED test case | 0 | TC146 的子项不另计为 TC |
|
|
||||||
|
|
||||||
G1-G8 证据来自多个源码提交,不能表述为所有旧 TC 都运行在最终 KLD 上。最终
|
|
||||||
`fcc85b93d` 基线接受了 TC157-TC161、相关回归以及双配置 build/load/mount smoke。
|
|
||||||
|
|
||||||
## 最终构建
|
|
||||||
|
|
||||||
FreeBSD 15 kernel `-Werror` 双配置均成功:
|
|
||||||
|
|
||||||
| 配置 | KLD SHA256 |
|
|
||||||
| --- | --- |
|
|
||||||
| `WITH_ZSTDIO=0` | `15fda9d334132cd81769ce4dff4f8411a6e2b4cf7531c352530d0de85f42a2d2` |
|
|
||||||
| `WITH_ZSTDIO=1` | `23782dc0ce7da188807d35020bf2d8c6044b796c5c9a8746b398ba784cd6ad4e` |
|
|
||||||
|
|
||||||
TC161 的私有 `nm` shim 正确使构建失败且不发布新 KLD;移除 shim 后使用
|
|
||||||
`/usr/bin/nm` 的正常重建 exit 0。两个最终 KLD 均完成独立加载和只读挂载 smoke。
|
|
||||||
|
|
||||||
## Code Review 结论
|
|
||||||
|
|
||||||
最终独立复核未发现 P0/P1。已修复的最后一批问题包括:
|
|
||||||
|
|
||||||
- 16/32-byte explicit extent table 全局严格顺序验证;
|
|
||||||
- extended compressed inode 的完整 48-bit `blocks_hi` 解码;
|
|
||||||
- special vnode size 与其他 setattr 字段组合时的 false success;
|
|
||||||
- dot-omitted 目录在 `OFF_MAX` 的 cookie/offset overflow;
|
|
||||||
- `build.sh` 对 `nm` 自身失败的可靠传播;
|
|
||||||
- NFS generation 文档与真实实现边界不一致。
|
|
||||||
|
|
||||||
从社区第三方维护者视角,未发现仍需消除的非必要 Linux/FreeBSD 结构、命名或
|
|
||||||
职责差异。保留的差异均来自 FreeBSD kernel API、锁、provider、pager、NFS 或
|
|
||||||
权限模型要求。
|
|
||||||
|
|
||||||
## 未完成与搁置
|
|
||||||
|
|
||||||
唯一批准搁置项是
|
|
||||||
[explicit mapped extent payload](../../issues/extent-metadata-fixture-unavailable.md):
|
|
||||||
|
|
||||||
- erofs-utils 1.8.6 不能生成或独立验证该新格式;
|
|
||||||
- 已尝试工具能力扫描、`--max-extent-bytes`、structured conversion、ABI/control
|
|
||||||
flow 对照以及多类负向 fixture;
|
|
||||||
- TC157 已证明 16/32-byte unordered table fail closed,但不能替代 mapped payload
|
|
||||||
的 source-identical 正向读取;
|
|
||||||
- 首个非零 `lstart` 和极大 extent-count 性能边界也保留为可选覆盖风险。
|
|
||||||
|
|
||||||
## 后续执行计划
|
|
||||||
|
|
||||||
1. 等待可生成并独立验证 explicit mapped-payload 的上游工具或可信 fixture。
|
|
||||||
2. 获得 fixture 后补充 4/8/16/32-byte 正向 record、partial reference、high words、
|
|
||||||
binary-search transition 和 final fragment 动态覆盖,使 TC146 从 PARTIAL 转 PASS。
|
|
||||||
3. 如后续项目另行启动 CI,再基于现有 Markdown 断言设计自动化;不得把当前手工
|
|
||||||
PASS 记录直接转换成无条件自动 PASS。
|
|
||||||
4. 后续源码变更继续执行受影响 TC、双配置 build、module smoke、scoped Git hygiene
|
|
||||||
和独立 review,不要求无差别重跑与改动无关的全部历史环境。
|
|
||||||
|
|
||||||
## 相关提交
|
|
||||||
|
|
||||||
正式八组手工验证:
|
|
||||||
|
|
||||||
- G1 `9ae22009f23a65320730072a780998e80aa9b728`
|
|
||||||
- G2 `aed7b68b79a5bd4115913f8361821c86fd58d2e2`
|
|
||||||
- G3 `381349b3847209a67d669264ac54a50a3599915c`
|
|
||||||
- G4 `f383bbbbff301a6bde18894f03ab88a8c0cc885a`
|
|
||||||
- G5 `c566d8ac6bf8e801082bbccf108451f6ee46ad40`
|
|
||||||
- G6 `f11fff5b8e8050e1017ed86f0bcf71042b2b45aa`
|
|
||||||
- G7 `f3ab2096fea3942317deb83fa051c84d3c124ec2`
|
|
||||||
- G8 `6f336d0a7387c8f110b19abad6e96f3ea17dba2e`
|
|
||||||
|
|
||||||
最终源码与验证收口:
|
|
||||||
|
|
||||||
- `f27b524a35b1c960be7e81884f9b928d9ac907e9`:metadata boundary 修复。
|
|
||||||
- `67d3c057fbcad5adc765ab9927da511e3221ac8f`:explicit extent header 解码修复。
|
|
||||||
- `fcc85b93d5f8fd9671686bd68bf3b086c8bd25cf`:TC157-TC161 规格与 helper。
|
|
||||||
- `12351cbb0a593474f4fcef68ffc5218d9c99dd46`:最终手工报告、覆盖、issue 和 README 汇总。
|
|
||||||
|
|
||||||
逐项证据见
|
|
||||||
`tests/results/manual/2026-08-09T1804Z-final-review-independent/manual-test-report.md`;
|
|
||||||
最终统计口径见 `docs/TEST_REPORT.md` 和 `tests/TEST-COVERAGE-MATRIX.md`。
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# repo22 第三次状态报告索引
|
|
||||||
|
|
||||||
- [第三次总体进度报告](2026-08-09-overall-progress.md):以
|
|
||||||
`12351cbb0a593474f4fcef68ffc5218d9c99dd46` 为最终验证快照,汇总已完成
|
|
||||||
feature 验证、code/style review、最终构建、剩余风险和后续计划。
|
|
||||||
|
|
||||||
本目录只记录本轮收尾状态。逐项命令、hash、errno 和清理证据以
|
|
||||||
`tests/results/manual/` 为准,issue 的触发、分析、尝试和验收条件以
|
|
||||||
`issues/` 为准。report-1 和 report-2 保留为历史快照,不因本报告改写。
|
|
||||||
@@ -1,726 +0,0 @@
|
|||||||
# repo22 任务 2:全面代码审查与风格优化评估
|
|
||||||
|
|
||||||
日期:2026-08-10
|
|
||||||
|
|
||||||
性质:只读评估,不含源码修改、测试实现或 CI 变更
|
|
||||||
|
|
||||||
范围:原任务中的“2. 进行全面的 code review 和 style 优化”
|
|
||||||
|
|
||||||
## 1. 执行结论
|
|
||||||
|
|
||||||
本轮以第三方社区维护者视角,对 repo22 的 FreeBSD EROFS 实现进行了新的严格
|
|
||||||
静态审查。审查逐条回应原任务 2 的三个目标:
|
|
||||||
|
|
||||||
1. 判断实现是否合理复用 FreeBSD kernel 已有能力,是否存在不必要的重写,或
|
|
||||||
反过来存在不应强行引用内核实现的场景。
|
|
||||||
2. 判断 BSD 与 Linux 的行为差异是否被正确识别,避免把 Linux 共同缺陷误记为
|
|
||||||
BSD 移植差异,也避免为追求外观一致而破坏 FreeBSD VFS、GEOM 和 errno 契约。
|
|
||||||
3. 判断两个独立仓库在文件职责、函数和变量命名、定义顺序、磁盘 ABI、注释和
|
|
||||||
style 上是否已经消除非必要差异。
|
|
||||||
|
|
||||||
结论是:repo22 的 FreeBSD API 集成和核心算法映射已有良好基础,但任务 2 尚不
|
|
||||||
能认定为全面完成。本轮确认:
|
|
||||||
|
|
||||||
| 等级 | 数量 | 结论 |
|
|
||||||
| --- | ---: | --- |
|
|
||||||
| P0 | 0 | 未发现当前静态证据可确认的立即阻断问题 |
|
|
||||||
| P1 | 2 | vnode 生命周期 UAF;未压缩 physical run/chunk 大读的巨型分配与 `uiomove()` 长度截断 |
|
|
||||||
| P2 | 4 | 目录排序、根类型、compact 加法回绕、explicit extent 首次全表扫描 |
|
|
||||||
| P3 | 6 | errno、时间、symlink、48-bit 边界、setattr、FRAGMENTS 注释/死分支 |
|
|
||||||
|
|
||||||
这些新 finding 均未在本轮动态复现,也未修复。本报告给出的测试均是后续建议,
|
|
||||||
不是已执行结果。CI 明确不在本轮范围。
|
|
||||||
|
|
||||||
任务 1 已完成的 feature 验证和手工测试记录不在本报告中重写。静态审查发现的
|
|
||||||
新风险也不应被误读为已推翻全部既有功能证据;它们需要后续按优先级复现、修复
|
|
||||||
并回归。
|
|
||||||
|
|
||||||
## 2. 审计方法与限制
|
|
||||||
|
|
||||||
### 2.1 方法
|
|
||||||
|
|
||||||
本轮采用以下互相独立的证据层:
|
|
||||||
|
|
||||||
- **源码静态比对**:逐文件映射 repo22 与 Linux 7.1.0-rc1 `fs/erofs`,比较磁盘
|
|
||||||
ABI、核心算法、函数职责、函数顺序和命名。
|
|
||||||
- **FreeBSD 契约核对**:直接检查 FreeBSD 15.0-RELEASE-p9 中 vnode、VFS、GEOM、
|
|
||||||
`uio`、pager、ACL、extattr、XZ、ZSTD 和参考文件系统实现。
|
|
||||||
- **历史检查**:确认 repo22 最终源码提交、Linux 参考导入提交、tree hash、历史
|
|
||||||
测试入口和 UDF helper 的可追溯程度。
|
|
||||||
- **机械检查**:执行 FreeBSD `checkstyle9.pl`,检查文件树、共同编译单元顺序、
|
|
||||||
死声明、硬编码旧目录和许可证标识。
|
|
||||||
- **独立复核**:对高风险 vnode 生命周期、目录排序、根类型、只读 `setattr`、
|
|
||||||
许可证措辞、UDF 来源措辞、旧测试入口和 style 统计进行了二次静态复核。
|
|
||||||
|
|
||||||
### 2.2 限制
|
|
||||||
|
|
||||||
- 本轮没有启动新的 FreeBSD 动态测试批次。
|
|
||||||
- 新 finding 尚未通过 fault injection、损坏镜像、并发卸载或大 I/O 实测。
|
|
||||||
- 性能风险只根据分配和扫描路径分析,未给出吞吐、延迟或内存峰值数据。
|
|
||||||
- 许可证部分只陈述仓库可观察事实,不作法律结论。
|
|
||||||
- Linux 与 FreeBSD 是独立仓库;本报告只要求维护者可识别的相似性,不要求共享
|
|
||||||
Git 历史、构建系统或平台抽象。
|
|
||||||
- `checkstyle9.pl` 自身标记部分规则为 experimental,因此输出是审查输入,不能
|
|
||||||
自动等同为每一项都必须修改。
|
|
||||||
|
|
||||||
## 3. 可复现基线
|
|
||||||
|
|
||||||
### 3.1 BSD 目标
|
|
||||||
|
|
||||||
- repo22 HEAD:`76cfb553e0951b428f9d426933a10d1fe18d2a0e`
|
|
||||||
- 最终源码变更提交:`67d3c057fbcad5adc765ab9927da511e3221ac8f`
|
|
||||||
- 当前 `src/` tree:`a605af0f01f83d67c199005e775e1a47a1610036`
|
|
||||||
- 从 `67d3c057f` 到本报告基线 HEAD,`src/` tree 未再变化。
|
|
||||||
|
|
||||||
### 3.2 Linux 独立参考
|
|
||||||
|
|
||||||
- 精简参考:`/work/dev-src-linux/fs/erofs`
|
|
||||||
- 版本:Linux 7.1.0-rc1
|
|
||||||
- 本地导入提交:`8be2be573d2b191c83d760b65c554f78eb95893c`
|
|
||||||
- EROFS tree:`b79b9a8b62f633e887a8b99075ff9412fabd7f83`
|
|
||||||
- `/work/linux-src/fs/erofs` 与精简参考内容及 tree hash 相同。
|
|
||||||
|
|
||||||
该 Linux 树只作为独立源码参考,不要求与 repo22 共仓。当前 `/work` 开发环境内
|
|
||||||
可以用提交和 tree hash 验证其身份;只获得独立 repo22 的社区维护者,则无法从
|
|
||||||
现有 repo22 文档唯一重建该基线,详见第 10 节。
|
|
||||||
|
|
||||||
### 3.3 FreeBSD API 参考
|
|
||||||
|
|
||||||
- 路径:`/work/dev-freebsd-releng`
|
|
||||||
- 版本:FreeBSD 15.0-RELEASE-p9
|
|
||||||
- 重点契约:`insmntque()`、`uiomove()`、`vfs_read_dirent()`、GEOM VFS、vnode pager、
|
|
||||||
POSIX.1e ACL、extattr、XZ Embedded、ZSTDIO 和参考文件系统。
|
|
||||||
|
|
||||||
### 3.4 提交卫生
|
|
||||||
|
|
||||||
创建 report-4 前,repo22 scoped tracked、staged、untracked 状态均为 0,且
|
|
||||||
`HEAD == xdm/main`。本次提交范围限定为 `current/report-4/`,不会修改既有源码、
|
|
||||||
测试、文档、issues、report-1 至 report-3 或 `current/README.md`。
|
|
||||||
|
|
||||||
## 4. 文件职责映射
|
|
||||||
|
|
||||||
### 4.1 共同或语义对应文件
|
|
||||||
|
|
||||||
| repo22 | Linux `fs/erofs` | 维护者视角结论 |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| `src/erofs_fs.h` | `erofs_fs.h` | 磁盘 ABI 应最严格对齐;字段布局正确性优先于平台风格 |
|
|
||||||
| `src/internal.h` | `internal.h`, `compress.h` | 内存结构和接口语义对应,FreeBSD 类型必然不同 |
|
|
||||||
| `src/super.c` | `super.c` | superblock、设备表、mount、statfs、生命周期 |
|
|
||||||
| `src/inode.c` | `inode.c` | inode 解码;Linux inode ops 由 BSD vnops 分担 |
|
|
||||||
| `src/data.c` | `data.c` | block/chunk mapping 对应;folio/iomap 改为 buffer/GEOM/uio |
|
|
||||||
| `src/dir.c` | `dir.c` | 目录结构解析对应;cookie 和 dirent 输出是 BSD 适配 |
|
|
||||||
| `src/namei.c` | `namei.c` | 两级二分搜索语义高度对应;namecache/锁为 BSD 适配 |
|
|
||||||
| `src/xattr.c` | `xattr.c` | 磁盘 xattr 解析对应;namespace、ACL、extattr API 不同 |
|
|
||||||
| `src/xattr.h` | `xattr.h` | 只应保留 FreeBSD 实际接口,当前仍有 Linux 残片 |
|
|
||||||
| `src/decompressor.c` | `decompressor.c` | dispatcher 对应;配置职责仍有非必要差异 |
|
|
||||||
| `src/decompressor_lzma.c` | `decompressor_lzma.c` | 算法对应;FreeBSD 侧私有嵌入 XZ Embedded |
|
|
||||||
| `src/decompressor_deflate.c` | `decompressor_deflate.c` | 直接调用 FreeBSD zlib,方向正确 |
|
|
||||||
| `src/decompressor_zstd.c` | `decompressor_zstd.c` | 使用内核 ZSTDIO,方向正确 |
|
|
||||||
| `src/zmap.c` | `zmap.c` | 压缩映射核心最接近 Linux,函数顺序对齐质量高 |
|
|
||||||
| `src/zdata.c` | `zdata.c` | 职责对应;同步读取与 Linux folio/pcluster pipeline 必然不同 |
|
|
||||||
| `src/Makefile` | `Makefile`, `Kconfig` | 只比较编译单元职责和顺序,不比较构建语法 |
|
|
||||||
|
|
||||||
### 4.2 Linux-only 文件,不应为了外观模拟
|
|
||||||
|
|
||||||
| Linux-only 文件 | 不在 repo22 创建空文件的理由 |
|
|
||||||
| --- | --- |
|
|
||||||
| `sysfs.c` | FreeBSD 无 Linux sysfs 模型,mount/sysctl 语义需独立设计 |
|
|
||||||
| `fileio.c` | Linux file-backed I/O 路径与当前 GEOM provider 模型不同 |
|
|
||||||
| `fscache.c` | Linux fscache/netfs 子系统在 FreeBSD 无直接对应 |
|
|
||||||
| `ishare.c` | Linux inode/xattr sharing 生命周期依赖其 VFS 内部模型 |
|
|
||||||
| `zutil.c` | Linux folio、bio、pcluster 工具层不适用于同步 BSD 读取路径 |
|
|
||||||
| `decompressor_crypto.c` | Linux Crypto API 后端在当前 FreeBSD 目标中无对应承诺 |
|
|
||||||
| `compress.h` | Linux 压缩调度、folio 和 stream 数据结构不能机械复制 |
|
|
||||||
|
|
||||||
缺少这些文件是必要平台差异,不是结构欠缺。为了目录看起来相同而新增空壳,会
|
|
||||||
制造虚假维护入口。
|
|
||||||
|
|
||||||
### 4.3 BSD-only 文件
|
|
||||||
|
|
||||||
| BSD-only 文件 | 必要性结论 |
|
|
||||||
| --- | --- |
|
|
||||||
| `src/erofs_vnops.c` | 必要。集中实现 VOP、pager、ACL、NFS file handle 和只读语义 |
|
|
||||||
| `src/lz4.c` | 必要。FreeBSD/OpenZFS LZ4 接口不匹配 EROFS raw block 和 partial 输出 |
|
|
||||||
| `src/erofs_defs.h` | 文件本身可存在,但当前含部分仅定义未使用的宏,必要性需缩减 |
|
|
||||||
|
|
||||||
## 5. Findings First
|
|
||||||
|
|
||||||
以下只列入已经过独立静态复核、或任务指定为已复核的结论。每项明确其类别,
|
|
||||||
避免把 Linux 共同问题写成 BSD 行为差异。
|
|
||||||
|
|
||||||
### 5.1 P0
|
|
||||||
|
|
||||||
无。
|
|
||||||
|
|
||||||
### 5.2 P1-1:`insmntque()` 失败后继续访问已回收 vnode
|
|
||||||
|
|
||||||
- **位置**:`src/inode.c:452` 调用 `insmntque()`;失败分支在
|
|
||||||
`src/inode.c:453-457` 释放 `en` 后又于 `src/inode.c:455` 写
|
|
||||||
`vp->v_data = NULL`。
|
|
||||||
- **FreeBSD 对照**:`sys/kern/vfs_subr.c:2303-2315` 在插入失败时清空
|
|
||||||
`v_data`、切换 dead ops、执行 `vgone()` 和 `vput()`;
|
|
||||||
`sys/kern/vfs_subr.c:2328-2341` 明确说明 `insmntque()` 会在失败时回收 vnode,
|
|
||||||
只有 `insmntque1()` 把清理留给调用者。
|
|
||||||
- **参考实现**:`sys/fs/cd9660/cd9660_vfsops.c:717-721` 失败后只释放私有
|
|
||||||
inode,不再解引用 vnode。
|
|
||||||
- **Linux 对照**:Linux `fs/erofs/inode.c` 使用 `iget5_locked()` /
|
|
||||||
`iget_failed()` 管理不同的 inode 生命周期,不能机械复制,但同样要求失败路径
|
|
||||||
不访问已交还对象。
|
|
||||||
- **触发与影响**:vnode 构造与强制或并发卸载竞争,进入
|
|
||||||
`MNTK_UNMOUNT`/`MNTK_UNMOUNTF` 失败路径。后续写可能成为释放后访问,并可能
|
|
||||||
清空已经复用 vnode 的 `v_data`,属于内核内存安全风险。
|
|
||||||
- **类别**:BSD 独有缺陷,源于 FreeBSD vnode 所有权契约。
|
|
||||||
- **修复方向**:采用 cd9660 所示所有权模式,失败后释放私有 `en`、清空输出并
|
|
||||||
返回,不再访问 `vp`。是否改用 `insmntque1()` 必须有明确的完整清理理由。
|
|
||||||
- **建议 Markdown 手工测试**:新增并发冷 lookup/getfh 与 `umount -f` 测试,
|
|
||||||
配合 vnode 分配压力;在 INVARIANTS/WITNESS 内核下记录 panic、WITNESS、引用
|
|
||||||
计数和清理状态。建议增加仅测试用故障注入以确定性触发插入失败。
|
|
||||||
- **状态**:已静态复核;未动态复现;未修复。
|
|
||||||
|
|
||||||
### 5.3 P1-2:一般未压缩 physical run/chunk 大读可触发巨型 `M_WAITOK` 分配和 `uiomove()` 长度截断
|
|
||||||
|
|
||||||
- **位置**:`src/data.c:493-500` 直接从 `uio_resid` 和映射 run 计算 `want`;
|
|
||||||
`src/data.c:514-518` 把该 `size_t` 长度传入读取路径;
|
|
||||||
`src/data.c:208-245` 的 `erofs_bread_device()` 使用
|
|
||||||
`malloc(len, M_EROFS, M_WAITOK)` 分配连续缓冲;`src/data.c:521` 再把 `size_t want`
|
|
||||||
传给 `uiomove()`。
|
|
||||||
- **FreeBSD 对照**:`sys/sys/uio.h:95` 声明
|
|
||||||
`int uiomove(void *cp, int n, struct uio *uio)`。因此大于等于 2 GiB 的 `size_t`
|
|
||||||
长度在传参时不能被该接口正确表达,可能截断为负值或零值并造成错误或无进展。
|
|
||||||
- **Linux 对照**:Linux `fs/erofs/data.c` 使用 folio/iomap 分页路径,不建立与
|
|
||||||
整个用户请求同尺寸的连续内核缓冲。该差异来自 I/O 模型,但当前无界分配不是
|
|
||||||
FreeBSD 所要求的必要差异。
|
|
||||||
- **触发与影响**:恶意或异常大 chunk/run,配合大 `VOP_READ`/`uio_resid`。影响
|
|
||||||
包括用户可控的巨型 `M_WAITOK` 连续内核分配、系统内存压力、长时间阻塞,以及
|
|
||||||
大于等于 2 GiB 时 `uiomove()` 截断或循环无进展。
|
|
||||||
- **类别**:BSD 独有缺陷,属于 I/O 分块和内核 API 宽度处理问题。
|
|
||||||
- **修复方向**:把读取固定分块到同时满足 buffer cache、`INT_MAX` 和合理内存
|
|
||||||
上限的尺寸;每轮验证 `uio_resid` 或 offset 必须前进;避免按整个 run 分配。
|
|
||||||
- **建议 Markdown 手工测试**:构造超大 chunk/run 的稀疏镜像,分别测试
|
|
||||||
`INT_MAX-1`、`INT_MAX`、`INT_MAX+1` 和大于 2 GiB 请求;记录 wired memory、
|
|
||||||
malloc failure、进度、信号中断、errno 和 mount/KLD 清理。测试必须设置资源
|
|
||||||
上限,避免把宿主机作为压力目标。
|
|
||||||
- **状态**:已静态复核;未动态复现;未修复。
|
|
||||||
|
|
||||||
### 5.4 P2-1:目录名称排序不变量未验证
|
|
||||||
|
|
||||||
- **位置**:`src/dir.c:72-109` 校验 dirent 数量、`nameoff` 单调、名称长度和非法
|
|
||||||
`/`,但不比较相邻名称;`src/namei.c:55-100` 执行块内二分,
|
|
||||||
`src/namei.c:103-125` 开始跨块二分选择。
|
|
||||||
- **Linux 对照**:Linux `fs/erofs/erofs_fs.h:280` 记录目录项按字典序排列;
|
|
||||||
Linux `fs/erofs/namei.c:45` 起的查找同样依赖该不变量,也未做全局排序验证。
|
|
||||||
- **触发与影响**:结构合法但名称降序、重复或跨块逆序的损坏镜像。实际存在的
|
|
||||||
名称可被静默返回为 `ENOENT`,随后建立负 namecache,使错误持续存在。
|
|
||||||
- **类别**:Linux 共同依赖的格式不变量;在 repo22“损坏结构返回
|
|
||||||
`EINTEGRITY`、不得静默 miss”的更严格政策下,是 BSD 当前一致性缺口,不应
|
|
||||||
描述成 BSD/Linux 行为差异。
|
|
||||||
- **修复方向**:对不可变目录执行一次全局严格递增验证,覆盖块内、跨块和重复
|
|
||||||
名称,并缓存结果;损坏统一返回 `EINTEGRITY`,不得写入负缓存。
|
|
||||||
- **建议 Markdown 手工测试**:构造块内降序、块内重复、跨块逆序、跨块重复四类
|
|
||||||
镜像;冷 lookup、重复 lookup、readdir 和 NFS lookup 均应返回
|
|
||||||
`EINTEGRITY`,并验证 namecache 无错误负项。
|
|
||||||
- **状态**:已静态复核;未动态复现;未修复。
|
|
||||||
|
|
||||||
### 5.5 P2-2:根 vnode 未验证为目录
|
|
||||||
|
|
||||||
- **位置**:`src/super.c:759-768` 的 `erofs_root()` 只调用 `erofs_vget()`;
|
|
||||||
`src/inode.c:471-475` 按 inode mode 设置 vnode 类型,并仅按 NID 设置 `VV_ROOT`。
|
|
||||||
- **Linux 对照**:Linux `fs/erofs/super.c:765-774` 加载 root inode 后明确执行
|
|
||||||
`S_ISDIR()`,非目录则释放并返回 `-EINVAL`。
|
|
||||||
- **FreeBSD 对照**:VFS mount 后续不会替 EROFS 强制验证其 `VFS_ROOT()` 返回
|
|
||||||
`VDIR`,文件系统必须自行维持该不变量。
|
|
||||||
- **触发与影响**:checksum-valid、但 root inode mode 被改为普通文件、symlink
|
|
||||||
或 FIFO 的镜像可能完成挂载;挂载点后续出现 `ENOTDIR` 或异常 vnode 语义。
|
|
||||||
- **类别**:BSD 独有缺口;Linux 已显式处理。
|
|
||||||
- **修复方向**:`erofs_vget()` 成功后验证 `(*vpp)->v_type == VDIR`,失败时正确
|
|
||||||
`vput()`。errno 可对齐 Linux 使用 `EINVAL`,或按 repo22 损坏政策使用
|
|
||||||
`EINTEGRITY`,但需统一文档。
|
|
||||||
- **建议 Markdown 手工测试**:分别生成 root inode 为 VREG、VLNK、VFIFO 的
|
|
||||||
checksum-valid 镜像,验证挂载失败、errno 稳定、无 mount/md/KLD 残留。
|
|
||||||
- **状态**:已静态复核;未动态复现;未修复。
|
|
||||||
|
|
||||||
### 5.6 P2-3:compact index 物理块号加法先发生 32-bit 回绕
|
|
||||||
|
|
||||||
- **位置**:`src/zmap.c:267`:
|
|
||||||
`m->pblk = le32dec(...) + nblk;`。`le32dec()` 和 `nblk` 均为 32-bit 范围,表达式
|
|
||||||
在赋给 64-bit `m->pblk` 前可能已经回绕。
|
|
||||||
- **Linux 对照**:Linux `fs/erofs/zmap.c:230-232` 使用同样的
|
|
||||||
`le32_to_cpu(...) + nblk` 结构,因此 Linux 参考也存在相同风险。
|
|
||||||
- **触发与影响**:基准物理块接近 `UINT32_MAX` 且 compact 索引累计 `nblk` 非零,
|
|
||||||
映射到错误的低地址,可能读到错误数据或触发后续一致性错误。
|
|
||||||
- **类别**:Linux 共同缺陷,绝不能为了源码相似而保留,也不能记成 BSD 差异。
|
|
||||||
- **修复方向**:在加法前显式提升到 64-bit,并使用 checked addition;随后按设备
|
|
||||||
块范围验证。
|
|
||||||
- **建议 Markdown 手工测试**:构造 base pblk 接近 `UINT32_MAX`、累计跨越边界的
|
|
||||||
compact 索引,验证映射不会回绕;同时测试恰好不溢出的边界和真实设备范围错误。
|
|
||||||
- **状态**:已静态复核;未动态复现;未修复。
|
|
||||||
|
|
||||||
### 5.7 P2-4:explicit extent 首次初始化执行有界 O(N) 全表扫描
|
|
||||||
|
|
||||||
- **位置**:`src/zmap.c:581-619` 的 `z_erofs_validate_extent_table()` 在首次初始化
|
|
||||||
时从 `index=0` 到 `en->z_extents-1` 逐项读取并验证严格递增;调用后才进入
|
|
||||||
二分映射路径。
|
|
||||||
- **Linux 对照**:Linux `fs/erofs/zmap.c:501-588` 映射 explicit extent 时按需
|
|
||||||
二分读取,没有 repo22 这一首次完整预扫描。
|
|
||||||
- **触发与影响**:超大 extent 表在首次访问时产生 O(N) 元数据 I/O 和延迟,攻击
|
|
||||||
者可用格式边界内的大计数制造明显可用性压力。
|
|
||||||
- **边界说明**:循环由 `en->z_extents` 严格限制,记录位置使用 checked arithmetic,
|
|
||||||
并验证 `lstart` 严格递增。当前证据不支持“无限循环”或“无边界访问”的说法。
|
|
||||||
- **类别**:BSD 独有的性能/可用性权衡,源于更严格的全表不变量验证,不是立即
|
|
||||||
correctness 失败。
|
|
||||||
- **修复方向**:先量化真实最坏情况。可评估分段验证、验证结果缓存、mount-time
|
|
||||||
预算或按二分访问范围逐步验证;任何优化都不能重新引入静默错误映射。
|
|
||||||
- **建议 Markdown 手工测试**:生成多档 extent count 的合法/末尾损坏表,测量
|
|
||||||
首次与重复 lookup/read 延迟、I/O 次数和内存;验证预算超限时 errno 和清理。
|
|
||||||
- **状态**:已静态复核;未做性能原型;未修复。
|
|
||||||
|
|
||||||
### 5.8 P3-1:DEFLATE 分配失败被统一映射为 `EIO`
|
|
||||||
|
|
||||||
- **位置**:`src/decompressor.c:246-257` 将所有后端非零返回统一转换为 `EIO`;
|
|
||||||
`src/decompressor_deflate.c` 的分配失败因而不能保留 `ENOMEM`。
|
|
||||||
- **Linux/FreeBSD 对照**:平台均区分资源耗尽和输入/设备错误;调用 FreeBSD
|
|
||||||
zlib 是正确的,但 wrapper 的返回契约过窄。
|
|
||||||
- **影响**:内存压力下诊断和上层重试策略失真。
|
|
||||||
- **类别**:BSD 独有 errno 映射问题。
|
|
||||||
- **修复方向**:后端返回正 errno,dispatcher 只做必要规范化。
|
|
||||||
- **建议测试**:故障注入 DEFLATE workspace/output 分配失败,要求 `ENOMEM`;损坏
|
|
||||||
流仍应为 `EIO` 或项目约定的完整性错误。
|
|
||||||
- **状态**:已静态复核;未动态复现;未修复。
|
|
||||||
|
|
||||||
### 5.9 P3-2:负 Unix 时间被拒绝,和 Linux 语义不一致
|
|
||||||
|
|
||||||
- **位置**:`src/inode.c:60-68` 以 `uint64_t seconds` 接收时间,并拒绝大于
|
|
||||||
`INT64_MAX` 的值。
|
|
||||||
- **Linux 对照**:Linux `fs/erofs/inode.c:108-109` 将磁盘 extended inode 的
|
|
||||||
64-bit 时间传给 inode time;Linux 时间模型允许 1970 年前的负时间语义。
|
|
||||||
- **影响**:使用补码表达负秒值的镜像在 BSD 被视为损坏,形成跨平台兼容差异。
|
|
||||||
- **类别**:BSD/Linux 行为差异,格式签名语义需先与上游规范确认。
|
|
||||||
- **修复方向**:确认磁盘字段的正式有符号语义,再采用显式 signed 解码和 FreeBSD
|
|
||||||
`timespec` 范围检查。
|
|
||||||
- **建议测试**:覆盖 `-1`、`INT64_MIN` 邻近值、epoch 和正最大值,在 Linux/BSD
|
|
||||||
上比较 stat 结果与 errno。
|
|
||||||
- **状态**:静态候选已复核;格式语义仍需上游确认;未修复。
|
|
||||||
|
|
||||||
### 5.10 P3-3:inline symlink 未拒绝声明长度内嵌 NUL
|
|
||||||
|
|
||||||
- **位置**:`src/data.c:529-533` 的 readlink 直接复用普通读取路径;
|
|
||||||
`src/data.c:493-525` 按 inode 声明长度移动字节,没有对 symlink payload 做 NUL
|
|
||||||
一致性检查。
|
|
||||||
- **Linux 对照**:Linux 同样主要依赖 inode size 和 VFS symlink 语义;本项不是
|
|
||||||
用于制造表面差异,而是要求 BSD 明确损坏镜像政策。
|
|
||||||
- **影响**:声明长度内部出现 NUL 时,不同调用者可能观察截断或不一致目标。
|
|
||||||
- **类别**:损坏输入处理缺口,是否需要拒绝应与 EROFS 格式语义统一。
|
|
||||||
- **修复方向**:确认格式是否禁止嵌入 NUL;若禁止,在 inode/readlink 验证中返回
|
|
||||||
`EINTEGRITY`,且不得影响合法非 NUL 目标。
|
|
||||||
- **建议测试**:inline 和非 inline symlink 分别构造中间 NUL、末尾 NUL、无 NUL
|
|
||||||
目标,比较 `readlink(2)`、namei 跟随和 NFS 行为。
|
|
||||||
- **状态**:静态候选已复核;格式语义待确认;未修复。
|
|
||||||
|
|
||||||
### 5.11 P3-4:48-bit end-exclusive 检查拒绝最后一个合法完整块
|
|
||||||
|
|
||||||
- **位置**:`src/zmap.c:895-898` 计算 `pend = m_pa + m_plen`,随后以
|
|
||||||
`(pend >> block_bits) >= (1ULL << 48)` 拒绝映射。
|
|
||||||
- **Linux 对照**:Linux 参考中的相关 48-bit 映射边界也存在同类 end-exclusive
|
|
||||||
处理风险。
|
|
||||||
- **触发与影响**:映射恰好结束在 48-bit 地址空间上界时,`pend` 是合法的
|
|
||||||
end-exclusive 值,但当前检查把最后一个完整合法块拒绝为 `EINTEGRITY`。
|
|
||||||
- **类别**:Linux 共同边界缺陷,不是 BSD 差异。
|
|
||||||
- **修复方向**:校验最后一个实际字节/块,或使用 `pend > limit` 的 byte limit
|
|
||||||
比较,并单独处理零长度。
|
|
||||||
- **建议测试**:覆盖最后合法块、越界一字节、越界一块和零长度映射。
|
|
||||||
- **状态**:已静态复核;未动态复现;未修复。
|
|
||||||
|
|
||||||
### 5.12 P3-5:birthtime-only `VOP_SETATTR()` 可假成功
|
|
||||||
|
|
||||||
- **位置**:`src/erofs_vnops.c:252-281` 检查 mode、uid、gid、atime、mtime、flags
|
|
||||||
和 size,但不检查 `va_birthtime`,最终可能返回 0。
|
|
||||||
- **FreeBSD 对照**:`VATTR_NULL()` 会把 birthtime 设为 `VNOVAL`,内核调用者可以
|
|
||||||
构造仅 birthtime 有效的请求。
|
|
||||||
- **触发与影响**:直接内核 VOP 调用可收到成功但属性未改变,违反只读 VOP 语义。
|
|
||||||
- **路径限定**:独立复核未确认普通用户态或 NFSv4 可绕过只读 mount 检查到达该
|
|
||||||
单属性路径,因此不能声称已有用户/NFS 可利用的假成功链。
|
|
||||||
- **类别**:BSD 独有 VOP 契约和未来维护问题,严重度降为 P3。
|
|
||||||
- **修复方向**:birthtime 变更返回 `EROFS`;对 type、nlink、fsid、fileid、
|
|
||||||
blocksize、rdev、bytes、generation 等结构字段明确返回 `EINVAL`。
|
|
||||||
- **建议测试**:扩展内核 probe,直接提交 birthtime-only 和各结构字段请求;本地
|
|
||||||
syscall 与 NFS 测试用于确认它们仍被只读层拒绝。
|
|
||||||
- **状态**:已静态复核;无已证实用户/NFS 路径;未修复。
|
|
||||||
|
|
||||||
### 5.13 P3-6:FRAGMENTS 特例分支不可达,注释与支持边界失配
|
|
||||||
|
|
||||||
- **位置**:`src/erofs_fs.h:56-64` 已把 `EROFS_FEATURE_INCOMPAT_FRAGMENTS` 放入
|
|
||||||
`EROFS_ALL_SUPPORTED_INCOMPAT`;`src/super.c:532` 因而从 `unsupported` 中清除该
|
|
||||||
bit,但 `src/super.c:533-549` 又试图在 `unsupported != 0` 时特例允许仅
|
|
||||||
FRAGMENTS 的组合。
|
|
||||||
- **Linux 对照**:Linux 通过实际 fragment/packed inode 路径表达支持,不需要
|
|
||||||
这种与 supported mask 自相矛盾的特例。
|
|
||||||
- **影响**:当前分支不可达,注释声称“窄允许”但真实代码已经把 FRAGMENTS 当作
|
|
||||||
一般 supported incompat bit,误导维护者判断支持边界。
|
|
||||||
- **类别**:BSD 独有死分支和文档一致性问题。
|
|
||||||
- **修复方向**:依据真实 feature 支持政策二选一:从 supported mask 移除后保留
|
|
||||||
严格特例,或删除死分支并准确文档化支持范围。
|
|
||||||
- **建议测试**:组合测试 FRAGMENTS、XATTR_PREFIXES、PLAIN_XATTR_PFX 和
|
|
||||||
`packed_nid`,记录 mount errno 和实际 fragment inode 访问结果。
|
|
||||||
- **状态**:已静态复核;未动态复现;未修复。
|
|
||||||
|
|
||||||
### 5.14 不列为 correctness finding:fragment `pstart_hi`
|
|
||||||
|
|
||||||
曾有候选认为 fragment extent 构造会丢失 `pstart_hi`。当前静态证据不足以确认该
|
|
||||||
字段在 fragment 记录格式中具有同样的高位语义,也不足以证明当前路径实际丢失
|
|
||||||
可用地址。因此本报告不把它列为 correctness finding,只保留为“与上游格式语义
|
|
||||||
确认”的待办。后续必须先取得格式规范或上游实现证据,再决定是否测试或修改。
|
|
||||||
|
|
||||||
## 6. FreeBSD 最佳实践与原生能力复用
|
|
||||||
|
|
||||||
| 领域 | 当前做法 | 评估与决策 |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| DEFLATE | `src/decompressor_deflate.c:28` 起调用 FreeBSD zlib | 正确复用;应保留,修正 errno 契约即可 |
|
|
||||||
| ZSTD | `src/decompressor_zstd.c` 使用 ZSTDIO API | 正确复用;FreeBSD 无通用独立 zstd KLD,不应伪造依赖 |
|
|
||||||
| MicroLZMA | `src/decompressor_lzma.c:14-38` 私有重命名并编译 XZ Embedded | 应保留本地实现;stock `xz.ko` 未定义 `XZ_DEC_MICROLZMA`,不能强行链接 |
|
|
||||||
| LZ4 | `src/lz4.c:21` 起实现 raw/partial decoder | 应保留;FreeBSD/OpenZFS 接口含不同 framing,且不满足 EROFS partial 语义 |
|
|
||||||
| 目录输出 | `src/dir.c:160-178` 自有 cookie helper | 不能机械替换;它额外验证 cookie 严格递增和容量短读 |
|
|
||||||
| `vfs_read_dirent()` | FreeBSD `sys/kern/vfs_subr.c:6814-6830` | 可原型化为输出层 helper,但必须保留 EROFS cookie 约束并回归 NFS |
|
|
||||||
| GEOM/VFS I/O | `src/super.c:226` 建 consumer,`src/data.c:250` 用 `bread()` | 符合 FreeBSD 文件系统惯用路径,不应改为 GEOM class 私有读接口 |
|
|
||||||
| vnode cache | `src/inode.c:435-460` 用 `vfs_hash_get/insert` | 总体正确;仅 `insmntque()` 失败所有权需修复 |
|
|
||||||
| pager | `src/erofs_vnops.c:434` 复用 local pager | 正确,避免重写 VM pager |
|
|
||||||
| ACL/extattr | `src/erofs_vnops.c:68` 等调用 POSIX.1e ACL/extattr API | 正确保留 BSD namespace 和权限差异 |
|
|
||||||
| CRC32C | `src/super.c:307` 使用 `calculate_crc32c()` | 正确复用 FreeBSD kernel helper |
|
|
||||||
| endian | 磁盘字段使用 `leXXtoh`,非对齐流使用 `leXXdec` | 正确;不应直接复制 Linux unaligned 宏 |
|
|
||||||
| checked arithmetic | 多处使用 compiler overflow builtin | 合理;FreeBSD 15 无更优的通用非 LinuxKPI 替代 |
|
|
||||||
|
|
||||||
### 6.1 为什么不能强行依赖 `xz.ko`
|
|
||||||
|
|
||||||
FreeBSD `sys/modules/xz/Makefile:5-20` 会编译 `xz_dec_lzma2.c` 并导出符号,但没有
|
|
||||||
定义 `XZ_DEC_MICROLZMA`。MicroLZMA 入口受该宏控制,因此 stock `xz.ko` 不提供
|
|
||||||
repo22 所需的 `xz_dec_microlzma_*` ABI。简单添加 `MODULE_DEPEND(erofs, xz, ...)`
|
|
||||||
不能解决符号缺失。
|
|
||||||
|
|
||||||
只有在 FreeBSD 正式启用并导出 MicroLZMA KPI,同时更新模块 ABI/version 后,
|
|
||||||
repo22 才应重新评估直接依赖。当前强行引用反而违反“优先复用,但不强制引用一切”
|
|
||||||
的原任务要求。
|
|
||||||
|
|
||||||
### 6.2 LZMA per-call allocation 是性能原型事项
|
|
||||||
|
|
||||||
`src/decompressor_lzma.c:55-66` 每次解压分配并释放 decoder state。Linux 使用可
|
|
||||||
复用 stream pool。当前没有证据证明它造成 correctness 错误,但并发压缩读取会
|
|
||||||
产生约 30 KiB state 的反复 malloc/free 和锁竞争。
|
|
||||||
|
|
||||||
后续应单独做 per-CPU、mount-local 或受限 pool 原型,测量并发吞吐、内存峰值、
|
|
||||||
卸载清理和字典变化。没有数据前,不应把缓存重构混入 correctness 批次。
|
|
||||||
|
|
||||||
## 7. BSD/Linux 行为差异分类
|
|
||||||
|
|
||||||
### 7.1 必要的 BSD 差异
|
|
||||||
|
|
||||||
- 正 errno,而不是 Linux 内核负 errno。
|
|
||||||
- VOP/VFS operation table、vnode lock、namecache、`vn_vget_ino()` 和
|
|
||||||
`vfs_hash_*` 生命周期。
|
|
||||||
- GEOM consumer、设备 vnode 和 buffer cache I/O,而不是 folio/iomap/bio。
|
|
||||||
- FreeBSD extattr user/system namespace、`extattr_check_cred()` 和 POSIX.1e ACL。
|
|
||||||
- readdir 的 `a_cookies`/`a_ncookies` ABI、synthetic dot cookie 和 NFS 恢复语义。
|
|
||||||
- `fifo_specops`、FreeBSD FID 布局、generation 与 `ESTALE` 校验。
|
|
||||||
- pager 使用 `vnode_pager_local_getpages*`。
|
|
||||||
|
|
||||||
这些差异应保留,不应为了外观接近 Linux 而移除。
|
|
||||||
|
|
||||||
### 7.2 Linux 共同缺陷
|
|
||||||
|
|
||||||
- compact index 32-bit 加法回绕,见 `src/zmap.c:267` 与 Linux
|
|
||||||
`fs/erofs/zmap.c:231`。
|
|
||||||
- 48-bit end-exclusive 最后合法块边界。
|
|
||||||
- 目录二分依赖排序;Linux 也未全局验证。repo22 可选择更严格验证,但不能把
|
|
||||||
上游共同不变量说成 BSD 偏差。
|
|
||||||
|
|
||||||
源码相似不是保留共同缺陷的理由。修复时应尽量沿用上游命名和 checked arithmetic
|
|
||||||
结构,并把可上游化的发现单独记录。
|
|
||||||
|
|
||||||
### 7.3 BSD 独有缺陷
|
|
||||||
|
|
||||||
- `insmntque()` 失败后的 vnode 释放后访问。
|
|
||||||
- chunk 大读的整段 `M_WAITOK` 分配和 `size_t` 到 `int` 的 `uiomove()` 传参。
|
|
||||||
- root vnode 未检查 `VDIR`。
|
|
||||||
- DEFLATE errno 归一化过度。
|
|
||||||
- birthtime-only `VOP_SETATTR()` 假成功。
|
|
||||||
- FRAGMENTS supported mask 与特例注释矛盾。
|
|
||||||
|
|
||||||
### 7.4 非必要维护差异
|
|
||||||
|
|
||||||
- `erofs_fs.h` 定义顺序、常量命名和字段注释没有尽量保持 Linux 顺序。
|
|
||||||
- 压缩配置 loader 集中于 `decompressor.c`,而 Linux 分布在各 backend。
|
|
||||||
- backend 函数名使用 `lzma_decompress`、`deflate_decompress`、
|
|
||||||
`zstd_decompress`,没有采用 Linux `z_erofs_*` 体系。
|
|
||||||
- `xattr.h`、`internal.h`、`erofs_defs.h` 中仍有失效 Linux 声明或未使用抽象。
|
|
||||||
- xattr prefix helper 命名、部分函数定义位置和空包装与 Linux 无必要不同。
|
|
||||||
|
|
||||||
### 7.5 需要原型或格式确认后再判断
|
|
||||||
|
|
||||||
- fragment extent 的 `pstart_hi` 语义。
|
|
||||||
- LZMA decoder state 缓存。
|
|
||||||
- 保留 cookie 验证的 `vfs_read_dirent()` 输出适配器。
|
|
||||||
- explicit extent 全表验证的分段/缓存策略。
|
|
||||||
- negative timestamp 与 inline symlink NUL 的正式格式语义。
|
|
||||||
|
|
||||||
## 8. 结构、命名和 style 对齐
|
|
||||||
|
|
||||||
### 8.1 正向对齐结果
|
|
||||||
|
|
||||||
- repo22 与 Linux 有 15 个共同 C/H 文件名。
|
|
||||||
- `src/namei.c` 的核心名称查找函数名称和顺序高度对应 Linux。
|
|
||||||
- `src/zmap.c` 的 13 个共享核心算法函数保持相同相对顺序,是当前对齐质量最高的
|
|
||||||
文件之一。
|
|
||||||
- `src/Makefile` 中 12 个共同编译单元保持与 Linux Makefile 相同的相对顺序。
|
|
||||||
- `erofs_vnops.c` 集中 BSD VOP glue,避免把 FreeBSD 代码散入所有 Linux 对应
|
|
||||||
算法文件,这一文件级差异是必要且有利于维护的。
|
|
||||||
|
|
||||||
### 8.2 `erofs_fs.h` 的非必要差异
|
|
||||||
|
|
||||||
BSD 与 Linux 都包含同一组核心磁盘结构,但 repo22 的结构顺序、常量命名和注释
|
|
||||||
存在明显漂移。例如 repo22 从 `src/erofs_fs.h:104` 定义 superblock,而 Linux
|
|
||||||
先定义 deviceslot;dirent、chunk index、map header 和 lcluster index 的位置也有
|
|
||||||
移动。机械审查对 19 个核心 struct/union 记录到 31/171 个顺序逆序对,顺序相似度
|
|
||||||
约 81.9%。
|
|
||||||
|
|
||||||
字段 packing、offset、endian 和 `_Static_assert` 是 correctness 约束,应保留 BSD
|
|
||||||
表达;结构定义顺序、字段语义注释和非平台相关名称则应尽量恢复 Linux,以降低
|
|
||||||
未来磁盘格式同步成本。`EROFS_ALL_SUPPORTED_INCOMPAT` 与 Linux 名称不同,也应
|
|
||||||
先判断是否存在真实语义差异,再决定是否保留。
|
|
||||||
|
|
||||||
### 8.3 压缩职责和命名
|
|
||||||
|
|
||||||
repo22 把 LZMA、DEFLATE、ZSTD 配置解析集中在 `src/decompressor.c`,Linux 则分别
|
|
||||||
放在对应 backend。调用 ABI 必须因 FreeBSD 内核 API 而不同,但配置 loader 的
|
|
||||||
文件职责和 `z_erofs_*` 命名并无平台限制。
|
|
||||||
|
|
||||||
建议在 correctness 修复完成后,单独评估把配置解析移回各 backend,并统一内部
|
|
||||||
命名。该重排必须保持双配置构建和全部压缩 Markdown 测试,不应与 P1/P2 修复混在
|
|
||||||
同一提交。
|
|
||||||
|
|
||||||
### 8.4 死代码和残留抽象
|
|
||||||
|
|
||||||
- `src/xattr.h:11-42` 保留注释掉的 Linux `CONFIG_*` 分支、未实现的
|
|
||||||
`erofs_xattr_handlers`、`struct inode` 和 `struct posix_acl` 声明。
|
|
||||||
- `src/internal.h:50-71` 保留未使用的同步解压/cache 枚举和 `erofs_buf`;
|
|
||||||
`src/internal.h:243-247` 的 `erofs_is_fileio_mode()` 固定返回 false。
|
|
||||||
- `src/erofs_defs.h:5-19` 的 CRC polynomial、inode slot bits 和 range-coder 常量
|
|
||||||
多项仅定义未使用;`src/inode.c:137-139` 仍直接使用字面量 5。
|
|
||||||
- `src/super.c` 的部分空包装和函数顺序可进一步与 Linux/FreeBSD 惯例收敛,但应
|
|
||||||
放在纯维护提交中。
|
|
||||||
|
|
||||||
### 8.5 失效测试入口和 harness
|
|
||||||
|
|
||||||
- `test_all_decompress.sh:2-7` 仍标记 repo19;其 `SRCDIR` 当前未实际使用,但测试
|
|
||||||
内容不验证 repo22 KLD。
|
|
||||||
- `test_chunk_based.sh:2-17` 实际进入 repo17,后续会 clean、写镜像、卸载模块、
|
|
||||||
配置 md 和 mount,具有真实误操作其他目录和全局系统状态的风险。
|
|
||||||
- `tests/test_decompress.c` 与 `tests/test_decompress_standalone.c` 已无法通过当前语法
|
|
||||||
检查,并仍按旧参数数量调用后端接口;当前接口见 `src/internal.h:314-322`。
|
|
||||||
|
|
||||||
`docs/architecture.md:242-245` 已声明这两个根脚本不能作为验收入口,但只写文档
|
|
||||||
不足以消除可执行误入口。后续应删除、移入明确的 historical 目录,或改为立即失败
|
|
||||||
并指向 `tests/TC*.md`。
|
|
||||||
|
|
||||||
### 8.6 文档陈旧
|
|
||||||
|
|
||||||
- `docs/architecture.md:79` 的 `erofs_mount` 示例与当前
|
|
||||||
`src/internal.h` 结构不一致,字段如 `z_algorithmformat`、`fragmentoff` 已陈旧。
|
|
||||||
- `docs/architecture.md:273` 声称“零拷贝”,但 `src/data.c:244-261` 明确执行
|
|
||||||
`malloc` 和 `memcpy`。
|
|
||||||
- Linux 基线只记录绝对工作区路径和版本,没有独立仓库可获取的上游 provenance。
|
|
||||||
|
|
||||||
### 8.7 style(9) 机械结果
|
|
||||||
|
|
||||||
使用 FreeBSD `tools/build/checkstyle9.pl` 0.31 对 `src/*.[ch]` 连续检查,结果稳定:
|
|
||||||
|
|
||||||
- 18 个文件;
|
|
||||||
- 48 warnings;
|
|
||||||
- 1 error;
|
|
||||||
- 44 个超过 80 列;
|
|
||||||
- 4 个块注释格式告警;
|
|
||||||
- 唯一 error:`src/erofs_fs.h:265` 的 `return 0` 缺 FreeBSD 风格括号。
|
|
||||||
|
|
||||||
其他可见项包括 `src/internal.h:11-12` 的 `sys/param.h // MUST FIRST` 实际位于
|
|
||||||
`sys/types.h` 后,SPDX 注释形式混用,以及部分 Makefile 空白不统一。
|
|
||||||
|
|
||||||
这些结果不能机械全改。磁盘 ABI 宏、静态断言和与 Linux 保持一致的行,可能有
|
|
||||||
理由超过 80 列。建议先制定“FreeBSD style(9) 优先、磁盘 ABI/上游同步可例外”的
|
|
||||||
仓库规则,再逐批清理。
|
|
||||||
|
|
||||||
## 9. 正向成果与保留项
|
|
||||||
|
|
||||||
本轮不能只列问题。以下成果符合原任务 2 的目标,应在后续优化中保留:
|
|
||||||
|
|
||||||
- 使用 `bsd.kmod.mk`,而不是维持 Linux Kbuild 兼容层。
|
|
||||||
- GEOM consumer、设备 vnode、`bread()` 和 buffer cache 的组合符合 FreeBSD 文件
|
|
||||||
系统路径。
|
|
||||||
- `vfs_hash_*`、vnode pager、ACL、extattr、CRC32C、endian helper 和 checked
|
|
||||||
arithmetic 的总体选型正确。
|
|
||||||
- DEFLATE 和 ZSTD 直接复用可用的 FreeBSD 内核实现。
|
|
||||||
- 不强行依赖缺少 MicroLZMA ABI 的 `xz.ko`,不强行套用不兼容的 OpenZFS LZ4。
|
|
||||||
- `namei.c` 和 `zmap.c` 核心函数顺序与 Linux 高度对应。
|
|
||||||
- Linux-only 文件没有以空壳方式复制到 BSD 仓库。
|
|
||||||
- FreeBSD-only VOP glue 集中在 `erofs_vnops.c`,平台边界清晰。
|
|
||||||
- 既有动态测试已覆盖多设备、压缩映射、xattr/ACL、NFS、48-bit 和边界行为;
|
|
||||||
本报告不重写这些 task 1 证据。
|
|
||||||
|
|
||||||
## 10. 可追溯性与许可证边界
|
|
||||||
|
|
||||||
### 10.1 仓库许可证材料
|
|
||||||
|
|
||||||
repo22 的 18 个生产 `src/*.[ch]` 文件均带 SPDX 标识:13 个
|
|
||||||
`GPL-2.0-only`、4 个 `BSD-2-Clause`、1 个 `MIT`。`docs/erofs.5:1-23` 自身包含
|
|
||||||
完整的 BSD 两条款文本。
|
|
||||||
|
|
||||||
但 repo22 根目录没有集中式 `LICENSE`、`COPYING`、`NOTICE`、许可证构成表或来源
|
|
||||||
清单。SPDX 可以识别文件当前声明,不能单独让第三方重建整个 KLD 的来源、整体
|
|
||||||
分发边界和权利链。
|
|
||||||
|
|
||||||
建议后续增加集中式许可证和来源 manifest,明确 GPL 派生核心、MIT 磁盘 ABI、
|
|
||||||
BSD VOP wrapper、本地 LZ4 和嵌入 XZ 源的关系。本报告不作兼容性或法律结论。
|
|
||||||
|
|
||||||
### 10.2 UDF helper 来源
|
|
||||||
|
|
||||||
`src/dir.c:158-178` 明确写有“modelled after UDF”。历史版本的 `erofs_uiodir`
|
|
||||||
与 FreeBSD `sys/fs/udf/udf_vnops.c:614-639` 在结构、分支顺序和控制流上高度接近;
|
|
||||||
当前版本已增加严格 cookie 单调性、结果枚举、容量检查和不同错误传播。
|
|
||||||
|
|
||||||
现有 Git 历史不足以区分最初是直接复制、紧密改写还是参考实现,因此不得断言
|
|
||||||
侵权或具体来源类别。应由作者确认来源过程,并据此决定是否补充 FreeBSD UDF 的
|
|
||||||
版权归属或说明。
|
|
||||||
|
|
||||||
### 10.3 Linux 基线外部可复现性
|
|
||||||
|
|
||||||
在当前 `/work` 单仓环境内,Linux 参考可由导入提交
|
|
||||||
`8be2be573d2b191c83d760b65c554f78eb95893c` 和 tree
|
|
||||||
`b79b9a8b62f633e887a8b99075ff9412fabd7f83` 验证。
|
|
||||||
|
|
||||||
`docs/architecture.md:160-163` 目前只记录本地绝对路径和 Linux 7.1-rc1 字符串,
|
|
||||||
没有官方上游 URL、上游 Git commit/tag、获取命令和校验值。因此内部审查可复现,
|
|
||||||
独立社区仓库的外部复现材料仍不完整。
|
|
||||||
|
|
||||||
## 11. 第三方维护者相似度
|
|
||||||
|
|
||||||
以下评分来自文件树、共同符号顺序、磁盘 ABI 顺序、FreeBSD API、代码卫生和文档
|
|
||||||
可复现性的综合人工/机械评估。它不是客观度量,也不代表 feature 完整度:
|
|
||||||
|
|
||||||
| 维度 | 暂评分 | 说明 |
|
|
||||||
| --- | ---: | --- |
|
|
||||||
| 文件树与职责 | 8.0/10 | 共同文件清晰,Linux-only/BSD-only 边界总体合理 |
|
|
||||||
| 核心算法命名和顺序 | 8.5/10 | namei/zmap 较好,压缩后端仍有差异 |
|
|
||||||
| 磁盘 ABI 头文件可同步性 | 6.0/10 | 布局重视正确性,但顺序、命名、注释漂移明显 |
|
|
||||||
| FreeBSD API 与构建集成 | 9.0/10 | GEOM、VFS、pager、ACL、压缩库选型总体正确 |
|
|
||||||
| 代码卫生与 style(9) | 5.5/10 | 死声明、旧入口、48 warnings/1 error |
|
|
||||||
| 社区文档与基线可复现性 | 5.0/10 | 内部可验证,独立仓库 provenance 不完整 |
|
|
||||||
| **综合维护者相似度** | **7.2/10** | 带权主观评估,用于维护排序,不是兼容性结论 |
|
|
||||||
|
|
||||||
综合分采用带权主观评估:文件树与职责 15%,核心算法命名和顺序 20%,磁盘 ABI
|
|
||||||
头文件可同步性 20%,FreeBSD API 与构建集成 20%,代码卫生与 style(9) 15%,社区
|
|
||||||
文档与基线可复现性 10%。计算为
|
|
||||||
`8.0*0.15 + 8.5*0.20 + 6.0*0.20 + 9.0*0.20 + 5.5*0.15 + 5.0*0.10 = 7.225`,
|
|
||||||
按一位小数四舍五入为 `7.2/10`。权重反映本任务更重视算法、ABI 和平台集成,仍不
|
|
||||||
应视为客观兼容性指标。
|
|
||||||
|
|
||||||
从第三方维护者视角,当前更准确的描述是:核心算法和主要 FreeBSD 适配已对齐,
|
|
||||||
但仍存在明确的 correctness 风险、结构漂移、代码卫生和可追溯性工作。
|
|
||||||
|
|
||||||
## 12. 后续执行路线
|
|
||||||
|
|
||||||
本报告只给出路线,不执行任何修改。
|
|
||||||
|
|
||||||
### 第一批:先处理两个 P1
|
|
||||||
|
|
||||||
1. 修复 `insmntque()` 失败后的 vnode UAF。
|
|
||||||
2. 对 chunk/physical read 建立严格分块上限,修复 `uiomove(int)` 宽度问题。
|
|
||||||
3. 为两个问题分别新增 Markdown 手工测试和独立 FreeBSD 动态报告。
|
|
||||||
|
|
||||||
该批次必须最小化变更面,不能混入文件重排或 style 清理。
|
|
||||||
|
|
||||||
### 第二批:P2 correctness 与边界测试
|
|
||||||
|
|
||||||
1. 目录全局严格排序验证与 namecache 负项检查。
|
|
||||||
2. root vnode `VDIR` 验证。
|
|
||||||
3. compact pblk 64-bit checked addition。
|
|
||||||
4. 量化 explicit extent 首次 O(N) 扫描,并决定预算/缓存策略。
|
|
||||||
|
|
||||||
每项一份或一组明确 Markdown 测试,复用既有 fixture helper,但不实现 CI。
|
|
||||||
|
|
||||||
### 第三批:P3 correctness、compatibility 与 semantic/style
|
|
||||||
|
|
||||||
1. correctness/API 契约:保留原 P3 严重度,分别修正 DEFLATE 分配失败 errno、
|
|
||||||
48-bit end-exclusive 最后合法完整块边界,以及 birthtime-only `VOP_SETATTR()`
|
|
||||||
的只读语义。
|
|
||||||
2. compatibility/格式语义:确认并实现 Linux 负时间戳兼容语义;明确 inline symlink
|
|
||||||
内嵌 NUL 的格式政策并补充拒绝或兼容测试。
|
|
||||||
3. semantic/style:删除或改写不可达的 FRAGMENTS 特例分支,使注释、supported mask
|
|
||||||
和真实支持边界一致。
|
|
||||||
|
|
||||||
六项均需各自的 Markdown 手工测试或同类成组测试,不得因进入后续批次而改变本报告
|
|
||||||
中的 P3 严重度。
|
|
||||||
|
|
||||||
### 第四批:低风险卫生、文档和 provenance
|
|
||||||
|
|
||||||
1. 删除或隔离 repo17/repo19 历史脚本和失配 C harness。
|
|
||||||
2. 清理 `xattr.h`、`internal.h`、`erofs_defs.h` 的死声明和死宏。
|
|
||||||
3. 修正 architecture 文档、零拷贝表述和 Linux 基线复现信息。
|
|
||||||
4. 增加 LICENSE/COPYING、许可证构成和来源 manifest。
|
|
||||||
5. 确认 UDF helper 和本地实现的作者归属。
|
|
||||||
6. 在规则明确后处理 style(9) 的确定性问题。
|
|
||||||
|
|
||||||
### 第五批:结构重排和压缩职责对齐
|
|
||||||
|
|
||||||
1. 恢复 `erofs_fs.h` 非平台相关定义顺序、注释和名称。
|
|
||||||
2. 评估把压缩配置 loader 移回各 backend。
|
|
||||||
3. 统一内部 `z_erofs_*` 命名和函数定义顺序。
|
|
||||||
4. 删除无行为包装,调整非必要函数位置差异。
|
|
||||||
|
|
||||||
该批次风险高于普通 style,必须用双配置构建、模块加载和全部相关 Markdown 测试
|
|
||||||
证明无行为变化。
|
|
||||||
|
|
||||||
### 第六批:性能原型
|
|
||||||
|
|
||||||
1. LZMA decoder state pool/cache。
|
|
||||||
2. explicit extent 验证缓存或分段策略。
|
|
||||||
3. `vfs_read_dirent()` 输出适配器。
|
|
||||||
|
|
||||||
原型必须提供基线、压力方法、内存峰值、卸载清理和退化行为;没有数据不合并。
|
|
||||||
|
|
||||||
## 13. 原任务三个目标的覆盖矩阵
|
|
||||||
|
|
||||||
| 原任务目标 | 已确认正向证据 | 本轮发现 | 尚未验证/后续 |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| 1. 最佳实践与 BSD 原生能力复用 | GEOM/bread、vfs_hash、pager、ACL/extattr、CRC/endian、DEFLATE/ZSTD 复用正确;LZ4/MicroLZMA 本地实现有技术理由 | `insmntque()` 契约违反;chunk 大分配;dir helper 需保留但可原型化输出层;LZMA per-call allocation | 动态复现 P1;XZ KPI、dir adapter、LZMA pool 原型 |
|
|
||||||
| 2. 正确处理 BSD/Linux 行为差异 | 正 errno、VOP/VFS、GEOM、namecache、cookie、ACL namespace、FID/generation 等必要差异清晰 | root 类型、setattr、errno、负时间;compact/48-bit/排序属于 Linux 共同问题,未误记为 BSD 差异 | negative time、symlink NUL、fragment pstart_hi 格式语义确认 |
|
|
||||||
| 3. 第三方维护者相似性 | 15 个共同文件;namei/zmap 和 Makefile 顺序质量高;未伪造 Linux-only 空文件 | erofs_fs 顺序/注释、压缩职责/命名、死代码、旧脚本、陈旧文档、style、provenance、许可证清单 | 逐批结构重排、来源确认、外部可复现基线、回归验证 |
|
|
||||||
|
|
||||||
因此,三个目标都已有实质正向成果,但目标 3 明显未达到“没有任何非必要差异”
|
|
||||||
的完成标准;目标 1 和目标 2 也因两个 P1 和若干 P2/P3 finding 需要继续工作。
|
|
||||||
|
|
||||||
## 14. 与 report-3 的关系
|
|
||||||
|
|
||||||
`current/report-3` 是任务 1 收尾时的历史快照。它关于 161 项 feature 手工验证、
|
|
||||||
构建、清理和当时已知 issue 的证据继续有效,本报告不修改也不重写这些结论。
|
|
||||||
|
|
||||||
但 report-3 中“未发现仍需消除的非必要 Linux/FreeBSD 结构、命名或职责差异”是
|
|
||||||
一个超出当时证据范围的绝对表述。当时没有保存:
|
|
||||||
|
|
||||||
- 全部文件的函数、变量和定义顺序对照;
|
|
||||||
- FreeBSD 原生 API 复用清单;
|
|
||||||
- Linux-only/BSD-only 文件逐项必要性论证;
|
|
||||||
- 死代码、失效入口、style(9)、来源和许可证审计;
|
|
||||||
- 独立仓库可重建的 Linux 基线 provenance。
|
|
||||||
|
|
||||||
因此,对任务 2 应以本报告作更精确限定:
|
|
||||||
|
|
||||||
> repo22 的核心算法和主要 FreeBSD 适配已取得良好对齐,但尚不能认定全面完成
|
|
||||||
> code review 和 style 优化;仍存在两个 P1、四个 P2、六个 P3,以及明确的结构、
|
|
||||||
> 代码卫生、style 和可追溯性工作。
|
|
||||||
|
|
||||||
该限定不回写 report-3,以保持历史报告不可变和审计链清晰。
|
|
||||||
|
|
||||||
## 15. 最终状态
|
|
||||||
|
|
||||||
- 本轮只创建 `current/report-4/`。
|
|
||||||
- 未修改 `src/`、`tests/`、`docs/`、`issues/`、既有 report 或 CI。
|
|
||||||
- 未声称任何 finding 已修复。
|
|
||||||
- 未把静态候选误写成动态复现结果。
|
|
||||||
- 新问题进入后续计划前,应先创建对应 Markdown 手工测试规格,再由独立执行者在
|
|
||||||
FreeBSD 15 环境中复现、修复和回归。
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
# report-4:任务 2 代码审查与风格评估
|
|
||||||
|
|
||||||
本目录记录 2026-08-10 对 repo22 原任务中“任务 2:进行全面的 code review
|
|
||||||
和 style 优化”的只读调查结果。
|
|
||||||
|
|
||||||
本次工作只做静态评估、源码契约核对、Linux/FreeBSD 严格比对、历史检查和
|
|
||||||
机械 style 检查,不修改生产源码、测试、既有文档、issues 或 CI。报告中的新
|
|
||||||
finding 尚未在 FreeBSD 虚拟机中动态复现,也尚未修复。
|
|
||||||
|
|
||||||
## 审计基线
|
|
||||||
|
|
||||||
- BSD 目标:`repo-community/repo22`,提交
|
|
||||||
`76cfb553e0951b428f9d426933a10d1fe18d2a0e`
|
|
||||||
- 最终源码变更提交:`67d3c057fbcad5adc765ab9927da511e3221ac8f`
|
|
||||||
- repo22 `src/` tree:`a605af0f01f83d67c199005e775e1a47a1610036`
|
|
||||||
- Linux 独立参考:`/work/dev-src-linux/fs/erofs`,Linux 7.1.0-rc1
|
|
||||||
- Linux 本地导入提交:`8be2be573d2b191c83d760b65c554f78eb95893c`
|
|
||||||
- Linux EROFS tree:`b79b9a8b62f633e887a8b99075ff9412fabd7f83`
|
|
||||||
- FreeBSD API 参考:`/work/dev-freebsd-releng`,15.0-RELEASE-p9
|
|
||||||
|
|
||||||
## 结论摘要
|
|
||||||
|
|
||||||
- 任务 1 的 161 项 feature 验证结论不在本报告中重写,也不因本报告自动失效。
|
|
||||||
- 任务 2 尚不能认定已经全面完成。本轮确认 `P0=0`、`P1=2`、`P2=4`、
|
|
||||||
`P3=6`,另有若干非 correctness 的结构、style、来源与性能原型工作。
|
|
||||||
- FreeBSD 原生 API 和构建集成总体合理,强行复用并不适用于 LZ4、MicroLZMA
|
|
||||||
和目录 cookie helper。
|
|
||||||
- 核心算法映射质量较高,但磁盘 ABI 头文件顺序、压缩职责、死代码、历史测试
|
|
||||||
入口、文档、style(9) 和外部可复现性仍有明确维护债务。
|
|
||||||
- 综合维护者相似度暂评为 `7.2/10`。该分数仅用于排序维护工作,不是客观质量
|
|
||||||
或兼容性指标。
|
|
||||||
|
|
||||||
## 文档索引
|
|
||||||
|
|
||||||
- [任务 2 详细代码审查与风格评估](2026-08-10-task2-code-review-style-assessment.md)
|
|
||||||
|
|
||||||
## 与既有报告的关系
|
|
||||||
|
|
||||||
`current/report-1` 至 `current/report-3` 保持历史快照。本目录不修改它们。
|
|
||||||
report-3 的 feature 验证结果继续作为任务 1 证据;其中“没有非必要差异”的绝对
|
|
||||||
表述,由本次更完整的结构、style、来源和许可证审计作更精确的限定。
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
# Manual Test Evidence
|
|
||||||
|
|
||||||
## Final Status
|
|
||||||
|
|
||||||
repo22 has 161 executable manual test cases, TC001-TC161, plus the non-executable
|
|
||||||
TC000 template. The canonical dated reports produce:
|
|
||||||
|
|
||||||
| Status | Count |
|
|
||||||
| --- | ---: |
|
|
||||||
| PASS | 160 |
|
|
||||||
| PARTIAL | 1 |
|
|
||||||
| FAIL / KERNEL-FAIL | 0 |
|
|
||||||
| ENVIRONMENT-UNAVAILABLE | 0 |
|
|
||||||
| SHELVED test case | 0 |
|
|
||||||
|
|
||||||
TC146 is the single PARTIAL case. Its HEAD2 and interlaced paths pass, while
|
|
||||||
the explicit mapped-payload positive fixture remains unavailable. That
|
|
||||||
shelved subitem is not counted as a second test case.
|
|
||||||
|
|
||||||
## Evidence Policy
|
|
||||||
|
|
||||||
Authoritative evidence consists of the numbered Markdown procedures,
|
|
||||||
deterministic field-asserting fixture helpers, native syscall/kernel probes,
|
|
||||||
and dated `tests/results/manual/*/manual-test-report.md` reports. Reports record
|
|
||||||
the exact source, module or fixture hashes, FreeBSD kernel behavior, errno, and
|
|
||||||
cleanup state.
|
|
||||||
|
|
||||||
Host-only fixture generation, static ABI review, and userspace erofs-utils
|
|
||||||
output are supporting evidence. They do not replace a required FreeBSD kernel
|
|
||||||
result. The suite is manual-only; no CI pipeline or automated kernel-test
|
|
||||||
harness is implemented or claimed.
|
|
||||||
|
|
||||||
## Canonical Runs
|
|
||||||
|
|
||||||
The final status uses these non-overlapping report groups for TC001-TC156:
|
|
||||||
|
|
||||||
| Group | Exact scope | Result |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| G1 | 32 IDs | 32 PASS |
|
|
||||||
| G2 | 13 IDs | 13 PASS |
|
|
||||||
| G3 | 31 IDs | 31 PASS after the dated TC060 fixed-source rerun |
|
|
||||||
| G4 | 27 IDs | 27 PASS |
|
|
||||||
| G5 | 24 IDs | 23 PASS, TC146 PARTIAL |
|
|
||||||
| G6 | 11 IDs | 11 PASS |
|
|
||||||
| G7 | 11 IDs | 11 PASS |
|
|
||||||
| G8 | 7 IDs | 7 PASS |
|
|
||||||
|
|
||||||
The G1-G8 tables contain exactly 156 rows and 156 unique IDs, with no missing
|
|
||||||
or duplicate TC from TC001-TC156. TC060's original G3 KERNEL-FAIL is historical
|
|
||||||
and is superseded by
|
|
||||||
`tests/results/manual/2026-08-09T1120Z-tc060-fix/manual-test-report.md`.
|
|
||||||
TC153 passed in the final G3 run and its issue is resolved.
|
|
||||||
|
|
||||||
TC157-TC161 are recorded in
|
|
||||||
`tests/results/manual/2026-08-09T1804Z-final-review-independent/manual-test-report.md`.
|
|
||||||
All five pass on exact source baseline
|
|
||||||
`fcc85b93d5f8fd9671686bd68bf3b086c8bd25cf`.
|
|
||||||
|
|
||||||
## TC111 Coverage Audit
|
|
||||||
|
|
||||||
A bounded audit of `tests/TC[0-9][0-9][0-9]-*.md` found 162 rows and 162 unique
|
|
||||||
IDs, TC000-TC161, with no missing or duplicate ID. Excluding TC000 leaves 161
|
|
||||||
executable specifications.
|
|
||||||
|
|
||||||
The audit also cross-checked the eight canonical group tables and the five
|
|
||||||
final-review rows. Final arithmetic is `155 PASS + 1 PARTIAL + 5 PASS`, or
|
|
||||||
160 PASS and one PARTIAL.
|
|
||||||
|
|
||||||
## Final Build Qualification
|
|
||||||
|
|
||||||
The final independent run rebuilt both configurations after the TC161 failing
|
|
||||||
`nm` shim and used `/usr/bin/nm` for the post-shim build:
|
|
||||||
|
|
||||||
| Configuration | KLD SHA256 |
|
|
||||||
| --- | --- |
|
|
||||||
| `WITH_ZSTDIO=0` | `15fda9d334132cd81769ce4dff4f8411a6e2b4cf7531c352530d0de85f42a2d2` |
|
|
||||||
| `WITH_ZSTDIO=1` | `23782dc0ce7da188807d35020bf2d8c6044b796c5c9a8746b398ba784cd6ad4e` |
|
|
||||||
|
|
||||||
Both KLDs loaded, mounted a qualified image read-only, unmounted, detached the
|
|
||||||
md provider, and unloaded. Final guest mount, md, EROFS KLD, and DTrace KLD
|
|
||||||
counts were zero.
|
|
||||||
|
|
||||||
G1-G8 evidence was collected across multiple source commits. It is not claimed
|
|
||||||
that all historical tests ran on the final KLD. The final code baseline was
|
|
||||||
independently exercised by TC157-TC161 and the affected dual-build,
|
|
||||||
module-load, and mount smoke.
|
|
||||||
|
|
||||||
## Issue Status
|
|
||||||
|
|
||||||
- TC010: RESOLVED by a real 16 TiB-plus sparse-provider statfs run.
|
|
||||||
- TC060: RESOLVED by the FreeBSD pathconf fix and exact-source rerun.
|
|
||||||
- TC153: RESOLVED by the multi-TiB Layout 0 directory lookup run.
|
|
||||||
- Explicit mapped payload: SHELVED as a detailed fixture/tooling limitation;
|
|
||||||
TC146 remains PARTIAL.
|
|
||||||
|
|
||||||
See `issues/README.md` for the current index and the individual files for
|
|
||||||
triggers, analysis, attempts, results, feature impact, and acceptance criteria.
|
|
||||||
@@ -1,283 +0,0 @@
|
|||||||
# repo22 架构设计
|
|
||||||
|
|
||||||
## 设计目标
|
|
||||||
|
|
||||||
repo22 提供尽量贴近 Linux `fs/erofs` 职责划分的 FreeBSD 15
|
|
||||||
只读实现,同时对 FreeBSD vnode、GEOM、pager、`dev_t` 和 NFS FID 语义做
|
|
||||||
必要适配。
|
|
||||||
|
|
||||||
## 核心原则
|
|
||||||
|
|
||||||
1. **Linux 对齐**:函数命名、文件组织、代码排序尽可能匹配 Linux 版本
|
|
||||||
2. **最小抽象**:避免不必要的封装层
|
|
||||||
3. **安全优先**:保留 repo19 的所有安全修复
|
|
||||||
4. **可维护性**:便于社区维护和与上游同步
|
|
||||||
|
|
||||||
## 文件组织
|
|
||||||
|
|
||||||
```
|
|
||||||
src/
|
|
||||||
├── super.c - 超级块、挂载、VFS 集成
|
|
||||||
├── inode.c - inode 读取和 vnode 管理
|
|
||||||
├── data.c - 数据块映射和解压缩
|
|
||||||
├── namei.c - 路径查找(二分搜索)
|
|
||||||
├── dir.c - 目录遍历和输出
|
|
||||||
├── xattr.c - 扩展属性和 ACL
|
|
||||||
├── erofs_vnops.c - VFS vnode 操作实现
|
|
||||||
├── decompressor.c - 压缩配置解析和统一调度
|
|
||||||
├── decompressor_lz4.c - FreeBSD 有界 LZ4 后端
|
|
||||||
├── decompressor_lzma.c - MicroLZMA 后端
|
|
||||||
├── decompressor_deflate.c - DEFLATE 后端
|
|
||||||
├── decompressor_zstd.c - 可选 ZSTDIO 后端
|
|
||||||
├── zmap.c - 压缩逻辑块映射
|
|
||||||
├── zdata.c - 压缩数据读取
|
|
||||||
├── internal.h - 内存结构和内部 API
|
|
||||||
├── erofs_fs.h - 磁盘格式定义
|
|
||||||
└── xattr.h - 扩展属性接口
|
|
||||||
```
|
|
||||||
|
|
||||||
## 分层架构
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────┐
|
|
||||||
│ VFS 层 (FreeBSD kernel) │
|
|
||||||
└─────────────┬───────────────────────┘
|
|
||||||
│
|
|
||||||
┌─────────────▼───────────────────────┐
|
|
||||||
│ VFS 接口层 │
|
|
||||||
│ - erofs_vnops.c │
|
|
||||||
│ - super.c (mount/unmount/root) │
|
|
||||||
└─────────────┬───────────────────────┘
|
|
||||||
│
|
|
||||||
┌─────────────▼───────────────────────┐
|
|
||||||
│ 文件系统逻辑层 │
|
|
||||||
│ - inode.c (erofs_read_inode) │
|
|
||||||
│ - namei.c (erofs_namei) │
|
|
||||||
│ - dir.c (erofs_readdir_block) │
|
|
||||||
│ - xattr.c (erofs_getxattr) │
|
|
||||||
└─────────────┬───────────────────────┘
|
|
||||||
│
|
|
||||||
┌─────────────▼───────────────────────┐
|
|
||||||
│ 数据访问层 │
|
|
||||||
│ - data.c (erofs_map_blocks) │
|
|
||||||
│ - data.c (erofs_read_data) │
|
|
||||||
│ - zmap.c / zdata.c │
|
|
||||||
│ - decompressor.c (z_erofs_decompress) │
|
|
||||||
└─────────────┬───────────────────────┘
|
|
||||||
│
|
|
||||||
┌─────────────▼───────────────────────┐
|
|
||||||
│ 块 I/O 层 │
|
|
||||||
│ - erofs_bread/erofs_brelse │
|
|
||||||
└─────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
## 核心数据结构
|
|
||||||
|
|
||||||
### erofs_mount (内存中的文件系统状态)
|
|
||||||
```c
|
|
||||||
struct erofs_mount {
|
|
||||||
struct mount *mnt; // FreeBSD mount 结构
|
|
||||||
struct vnode *devvp; // 块设备 vnode
|
|
||||||
struct g_consumer *cp; // GEOM consumer
|
|
||||||
|
|
||||||
uint32_t block_size; // 块大小
|
|
||||||
uint64_t root_nid; // 根目录 NID
|
|
||||||
uint32_t feature_compat; // 特性标志
|
|
||||||
uint32_t feature_incompat;
|
|
||||||
|
|
||||||
struct erofs_sb_lz4_info lz4; // LZ4 参数
|
|
||||||
struct erofs_deviceslot *devs; // 设备表
|
|
||||||
struct erofs_xattr_prefix_item *xattr_prefixes; // xattr 前缀表
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### erofs_node (内存中的 inode)
|
|
||||||
```c
|
|
||||||
struct erofs_node {
|
|
||||||
struct vnode *vnode; // 关联的 vnode
|
|
||||||
uint64_t nid; // 节点 ID
|
|
||||||
uint64_t size; // 文件大小
|
|
||||||
uint8_t datalayout; // 数据布局类型
|
|
||||||
|
|
||||||
// 压缩相关
|
|
||||||
uint8_t z_algorithmformat;
|
|
||||||
uint8_t z_lclusterbits;
|
|
||||||
|
|
||||||
// Chunk-based 相关
|
|
||||||
uint16_t chunkformat;
|
|
||||||
uint8_t chunkbits;
|
|
||||||
|
|
||||||
// Fragment 相关
|
|
||||||
uint32_t fragmentoff;
|
|
||||||
bool fragment;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## 关键实现细节
|
|
||||||
|
|
||||||
### 1. 数据布局支持
|
|
||||||
|
|
||||||
支持 4 种数据布局:
|
|
||||||
- **FLAT_PLAIN**: 连续块
|
|
||||||
- **FLAT_INLINE**: 最后一个逻辑块位于 inode metadata block 内,且受声明
|
|
||||||
image/metabox bounds 约束
|
|
||||||
- **CHUNK_BASED**: 固定大小 chunk,支持稀疏文件
|
|
||||||
- **COMPRESSED**: 可变大小压缩 cluster
|
|
||||||
|
|
||||||
### 2. 压缩算法
|
|
||||||
|
|
||||||
支持 4 种压缩算法及未压缩 transform:
|
|
||||||
- LZ4 (LZ4HC)
|
|
||||||
- LZMA
|
|
||||||
- DEFLATE
|
|
||||||
- ZSTD
|
|
||||||
- 未压缩
|
|
||||||
|
|
||||||
### 3. 高级特性
|
|
||||||
|
|
||||||
- ✅ **ztailpacking**: 压缩文件尾部内联
|
|
||||||
- ✅ **fragments**: 已验证的 fragment-backed 压缩文件与 metabox carrier
|
|
||||||
- ⚠️ **dedupe**: 仅声明已验证的 fragment/partial-reference 形式,不宣称
|
|
||||||
覆盖所有未来编码
|
|
||||||
- ✅ **xattr_prefixes**: 共享 xattr 前缀表
|
|
||||||
- ✅ **device_table**: 多设备支持
|
|
||||||
- ✅ **metabox**: 每 inode 元数据盒
|
|
||||||
|
|
||||||
### 4. 安全机制
|
|
||||||
|
|
||||||
repo22 的边界策略:
|
|
||||||
- 所有指针操作前检查边界
|
|
||||||
- 所有算术运算检查溢出
|
|
||||||
- 所有分配检查大小合理性
|
|
||||||
- 递归深度限制
|
|
||||||
- 设备 ID 和块地址验证
|
|
||||||
|
|
||||||
## 与 Linux 版本的差异
|
|
||||||
|
|
||||||
### 对照基线
|
|
||||||
|
|
||||||
本轮维护逐文件对照工作区中的 `/work/dev-src-linux/fs/erofs`。该目录是导入的
|
|
||||||
Linux 7.1-rc1 EROFS 参考快照;对照不依赖 repo22 与 Linux 树具有共同 Git
|
|
||||||
历史。`/work/linux-src/fs/erofs` 中对应文件与该精简快照字节一致,但不是本轮
|
|
||||||
文件映射的依据。
|
|
||||||
|
|
||||||
### 必要差异(FreeBSD 适配)
|
|
||||||
|
|
||||||
1. **内存分配**:使用 `malloc(..., M_EROFS, ...)` 而非 `kmalloc()`
|
|
||||||
2. **块 I/O**:通过 GEOM consumer 和 FreeBSD vnode/buffer 接口读取 provider
|
|
||||||
3. **VFS 接口**:`erofs_vnops.c` 实现 FreeBSD `vop_vector`,不照搬 Linux
|
|
||||||
`inode_operations`、folio 或 iomap 接口
|
|
||||||
4. **错误约定**:内核入口返回正的 FreeBSD errno;Linux 负 errno 或
|
|
||||||
`ERR_PTR` 仅作为算法对照,不能机械移植
|
|
||||||
5. **压缩后端**:BSD 调度器跨编译单元调用 `internal.h` 中的简单后端 API;
|
|
||||||
Linux 使用 `struct z_erofs_decompressor` 和不同的内存/页面生命周期
|
|
||||||
6. **LZ4 文件职责**:BSD 保留独立 `decompressor_lz4.c` 有界解码器;Linux LZ4 路径位于
|
|
||||||
`decompressor.c` 并依赖 Linux 内核 LZ4/page API
|
|
||||||
7. **平台特性**:Linux `sysfs.c`、`fileio.c`、`fscache.c`、`ishare.c` 和
|
|
||||||
`zutil.c` 没有无条件对应物,不为文件外观引入空包装
|
|
||||||
8. **构建架构**:当前只验证 FreeBSD 15 amd64,Makefile 明确拒绝其他
|
|
||||||
`MACHINE_ARCH`
|
|
||||||
|
|
||||||
### 保持一致的部分
|
|
||||||
|
|
||||||
- 静态目录 helper 使用 Linux 名称 `find_target_dirent`
|
|
||||||
- LZMA、DEFLATE、ZSTD 后端使用 Linux 文件名 `decompressor_*.c`
|
|
||||||
- Makefile 先列 metadata/VFS 文件,再列压缩调度、映射和后端文件
|
|
||||||
- 跨文件后端声明集中在 `internal.h`,不在调用方手写 `extern`
|
|
||||||
- `erofs_fs.h` 的磁盘格式定义和核心目录/映射算法按 Linux 语义核对
|
|
||||||
|
|
||||||
## 代码规范
|
|
||||||
|
|
||||||
### 命名约定
|
|
||||||
- 公共函数:`erofs_<module>_<action>`
|
|
||||||
- 静态函数:描述性名称,无固定前缀
|
|
||||||
- 宏:`EROFS_*` 全大写
|
|
||||||
- 结构体:`struct erofs_*`
|
|
||||||
|
|
||||||
### 函数排序(每个文件)
|
|
||||||
1. 辅助函数(static)
|
|
||||||
2. 核心逻辑函数
|
|
||||||
3. VFS 接口函数
|
|
||||||
4. 模块注册/清理(仅 super.c)
|
|
||||||
|
|
||||||
### 错误处理
|
|
||||||
```c
|
|
||||||
int erofs_function(...)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
void *buf = NULL;
|
|
||||||
|
|
||||||
// 操作...
|
|
||||||
if (条件) {
|
|
||||||
error = EINVAL;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
if (buf)
|
|
||||||
erofs_brelse(buf);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 测试策略
|
|
||||||
|
|
||||||
### 单元测试
|
|
||||||
|
|
||||||
不存在受支持的用户态单元测试入口。旧的 `src/Makefile.test`、
|
|
||||||
`tests/test_decompress.c` 和 `tests/test_decompress_standalone.c` 尝试把内核解压
|
|
||||||
源码按不匹配的用户态 ABI 链接;这些入口均已退役并删除,不能作为可运行测试或
|
|
||||||
feature 验证证据。
|
|
||||||
|
|
||||||
旧的 `test_super.c` 和 `test_inode.c` 只重复了测试文件中的公式,并未调用
|
|
||||||
内核生产解析路径,其中 inode harness 还引用过已删除的磁盘字段。它们已退役,
|
|
||||||
不得作为 feature 验证证据。superblock、inode、pager 和错误路径必须使用
|
|
||||||
`TC*.md` 中的确定性镜像,经 FreeBSD 内核模块实际挂载或访问验证。
|
|
||||||
|
|
||||||
### 集成测试
|
|
||||||
|
|
||||||
仓库根目录遗留的 `test_all_decompress.sh` 和 `test_chunk_based.sh` 包含其他
|
|
||||||
repo 的硬编码路径,不能作为 repo22 的测试入口或验收证据。受支持的验证方式是
|
|
||||||
直接执行 `tests/TC*.md` 中记录的 FreeBSD 15 内核步骤,并将命令、errno、哈希和
|
|
||||||
清理状态写入 `tests/results/manual/` 下的日期报告。
|
|
||||||
|
|
||||||
### VM 测试
|
|
||||||
- 挂载真实镜像
|
|
||||||
- 文件读取验证
|
|
||||||
- 性能基准测试
|
|
||||||
|
|
||||||
## 维护指南
|
|
||||||
|
|
||||||
### 同步上游 Linux 变更
|
|
||||||
|
|
||||||
1. 选定明确的 Linux `fs/erofs` 快照;当前工作区基线为
|
|
||||||
`/work/dev-src-linux/fs/erofs`
|
|
||||||
2. 逐文件识别修改,不假设两个实现共享提交历史
|
|
||||||
3. 检查是否为磁盘格式变更(`erofs_fs.h`)或 Linux 专属 VFS/page API
|
|
||||||
4. 只移植语义上适用的算法,并保留 FreeBSD errno、锁、GEOM 和 vnode 约定
|
|
||||||
5. 运行双配置构建、模块加载和真实镜像挂载测试
|
|
||||||
|
|
||||||
### 添加新特性
|
|
||||||
|
|
||||||
1. 在 `erofs_fs.h` 添加磁盘格式定义
|
|
||||||
2. 在 `internal.h` 添加内存结构
|
|
||||||
3. 实现解析逻辑(data.c/inode.c)
|
|
||||||
4. 添加确定性 fixture 和对应的 `TC*.md` 内核测试
|
|
||||||
5. 更新文档
|
|
||||||
|
|
||||||
## 性能考虑
|
|
||||||
|
|
||||||
- **零拷贝**:直接从缓冲区缓存读取
|
|
||||||
- **延迟加载**:仅在需要时读取 inode 元数据
|
|
||||||
- **缓存友好**:利用 FreeBSD 的 vnode 缓存
|
|
||||||
- **批量操作**:目录读取一次性处理多个条目
|
|
||||||
|
|
||||||
## 已知限制
|
|
||||||
|
|
||||||
- 不支持写操作(只读文件系统)
|
|
||||||
- 不支持 FUSE 模式
|
|
||||||
- 构建和运行时验证目前仅覆盖 FreeBSD 15 amd64
|
|
||||||
- 不实现 Linux file-backed、fscache、page-cache sharing 或 sysfs 控制面
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
# repo-pre-2 Capability Record
|
|
||||||
|
|
||||||
## Status Vocabulary
|
|
||||||
|
|
||||||
This document separates inherited pre1 claims from fresh pre2 validation:
|
|
||||||
|
|
||||||
- `INHERITED CLAIM`: documented by the unchanged pre1 snapshot; not re-tested
|
|
||||||
for pre2.
|
|
||||||
- `STATIC GATE`: visible in tracked source or build declarations; runtime
|
|
||||||
behavior was not exercised.
|
|
||||||
- `NOT IMPLEMENTED`: explicitly excluded by inherited project documentation.
|
|
||||||
- `NOT CLAIMED`: inherited documentation deliberately limits the support
|
|
||||||
claim.
|
|
||||||
- `NOT RUN`: no build or runtime validation was performed for repo-pre-2.
|
|
||||||
|
|
||||||
`INHERITED CLAIM` is provenance, not a new PASS result. Existing reports under
|
|
||||||
`tests/results/manual/` describe earlier pre1 work and must not be cited as a
|
|
||||||
fresh repo-pre-2 execution.
|
|
||||||
|
|
||||||
## Snapshot Evidence
|
|
||||||
|
|
||||||
```text
|
|
||||||
repo-pre-1 source tree: 6a5a1a49d4a4e08f6ef1155de240500e63a15365
|
|
||||||
repo-pre-2 initial tree: 6a5a1a49d4a4e08f6ef1155de240500e63a15365
|
|
||||||
src-linux reference tree: b79b9a8b62f633e887a8b99075ff9412fabd7f83
|
|
||||||
runtime validation: NOT RUN
|
|
||||||
```
|
|
||||||
|
|
||||||
The inherited claims below are transcribed at category level from `README.md`
|
|
||||||
and `docs/features.md`. They are not an independent feature review.
|
|
||||||
|
|
||||||
## Capability Matrix
|
|
||||||
|
|
||||||
| Area | Inherited pre1 claim or static declaration | Pre2 status |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Mount and metadata | Read-only mount/unmount, `statfs`, superblock checksum and bounds, compact/extended inodes, 48-bit fields | INHERITED CLAIM; NOT RUN |
|
|
||||||
| Plain data | Flat plain, flat inline, tail bounds, and logical block accounting | INHERITED CLAIM; NOT RUN |
|
|
||||||
| Chunk and devices | Chunk indexes, holes, device tables, explicit devices, and flatdev mapping | INHERITED CLAIM; NOT RUN |
|
|
||||||
| Compressed data | LZ4, MicroLZMA, DEFLATE, full/compact indexes, partial references, HEAD2, ztailpacking, and qualified fragment forms | INHERITED CLAIM; NOT RUN |
|
|
||||||
| ZSTD | Source is always listed; `WITH_ZSTDIO=1` adds `ZSTDIO`, while the default is `0` | STATIC GATE; runtime NOT RUN |
|
|
||||||
| Directories and vnode operations | Lookup, readdir, cookies, namecache, access, readlink, pathconf, pager integration, and read-only mutation rejection | INHERITED CLAIM; NOT RUN |
|
|
||||||
| Xattrs and ACLs | Inline/shared namespaces, metabox storage, long/packed prefixes, and POSIX ACL reads | INHERITED CLAIM; NOT RUN |
|
|
||||||
| NFS export | 64-bit NIDs, generation handling, and malformed/stale handle validation | INHERITED CLAIM; NOT RUN |
|
|
||||||
| Build target | `src/Makefile` rejects architectures other than `amd64` | STATIC GATE; build NOT RUN |
|
|
||||||
| Write support | Writable filesystem operations | NOT IMPLEMENTED |
|
|
||||||
| `VOP_BMAP` | Explicitly unsupported in inherited documentation | NOT IMPLEMENTED |
|
|
||||||
| Complete future-format parity | All future incompat features and every dedupe encoding | NOT CLAIMED |
|
|
||||||
| Explicit compressed-extent positive payload | Inherited documentation records only partial coverage | NOT CLAIMED; NOT RUN |
|
|
||||||
| Performance guarantees | Manual observations are not a performance contract | NOT CLAIMED |
|
|
||||||
|
|
||||||
## Interpretation Rules
|
|
||||||
|
|
||||||
1. Source presence, feature-bit definitions, or build selection do not prove a
|
|
||||||
runtime capability.
|
|
||||||
2. A pre1 manual report does not become a pre2 PASS merely because the initial
|
|
||||||
trees match.
|
|
||||||
3. Phase 1 mechanical edits must not expand or reduce this capability matrix.
|
|
||||||
4. A future status change requires recorded evidence from an actually executed
|
|
||||||
validation step.
|
|
||||||
|
|
||||||
## Current Validation Declaration
|
|
||||||
|
|
||||||
No build, QEMU execution, test script, smoke test, mount, malformed-image
|
|
||||||
probe, or performance measurement was run for this initialization. The current
|
|
||||||
repo-pre-2 runtime validation result is therefore `NOT RUN` in every category.
|
|
||||||
-271
@@ -1,271 +0,0 @@
|
|||||||
.\" Copyright (c) 2026
|
|
||||||
.\" All rights reserved.
|
|
||||||
.\"
|
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
|
||||||
.\" modification, are permitted provided that the following conditions
|
|
||||||
.\" are met:
|
|
||||||
.\" 1. Redistributions of source code must retain the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer.
|
|
||||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer in the
|
|
||||||
.\" documentation and/or other materials provided with the distribution.
|
|
||||||
.\"
|
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
||||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
.\" SUCH DAMAGE.
|
|
||||||
.\"
|
|
||||||
.Dd August 9, 2026
|
|
||||||
.Dt EROFS 5
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm erofs
|
|
||||||
.Nd Enhanced Read-Only File System
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
To mount an
|
|
||||||
.Nm
|
|
||||||
volume:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
mount -t erofs /dev/da0 /mnt
|
|
||||||
.Ed
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
driver provides read-only support for the Enhanced Read-Only File System
|
|
||||||
(EROFS), a modern compressed read-only filesystem designed for space
|
|
||||||
efficiency and performance.
|
|
||||||
EROFS is widely used in Linux distributions and mobile systems for root
|
|
||||||
filesystems, firmware images, and container layers.
|
|
||||||
.Pp
|
|
||||||
The
|
|
||||||
.Fx
|
|
||||||
implementation supports multiple compression algorithms, various data layouts,
|
|
||||||
extended attributes, and multi-device configurations.
|
|
||||||
.Pp
|
|
||||||
The currently qualified build target is
|
|
||||||
.Fx 15
|
|
||||||
on
|
|
||||||
.Sy amd64 .
|
|
||||||
The module Makefile rejects other architectures because they have not been
|
|
||||||
validated against this implementation's kernel ABI.
|
|
||||||
.Sh FEATURES
|
|
||||||
.Ss Inode Types
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
driver supports both compact and extended inode formats:
|
|
||||||
.Bl -bullet -compact
|
|
||||||
.It
|
|
||||||
Compact inodes (32 bytes) for typical files
|
|
||||||
.It
|
|
||||||
Extended inodes (64 bytes) with extended metadata
|
|
||||||
.It
|
|
||||||
Special handling for single-link files
|
|
||||||
.It
|
|
||||||
Inline data (tailpacking) for small files
|
|
||||||
.El
|
|
||||||
.Ss Data Layouts
|
|
||||||
.Bl -bullet -compact
|
|
||||||
.It
|
|
||||||
.Sy FLAT_PLAIN :
|
|
||||||
Uncompressed contiguous data
|
|
||||||
.It
|
|
||||||
.Sy FLAT_INLINE :
|
|
||||||
Uncompressed data with inline tail
|
|
||||||
.It
|
|
||||||
.Sy Chunk-based :
|
|
||||||
Fixed-size chunks for multi-device support
|
|
||||||
.It
|
|
||||||
.Sy Compressed :
|
|
||||||
LZ4, DEFLATE, zstd, or LZMA compressed data with pcluster mapping
|
|
||||||
.El
|
|
||||||
.Ss Compression Algorithms
|
|
||||||
.Bl -tag -width "MicroLZMA"
|
|
||||||
.It Sy LZ4
|
|
||||||
Fast decompression for general-purpose use, including ztailpacking
|
|
||||||
(compressed tail in inode metadata)
|
|
||||||
.It Sy DEFLATE
|
|
||||||
Standard compression with good compression ratio
|
|
||||||
.It Sy zstd
|
|
||||||
High compression ratio when the module is built with
|
|
||||||
.Va WITH_ZSTDIO=1 .
|
|
||||||
ZSTD support is disabled by default
|
|
||||||
.Pq Va WITH_ZSTDIO=0 ,
|
|
||||||
and an enabled module requires a kernel built with
|
|
||||||
.Cd "options ZSTDIO" .
|
|
||||||
.It Sy LZMA/MicroLZMA
|
|
||||||
Maximum compression ratio for space-constrained environments
|
|
||||||
.El
|
|
||||||
.Ss Extended Attributes
|
|
||||||
.Bl -bullet -compact
|
|
||||||
.It
|
|
||||||
Shared extended attributes with metabox container support
|
|
||||||
.It
|
|
||||||
Inline extended attributes
|
|
||||||
.It
|
|
||||||
Long-prefix extended attribute support
|
|
||||||
.It
|
|
||||||
Packed prefix table support
|
|
||||||
.It
|
|
||||||
POSIX ACL support (access and default ACLs)
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
User namespace attributes are exposed without prefix; system namespace
|
|
||||||
attributes retain their full qualified names (trusted.*, security.*).
|
|
||||||
.Pp
|
|
||||||
Linux POSIX access/default ACL xattrs are decoded into
|
|
||||||
.Fx
|
|
||||||
POSIX.1e ACLs when present.
|
|
||||||
ACL and xattr mutation remains read-only.
|
|
||||||
.Ss Advanced Features
|
|
||||||
.Bl -bullet -compact
|
|
||||||
.It
|
|
||||||
Superblock CRC32C verification
|
|
||||||
.It
|
|
||||||
48-bit block count and root nid support
|
|
||||||
.It
|
|
||||||
Device table for multi-device volumes
|
|
||||||
.It
|
|
||||||
Qualified fragment-backed compressed files and metabox carriers
|
|
||||||
.It
|
|
||||||
VFS hash integration and namecache support
|
|
||||||
.It
|
|
||||||
Directory entry optimization (dot_omitted handling)
|
|
||||||
.It
|
|
||||||
NFS export with stable superblock-seeded per-inode file-handle generations
|
|
||||||
.It
|
|
||||||
.Fx
|
|
||||||
local vnode pager support for read-only mappings
|
|
||||||
.El
|
|
||||||
.Sh MOUNT OPTIONS
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
filesystem supports standard read-only mount options and the following
|
|
||||||
filesystem-specific option:
|
|
||||||
.Bl -tag -width "device.N=/dev/mdN"
|
|
||||||
.It Cm device.N= Ns Pa path
|
|
||||||
Map one-based on-disk external device slot
|
|
||||||
.Ar N
|
|
||||||
to the disk provider at
|
|
||||||
.Ar path .
|
|
||||||
The slot number is part of the option name, so option order has no effect.
|
|
||||||
Every declared external slot must be supplied exactly once when external blob
|
|
||||||
providers are used.
|
|
||||||
Reusing the primary provider or one external provider for
|
|
||||||
multiple slots is rejected.
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
There is no filesystem-specific
|
|
||||||
.Pa /sbin/mount_erofs
|
|
||||||
utility in this repository.
|
|
||||||
Use the generic
|
|
||||||
.Xr mount 8
|
|
||||||
frontend with
|
|
||||||
.Fl t Cm erofs ;
|
|
||||||
it passes the filesystem-specific option names to
|
|
||||||
.Xr nmount 2 .
|
|
||||||
.Pp
|
|
||||||
If the image has a device table and no
|
|
||||||
.Cm device.N
|
|
||||||
options are supplied, the primary provider is treated as a flatdev image.
|
|
||||||
It
|
|
||||||
must contain every declared device range at its on-disk unified block address.
|
|
||||||
The driver forces every successful mount read-only.
|
|
||||||
An explicit
|
|
||||||
.Fl o Cm rw
|
|
||||||
request therefore still produces a read-only mount; it does not enable writes
|
|
||||||
and is not rejected solely because
|
|
||||||
.Cm rw
|
|
||||||
was requested.
|
|
||||||
Mutating vnode operations fail with
|
|
||||||
.Er EROFS .
|
|
||||||
.Sh EXAMPLES
|
|
||||||
Mount an EROFS image from a disk device:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
mount -t erofs -o ro /dev/da0s1 /mnt
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
Mount an EROFS image from a regular file using
|
|
||||||
.Xr mdconfig 8 :
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
mdconfig -a -t vnode -f rootfs.img -u 0
|
|
||||||
mount -t erofs -o ro /dev/md0 /mnt
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
Mount a split image with two external blob slots.
|
|
||||||
The deliberately reversed
|
|
||||||
option order demonstrates that slot mapping is deterministic:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
mdconfig -a -t vnode -f primary.img -u 90
|
|
||||||
mdconfig -a -t vnode -f blob1.img -u 91
|
|
||||||
mdconfig -a -t vnode -f blob2.img -u 92
|
|
||||||
mount -t erofs -o ro -o device.2=/dev/md92 \
|
|
||||||
-o device.1=/dev/md91 /dev/md90 /mnt
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
Mount a flatdev image containing the primary image followed by all declared
|
|
||||||
unified device ranges:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
mdconfig -a -t vnode -f combined-flatdev.img -u 90
|
|
||||||
mount -t erofs -o ro /dev/md90 /mnt
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
Unmount an EROFS filesystem:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
umount /mnt
|
|
||||||
.Ed
|
|
||||||
.Sh DIAGNOSTICS
|
|
||||||
Error messages are logged via
|
|
||||||
.Xr printf 9
|
|
||||||
when filesystem inconsistencies are detected, such as:
|
|
||||||
.Bl -bullet -compact
|
|
||||||
.It
|
|
||||||
Invalid superblock magic number
|
|
||||||
.It
|
|
||||||
Superblock CRC32C checksum mismatch
|
|
||||||
.It
|
|
||||||
Unsupported compression algorithm
|
|
||||||
.It
|
|
||||||
Invalid inode format
|
|
||||||
.It
|
|
||||||
Invalid or unrepresentable inode timestamps
|
|
||||||
.It
|
|
||||||
Corrupted directory entries
|
|
||||||
.It
|
|
||||||
Compressed extent address arithmetic overflow
|
|
||||||
.It
|
|
||||||
Inline data crossing its inode metadata block or declared backing bounds
|
|
||||||
.It
|
|
||||||
Missing, short, or orphaned external providers
|
|
||||||
.It
|
|
||||||
Malformed or overlapping device-table ranges
|
|
||||||
.El
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr nmount 2 ,
|
|
||||||
.Xr mdconfig 8 ,
|
|
||||||
.Xr mount 8 ,
|
|
||||||
.Xr umount 8 ,
|
|
||||||
.Xr printf 9
|
|
||||||
.Sh HISTORY
|
|
||||||
EROFS was originally developed for Linux by Huawei in 2019.
|
|
||||||
The
|
|
||||||
.Fx
|
|
||||||
implementation first appeared in 2026.
|
|
||||||
.Sh AUTHORS
|
|
||||||
.An Ruicheng Pan
|
|
||||||
.Sh BUGS
|
|
||||||
.Bl -bullet -compact
|
|
||||||
.It
|
|
||||||
The driver is read-only and does not claim support for every future EROFS
|
|
||||||
incompat feature or every dedupe encoding.
|
|
||||||
.It
|
|
||||||
There is no automated kernel regression harness; the repository records
|
|
||||||
.Fx 15
|
|
||||||
manual-test procedures and results.
|
|
||||||
.El
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
# EROFS Feature Status
|
|
||||||
|
|
||||||
This list describes behavior implemented and manually qualified in the
|
|
||||||
FreeBSD 15 module. It is not a claim of complete Linux EROFS feature parity.
|
|
||||||
|
|
||||||
## Filesystem and Metadata
|
|
||||||
|
|
||||||
- Read-only mount/unmount and `statfs`.
|
|
||||||
- Superblock CRC32C, declared image/media bounds, 48-bit block/root-NID decode.
|
|
||||||
- Compact and extended inodes.
|
|
||||||
- Correct compact non-directory `I_NLINK_1` semantics and directory
|
|
||||||
`dot_omitted` semantics.
|
|
||||||
- Linux `new_decode_dev` major/minor decoding followed by FreeBSD `makedev()`.
|
|
||||||
- Superblock-seeded, inode-metadata-derived vnode/NFS generation synchronized
|
|
||||||
with `va_gen`; metadata-identical payload replacement is outside the stale
|
|
||||||
handle guarantee.
|
|
||||||
- NFS export, 64-bit NID file handles, stale-generation and malformed-FID
|
|
||||||
validation.
|
|
||||||
|
|
||||||
## Data Layouts
|
|
||||||
|
|
||||||
- `FLAT_PLAIN` and `FLAT_INLINE` reads.
|
|
||||||
- Inline tails constrained to the inode metadata block and declared backing
|
|
||||||
bounds.
|
|
||||||
- Chunk-based files, chunk indexes, holes, device tables, explicit devices,
|
|
||||||
and flatdev mapping.
|
|
||||||
- LZ4, MicroLZMA, DEFLATE, and ZSTD compressed reads.
|
|
||||||
- Full and compact indexes, partial references, HEAD2/interlaced records,
|
|
||||||
ztailpacking, and fragment-backed compressed data used by qualified images.
|
|
||||||
- Compressed `va_bytes`/`st_blocks` from the complete 48-bit on-disk compressed
|
|
||||||
block count; plain, inline, and chunk files retain logical block rounding.
|
|
||||||
|
|
||||||
## Vnode and Directory Operations
|
|
||||||
|
|
||||||
- `vget`, root lookup, `vfs_hash`, namecache, and `vn_vget_ino` integration.
|
|
||||||
- `lookup`, `readdir`, stable restart cookies, cold nested lookup, and
|
|
||||||
Linux-compatible nonzero final-name padding.
|
|
||||||
- Shared strict validation for dirent arrays, `nameoff`, block bounds, and
|
|
||||||
illegal names.
|
|
||||||
- `getattr`, access checks, `readlink`, `pathconf`, and read-only mutation
|
|
||||||
rejection, including combined special-vnode setattr requests.
|
|
||||||
- FreeBSD 15 `vnode_pager_local_getpages` and compatible async pager entry;
|
|
||||||
`VOP_BMAP` remains explicitly unsupported.
|
|
||||||
|
|
||||||
## Xattrs and ACLs
|
|
||||||
|
|
||||||
- Inline and shared `user.*`, `trusted.*`, and `security.*` attributes.
|
|
||||||
- Shared attributes in primary metadata and metabox containers.
|
|
||||||
- Long-prefix and packed-prefix-table lookup.
|
|
||||||
- FreeBSD user/system namespace exposure and POSIX access/default ACL reads.
|
|
||||||
- Read-only xattr/ACL mutation behavior.
|
|
||||||
|
|
||||||
## Documentation and Validation
|
|
||||||
|
|
||||||
- `erofs(5)` manual page.
|
|
||||||
- Markdown manual tests TC001-TC161, with unresolved cases tracked in
|
|
||||||
`issues/`.
|
|
||||||
- FreeBSD 15 manual reports with fixture hashes and cleanup evidence.
|
|
||||||
- Final explicit-extent ordering, 48-bit allocation, special setattr,
|
|
||||||
`OFF_MAX` directory-cookie, and build-tool failure checks.
|
|
||||||
|
|
||||||
## Build Qualification
|
|
||||||
|
|
||||||
- FreeBSD 15 `amd64` is the only currently validated and accepted target;
|
|
||||||
`src/Makefile` rejects other architectures.
|
|
||||||
- ZSTD support is disabled by default (`WITH_ZSTDIO=0`). Opt-in builds use
|
|
||||||
`WITH_ZSTDIO=1` and require a kernel built with `options ZSTDIO`.
|
|
||||||
|
|
||||||
## Not Implemented or Not Claimed
|
|
||||||
|
|
||||||
- Writable filesystem operations.
|
|
||||||
- A CI pipeline or automated kernel-test harness.
|
|
||||||
- Positive mapped-payload execution of the explicit compressed-extent format;
|
|
||||||
TC146 remains PARTIAL and the fixture limitation is tracked under `issues/`.
|
|
||||||
- Blanket support for every future EROFS incompat feature or every dedupe
|
|
||||||
encoding; only the explicitly qualified fragment/metabox forms are claimed.
|
|
||||||
- Performance guarantees from the manual throughput observations.
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# Pre10 Baseline
|
|
||||||
|
|
||||||
Pre10 was created as an exact tracked-tree snapshot of `repo-pre-9` before
|
|
||||||
any Pre10 planning or source changes.
|
|
||||||
|
|
||||||
## Source identity
|
|
||||||
|
|
||||||
- Repository HEAD: `bedc8dae477ba0e82a4a7c4f0de7ccdd41696004`
|
|
||||||
- `repo-pre-9` tree: `54b2845b80c33f05109af1fea84e962aca3a82d3`
|
|
||||||
- `repo-pre-9/src` tree: `e657e8a63b097b061670f75ca01947a568ef33d5`
|
|
||||||
|
|
||||||
## Copy verification
|
|
||||||
|
|
||||||
Before this baseline file was added, `repo-pre-10` matched `repo-pre-9` in:
|
|
||||||
|
|
||||||
- file and directory manifest;
|
|
||||||
- byte-for-byte file contents;
|
|
||||||
- file modes and timestamps;
|
|
||||||
- complete subtree tree hash;
|
|
||||||
- `src` subtree tree hash.
|
|
||||||
|
|
||||||
The copied tree contained no nested `.git` directory, image, binary build
|
|
||||||
artifact, temporary file, or file larger than 10 MiB.
|
|
||||||
|
|
||||||
## Pre9 validation reference
|
|
||||||
|
|
||||||
The final Pre9 manual QEMU smoke validation is recorded in
|
|
||||||
[`pre9-cache-final-manual-validation.md`](pre9-cache-final-manual-validation.md).
|
|
||||||
It reports successful KLD build/load and read-only mounts, correct LZMA
|
|
||||||
single-read and full-file hashes, successful concurrent LZMA reads, a passing
|
|
||||||
LZ4 regression read, and complete test resource cleanup.
|
|
||||||
|
|
||||||
## Pre10 state
|
|
||||||
|
|
||||||
No Pre10 source, build, configuration, or planning change has been made. This
|
|
||||||
file only records the snapshot baseline.
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
# Pre10 Batch A: Compatibility Cleanup and Ordering
|
|
||||||
|
|
||||||
## Scope and baseline
|
|
||||||
|
|
||||||
Batch A changes only `src/internal.h`, `src/data.c`, and `src/zmap.c`. It is a
|
|
||||||
source-only structural change based on commit
|
|
||||||
`b5d6f5ce0696407f9f1cb3f0a9f8cbab643eea49`. No QEMU or feature test was run.
|
|
||||||
|
|
||||||
The starting blobs were:
|
|
||||||
|
|
||||||
| Path | Blob |
|
|
||||||
| --- | --- |
|
|
||||||
| `src/internal.h` | `cfa15de12b73319322ebb33049a7f14b9eb5c271` |
|
|
||||||
| `src/data.c` | `fdc138b0dad12501d842bae124c8c020793dbc97` |
|
|
||||||
| `src/zmap.c` | `51170741a0fb5eced814db898c1a233e8a23088a` |
|
|
||||||
|
|
||||||
## Removed compatibility declarations
|
|
||||||
|
|
||||||
Repository-wide fixed-string searches covered all files below
|
|
||||||
`repo-pre-10`, including source, the Makefile, and documentation. The only
|
|
||||||
non-definition match was an old review report describing
|
|
||||||
`erofs_is_fileio_mode()` as dead code.
|
|
||||||
|
|
||||||
| Candidate | Source consumers | Result |
|
|
||||||
| --- | ---: | --- |
|
|
||||||
| `EROFS_SYNC_DECOMPRESS_AUTO` and related enum values | 0 | Removed |
|
|
||||||
| `EROFS_ZIP_CACHE_DISABLED` and related enum values | 0 | Removed |
|
|
||||||
| `struct erofs_buf` | 0 | Removed |
|
|
||||||
| `__EROFS_BUF_INITIALIZER` | 0 | Removed |
|
|
||||||
| `erofs_map_blocks.buf` | 0 | Removed with its dead type |
|
|
||||||
| `erofs_is_fileio_mode()` | 0 | Removed |
|
|
||||||
|
|
||||||
These declarations modeled Linux facilities that the synchronous contiguous-
|
|
||||||
buffer FreeBSD path does not implement. Their removal does not replace or
|
|
||||||
alter the mount-owned decoded LZMA extent cache introduced in Pre9.
|
|
||||||
|
|
||||||
## Declaration and definition order
|
|
||||||
|
|
||||||
`internal.h` now exposes explicit groups for buffer/device I/O, inode/vnode
|
|
||||||
lifecycle, directory operations, logical mapping/file data, compressed
|
|
||||||
mapping/data, compression configuration/backends, and VOP vectors. Existing
|
|
||||||
signatures are unchanged.
|
|
||||||
|
|
||||||
In `data.c`, the regular-file wrapper now precedes the symlink wrapper, matching
|
|
||||||
the header's file-data grouping. Both wrappers retain their original bodies
|
|
||||||
and continue to delegate to `erofs_read_uio()`.
|
|
||||||
|
|
||||||
In `zmap.c`, `z_erofs_read_extent()` now follows the overflow-safe extent
|
|
||||||
position helpers it consumes. The Linux-shared compressed-index and map
|
|
||||||
functions retain their existing relative order; FreeBSD-only explicit-extent
|
|
||||||
helpers remain one contiguous responsibility group.
|
|
||||||
|
|
||||||
The reordering was deliberately bounded by the existing static call topology:
|
|
||||||
|
|
||||||
- `erofs_check_device_range()` remains before `erofs_map_dev()`;
|
|
||||||
- `erofs_inline_tail_start()` and `erofs_map_blocks_chunk()` remain before
|
|
||||||
`erofs_map_blocks()`;
|
|
||||||
- `erofs_bread_device()` remains before `erofs_bread()` and
|
|
||||||
`erofs_read_physical()`;
|
|
||||||
- `erofs_read_uio()` remains before both public vnode read wrappers;
|
|
||||||
- compressed-index decode/load helpers remain before their callers;
|
|
||||||
- `z_erofs_map_blocks_fo()` and `z_erofs_validate_extent_table()` remain
|
|
||||||
before `z_erofs_fill_inode()`; and
|
|
||||||
- fill, full/explicit mapping, and sanity helpers remain before
|
|
||||||
`z_erofs_map_blocks_iter()`.
|
|
||||||
|
|
||||||
No extra static prototype was introduced. Broader movement of
|
|
||||||
`erofs_map_dev()` was rejected in this batch because matching Linux's exact
|
|
||||||
position would either violate the current dependency order or add a prototype
|
|
||||||
solely to support cosmetic movement.
|
|
||||||
|
|
||||||
## Preserved behavior
|
|
||||||
|
|
||||||
- No function signature, return value, allocation flag, lock operation,
|
|
||||||
`bread`/`brelse` ownership, mapping flag, or control-flow statement changed.
|
|
||||||
- No structure field used by runtime code moved or changed.
|
|
||||||
- The Pre9 decoded extent cache fields, initialization/finalization calls,
|
|
||||||
key, lock, and one-entry-per-mount policy are untouched.
|
|
||||||
- No Linux page, folio, bio, workqueue, XArray, shrinker, or compatibility
|
|
||||||
wrapper was introduced.
|
|
||||||
|
|
||||||
## Static validation
|
|
||||||
|
|
||||||
| Check | Result | Evidence |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Removed-symbol search | PASS | Every removed enum, type, initializer, helper, and `map_blocks.buf` access has zero source/Makefile matches. |
|
|
||||||
| Prototype uniqueness | PASS | Each of the 25 grouped cross-file declarations occurs exactly once in `internal.h`. |
|
|
||||||
| `erofs_read_file()` body | PASS | Parent and working-tree normalized hashes are both `acc4cb05f9a1eb4a0066f8e4d6f3e84c8a69cfb70c762233a61ab08e84836aef`. |
|
|
||||||
| `erofs_readlink_target()` body | PASS | Parent and working-tree normalized hashes are both `73cc37f21f0c66a2c6bb27d39cc9f93f38df1994c7d386dacb5efc7734aa6a89`. |
|
|
||||||
| `z_erofs_read_extent()` body | PASS | Parent and working-tree normalized hashes are both `9145b1220329a2d113c69971c94537a99467a7252f3ea564b695a4530ea8e11d`. |
|
|
||||||
| Changed-path allowlist | PASS | Only the three source files and this Batch A report changed. |
|
|
||||||
| `git diff --check` | PASS | No whitespace errors. |
|
|
||||||
| QEMU/build | NOT RUN | Reserved for final aggregate Pre10 validation. |
|
|
||||||
|
|
||||||
The final Pre10 guest build and smoke run are intentionally deferred to the
|
|
||||||
aggregate validation stage defined by `planning/pre10/validation.md`.
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
# Pre10 Batch B: Bounded Metadata Helpers
|
|
||||||
|
|
||||||
## Scope and baseline
|
|
||||||
|
|
||||||
Batch B is a source-only extraction based on commit
|
|
||||||
`3c7c774b296a2ee90578a78f372aad5fd2edbec6`. It changes only
|
|
||||||
`src/super.c`, `src/data.c`, and `src/inode.c`, plus this report. No build,
|
|
||||||
QEMU smoke, or feature test was run.
|
|
||||||
|
|
||||||
The extraction keeps ownership at the original FreeBSD lifecycle boundaries:
|
|
||||||
|
|
||||||
- `erofs_mountfs()` still owns mount allocation, the primary GEOM transfer,
|
|
||||||
extent-cache lifecycle, device scanning, internal inode setup, publication,
|
|
||||||
and the single `erofs_sb_free()` failure path.
|
|
||||||
- `erofs_map_dev()` still owns device selection, range and overflow checks,
|
|
||||||
flat-device behavior, and all `ENODEV`/`EINTEGRITY` returns.
|
|
||||||
- `erofs_vget()` still owns vnode allocation, locking, mount association,
|
|
||||||
hash insertion, construction state, publication, and failure cleanup.
|
|
||||||
|
|
||||||
## Superblock helper
|
|
||||||
|
|
||||||
`erofs_read_superblock()` now reads the on-disk superblock into a temporary
|
|
||||||
buffer, copies the fixed 144-byte structure to caller-owned stack storage,
|
|
||||||
releases the temporary buffer, and performs the existing validation and field
|
|
||||||
decode in the original order. It also retains the existing device-size,
|
|
||||||
checksum, generation-seed, metabox-NID, and compression-configuration checks.
|
|
||||||
|
|
||||||
The helper does not allocate or publish the mount, open extra devices, create
|
|
||||||
internal inodes, initialize xattrs, or own failure cleanup. `erofs_mountfs()`
|
|
||||||
still calls, in order:
|
|
||||||
|
|
||||||
```text
|
|
||||||
z_erofs_extent_cache_init
|
|
||||||
erofs_read_superblock
|
|
||||||
erofs_scan_devices
|
|
||||||
shared-EA/metabox combination check
|
|
||||||
erofs_init_packed_inode
|
|
||||||
erofs_init_metabox_inode
|
|
||||||
erofs_xattr_prefixes_init
|
|
||||||
mount publication and flag setup
|
|
||||||
```
|
|
||||||
|
|
||||||
All prior superblock outcomes remain at the same semantic boundary:
|
|
||||||
|
|
||||||
| Condition | Preserved result |
|
|
||||||
| --- | --- |
|
|
||||||
| read failure | underlying `erofs_bread()` error |
|
|
||||||
| invalid magic or block geometry | `EINVAL` |
|
|
||||||
| unsupported directory blocks or feature bits | `EOPNOTSUPP` |
|
|
||||||
| invalid xattr, timestamp, or metabox metadata | `EINTEGRITY` |
|
|
||||||
| invalid device geometry | existing `EINVAL`, `EINTEGRITY`, or `ENXIO` |
|
|
||||||
| checksum mismatch | `EINTEGRITY` |
|
|
||||||
| generation/config read failure | existing underlying error |
|
|
||||||
|
|
||||||
Copying the superblock before releasing its read buffer makes its lifetime
|
|
||||||
explicit. The copy remains available to `erofs_scan_devices()` and volume-name
|
|
||||||
publication, while checksum and compression configuration reads continue to
|
|
||||||
use their existing independent I/O helpers.
|
|
||||||
|
|
||||||
## Device-map helper
|
|
||||||
|
|
||||||
`erofs_fill_map_dev()` is a pure assignment helper for `m_em`, `m_dif`, and
|
|
||||||
`m_pa`. It has no branches, errors, allocation, I/O, or ownership effects.
|
|
||||||
|
|
||||||
The caller retains all explicit-device and unified-range selection, arithmetic
|
|
||||||
overflow checks, physical range validation, flat-device handling, and external
|
|
||||||
device availability checks. In particular:
|
|
||||||
|
|
||||||
- flat explicit mappings still use the primary device and add the unified
|
|
||||||
offset to the existing physical address;
|
|
||||||
- flat implicit mappings still retain the primary device and unified address;
|
|
||||||
- non-flat explicit mappings select the requested extra device only after all
|
|
||||||
validation succeeds; and
|
|
||||||
- non-flat implicit misses still return success with the initial primary map.
|
|
||||||
|
|
||||||
## Vnode helper
|
|
||||||
|
|
||||||
`erofs_fill_vnode()` sets only the inode-derived vnode type, FIFO operation
|
|
||||||
vector, and `VV_ROOT` flag. It runs after `erofs_read_inode()` succeeds and
|
|
||||||
immediately before `VSTATE_CONSTRUCTED`, while `erofs_vget()` still holds the
|
|
||||||
exclusive vnode lock.
|
|
||||||
|
|
||||||
Hash lookup/insertion, allocation, `insmntque()`, locking, race handling,
|
|
||||||
failure `vgone()`/`vput()`, shared-lock downgrade, and `*vpp` publication remain
|
|
||||||
in `erofs_vget()` in their original order.
|
|
||||||
|
|
||||||
## Known pre-existing risk
|
|
||||||
|
|
||||||
The `insmntque()` failure branch remains unchanged. FreeBSD's `insmntque()` may
|
|
||||||
reclaim and release the vnode on failure, while the existing EROFS branch then
|
|
||||||
accesses `vp->v_data`. This possible use-after-release is outside a helper-only
|
|
||||||
batch and was deliberately not mixed into this commit. Consequently, this
|
|
||||||
report does not claim that the pre-existing vnode cleanup path is correct.
|
|
||||||
|
|
||||||
## Static validation
|
|
||||||
|
|
||||||
| Check | Result | Evidence |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Changed-path allowlist | PASS | Only three allowed source files and this report changed. |
|
|
||||||
| Helper ownership | PASS | Each helper is `static` and has one direct caller. |
|
|
||||||
| Mount lifecycle order | PASS | Cache init, device scan, internal inode/xattr setup, publication, and `erofs_sb_free()` remain in `erofs_mountfs()`. |
|
|
||||||
| Device-map errors | PASS | All range, overflow, device-selection, `ENODEV`, and `EINTEGRITY` branches remain in `erofs_map_dev()`. |
|
|
||||||
| Vnode lifecycle order | PASS | `insmntque()`, hash insertion, inode read, construction, downgrade, and publication retain their order. |
|
|
||||||
| `git diff --check` | PASS | No whitespace errors. |
|
|
||||||
| Build/QEMU/feature test | NOT RUN | Reserved for later aggregate Pre10 validation. |
|
|
||||||
|
|
||||||
The pre-existing `insmntque()` concern is deferred; no new errno, logging,
|
|
||||||
ABI, Linux lifecycle facade, or Pre9 decoded-cache change was introduced.
|
|
||||||
@@ -1,216 +0,0 @@
|
|||||||
# Pre10 Batch C: BSD Decompressor Request Dispatch
|
|
||||||
|
|
||||||
Status: **STATIC PASS; RUNTIME NOT RUN**
|
|
||||||
|
|
||||||
This batch aligns the BSD decompressor boundary with the Linux source shape
|
|
||||||
where the responsibility is equivalent. It keeps the FreeBSD implementation
|
|
||||||
synchronous and contiguous-buffer based. No page, folio, bio, workqueue,
|
|
||||||
XArray, shrinker, or asynchronous decompression abstraction was added.
|
|
||||||
|
|
||||||
## Baseline and Scope
|
|
||||||
|
|
||||||
The implementation starts from Pre10 commit `d3c1cb90` and preserves Batch A,
|
|
||||||
Batch B, and the documented `insmntque()` lifecycle issue. The source changes
|
|
||||||
are limited to:
|
|
||||||
|
|
||||||
```text
|
|
||||||
repo-pre-10/src/internal.h
|
|
||||||
repo-pre-10/src/decompressor.c
|
|
||||||
repo-pre-10/src/lz4.c
|
|
||||||
repo-pre-10/src/decompressor_lzma.c
|
|
||||||
repo-pre-10/src/decompressor_deflate.c
|
|
||||||
repo-pre-10/src/decompressor_zstd.c
|
|
||||||
```
|
|
||||||
|
|
||||||
`zdata.c` was inspected but did not need a mechanical edit: its existing call
|
|
||||||
to `z_erofs_decompress()` remains the sole dispatcher call, and its buffer
|
|
||||||
release and decoded LZMA extent-cache publication remain unchanged.
|
|
||||||
|
|
||||||
## Request Contract
|
|
||||||
|
|
||||||
The new request is stack-owned by `z_erofs_decompress()` and is valid only for
|
|
||||||
the synchronous callback invocation:
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct z_erofs_decompress_req {
|
|
||||||
struct erofs_mount *em;
|
|
||||||
const struct erofs_map_blocks *map;
|
|
||||||
const void *in;
|
|
||||||
size_t inputsize;
|
|
||||||
void *out;
|
|
||||||
size_t outputsize;
|
|
||||||
bool partial_decoding;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Field mapping is direct:
|
|
||||||
|
|
||||||
| Request field | Previous source | Ownership |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| `em` | `em` / codec configuration arguments | Borrowed mount, never retained |
|
|
||||||
| `map` | `map` and its algorithm/offset fields | Borrowed mapping, never retained |
|
|
||||||
| `in` | `src` after padding removal | Borrowed compressed buffer |
|
|
||||||
| `inputsize` | `srclen` after padding removal | Value copy |
|
|
||||||
| `out` | `dst` | Borrowed decoded buffer |
|
|
||||||
| `outputsize` | `dstlen` | Value copy |
|
|
||||||
| `partial_decoding` | `partial` | Value copy |
|
|
||||||
|
|
||||||
The request does not own either data buffer. `zdata.c` continues to release
|
|
||||||
the compressed buffer with `erofs_brelse()`, and continues to free or publish
|
|
||||||
the decoded allocation after the callback returns.
|
|
||||||
|
|
||||||
The descriptor callback is intentionally synchronous:
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct z_erofs_decompressor {
|
|
||||||
const char *name;
|
|
||||||
int (*config)(struct erofs_mount *,
|
|
||||||
const struct erofs_super_block *, const void *, size_t);
|
|
||||||
int (*decompress)(const struct z_erofs_decompress_req *);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
The configuration callback receives the superblock argument because the LZ4
|
|
||||||
legacy configuration path uses it. The other codec configuration callbacks
|
|
||||||
retain their previous inputs and explicitly ignore that additional argument.
|
|
||||||
|
|
||||||
## Descriptor Coverage
|
|
||||||
|
|
||||||
`decompressor.c` contains one static array indexed by the on-disk algorithm
|
|
||||||
number. The entries are:
|
|
||||||
|
|
||||||
```text
|
|
||||||
0 LZ4 config + z_erofs_lz4_decompress
|
|
||||||
1 LZMA config + z_erofs_lzma_decompress
|
|
||||||
2 DEFLATE config + z_erofs_deflate_decompress
|
|
||||||
3 ZSTD config + z_erofs_zstd_decompress
|
|
||||||
4 SHIFTED plain transform callback
|
|
||||||
5 INTERLACED plain transform callback
|
|
||||||
```
|
|
||||||
|
|
||||||
The first four entries cover every real EROFS compression algorithm currently
|
|
||||||
defined by `erofs_fs.h`. The two runtime-only entries cover the existing plain
|
|
||||||
mapping forms. No duplicate backend entry point or compatibility wrapper is
|
|
||||||
present.
|
|
||||||
|
|
||||||
Configuration parsing preserves the old ordering:
|
|
||||||
|
|
||||||
1. Read the configuration record and its payload.
|
|
||||||
2. Return the read error immediately if either read fails.
|
|
||||||
3. Select the descriptor and invoke its configuration callback.
|
|
||||||
4. Release the payload with `erofs_brelse()`.
|
|
||||||
5. Return the callback's original error unchanged.
|
|
||||||
|
|
||||||
This retains the existing I/O-error priority. Unknown on-disk algorithm bits
|
|
||||||
are rejected before configuration reads by the existing
|
|
||||||
`Z_EROFS_ALL_COMPR_ALGS` mask check. A supported algorithm whose configuration
|
|
||||||
is unavailable returns `EOPNOTSUPP` from its existing callback. In particular,
|
|
||||||
the no-`ZSTDIO` build still emits the existing mount error and returns
|
|
||||||
`EOPNOTSUPP`.
|
|
||||||
|
|
||||||
## Decode and Error Semantics
|
|
||||||
|
|
||||||
The old and new paths have the following equivalent behavior:
|
|
||||||
|
|
||||||
| Condition | Result before Batch C | Result after Batch C |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Shifted/interlaced output larger than input | `EINTEGRITY` | `EINTEGRITY` |
|
|
||||||
| Shifted/interlaced transform success | `0` | `0` |
|
|
||||||
| Invalid algorithm format | `EOPNOTSUPP` | `EOPNOTSUPP` |
|
|
||||||
| Required zero-padding absent | `EINTEGRITY` | `EINTEGRITY` |
|
|
||||||
| LZMA dictionary not configured | `EINTEGRITY` | `EINTEGRITY` |
|
|
||||||
| Backend success | `0` | `0` |
|
|
||||||
| Any backend failure | `EIO` | `EIO` |
|
|
||||||
|
|
||||||
Padding removal remains in the dispatcher and is performed before the backend
|
|
||||||
request is updated. The LZ4 zero-padding exception remains unchanged. The LZMA
|
|
||||||
dictionary check remains before callback dispatch. Backend-specific checks are
|
|
||||||
unchanged apart from reading their previous parameters from the request or
|
|
||||||
mount configuration:
|
|
||||||
|
|
||||||
- LZ4 preserves literal/match bounds, overlap copying, partial completion,
|
|
||||||
and trailing-zero validation.
|
|
||||||
- MicroLZMA preserves input/output size limits, dictionary selection, decoder
|
|
||||||
shutdown, full-stream consumption, and partial output acceptance.
|
|
||||||
- DEFLATE preserves window validation, `inflateEnd()`, no-progress detection,
|
|
||||||
output completion, and full-stream input consumption.
|
|
||||||
- ZSTD preserves window selection, decoder destruction on every initialized
|
|
||||||
path, no-progress detection, output completion, and full-stream consumption.
|
|
||||||
|
|
||||||
## Consumer and Symbol Proof
|
|
||||||
|
|
||||||
Before the change, repository searches found exactly one in-tree consumer of
|
|
||||||
each old backend symbol: the switch in `decompressor.c`. The only consumer of
|
|
||||||
`z_erofs_decompress()` is `zdata.c`. After the change:
|
|
||||||
|
|
||||||
```text
|
|
||||||
old lz4_decompress 0 definitions/references
|
|
||||||
old lzma_decompress 0 definitions/references
|
|
||||||
old deflate_decompress 0 definitions/references
|
|
||||||
old zstd_decompress 0 definitions/references
|
|
||||||
|
|
||||||
new LZ4 backend one definition, one descriptor reference, one prototype
|
|
||||||
new LZMA backend one definition, one descriptor reference, one prototype
|
|
||||||
new DEFLATE backend one definition, one descriptor reference, one prototype
|
|
||||||
new ZSTD backend two definitions for #ifdef/#else, one descriptor reference,
|
|
||||||
one prototype
|
|
||||||
```
|
|
||||||
|
|
||||||
The two ZSTD definitions are mutually exclusive build branches, not duplicate
|
|
||||||
runtime implementations. No old-name wrapper was retained because no real
|
|
||||||
consumer remains.
|
|
||||||
|
|
||||||
## Cache and Ownership Review
|
|
||||||
|
|
||||||
The Pre9 decoded LZMA cache policy is untouched. The request callback returns
|
|
||||||
before the cache code runs, so the following remain owned by `zdata.c`:
|
|
||||||
|
|
||||||
- compressed-buffer release;
|
|
||||||
- decoded allocation cleanup on failure;
|
|
||||||
- decoded extent publication;
|
|
||||||
- duplicate-cache replacement and old-entry freeing;
|
|
||||||
- one-entry-per-mount bound and cache lock lifecycle.
|
|
||||||
|
|
||||||
No callback stores the request pointer or either borrowed buffer after return.
|
|
||||||
|
|
||||||
## Static Checks
|
|
||||||
|
|
||||||
The following checks were run before this report was written:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git diff --check
|
|
||||||
git diff --name-only | sort
|
|
||||||
grep -RInE '(^|[^_])(lz4_decompress|lzma_decompress|deflate_decompress|zstd_decompress)\\(' repo-pre-10/src
|
|
||||||
grep -RInE 'z_erofs_(lz4|lzma|deflate|zstd)_decompress' repo-pre-10/src
|
|
||||||
grep -RInE '\\b(page|folio|bio|workqueue|xarray|shrinker)\\b' \\
|
|
||||||
repo-pre-10/src/internal.h repo-pre-10/src/decompressor.c \\
|
|
||||||
repo-pre-10/src/lz4.c repo-pre-10/src/decompressor_lzma.c \\
|
|
||||||
repo-pre-10/src/decompressor_deflate.c repo-pre-10/src/decompressor_zstd.c \\
|
|
||||||
repo-pre-10/src/zdata.c
|
|
||||||
```
|
|
||||||
|
|
||||||
Results:
|
|
||||||
|
|
||||||
- `git diff --check`: PASS.
|
|
||||||
- Changed paths: only the six allowed source files: PASS.
|
|
||||||
- Old backend symbol search: no matches: PASS.
|
|
||||||
- New backend definitions and descriptor references: PASS.
|
|
||||||
- Forbidden Linux memory-model concepts in the changed codec boundary: no
|
|
||||||
matches: PASS.
|
|
||||||
- Descriptor entries: six unique designated entries covering algorithms 0-5:
|
|
||||||
PASS.
|
|
||||||
- `zdata.c` cache and ownership diff: unchanged: PASS.
|
|
||||||
|
|
||||||
The host is not a FreeBSD build environment, so this batch does not claim a
|
|
||||||
KLD build. Per the Pre10 instruction, QEMU smoke testing and the full feature
|
|
||||||
matrix were not run in this batch.
|
|
||||||
|
|
||||||
## Concerns and Deferred Validation
|
|
||||||
|
|
||||||
The primary remaining validation is a FreeBSD guest KLD build followed by the
|
|
||||||
planned Pre10 smoke run. That runtime work is intentionally separate from this
|
|
||||||
static implementation batch. Full feature tests remain outside Pre10.
|
|
||||||
|
|
||||||
The existing `erofs_vget()` `insmntque()` failure-path P1 remains documented
|
|
||||||
in `repo-pre-10/issues/erofs-vget-insmntque-failure-use-after-release.md` and
|
|
||||||
was not changed here.
|
|
||||||
@@ -1,347 +0,0 @@
|
|||||||
# Pre10 Completion and Targeted Smoke Report
|
|
||||||
|
|
||||||
Status: **PRE10 IMPLEMENTATION COMPLETE; TARGETED SMOKE PASS; FULL FEATURE TEST NOT RUN**
|
|
||||||
|
|
||||||
Date: 2026-08-13
|
|
||||||
|
|
||||||
## Scope and goals
|
|
||||||
|
|
||||||
Pre10 is a controlled maintenance-alignment release based on the final Pre9
|
|
||||||
tree. Its purpose is to make the FreeBSD EROFS implementation easier to compare
|
|
||||||
and maintain alongside the independent Linux EROFS repository without copying
|
|
||||||
Linux-only lifecycle or memory-management models.
|
|
||||||
|
|
||||||
The planned work was limited to three source batches:
|
|
||||||
|
|
||||||
1. Remove unused Linux-shaped compatibility declarations and improve source
|
|
||||||
ordering.
|
|
||||||
2. Extract bounded helpers where Linux and FreeBSD responsibilities are
|
|
||||||
comparable, while retaining FreeBSD ownership and errno behavior.
|
|
||||||
3. Introduce a BSD-native synchronous decompressor request and descriptor
|
|
||||||
boundary with Linux-comparable codec names.
|
|
||||||
|
|
||||||
Full feature validation, CI execution, performance redesign, Linux page/folio/
|
|
||||||
bio/workqueue integration, and new format support were outside Pre10. This
|
|
||||||
report does not claim that every EROFS feature was tested.
|
|
||||||
|
|
||||||
## Repository history and identities
|
|
||||||
|
|
||||||
The relevant pushed commits are:
|
|
||||||
|
|
||||||
| Commit | Purpose |
|
|
||||||
| --- | --- |
|
|
||||||
| `cdfcd79640f252830c4e507f65aa7387eaa98ae0` | Snapshot `repo-pre-10` from the current `repo-pre-9`. |
|
|
||||||
| `b5d6f5ce0696407f9f1cb3f0a9f8cbab643eea49` | Add the Pre10 execution plan under `planning/pre10/`. |
|
|
||||||
| `3c7c774b296a2ee90578a78f372aad5fd2edbec6` | Batch A compatibility cleanup and ordering. |
|
|
||||||
| `8c246ea3c4dbf94b92d1f27a9d1b6b6eda582c31` | Batch B bounded metadata helper extraction. |
|
|
||||||
| `d3c1cb90b21ae8a97f549bc256d120268e5d09e9` | Record the discovered `insmntque()` vnode lifecycle issue. |
|
|
||||||
| `5c8a47e916b1521cb8a35ec4f546e5e16fb8c2dc` | Batch C decompressor request and descriptor alignment. |
|
|
||||||
| `9fbf0d7e24084d2342ecd61eff21592b1a83d225` | Fix `insmntque()` failure ownership. |
|
|
||||||
| `ff6586c2b24e155a3cbdf55b2ed80edb36d3e406` | Clarify the issue status after the source fix. This is the commit tested by the final smoke run. |
|
|
||||||
|
|
||||||
The snapshot report records the Pre9 source tree inherited by Pre10 as
|
|
||||||
`e657e8a63b097b061670f75ca01947a568ef33d5`. The final smoke runner independently
|
|
||||||
recorded these tested identities:
|
|
||||||
|
|
||||||
```text
|
|
||||||
commit=ff6586c2b24e155a3cbdf55b2ed80edb36d3e406
|
|
||||||
repo_pre_10_tree=3387e32efbcb0bec7e0bb57ecfc42daf9b962d28
|
|
||||||
src_tree=ec684d8dbd7662070234da1fe947aba48a293db8
|
|
||||||
```
|
|
||||||
|
|
||||||
Evidence: `/work/tests-dev/temp/pre10-smoke-final-20260813T102543Z/dut-identities.txt`.
|
|
||||||
|
|
||||||
## Batch A: compatibility cleanup and ordering
|
|
||||||
|
|
||||||
Batch A changed `src/internal.h`, `src/data.c`, and `src/zmap.c`.
|
|
||||||
|
|
||||||
Repository-wide consumer searches proved that the following declarations did
|
|
||||||
not represent implemented FreeBSD behavior and had no source, Makefile, ABI,
|
|
||||||
initializer, or field-access consumer:
|
|
||||||
|
|
||||||
- `EROFS_SYNC_DECOMPRESS_*`;
|
|
||||||
- `EROFS_ZIP_CACHE_*`;
|
|
||||||
- `struct erofs_buf` and `__EROFS_BUF_INITIALIZER`;
|
|
||||||
- the unused `erofs_map_blocks.buf` member; and
|
|
||||||
- `erofs_is_fileio_mode()`.
|
|
||||||
|
|
||||||
Removing these declarations improves maintainability because the FreeBSD tree
|
|
||||||
no longer advertises Linux mechanisms that it does not implement. The real
|
|
||||||
FreeBSD synchronous contiguous-buffer path and the Pre9 mount-owned decoded
|
|
||||||
LZMA extent cache remain explicit and unchanged.
|
|
||||||
|
|
||||||
Declarations and existing function definitions were grouped by actual
|
|
||||||
responsibility, closer to the Linux source's readable organization where the
|
|
||||||
responsibilities match. Static call topology was preserved, and moved function
|
|
||||||
bodies were compared for equivalence. No return value, allocation flag, lock,
|
|
||||||
mapping flag, `bread`/`brelse` ownership rule, or runtime structure field was
|
|
||||||
changed.
|
|
||||||
|
|
||||||
Detailed evidence: `repo-pre-10/docs/pre10-batch-a.md`.
|
|
||||||
|
|
||||||
## Batch B: bounded FreeBSD helper boundaries
|
|
||||||
|
|
||||||
Batch B changed `src/super.c`, `src/data.c`, and `src/inode.c`.
|
|
||||||
|
|
||||||
It extracted three `static` helpers with one direct caller each:
|
|
||||||
|
|
||||||
- `erofs_read_superblock()` isolates superblock read, fixed-size copy,
|
|
||||||
validation, field decode, checksum, generation seed, and compression
|
|
||||||
configuration parsing. `erofs_mountfs()` still owns mount allocation, GEOM
|
|
||||||
transfer, device scanning, internal inode setup, publication, and the single
|
|
||||||
mount cleanup path.
|
|
||||||
- `erofs_fill_map_dev()` performs only the final `m_em`, `m_dif`, and `m_pa`
|
|
||||||
assignments. Device selection, range checks, overflow checks, flat-device
|
|
||||||
semantics, and `ENODEV`/`EINTEGRITY` decisions remain in `erofs_map_dev()`.
|
|
||||||
- `erofs_fill_vnode()` performs only inode-derived vnode field setup. FreeBSD
|
|
||||||
vnode allocation, locking, mount association, hash insertion, race handling,
|
|
||||||
construction state, downgrade, publication, and cleanup remain in
|
|
||||||
`erofs_vget()`.
|
|
||||||
|
|
||||||
These boundaries improve Linux/FreeBSD visual comparability at the function
|
|
||||||
responsibility level while deliberately retaining the FreeBSD GEOM, vnode,
|
|
||||||
hash, lock, and cleanup contracts. Linux lifecycle names such as `iget` or
|
|
||||||
`fill_super` were not adopted where their semantics would be misleading.
|
|
||||||
|
|
||||||
Detailed evidence: `repo-pre-10/docs/pre10-batch-b.md`.
|
|
||||||
|
|
||||||
## Batch C: BSD decompressor request dispatch
|
|
||||||
|
|
||||||
Batch C changed `src/internal.h`, `src/decompressor.c`, `src/lz4.c`,
|
|
||||||
`src/decompressor_lzma.c`, `src/decompressor_deflate.c`, and
|
|
||||||
`src/decompressor_zstd.c`.
|
|
||||||
|
|
||||||
It introduced a stack-owned, synchronous, contiguous-buffer
|
|
||||||
`z_erofs_decompress_req` and a descriptor table covering LZ4, LZMA, DEFLATE,
|
|
||||||
ZSTD, SHIFTED, and INTERLACED. Codec entry points now use the Linux-comparable
|
|
||||||
names `z_erofs_lz4_decompress`, `z_erofs_lzma_decompress`,
|
|
||||||
`z_erofs_deflate_decompress`, and `z_erofs_zstd_decompress` because their
|
|
||||||
functional roles are equivalent.
|
|
||||||
|
|
||||||
The interface remains BSD-native:
|
|
||||||
|
|
||||||
- no page, folio, bio, workqueue, XArray, shrinker, asynchronous request, or
|
|
||||||
Linux ownership wrapper was introduced;
|
|
||||||
- request fields borrow the existing compressed and decoded buffers only for
|
|
||||||
the synchronous callback;
|
|
||||||
- `zdata.c` still owns buffer release and LZMA decoded-cache publication;
|
|
||||||
- plain SHIFTED/INTERLACED transforms remain in the existing dispatch model;
|
|
||||||
- LZ4 padding behavior, partial-decoding source, LZMA dictionary validation,
|
|
||||||
ZSTD conditional availability, and codec resource release remain unchanged;
|
|
||||||
- configuration I/O errors preserve priority and backend failures remain
|
|
||||||
normalized to the existing `EIO` result.
|
|
||||||
|
|
||||||
This gives third-party maintainers a recognizable request/descriptor and codec
|
|
||||||
naming shape without importing Linux kernel runtime assumptions.
|
|
||||||
|
|
||||||
Detailed evidence: `repo-pre-10/docs/pre10-batch-c.md`.
|
|
||||||
|
|
||||||
## P1 vnode lifecycle finding and fix
|
|
||||||
|
|
||||||
Independent Batch B review found a pre-existing P1 ownership violation in
|
|
||||||
`erofs_vget()`: after `insmntque()` returned an error, the old branch wrote
|
|
||||||
through `vp->v_data` even though FreeBSD may already have executed `vgone()`
|
|
||||||
and `vput()` and ended caller ownership of that vnode.
|
|
||||||
|
|
||||||
Commit `9fbf0d7e24084d2342ecd61eff21592b1a83d225` applied the minimal ownership
|
|
||||||
fix. The error branch now frees only the independently allocated `en`, clears
|
|
||||||
`*vpp`, returns the original error, and performs no further access, unlock,
|
|
||||||
reclaim, or release operation on `vp`. The successful path, vnode hash race,
|
|
||||||
lock state, errno, and later reclaim path were not changed.
|
|
||||||
|
|
||||||
Static ownership review confirms that the kernel failure path clears
|
|
||||||
`v_data`, installs `dead_vnodeops`, and owns vnode cleanup; dead vnode reclaim
|
|
||||||
does not release the filesystem's separately allocated `en`, so exactly one
|
|
||||||
caller-side `free(en, M_EROFS)` remains necessary.
|
|
||||||
|
|
||||||
The source defect is fixed, but runtime closure is still pending. Closing the
|
|
||||||
issue requires a dedicated mount/unmount race test that repeatedly creates or
|
|
||||||
looks up uncached vnodes while normal and forced unmount are attempted, with
|
|
||||||
kernel diagnostics capable of detecting stale vnode access, memory corruption,
|
|
||||||
lock misuse, and double release. The ordinary smoke test below does not trigger
|
|
||||||
or prove this teardown race.
|
|
||||||
|
|
||||||
Issue record:
|
|
||||||
`repo-pre-10/issues/erofs-vget-insmntque-failure-use-after-release.md`.
|
|
||||||
|
|
||||||
## Static review result
|
|
||||||
|
|
||||||
The final static review accepted Batches A, B, and C and the P1 fix. Checks
|
|
||||||
included changed-path allowlists, zero-consumer proof, prototype and backend
|
|
||||||
symbol uniqueness, descriptor coverage and bounds, normalized moved-function
|
|
||||||
body comparison, cleanup/ownership matrices, errno preservation, mount and
|
|
||||||
vnode lifecycle ordering, cache ownership, forbidden Linux mechanism searches,
|
|
||||||
conflict-marker searches, clean-worktree checks, `git diff --check`, and local
|
|
||||||
`HEAD`/`xdm/main` agreement at each pushed boundary.
|
|
||||||
|
|
||||||
No new P0 or P1 defect was found in the three planned batches. Static review is
|
|
||||||
not runtime proof. In particular, it does not close the dedicated vnode
|
|
||||||
teardown race test or the older explicit-extent positive-fixture gap recorded
|
|
||||||
under `repo-pre-10/issues/`.
|
|
||||||
|
|
||||||
## Initial inconclusive smoke attempts
|
|
||||||
|
|
||||||
Two isolated attempts preceded the final PASS. Neither is treated as a DUT
|
|
||||||
failure or a PASS.
|
|
||||||
|
|
||||||
### Attempt 1
|
|
||||||
|
|
||||||
Evidence directory:
|
|
||||||
`/work/tests-dev/temp/pre10-smoke-20260813T100326Z`.
|
|
||||||
|
|
||||||
The readiness probe began before the QEMU process had actually started, then
|
|
||||||
performed repeated SSH handshakes while the TCG guest was still becoming
|
|
||||||
responsive. Sources and fixtures were eventually transferred and the build log
|
|
||||||
reached the final module link/strip stage, but the long SSH build session ended
|
|
||||||
with transport status `255`. No reliable KLD SHA, `kldload`, or `kldstat`
|
|
||||||
evidence was produced.
|
|
||||||
|
|
||||||
The first runner incorrectly continued into the plain case after the failed
|
|
||||||
build/load stage. The guest reported `Invalid fstype`, while `results.txt`
|
|
||||||
incorrectly recorded `mount_status=0` because the exit status was not captured
|
|
||||||
immediately after `mount`. Since module loading was never proven and the
|
|
||||||
runner's status recording was unsound, the mount result is not attributable to
|
|
||||||
Pre10 and the attempt is **INCONCLUSIVE**, not FAIL or PASS.
|
|
||||||
|
|
||||||
### Attempt 2
|
|
||||||
|
|
||||||
Evidence directory:
|
|
||||||
`/work/tests-dev/temp/pre10-smoke-retry-20260813T101136Z`.
|
|
||||||
|
|
||||||
The fresh guest booted and returned a valid FreeBSD identity after intermittent
|
|
||||||
connection refusals, banner timeouts, and resets. The orchestration then exited
|
|
||||||
almost immediately. The claimed SCP failure was not backed by an actual
|
|
||||||
`scp-images.log`; only a failed attempt to tail that missing file remained.
|
|
||||||
No build, module load, mount, or hash result exists. This attempt is also
|
|
||||||
**INCONCLUSIVE** and provides no DUT verdict.
|
|
||||||
|
|
||||||
Both attempts stopped only their owned QEMU process, released ports `10040`
|
|
||||||
and `10041`, deleted their disposable overlays, preserved the immutable base,
|
|
||||||
and left guard PID `26318` and port `9222` unchanged.
|
|
||||||
|
|
||||||
The infrastructure diagnosis was recorded at
|
|
||||||
`/work/tests-dev/fix-todo/pre10-smoke-ssh-banner-timeout.md`. Its original
|
|
||||||
`PENDING_FIX` verdict describes those two attempts; the corrected final runner
|
|
||||||
below subsequently completed the required targeted smoke.
|
|
||||||
|
|
||||||
## Corrected fail-fast runner
|
|
||||||
|
|
||||||
The successful run used a new directory and port `10042`, a fresh disposable
|
|
||||||
overlay, 4096 MiB and two TCG CPUs, and a strictly ordered runner:
|
|
||||||
|
|
||||||
1. Verify exact Git, base-image, fixture, guard, and port identities before
|
|
||||||
starting QEMU.
|
|
||||||
2. Start QEMU and record its owned PID before beginning readiness checks.
|
|
||||||
3. Wait for TCP, require two consecutive successful FreeBSD SSH identity
|
|
||||||
checks, and establish one persistent SSH ControlMaster connection.
|
|
||||||
4. Transfer the source archive, guest scripts, and all fixtures in one batch,
|
|
||||||
then verify fixture hashes in the guest.
|
|
||||||
5. Run the guest build as a background job that writes `build.rc` and a
|
|
||||||
completion sentinel; poll the sentinel rather than depending on one long
|
|
||||||
SSH session.
|
|
||||||
6. Stop immediately unless the build return is zero, `erofs.ko` exists, its
|
|
||||||
hash is recorded, `kldload` succeeds, and `kldstat -n erofs` proves the
|
|
||||||
module is loaded.
|
|
||||||
7. Run each filesystem case separately and immediately record attach, mount,
|
|
||||||
mount-proof, hash, unmount, and detach return codes. A missing proof or
|
|
||||||
nonzero result stops the runner and cannot be converted to PASS.
|
|
||||||
8. Review guest cleanup and `dmesg`, unload the module, and prove it is absent.
|
|
||||||
9. Use the cleanup trap to stop only the recorded QEMU PID, release only the
|
|
||||||
run-owned port and overlay, and revalidate the immutable base and guard VM.
|
|
||||||
|
|
||||||
Runner evidence:
|
|
||||||
`/work/tests-dev/temp/pre10-smoke-final-20260813T102543Z/runner.sh` and
|
|
||||||
`runner.log`.
|
|
||||||
|
|
||||||
## Final targeted smoke result
|
|
||||||
|
|
||||||
Final evidence directory:
|
|
||||||
`/work/tests-dev/temp/pre10-smoke-final-20260813T102543Z`.
|
|
||||||
|
|
||||||
Overall result: **PASS** for the targeted Pre10 smoke scope.
|
|
||||||
|
|
||||||
### Isolation
|
|
||||||
|
|
||||||
- Immutable base image mode before and after: `0444`.
|
|
||||||
- Immutable base image SHA-256 before and after:
|
|
||||||
`67f359621f23a1d745f0889370cbb99a096cee3e99a0b2f3bb18fc7a91bf6fef`.
|
|
||||||
- The `.bp` was not booted or modified directly; the run used a disposable
|
|
||||||
qcow2 overlay.
|
|
||||||
- Guard PID: `26318`; guard SSH port: `9222`.
|
|
||||||
- Guard command identity and `/proc` start value `1102996924` matched before
|
|
||||||
and after, and port `9222` remained reachable.
|
|
||||||
|
|
||||||
Evidence: `base-before.txt`, `cleanup-status.txt`, `guard-before.txt`,
|
|
||||||
`guard-command-before.txt`, `guard-command-after.txt`,
|
|
||||||
`guard-start-before.txt`, and `guard-start-after.txt` in the final evidence
|
|
||||||
directory.
|
|
||||||
|
|
||||||
### KLD build, load, and unload
|
|
||||||
|
|
||||||
- FreeBSD guest build return: `0`.
|
|
||||||
- Built KLD SHA-256:
|
|
||||||
`4ce2d44a0902502a40f07805606485c99869371b3cbab1c70ee19a8ac29d90f1`.
|
|
||||||
- The loaded module hash matched the built module hash.
|
|
||||||
- `kldstat` showed `erofs.ko` loaded as module ID `5`.
|
|
||||||
- `kldunload` succeeded, and the final `kldstat -n erofs` correctly reported
|
|
||||||
that no such loaded module remained.
|
|
||||||
|
|
||||||
Evidence: `build-result.out`, `build-result.rc`, `module-load.out`,
|
|
||||||
`module-load.rc`, and `guest-evidence.tar.gz`.
|
|
||||||
|
|
||||||
### Filesystem cases
|
|
||||||
|
|
||||||
| Case | Mounted file SHA-256 | Time | Result |
|
|
||||||
| --- | --- | ---: | --- |
|
|
||||||
| Plain `/data.txt` | `056f8f7585667dc695e2edf936deaf84cfee0f88671ba6cd5be22ce890763433` | `0s` | PASS |
|
|
||||||
| LZ4 `/compressed.bin` | `3ff012b76087c4da65ce0b69813a76f47ea367e95782edf8b8cd6cd3ec4d1880` | `5s` | PASS |
|
|
||||||
| LZMA full `/level.dat` | `ddda39737f0f6093e828a032ec161511fefbb1fa361bc6cbffdbc91e48e4c461` | `2s` | PASS |
|
|
||||||
|
|
||||||
Each case recorded zero returns for md attach, EROFS mount, mount proof,
|
|
||||||
full-file hash, unmount, and md detach. The exact fixture image hashes were:
|
|
||||||
|
|
||||||
```text
|
|
||||||
plain image 3785ca07e7bd16f6c611191596ae0314253c0ae9b7217a4b22de25799b0f08ac
|
|
||||||
LZ4 image 967cc1b625546f9f9f881472e71cc3d849c65feb4e98e67fbfdc9b90a4be6dda
|
|
||||||
LZMA image 32107a084b27362a093768b88746c37c2e99a74b9f1301a9d4046988479defe9
|
|
||||||
```
|
|
||||||
|
|
||||||
Evidence: `fixture-host-sha256.txt`, `results.txt`, and the per-case files in
|
|
||||||
`guest-evidence.tar.gz`.
|
|
||||||
|
|
||||||
### Kernel messages and cleanup
|
|
||||||
|
|
||||||
The post-test `dmesg` delta and suspect scan were empty: no EROFS mount,
|
|
||||||
integrity, decompression, panic, or assertion error was found. After all cases,
|
|
||||||
only the guest root filesystem and `devfs` remained mounted, no test md device
|
|
||||||
remained, and the EROFS module was unloaded.
|
|
||||||
|
|
||||||
Host cleanup also passed:
|
|
||||||
|
|
||||||
- the run-owned QEMU process stopped;
|
|
||||||
- port `10042` was released;
|
|
||||||
- the disposable overlay was deleted;
|
|
||||||
- the base image mode and hash were unchanged; and
|
|
||||||
- the guard VM remained unchanged and reachable.
|
|
||||||
|
|
||||||
Evidence: `dmesg-delta.txt`, `dmesg-suspect.txt`, `final-guest-state.out`,
|
|
||||||
`cleanup-status.txt`, and `guest-evidence.tar.gz`.
|
|
||||||
|
|
||||||
## Validation limits and conclusion
|
|
||||||
|
|
||||||
Pre10's planned source changes are complete, independently statically reviewed,
|
|
||||||
committed, pushed, built in a FreeBSD guest, and covered by the targeted plain,
|
|
||||||
LZ4, and LZMA smoke run. That targeted scope passed at tested commit
|
|
||||||
`ff6586c2b24e155a3cbdf55b2ed80edb36d3e406`.
|
|
||||||
|
|
||||||
No full feature test and no `/work/tests-dev/test_all.py` run was performed.
|
|
||||||
This report therefore does not claim all features, codecs, mapping layouts,
|
|
||||||
multi-device behavior, partial references, tailpacking, memory pressure, or
|
|
||||||
concurrent teardown behavior passed.
|
|
||||||
|
|
||||||
A feature-specific test is still required to close the fixed `insmntque()`
|
|
||||||
issue's runtime-validation status: the dedicated normal/forced mount-unmount
|
|
||||||
race with uncached vnode creation and kernel diagnostics described above. It
|
|
||||||
is desirable and required for issue closure, but it was not run because the
|
|
||||||
instruction for Pre10 was smoke testing only and explicitly excluded feature
|
|
||||||
testing.
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# Pre11 Baseline
|
|
||||||
|
|
||||||
Pre11 was created as an exact snapshot copy of `repo-pre-10` before any
|
|
||||||
Pre11 planning or implementation changes.
|
|
||||||
|
|
||||||
## Source identity
|
|
||||||
|
|
||||||
- Repository source commit: `c191517f3799291852f8673e90b0f1be8427d3a9`
|
|
||||||
- `repo-pre-10` tree: `53d5c5fadc2d1fabf83346eadadec44c97c85c10`
|
|
||||||
- `repo-pre-10/src` tree: `ec684d8dbd7662070234da1fe947aba48a293db8`
|
|
||||||
|
|
||||||
## Destination identity before this document
|
|
||||||
|
|
||||||
- `repo-pre-11` tree: `53d5c5fadc2d1fabf83346eadadec44c97c85c10`
|
|
||||||
- `repo-pre-11/src` tree: `ec684d8dbd7662070234da1fe947aba48a293db8`
|
|
||||||
|
|
||||||
## Exact copy verification
|
|
||||||
|
|
||||||
Before this baseline document was added, `repo-pre-10` and `repo-pre-11`
|
|
||||||
were verified identical by:
|
|
||||||
|
|
||||||
- recursive byte-for-byte content comparison;
|
|
||||||
- complete file and directory manifest comparison;
|
|
||||||
- file type, mode, and symbolic-link target comparison;
|
|
||||||
- identical complete subtree tree IDs;
|
|
||||||
- identical `src` subtree tree IDs.
|
|
||||||
|
|
||||||
The snapshot contains the same 307 tracked files as `repo-pre-10`. No nested
|
|
||||||
Git repository, external untracked file, generated image, temporary artifact,
|
|
||||||
or file larger than 10 MiB was introduced by the copy.
|
|
||||||
|
|
||||||
## Pre11 state
|
|
||||||
|
|
||||||
No implementation, build, configuration, or behavior change has occurred.
|
|
||||||
This file only records the Pre11 snapshot baseline.
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# Pre11 Batch A
|
|
||||||
|
|
||||||
This batch performs two mechanical vocabulary alignments:
|
|
||||||
|
|
||||||
- `struct erofs_mount.block_bits` is renamed to `blkszbits`.
|
|
||||||
- `erofs_fill_map_dev()` is renamed to `erofs_fill_from_devinfo()`.
|
|
||||||
|
|
||||||
No types, expressions, control flow, ownership rules, error handling, or runtime behavior were changed. Semantic type alias changes were deferred because they were not needed for this pure mechanical batch.
|
|
||||||
|
|
||||||
Validation is limited to identifier occurrence checks, diff inspection, and `git diff --check`. Build and runtime testing are deferred to the later Pre11 validation stage.
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
# Pre11 Batch B: Vnode Operation Scaffolding
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This batch is a behavior-preserving cleanup limited to vnode operation
|
|
||||||
scaffolding:
|
|
||||||
|
|
||||||
- removed the unused `EROFS_MOUNT_XATTR_USER` option bit;
|
|
||||||
- removed the zero-consumer `erofs_node.vnode` field and its only assignment;
|
|
||||||
- grouped VOP forward declarations and `erofs_vnodeops` initializers by
|
|
||||||
responsibility.
|
|
||||||
|
|
||||||
No function definitions, VOP registrations, lock or reclaim behavior,
|
|
||||||
`vnode_create_vobject()` error handling, or FIFO operations were changed.
|
|
||||||
|
|
||||||
## Consumer Audit
|
|
||||||
|
|
||||||
Before the edit, `EROFS_MOUNT_XATTR_USER` appeared only at its definition.
|
|
||||||
The `erofs_node.vnode` member appeared only in the structure definition and in
|
|
||||||
the single assignment performed by `erofs_vget()`; it had no read, address, ABI,
|
|
||||||
initializer, or offset consumer.
|
|
||||||
|
|
||||||
After the edit, both removed symbols have zero source-tree matches.
|
|
||||||
|
|
||||||
## VOP Vector Equivalence
|
|
||||||
|
|
||||||
Before reordering:
|
|
||||||
|
|
||||||
- `erofs_vnodeops`: 24 raw entries, 24 unique normalized `field=value` entries;
|
|
||||||
- `erofs_fifoops`: 14 raw entries, 14 unique normalized `field=value` entries.
|
|
||||||
|
|
||||||
After reordering:
|
|
||||||
|
|
||||||
- `erofs_vnodeops`: 24 raw entries, 24 unique entries, with the sorted
|
|
||||||
normalized set identical to the before snapshot;
|
|
||||||
- `erofs_fifoops`: 14 raw entries, 14 unique entries, with both the sorted set
|
|
||||||
and original entry sequence identical to the before snapshot.
|
|
||||||
|
|
||||||
## Validation
|
|
||||||
|
|
||||||
The batch uses static checks only:
|
|
||||||
|
|
||||||
- normalized before/after VOP vector set comparison;
|
|
||||||
- raw entry count versus unique entry count;
|
|
||||||
- removed-symbol zero-consumer search;
|
|
||||||
- changed-path whitelist;
|
|
||||||
- `git diff --check` and conflict-marker scan.
|
|
||||||
|
|
||||||
No build, QEMU smoke test, or feature test was run for this mechanical batch.
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
# Pre11 Batch C: ACL Parsing Responsibilities
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This batch mechanically separates POSIX ACL wire-format parsing from the
|
|
||||||
FreeBSD vnode and xattr acquisition path.
|
|
||||||
|
|
||||||
Modified files:
|
|
||||||
|
|
||||||
- `src/xattr.c`
|
|
||||||
- `docs/pre11-batch-c.md`
|
|
||||||
|
|
||||||
No xattr body loading, header-only xattr behavior, namespace handling, public
|
|
||||||
VOP interface, build configuration, or test infrastructure was changed.
|
|
||||||
|
|
||||||
## Responsibility Split
|
|
||||||
|
|
||||||
`erofs_get_acl()` continues to own:
|
|
||||||
|
|
||||||
- mount option and ACL type validation;
|
|
||||||
- the default-ACL directory restriction;
|
|
||||||
- no-ACL filter handling and mode fallback;
|
|
||||||
- xattr namespace and name selection;
|
|
||||||
- both `erofs_getxattr()` stages;
|
|
||||||
- FreeBSD `uio` and `iovec` setup;
|
|
||||||
- `ENOATTR` fallback and the stack input buffer.
|
|
||||||
|
|
||||||
The new `erofs_posix_acl_from_xattr()` receives an already-read buffer and
|
|
||||||
owns only wire-format validation and ACL population. It borrows both the input
|
|
||||||
buffer and output ACL and performs no allocation, release, lookup, or vnode
|
|
||||||
operation.
|
|
||||||
|
|
||||||
`erofs_acl_from_mode()` now receives the inode mode directly. This preserves
|
|
||||||
the original fallback writes while preventing the parser from depending on an
|
|
||||||
`erofs_node`.
|
|
||||||
|
|
||||||
## Moved-Code Mapping
|
|
||||||
|
|
||||||
The parsing block formerly at the end of `erofs_get_acl()` was moved in the
|
|
||||||
same statement order into `erofs_posix_acl_from_xattr()`:
|
|
||||||
|
|
||||||
1. Header length and entry-size remainder validation.
|
|
||||||
2. Header copy and version validation.
|
|
||||||
3. Entry count calculation and maximum check.
|
|
||||||
4. Zero-entry mode fallback.
|
|
||||||
5. `acl_cnt` assignment and phase initialization.
|
|
||||||
6. Permission validation before tag-phase validation.
|
|
||||||
7. Tag phase transitions and `UINT32_MAX` rules.
|
|
||||||
8. Duplicate named user and group ID checks.
|
|
||||||
9. ACL entry writes and undefined-ID mapping.
|
|
||||||
10. The short-circuit `phase != 6 || acl_posix1e_check(aclp) != 0` check.
|
|
||||||
|
|
||||||
No ACL zeroing or additional field initialization was added. Partial ACL
|
|
||||||
mutation on malformed input remains possible exactly as before.
|
|
||||||
|
|
||||||
## Branch Matrix
|
|
||||||
|
|
||||||
| Input or state | Preserved result |
|
|
||||||
| --- | --- |
|
|
||||||
| POSIX ACL mount option disabled | `EOPNOTSUPP` in caller |
|
|
||||||
| Unsupported ACL type | `EINVAL` in caller |
|
|
||||||
| Default ACL requested for non-directory | `EINVAL` in caller |
|
|
||||||
| No-ACL filter match | Mode-derived ACL in caller |
|
|
||||||
| ACL xattr absent | Mode-derived ACL in caller |
|
|
||||||
| Xattr lookup/read failure | Original error from caller |
|
|
||||||
| Oversized xattr or nonzero UIO residual | `EINTEGRITY` in caller |
|
|
||||||
| Short or misaligned wire value | `EINTEGRITY` in parser |
|
|
||||||
| Unsupported wire version | `EINTEGRITY` in parser |
|
|
||||||
| Entry count above limit | `EINTEGRITY` in parser |
|
|
||||||
| Zero entries | Mode-derived ACL in parser |
|
|
||||||
| Invalid permission, phase, tag, or ID | `EINTEGRITY` in parser |
|
|
||||||
| Duplicate named user/group ID | `EINTEGRITY` in parser |
|
|
||||||
| Missing required mask or incomplete phase | `EINTEGRITY` in parser |
|
|
||||||
| Valid ACL | Identical ACL entry population and success |
|
|
||||||
|
|
||||||
## Resource And Error Audit
|
|
||||||
|
|
||||||
- The input buffer remains stack-owned by `erofs_get_acl()`.
|
|
||||||
- The parser does not allocate, free, or retain pointers.
|
|
||||||
- There are no new cleanup paths.
|
|
||||||
- Xattr errors, UIO residual errors, wire errors, and ACL validation errors
|
|
||||||
retain their previous ordering.
|
|
||||||
- `erofs_xattr_load_body()` and its release paths were not modified.
|
|
||||||
- The optional header validation helper was intentionally omitted to avoid
|
|
||||||
touching the known header-only behavior.
|
|
||||||
|
|
||||||
## Static Verification
|
|
||||||
|
|
||||||
The batch is validated with:
|
|
||||||
|
|
||||||
- a strict two-file path whitelist;
|
|
||||||
- unique definitions of `erofs_get_acl()`, `erofs_acl_from_mode()`, and
|
|
||||||
`erofs_posix_acl_from_xattr()`;
|
|
||||||
- pre/post comparison of parser returns, phase transitions, ACL writes, and
|
|
||||||
duplicate-ID checks;
|
|
||||||
- `git diff --check`;
|
|
||||||
- confirmation that `erofs_xattr_load_body()` is absent from the source diff.
|
|
||||||
|
|
||||||
No build, QEMU smoke test, or feature test was run for this mechanical split.
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Pre11 Batch D
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
- Rename `src/lz4.c` to `src/decompressor_lz4.c`.
|
|
||||||
- Update the source list and current architecture references to the new filename.
|
|
||||||
|
|
||||||
## Equivalence
|
|
||||||
|
|
||||||
- The pre-rename `lz4.c` blob and renamed `decompressor_lz4.c` blob are identical.
|
|
||||||
- Byte comparison confirms the renamed source content is unchanged.
|
|
||||||
- Rename detection reports a 100% rename.
|
|
||||||
- LZ4 definitions, declarations, descriptor references, and `lz4_finish` call counts are unchanged.
|
|
||||||
|
|
||||||
## Behavior and Testing
|
|
||||||
|
|
||||||
- This batch changes filenames and documentation only; it makes no behavior changes.
|
|
||||||
- No build, QEMU run, feature test, or other test was run.
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
# Pre11 Batch E: Mount Device Argument Cleanup
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This batch consolidates caller-owned `device.N` argument cleanup in
|
|
||||||
`erofs_mount()` and removes two impossible allocation checks. It does not
|
|
||||||
change mount option semantics, GEOM ownership, device slot validation, mount
|
|
||||||
error text, or any filesystem behavior.
|
|
||||||
|
|
||||||
Modified files:
|
|
||||||
|
|
||||||
- `src/super.c`
|
|
||||||
- `docs/pre11-batch-e.md`
|
|
||||||
|
|
||||||
## Changes
|
|
||||||
|
|
||||||
After `erofs_parse_device_options()` succeeds, every exit from
|
|
||||||
`erofs_mount()` now reaches one `out_args` label. Parse failure still returns
|
|
||||||
directly because no caller-owned argument array has been transferred.
|
|
||||||
|
|
||||||
The operation order remains:
|
|
||||||
|
|
||||||
1. `erofs_parse_device_options()`
|
|
||||||
2. `vfs_filteropt()`
|
|
||||||
3. `vfs_getopt()`
|
|
||||||
4. `erofs_open_device()`
|
|
||||||
5. `erofs_update_iosize_max()`
|
|
||||||
6. `erofs_mountfs()`
|
|
||||||
7. `erofs_free_device_args()`
|
|
||||||
8. `vfs_mountedfrom()`
|
|
||||||
9. `erofs_statfs()`
|
|
||||||
|
|
||||||
`out_args` only frees copied device arguments. It does not inspect or release
|
|
||||||
`primary`. The existing `erofs_mountfs()` ownership transfer and all GEOM
|
|
||||||
cleanup paths remain unchanged.
|
|
||||||
|
|
||||||
The checks for `NULL` immediately following allocation of `packed_inode` and
|
|
||||||
`metabox_en` were removed. Both allocations retain `M_WAITOK | M_ZERO`, so a
|
|
||||||
successful return cannot produce `NULL`. No other allocation checks or flags
|
|
||||||
were changed.
|
|
||||||
|
|
||||||
## Ownership Paths
|
|
||||||
|
|
||||||
| Path | Copied arguments | Primary device | Result |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| Parse failure | No caller ownership | Not opened | Return parser error directly |
|
|
||||||
| Option filter failure | Freed at `out_args` | Not opened | Return `EINVAL` |
|
|
||||||
| Invalid or missing `from` | Freed at `out_args` | Not opened | Return `EINVAL` |
|
|
||||||
| Primary open failure | Freed at `out_args` | Open helper retains its existing cleanup contract | Return open error |
|
|
||||||
| Mount setup failure | Freed at `out_args` | Ownership already transferred at `erofs_mountfs()` entry | Return mount error |
|
|
||||||
| Success | Freed at `out_args` | Owned by the mounted filesystem | Publish mounted-from and run `statfs()` |
|
|
||||||
|
|
||||||
## Static Verification
|
|
||||||
|
|
||||||
- `erofs_free_device_args()` has one caller after the change.
|
|
||||||
- `erofs_mountfs()` and `erofs_sb_free()` are unchanged.
|
|
||||||
- The relative order of option filtering, option access, primary open, I/O
|
|
||||||
sizing, mount setup, argument cleanup, mounted-from publication, and statfs
|
|
||||||
is unchanged.
|
|
||||||
- Existing errno values and mount error strings are unchanged.
|
|
||||||
- Duplicate and missing external-device slot behavior is unchanged.
|
|
||||||
- `git diff --check` passes.
|
|
||||||
- The diff is restricted to the two declared Batch E files.
|
|
||||||
|
|
||||||
## Validation Status
|
|
||||||
|
|
||||||
No build, QEMU smoke test, or feature test was run for this batch. Runtime
|
|
||||||
validation is deferred to the final Pre11 build and targeted smoke test.
|
|
||||||
@@ -1,480 +0,0 @@
|
|||||||
# Pre11 Completion and Smoke Report
|
|
||||||
|
|
||||||
## Status
|
|
||||||
|
|
||||||
Pre11 is complete for its approved mechanical maintenance scope.
|
|
||||||
|
|
||||||
- Final implementation commit tested: `040fc69025c5031436205c3acd421be1d95fe86b`
|
|
||||||
- Final `repo-pre-11` tree: `f0cca92670c76ab13cc5b9353d5aeb993effa6e2`
|
|
||||||
- Final `repo-pre-11/src` tree: `c4aac4d69cb25a4b049239d0c1f422dcb89465d6`
|
|
||||||
- Static review: `ACCEPT`, with no P0-P3 findings in the included changes
|
|
||||||
- FreeBSD KLD build: `PASS`, using `WITH_ZSTDIO=0`
|
|
||||||
- Targeted plain/LZ4/LZMA QEMU smoke: `PASS`
|
|
||||||
- Full feature test and `test_all.py`: `NOT RUN`
|
|
||||||
|
|
||||||
This report does not claim full feature validation. Pre11 deliberately contains
|
|
||||||
mechanical naming, responsibility, dead-scaffolding, file-layout, and cleanup
|
|
||||||
changes that could be reviewed for behavioral equivalence and then covered by a
|
|
||||||
focused build and smoke run. Behavior changes requiring purpose-built fixtures
|
|
||||||
remain deferred.
|
|
||||||
|
|
||||||
## Snapshot and Planning
|
|
||||||
|
|
||||||
Pre11 was created from the completed Pre10 tree in:
|
|
||||||
|
|
||||||
```text
|
|
||||||
0483dcb41c2a980badb829ff4d17361bd1fec930
|
|
||||||
snapshot: create repo-pre-11 from repo-pre-10
|
|
||||||
```
|
|
||||||
|
|
||||||
At the snapshot boundary, `repo-pre-10/src` and `repo-pre-11/src` were both:
|
|
||||||
|
|
||||||
```text
|
|
||||||
ec684d8dbd7662070234da1fe947aba48a293db8
|
|
||||||
```
|
|
||||||
|
|
||||||
The executable Pre11 plan was added in:
|
|
||||||
|
|
||||||
```text
|
|
||||||
9ad1fa0cf8ba251b574da033bf0c9fad83acaa38
|
|
||||||
docs: add pre11 execution plan
|
|
||||||
```
|
|
||||||
|
|
||||||
The original plan included several candidates that would have changed visible
|
|
||||||
filesystem behavior. An independent boundary review narrowed the release in:
|
|
||||||
|
|
||||||
```text
|
|
||||||
c89c228ac1817cfd0337905b39247245eaa67f3b
|
|
||||||
docs: narrow pre11 execution boundaries
|
|
||||||
```
|
|
||||||
|
|
||||||
The narrowed scope retained only work that could preserve control flow, errno,
|
|
||||||
on-disk interpretation, vnode and GEOM ownership, iterator order, decompressor
|
|
||||||
semantics, and cache lifetime. The following candidates were removed from
|
|
||||||
implementation because honest validation would require targeted feature tests:
|
|
||||||
|
|
||||||
- root vnode type rejection;
|
|
||||||
- zero-length mapping behavior in the UIO reader;
|
|
||||||
- header-only xattr semantics;
|
|
||||||
- duplicate or missing `device.N` behavior;
|
|
||||||
- direct propagation of `vnode_create_vobject()` errors;
|
|
||||||
- broad map, inode, directory, and name-lookup interface reshaping.
|
|
||||||
|
|
||||||
This narrowing allowed Pre11 to remain a comparatively large maintenance
|
|
||||||
release without mixing low-risk structural alignment with unvalidated semantic
|
|
||||||
changes.
|
|
||||||
|
|
||||||
## Batch A: Type and Vocabulary Alignment
|
|
||||||
|
|
||||||
Commit:
|
|
||||||
|
|
||||||
```text
|
|
||||||
b4e38c9fb15df127470d70bc144404f1f3afa2af
|
|
||||||
pre11: align mount and device helper vocabulary
|
|
||||||
```
|
|
||||||
|
|
||||||
Exact changes:
|
|
||||||
|
|
||||||
- renamed `struct erofs_mount.block_bits` to `blkszbits` across its consumers;
|
|
||||||
- renamed the private `erofs_fill_map_dev()` helper to
|
|
||||||
`erofs_fill_from_devinfo()`;
|
|
||||||
- added the Batch A implementation report.
|
|
||||||
|
|
||||||
Linux-maintenance benefit:
|
|
||||||
|
|
||||||
- `blkszbits` matches established EROFS vocabulary and makes comparisons with
|
|
||||||
Linux mount geometry code more direct;
|
|
||||||
- `erofs_fill_from_devinfo()` describes the same responsibility as the Linux
|
|
||||||
helper without importing Linux block-device objects into FreeBSD.
|
|
||||||
|
|
||||||
BSD invariants retained:
|
|
||||||
|
|
||||||
- field type, width, units, expressions, overflow handling, and structure
|
|
||||||
layout were unchanged;
|
|
||||||
- the helper remained a private FreeBSD device-map field filler;
|
|
||||||
- GEOM provider selection, range checks, flat-device behavior, errno, and
|
|
||||||
physical I/O remained unchanged;
|
|
||||||
- no broad or search-driven integer type replacement was performed.
|
|
||||||
|
|
||||||
Static checks confirmed 48 intended `block_bits` replacements, zero remaining
|
|
||||||
old identifiers, four helper-name replacements, zero stale helper references,
|
|
||||||
and a source diff containing only the approved identifier changes.
|
|
||||||
|
|
||||||
## Batch B: Vnode Operation Scaffolding
|
|
||||||
|
|
||||||
Commit:
|
|
||||||
|
|
||||||
```text
|
|
||||||
67625d3afebb9142e69b19afd08cdfc1d2adaac5
|
|
||||||
refactor: clean up vnode operation scaffolding
|
|
||||||
```
|
|
||||||
|
|
||||||
Exact changes:
|
|
||||||
|
|
||||||
- removed the unused `EROFS_MOUNT_XATTR_USER` option bit;
|
|
||||||
- removed the zero-consumer `erofs_node.vnode` member and its only assignment;
|
|
||||||
- grouped VOP declarations and `erofs_vnodeops` initializers by responsibility;
|
|
||||||
- added the Batch B implementation report.
|
|
||||||
|
|
||||||
Linux-maintenance benefit:
|
|
||||||
|
|
||||||
- removes misleading compatibility-shaped state that had no consumer;
|
|
||||||
- presents vnode operations in a responsibility-oriented order that is easier
|
|
||||||
to compare with upstream filesystem responsibilities while retaining the
|
|
||||||
native FreeBSD operation table.
|
|
||||||
|
|
||||||
BSD invariants retained:
|
|
||||||
|
|
||||||
- no VOP function definition or registration changed;
|
|
||||||
- `erofs_vnodeops` retained 24 unique `field=value` entries;
|
|
||||||
- `erofs_fifoops` retained 14 unique entries and its original sequence;
|
|
||||||
- `fifo_specops`, vnode locking, hash insertion, reclaim, pager behavior, and
|
|
||||||
`vnode_create_vobject()` errno translation were unchanged.
|
|
||||||
|
|
||||||
The removed symbols had no reads, address consumers, initializer dependencies,
|
|
||||||
offset consumers, or external ABI use.
|
|
||||||
|
|
||||||
## Batch C: ACL Parsing Responsibilities
|
|
||||||
|
|
||||||
Commit:
|
|
||||||
|
|
||||||
```text
|
|
||||||
a86b5cac4d193d131de8870bca4132fdc881f992
|
|
||||||
erofs: split ACL parsing responsibilities
|
|
||||||
```
|
|
||||||
|
|
||||||
Exact changes:
|
|
||||||
|
|
||||||
- extracted private `erofs_posix_acl_from_xattr()` from `erofs_get_acl()`;
|
|
||||||
- changed the private mode fallback helper to receive the inode mode directly;
|
|
||||||
- left xattr acquisition and all FreeBSD VOP/UIO responsibilities in the
|
|
||||||
caller;
|
|
||||||
- added the Batch C implementation report.
|
|
||||||
|
|
||||||
Linux-maintenance benefit:
|
|
||||||
|
|
||||||
- separates wire-format ACL parsing from filesystem acquisition and VOP glue,
|
|
||||||
matching the upstream responsibility split more closely;
|
|
||||||
- gives maintainers a bounded parser to compare without introducing Linux ACL
|
|
||||||
objects, RCU, xattr handlers, or inode lifecycle assumptions.
|
|
||||||
|
|
||||||
BSD invariants retained:
|
|
||||||
|
|
||||||
- mount-option checks, ACL type validation, default-ACL directory checks,
|
|
||||||
namespace selection, both `erofs_getxattr()` stages, UIO setup, and `ENOATTR`
|
|
||||||
fallback remain in `erofs_get_acl()`;
|
|
||||||
- parser validation order, positive errno, tag phases, duplicate ID checks,
|
|
||||||
`UINT32_MAX` handling, partial ACL writes, and final
|
|
||||||
`acl_posix1e_check()` ordering remain unchanged;
|
|
||||||
- input storage remains caller-owned stack memory, with no new allocation or
|
|
||||||
cleanup path;
|
|
||||||
- `erofs_xattr_load_body()` and the known header-only xattr behavior were not
|
|
||||||
changed.
|
|
||||||
|
|
||||||
Static comparison confirmed equivalent branch, error, phase-transition, and
|
|
||||||
ACL-population behavior.
|
|
||||||
|
|
||||||
## Batch D: LZ4 Backend File Responsibility
|
|
||||||
|
|
||||||
Commit:
|
|
||||||
|
|
||||||
```text
|
|
||||||
e631e33a1b8c053ebcb2d737af33e363cba48b34
|
|
||||||
erofs: align LZ4 backend file responsibility
|
|
||||||
```
|
|
||||||
|
|
||||||
Exact changes:
|
|
||||||
|
|
||||||
- renamed `src/lz4.c` to `src/decompressor_lz4.c`;
|
|
||||||
- updated the Makefile source entry;
|
|
||||||
- updated current architecture documentation references;
|
|
||||||
- added the Batch D implementation report.
|
|
||||||
|
|
||||||
Linux-maintenance benefit:
|
|
||||||
|
|
||||||
- makes the filename communicate that the translation unit is the LZ4 codec
|
|
||||||
backend beside `decompressor_lzma.c`, `decompressor_deflate.c`, and
|
|
||||||
`decompressor_zstd.c`;
|
|
||||||
- reduces unnecessary file-layout differences when maintainers inspect codec
|
|
||||||
implementations across the independent Linux and FreeBSD repositories.
|
|
||||||
|
|
||||||
BSD invariants retained:
|
|
||||||
|
|
||||||
- Git identified a 100% rename;
|
|
||||||
- the old and new source blobs are both
|
|
||||||
`2cc19f5eb0c283e12ba0a3a4334b8817a1686888`;
|
|
||||||
- function bodies, request ABI, descriptor registration, input/output bounds,
|
|
||||||
partial decode behavior, and error normalization were unchanged;
|
|
||||||
- historical reports and historical test evidence were not rewritten.
|
|
||||||
|
|
||||||
## Batch E: Mount Device Argument Cleanup
|
|
||||||
|
|
||||||
Commit:
|
|
||||||
|
|
||||||
```text
|
|
||||||
040fc69025c5031436205c3acd421be1d95fe86b
|
|
||||||
erofs: consolidate mount device argument cleanup
|
|
||||||
```
|
|
||||||
|
|
||||||
Exact changes:
|
|
||||||
|
|
||||||
- consolidated caller-owned copied `device.N` argument release into one
|
|
||||||
`out_args` exit in `erofs_mount()`;
|
|
||||||
- removed two impossible NULL checks immediately following
|
|
||||||
`M_WAITOK | M_ZERO` allocations;
|
|
||||||
- added the Batch E implementation report.
|
|
||||||
|
|
||||||
Linux-maintenance benefit:
|
|
||||||
|
|
||||||
- makes mount setup ownership and cleanup easier to audit by reducing repeated
|
|
||||||
release sites;
|
|
||||||
- removes defensive branches that contradict the FreeBSD `M_WAITOK` contract,
|
|
||||||
keeping BSD-specific allocation behavior explicit instead of emulating a
|
|
||||||
nullable Linux allocation path.
|
|
||||||
|
|
||||||
BSD invariants retained:
|
|
||||||
|
|
||||||
- operation order remains parse, filter, get option, open primary, update I/O
|
|
||||||
size, mount setup, free copied arguments, publish mounted-from, and statfs;
|
|
||||||
- parse failure still returns before caller ownership exists;
|
|
||||||
- `out_args` releases only copied arguments and never releases `primary`;
|
|
||||||
- `erofs_mountfs()` still takes ownership of `primary` at entry;
|
|
||||||
- `erofs_mountfs()`, `erofs_sb_free()`, reverse external-device cleanup, errno,
|
|
||||||
and mount error text are unchanged;
|
|
||||||
- duplicate and missing external-device slot behavior remains deferred.
|
|
||||||
|
|
||||||
## Static Review
|
|
||||||
|
|
||||||
Independent reviews were performed after the individual batches and again over
|
|
||||||
the complete source range from `0483dcb` through `040fc690`.
|
|
||||||
|
|
||||||
The final review found no P0-P3 issue in the included Pre11 source changes and
|
|
||||||
accepted all five batches. It confirmed:
|
|
||||||
|
|
||||||
- the source changes were confined to the approved Batch A-E paths;
|
|
||||||
- no deferred behavior fix entered the source;
|
|
||||||
- old identifiers had no stale consumers and new private helpers had unique
|
|
||||||
definitions and expected call counts;
|
|
||||||
- both VOP vectors retained the same registration mappings;
|
|
||||||
- ACL acquisition, parsing, fallback, errno, and partial-write behavior were
|
|
||||||
preserved;
|
|
||||||
- the LZ4 backend was a byte-identical rename and the Makefile contained the
|
|
||||||
new filename once;
|
|
||||||
- mount cleanup retained error order and GEOM ownership;
|
|
||||||
- uncompressed mapping interfaces, directory/name lookup, decompressor request
|
|
||||||
ABI, LZMA cache policy, disk structures, and Linux reference sources were not
|
|
||||||
changed;
|
|
||||||
- `git diff --check` passed and the implementation worktree was clean before
|
|
||||||
runtime validation.
|
|
||||||
|
|
||||||
The final source delta from the snapshot contains 202 insertions and 188
|
|
||||||
deletions across ten source paths, including the 100% LZ4 file rename. Much of
|
|
||||||
that textual delta is identifier replacement, declaration/vector reordering,
|
|
||||||
or moved ACL parser code rather than new behavior.
|
|
||||||
|
|
||||||
## First Smoke Attempt: Infrastructure Failure
|
|
||||||
|
|
||||||
Evidence directory:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/work/tests-dev/temp/pre11-smoke-final-20260813T122923Z
|
|
||||||
```
|
|
||||||
|
|
||||||
Result: `FAIL`, specifically an infrastructure failure before DUT transfer or
|
|
||||||
execution.
|
|
||||||
|
|
||||||
The guest reached FreeBSD and two SSH identity probes succeeded, but the first
|
|
||||||
runner opened an SSH ControlMaster using a detached invocation. The open command
|
|
||||||
returned success and created the control socket, then the master terminated or
|
|
||||||
lost its connection before the immediate health check. The check failed with:
|
|
||||||
|
|
||||||
```text
|
|
||||||
Control socket connect(.../control.sock): Connection refused
|
|
||||||
```
|
|
||||||
|
|
||||||
The test stopped before source transfer, KLD build, module load, or any EROFS
|
|
||||||
mount. Therefore this attempt is not a PASS, but it is also not evidence of a
|
|
||||||
Pre11 build or driver failure. Its source archive SHA was:
|
|
||||||
|
|
||||||
```text
|
|
||||||
5bbffb101364f350fe1a3771b6f018bc10a68785d8c55cc2a186273a074e9182
|
|
||||||
```
|
|
||||||
|
|
||||||
The owned QEMU stopped, port `10043` was released, its overlay was removed, the
|
|
||||||
base image remained unchanged, and the retained guard VM remained reachable.
|
|
||||||
The run's cleanup status was nonzero only because closing the already-dead
|
|
||||||
ControlMaster returned an error.
|
|
||||||
|
|
||||||
## Corrected Smoke Retry
|
|
||||||
|
|
||||||
Evidence directory:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/work/tests-dev/temp/pre11-smoke-retry-final-20260813T124214Z
|
|
||||||
```
|
|
||||||
|
|
||||||
Result: `PASS`.
|
|
||||||
|
|
||||||
The retry used an SSH master process in normal foreground mode but launched it
|
|
||||||
in the runner shell background, without `ssh -f`. The runner captured the real
|
|
||||||
master PID, repeatedly required both `kill -0` and `ssh -O check` to succeed,
|
|
||||||
and refused to transfer sources unless the master remained alive. Long build
|
|
||||||
work ran inside the guest with a completion sentinel, so one long SSH command
|
|
||||||
was not treated as the build lifetime.
|
|
||||||
|
|
||||||
Tested identities:
|
|
||||||
|
|
||||||
```text
|
|
||||||
commit: 040fc69025c5031436205c3acd421be1d95fe86b
|
|
||||||
repo-pre-11 tree: f0cca92670c76ab13cc5b9353d5aeb993effa6e2
|
|
||||||
src tree: c4aac4d69cb25a4b049239d0c1f422dcb89465d6
|
|
||||||
source archive: 179b80365c26295770afab58f1209ae3fffd73182ada0bcf97ea027904f781e9
|
|
||||||
guest: FreeBSD 15.0-RELEASE-p8
|
|
||||||
```
|
|
||||||
|
|
||||||
The archive hashes differ between attempts because separately generated gzip
|
|
||||||
archives are not required to be byte-reproducible. Both identity files name the
|
|
||||||
same committed repository and source trees; only the passing retry is used as
|
|
||||||
runtime evidence.
|
|
||||||
|
|
||||||
## Build and Module Lifecycle
|
|
||||||
|
|
||||||
The committed `repo-pre-11` archive was transferred to the disposable guest,
|
|
||||||
validated there, extracted, and built with:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
make WITH_ZSTDIO=0
|
|
||||||
```
|
|
||||||
|
|
||||||
Results:
|
|
||||||
|
|
||||||
- guest build return code: `0`;
|
|
||||||
- `erofs.ko` SHA256:
|
|
||||||
`77ce41bff5cb7d7c934dd9dba20ba06c20b660ad15ebfc4210f86f6473dffbf7`;
|
|
||||||
- `kldload /root/pre11-smoke/erofs.ko`: success;
|
|
||||||
- `kldstat -n erofs`: success, reporting `erofs.ko` loaded;
|
|
||||||
- all smoke mounts and md providers were released;
|
|
||||||
- `kldunload erofs`: success;
|
|
||||||
- the post-unload `kldstat -n erofs` check confirmed the module was absent.
|
|
||||||
|
|
||||||
`WITH_ZSTDIO=1` was not built and is not claimed as tested.
|
|
||||||
|
|
||||||
## Smoke Cases
|
|
||||||
|
|
||||||
Each case used an independently attached vnode-backed md provider, required a
|
|
||||||
successful EROFS mount to be visible in `mount -p`, computed the complete target
|
|
||||||
file hash, then unmounted and detached the provider before the next case.
|
|
||||||
|
|
||||||
| Case | Target SHA256 | Elapsed | Provider | Result |
|
|
||||||
| --- | --- | ---: | --- | --- |
|
|
||||||
| Plain | `056f8f7585667dc695e2edf936deaf84cfee0f88671ba6cd5be22ce890763433` | 0 s | `md70` | PASS |
|
|
||||||
| LZ4 | `3ff012b76087c4da65ce0b69813a76f47ea367e95782edf8b8cd6cd3ec4d1880` | 5 s | `md71` | PASS |
|
|
||||||
| LZMA | `ddda39737f0f6093e828a032ec161511fefbb1fa361bc6cbffdbc91e48e4c461` | 2 s | `md72` | PASS |
|
|
||||||
|
|
||||||
The LZMA case hashed the complete file. No timeout, mount failure, hash mismatch,
|
|
||||||
unmount failure, or md detach failure occurred.
|
|
||||||
|
|
||||||
## Kernel Messages and Cleanup
|
|
||||||
|
|
||||||
The runner captured `dmesg` before loading the module and after all smoke cases.
|
|
||||||
The delta contained no EROFS error, decompression failure, panic, or assertion;
|
|
||||||
the suspect-output file is empty.
|
|
||||||
|
|
||||||
Cleanup evidence records:
|
|
||||||
|
|
||||||
```text
|
|
||||||
qemu_stopped=1
|
|
||||||
port_released=1
|
|
||||||
overlay_removed=1
|
|
||||||
base_mode_after=444
|
|
||||||
base_sha_after=67f359621f23a1d745f0889370cbb99a096cee3e99a0b2f3bb18fc7a91bf6fef
|
|
||||||
guard_unchanged_and_reachable=1
|
|
||||||
body_rc=0
|
|
||||||
cleanup_rc=0
|
|
||||||
```
|
|
||||||
|
|
||||||
The test owned only port `10044`, its QEMU PID, its ControlMaster PID, and its
|
|
||||||
overlay. All were closed or removed. The permanent base image was never booted
|
|
||||||
directly and retained mode `0444` and its original SHA256. The retained guard VM
|
|
||||||
PID `26318` kept start time `1102996924`, an identical command line, and a
|
|
||||||
reachable forwarded SSH port at `9222`.
|
|
||||||
|
|
||||||
## Feature-Test Decision
|
|
||||||
|
|
||||||
No feature test and no `test_all.py` run was performed.
|
|
||||||
|
|
||||||
That decision is appropriate for the included Pre11 scope because:
|
|
||||||
|
|
||||||
- Batch A changed only private identifiers;
|
|
||||||
- Batch B removed proven dead state and reordered designated VOP initializers
|
|
||||||
without changing their mappings;
|
|
||||||
- Batch C mechanically moved parser statements while retaining inputs, outputs,
|
|
||||||
writes, error order, and ownership;
|
|
||||||
- Batch D was a byte-identical file rename;
|
|
||||||
- Batch E consolidated one caller-owned cleanup action and removed checks that
|
|
||||||
cannot be reached after `M_WAITOK` allocation.
|
|
||||||
|
|
||||||
Static equivalence review plus the FreeBSD build and plain/LZ4/LZMA smoke is
|
|
||||||
sufficient evidence for these changes. It is not sufficient for the deferred
|
|
||||||
behavior changes below, and this report does not claim otherwise.
|
|
||||||
|
|
||||||
## Deferred Behavior and Required Targeted Tests
|
|
||||||
|
|
||||||
### Non-directory root
|
|
||||||
|
|
||||||
The current root path does not add a new rejection for a root NID that resolves
|
|
||||||
to a non-directory vnode. A future fix requires a purpose-built image and checks
|
|
||||||
for mount errno, vnode release, mount error text, and complete cleanup.
|
|
||||||
|
|
||||||
### Zero-length internal run
|
|
||||||
|
|
||||||
The uncompressed UIO reader's existing `run_len == 0` behavior was not changed.
|
|
||||||
A future fix requires a corrupt mapping fixture that reaches a zero-length run
|
|
||||||
while the request remains inside the file, with exact comparison to the
|
|
||||||
contiguous-buffer path and expected `EINTEGRITY`.
|
|
||||||
|
|
||||||
### Header-only xattr
|
|
||||||
|
|
||||||
The existing behavior for an ibody containing only the xattr header was not
|
|
||||||
changed. Targeted coverage must distinguish zero and nonzero shared counts,
|
|
||||||
name filters, get/list results, ACL mode fallback, and corruption results.
|
|
||||||
|
|
||||||
### Duplicate or missing device slots
|
|
||||||
|
|
||||||
`device.N` slot parsing behavior and diagnostics were not changed. Future tests
|
|
||||||
must cover duplicate, out-of-order, missing, excessive, and malformed slots,
|
|
||||||
flat and non-flat device tables, exact errno and mount error text, and GEOM
|
|
||||||
cleanup.
|
|
||||||
|
|
||||||
### `insmntque()` race closure
|
|
||||||
|
|
||||||
The earlier ownership fix remains accepted by static lifecycle review but is
|
|
||||||
not runtime-closed by ordinary smoke. A dedicated mount/unmount or forced
|
|
||||||
unmount race must stress vnode creation and inspect panic, use-after-free, lock,
|
|
||||||
reference, and cleanup behavior.
|
|
||||||
|
|
||||||
### Explicit mapped extent fixtures
|
|
||||||
|
|
||||||
Positive payload fixtures are still unavailable for explicit mapped extent
|
|
||||||
records of 4, 8, 16, and 32 bytes. No restructuring or coverage claim should be
|
|
||||||
made until validated mappings and file hashes exist.
|
|
||||||
|
|
||||||
### `vnode_create_vobject()` errno
|
|
||||||
|
|
||||||
Pre11 intentionally retains the current conversion of a nonzero
|
|
||||||
`vnode_create_vobject()` result to `ENOMEM`. Direct propagation is a visible
|
|
||||||
behavior change and requires controlled pager failure or fault injection that
|
|
||||||
verifies the caller-visible errno and vnode state.
|
|
||||||
|
|
||||||
## Final Conclusion
|
|
||||||
|
|
||||||
Pre11 completed all five narrowed maintenance batches, passed independent
|
|
||||||
static review, built successfully as a FreeBSD KLD, and passed the required
|
|
||||||
plain, LZ4, and full-file LZMA smoke. The first smoke attempt was correctly
|
|
||||||
classified as an infrastructure failure before DUT transfer or build; the
|
|
||||||
corrected retry provides the runtime evidence.
|
|
||||||
|
|
||||||
Pre11 improves cross-repository maintainability without replacing native
|
|
||||||
FreeBSD vnode, GEOM, UIO, pager, ACL, or synchronous decompression contracts.
|
|
||||||
Full feature validation remains outside this release and must not be inferred
|
|
||||||
from the targeted smoke result.
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Pre12 Baseline
|
|
||||||
|
|
||||||
`repo-pre-12` was created as an exact snapshot copy of `repo-pre-11` before this document was added.
|
|
||||||
|
|
||||||
- Source commit: `88fc67742e6c173e14538d4fcd556a45a385c2c9`
|
|
||||||
- Source tree (`repo-pre-11`): `5b8c637bcb535f330d894f30660bb5e65db70048`
|
|
||||||
- Copied tree before this document (`repo-pre-12`): `5b8c637bcb535f330d894f30660bb5e65db70048`
|
|
||||||
- Source `src` tree: `c4aac4d69cb25a4b049239d0c1f422dcb89465d6`
|
|
||||||
- Copied `src` tree: `c4aac4d69cb25a4b049239d0c1f422dcb89465d6`
|
|
||||||
|
|
||||||
Copy verification used a recursive comparison that preserved and checked file modes and symbolic links. The complete tree IDs matched before this document was added. Adding this document does not modify the copied `src` tree.
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# Pre12 Batch 01
|
|
||||||
|
|
||||||
This batch aligns the planned in-memory NID, block-number, and byte-offset
|
|
||||||
declarations with the existing `erofs_nid_t`, `erofs_blk_t`, and
|
|
||||||
`erofs_off_t` aliases.
|
|
||||||
|
|
||||||
The source whitelist was limited to eight fields in `internal.h`, the
|
|
||||||
`erofs_iloc`, `erofs_nid_is_valid`, `erofs_read_inode`, and `erofs_vfs_hash`
|
|
||||||
declarations and definitions, and the byte-offset parameters of
|
|
||||||
`erofs_bread`, `erofs_read_physical`, and `erofs_read_metadata`.
|
|
||||||
|
|
||||||
All three aliases are direct `uint64_t` typedefs. Static assertions confirmed
|
|
||||||
that each is an unsigned, 8-byte type with the same alignment and exact C type
|
|
||||||
compatibility as `uint64_t`. Consequently every replaced field has identical
|
|
||||||
size and alignment, so both structure sizes, alignments, field order, and all
|
|
||||||
target `offsetof` values are unchanged. Function parameter and return ABI
|
|
||||||
representations are also unchanged, and the vnode hash still consumes the
|
|
||||||
same complete 8-byte NID object.
|
|
||||||
|
|
||||||
The source diff is limited to the planned fields, function declarations and
|
|
||||||
definitions, and necessary local declaration splits. No expressions, field
|
|
||||||
order, on-disk types, control flow, error handling, or formatting outside
|
|
||||||
those declarations changed.
|
|
||||||
|
|
||||||
Validation used exact declaration inventory checks, token-diff inspection,
|
|
||||||
declaration/definition signature comparison, arithmetic and hash review,
|
|
||||||
compile-time type assertions, and `git diff --check`. No planned point was
|
|
||||||
skipped and no out-of-scope candidate was changed. No build, QEMU, smoke,
|
|
||||||
feature, or other dynamic test was run.
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# Pre12 Batch 02
|
|
||||||
|
|
||||||
This batch replaces exactly three potentially unaligned typed loads with the
|
|
||||||
FreeBSD little-endian byte decoders planned for Pre12.
|
|
||||||
|
|
||||||
- `xattr.c`: `hdrbuf` contains two raw metadata bytes returned by
|
|
||||||
`erofs_xattr_read_backing(..., sizeof(raw_len), ...)`; `le16dec(hdrbuf)`
|
|
||||||
decodes the prefix-record length.
|
|
||||||
- `inode.c`: `buf` contains at least one complete 32-byte compact on-disk inode
|
|
||||||
returned by `erofs_read_metadata`; its first two bytes are the little-endian
|
|
||||||
`i_format` field decoded by `le16dec(buf)`.
|
|
||||||
- `data.c`: the non-indexes branch sets `entry_size` to
|
|
||||||
`EROFS_BLOCK_MAP_ENTRY_SIZE == sizeof(__le32) == 4`; `idx` points to those
|
|
||||||
four raw block-map bytes and `le32dec(idx)` decodes the block address.
|
|
||||||
|
|
||||||
For bytes `b0..b3`, both old expressions and the new helpers produce
|
|
||||||
`b0 | b1 << 8` or `b0 | b1 << 8 | b2 << 16 | b3 << 24`. On a little-endian
|
|
||||||
host the typed load already has that value; on a big-endian host `leXXtoh`
|
|
||||||
byte-swaps the typed value to that same formula. The helpers preserve this
|
|
||||||
result while avoiding any alignment requirement.
|
|
||||||
|
|
||||||
`xattr.c` and `data.c` receive the helpers through `internal.h` to
|
|
||||||
`erofs_fs.h` to `<sys/endian.h>`; `inode.c` also includes `<sys/endian.h>`
|
|
||||||
directly. Existing `le16dec` and `le32dec` consumers confirm the established
|
|
||||||
include convention. Error checks, branches, value ranges, and buffer release
|
|
||||||
ordering are unchanged. No point was skipped and no other endian read was
|
|
||||||
changed.
|
|
||||||
|
|
||||||
Validation used exact-expression counts, buffer-source and length inspection,
|
|
||||||
symbolic endian equivalence, source-diff inspection, and `git diff --check`.
|
|
||||||
No build, QEMU, smoke, feature, or other dynamic test was run.
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
# Pre12 Batch 03: POSIX ACL mode helper
|
|
||||||
|
|
||||||
## Change
|
|
||||||
|
|
||||||
- In `src/xattr.c`, `erofs_acl_from_mode` now obtains the owner, group, and
|
|
||||||
other permissions with `acl_posix1e_mode_to_perm`.
|
|
||||||
- The helper tags are `ACL_USER_OBJ`, `ACL_GROUP_OBJ`, and `ACL_OTHER`, matching
|
|
||||||
the adjacent `ae_tag` assignments.
|
|
||||||
- No other function lines, ACL entry ordering, `acl_cnt`, IDs, default ACL
|
|
||||||
handling, fallback behavior, flags, errno behavior, or control flow changed.
|
|
||||||
|
|
||||||
## Helper confirmation
|
|
||||||
|
|
||||||
- The local FreeBSD header `sys/sys/acl.h` declares
|
|
||||||
`acl_posix1e_mode_to_perm(acl_tag_t tag, mode_t mode)` for kernel consumers.
|
|
||||||
- The local FreeBSD implementation in `sys/kern/subr_acl_posix1e.c` maps
|
|
||||||
`ACL_USER_OBJ` from `S_IRWXU`, `ACL_GROUP_OBJ` from `S_IRWXG`, and
|
|
||||||
`ACL_OTHER` from `S_IRWXO`, returning the corresponding POSIX ACL read,
|
|
||||||
write, and execute permission bits.
|
|
||||||
- `src/xattr.c` already includes `<sys/acl.h>`; no include change was needed.
|
|
||||||
|
|
||||||
## Exhaustive equivalence
|
|
||||||
|
|
||||||
A temporary standalone C program reproduced the local FreeBSD helper logic and
|
|
||||||
compared it with the three replaced expressions for every permission mode from
|
|
||||||
`0000` through `0777`:
|
|
||||||
|
|
||||||
```text
|
|
||||||
equivalent=1536/1536 modes=512 tags=3 mismatches=0
|
|
||||||
temporary_cleanup=ok
|
|
||||||
```
|
|
||||||
|
|
||||||
This covers 512 modes for each of the three tags. The temporary source and
|
|
||||||
executable were deleted and are not part of the repository.
|
|
||||||
|
|
||||||
## Static validation
|
|
||||||
|
|
||||||
- The `erofs_acl_from_mode` function is line-for-line unchanged except for the
|
|
||||||
three `ae_perm` expressions.
|
|
||||||
- The source diff changes only those three expressions; this document is the
|
|
||||||
only added file.
|
|
||||||
- `git diff --check` and `git diff --cached --check` completed without errors.
|
|
||||||
- Before commit, both unstaged status and staged status contained only
|
|
||||||
`src/xattr.c` and `docs/pre12-batch-03.md` under `repo-pre-12`.
|
|
||||||
|
|
||||||
## Tests not run
|
|
||||||
|
|
||||||
Per the Batch 03 execution constraints, no project build, QEMU run, smoke test,
|
|
||||||
or feature test was run.
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# Pre12 Batch 04: Private compression header
|
|
||||||
|
|
||||||
## Change
|
|
||||||
|
|
||||||
- Added `src/compress.h` for the decompressor request, descriptor, and backend
|
|
||||||
private declarations previously located in `src/internal.h`.
|
|
||||||
- Added the header only to `decompressor.c` and the LZ4, LZMA, Deflate, and
|
|
||||||
ZSTD backend translation units.
|
|
||||||
- Kept the runtime compression enum, `z_erofs_parse_cfgs`, and the public
|
|
||||||
`z_erofs_decompress` declaration in `src/internal.h`.
|
|
||||||
- Preserved every migrated declaration signature and storage duration. No
|
|
||||||
function body, callback, conditional compilation block, errno path, or
|
|
||||||
buffer ownership changed.
|
|
||||||
|
|
||||||
## Static validation
|
|
||||||
|
|
||||||
- The `compress.h` consumer set is exactly the five planned decompressor
|
|
||||||
translation units; `super.c`, `zdata.c`, and all other public callers still
|
|
||||||
include only `internal.h`.
|
|
||||||
- The include graph is acyclic: `compress.h` includes `internal.h`, while
|
|
||||||
`internal.h` does not include `compress.h`.
|
|
||||||
- Exact searches found one definition of each migrated structure and one
|
|
||||||
declaration of each migrated backend function. The old declarations are
|
|
||||||
absent from `internal.h`.
|
|
||||||
- The new header contains no Linux page, folio, bio, workqueue, XArray,
|
|
||||||
shrinker, compatibility, or related runtime declarations.
|
|
||||||
- Source diff inspection and declaration normalization confirmed that this is
|
|
||||||
a declaration-only move plus the five include additions.
|
|
||||||
- `git diff --check` and `git diff --cached --check` completed without errors.
|
|
||||||
|
|
||||||
## Tests not run
|
|
||||||
|
|
||||||
Per the execution constraints, no build, QEMU run, smoke test, feature test,
|
|
||||||
or other dynamic test was run. The planned `WITH_ZSTDIO=0` and
|
|
||||||
`WITH_ZSTDIO=1` KLD builds remain required during final validation.
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# Pre12 Batch 05: ZSTD window lower bound
|
|
||||||
|
|
||||||
## Change
|
|
||||||
|
|
||||||
- Removed only the `rq->em->zstd_windowlog + 10 < 10` subcondition from
|
|
||||||
`z_erofs_zstd_decompress`.
|
|
||||||
- Preserved the `> 20` upper bound, the `outputsize == 0` check, every
|
|
||||||
`return (-1)`, all ZSTD calls, resource release, and the complete disabled
|
|
||||||
`#else` stub.
|
|
||||||
- Did not change ZSTD configuration parsing, accepted configuration range,
|
|
||||||
conditional compilation, errno behavior, or control flow after the guard.
|
|
||||||
|
|
||||||
## Static proof
|
|
||||||
|
|
||||||
- `struct erofs_mount.zstd_windowlog` is `uint8_t`, so integer promotion gives
|
|
||||||
a value in the range 0 through 255.
|
|
||||||
- Adding 10 therefore produces a minimum value of 10; comparison with `< 10`
|
|
||||||
is unreachable for every representable field value.
|
|
||||||
- `z_erofs_load_zstd_config` still rejects `windowlog > 10`, so configured
|
|
||||||
mount values and the remaining decompression upper-bound behavior are
|
|
||||||
unchanged.
|
|
||||||
- Normalized function comparison confirms that the only removed logical
|
|
||||||
tokens are the single unreachable lower-bound subcondition and its `||`.
|
|
||||||
- `git diff --check` and `git diff --cached --check` completed without errors.
|
|
||||||
|
|
||||||
## Tests not run
|
|
||||||
|
|
||||||
Per the execution constraints, no build, QEMU run, smoke test, feature test,
|
|
||||||
or other dynamic test was run. A FreeBSD KLD build with `WITH_ZSTDIO=1`
|
|
||||||
remains mandatory during final validation so this enabled function body is
|
|
||||||
compiled.
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
# Pre-12 Batch 06: codec descriptor ownership
|
|
||||||
|
|
||||||
Date: 2026-08-13
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
- Moved the LZMA, DEFLATE, and ZSTD descriptors into their backend source
|
|
||||||
files.
|
|
||||||
- Made their backend-only config, decompress, and availability helpers
|
|
||||||
`static`.
|
|
||||||
- Kept the LZ4 config loader and descriptor, plus the SHIFTED and INTERLACED
|
|
||||||
descriptors and transform, in `src/decompressor.c`.
|
|
||||||
- Replaced the central descriptor object array with the descriptor pointer
|
|
||||||
table `z_erofs_decomp`.
|
|
||||||
- Reduced `src/compress.h` to the three backend descriptor declarations and
|
|
||||||
the LZ4 decompress prototype needed by the central descriptor.
|
|
||||||
|
|
||||||
## Descriptor tuples
|
|
||||||
|
|
||||||
The normalized tuples are unchanged before and after this batch:
|
|
||||||
|
|
||||||
| Index | Name | Config callback | Decompress callback | Compile condition |
|
|
||||||
| --- | --- | --- | --- | --- |
|
|
||||||
| `Z_EROFS_COMPRESSION_LZ4` | `lz4` | `z_erofs_load_lz4_config` | `z_erofs_lz4_decompress` | always |
|
|
||||||
| `Z_EROFS_COMPRESSION_LZMA` | `lzma` | `z_erofs_load_lzma_config` | `z_erofs_lzma_decompress` | always |
|
|
||||||
| `Z_EROFS_COMPRESSION_DEFLATE` | `deflate` | `z_erofs_load_deflate_config` | `z_erofs_deflate_decompress` | always |
|
|
||||||
| `Z_EROFS_COMPRESSION_ZSTD` | `zstd` | `z_erofs_load_zstd_config` | `z_erofs_zstd_decompress` | descriptor and config always; decompress implementation selected by `ZSTDIO` |
|
|
||||||
| `Z_EROFS_COMPRESSION_SHIFTED` | `shifted` | `NULL` | `z_erofs_transform_plain` | always |
|
|
||||||
| `Z_EROFS_COMPRESSION_INTERLACED` | `interlaced` | `NULL` | `z_erofs_transform_plain` | always |
|
|
||||||
|
|
||||||
## Static validation
|
|
||||||
|
|
||||||
- Confirmed one declaration and one definition for each backend descriptor;
|
|
||||||
the only additional occurrence is its central pointer-table entry.
|
|
||||||
- Confirmed the LZMA and DEFLATE config/decompress helpers have no external
|
|
||||||
consumers and are now `static` in their backends.
|
|
||||||
- Confirmed the ZSTD config/decompress/availability helpers have no external
|
|
||||||
consumers and are now `static`; the two decompress definitions are mutually
|
|
||||||
exclusive under `#ifdef ZSTDIO`.
|
|
||||||
- Confirmed `z_erofs_decomp` explicitly fills all six runtime indices in the
|
|
||||||
original order. Decompression retains the array-length bound, rejects a
|
|
||||||
null table entry, and rejects a null decompress callback with
|
|
||||||
`EOPNOTSUPP`. Config parsing retains the existing compression-config loop
|
|
||||||
bound and treats a null entry or null config callback as `EOPNOTSUPP` before
|
|
||||||
releasing the config buffer on the existing path.
|
|
||||||
- Confirmed the `WITH_ZSTDIO=0` static conditional path remained valid;
|
|
||||||
actual build deferred to final validation. Without `ZSTDIO`, the path
|
|
||||||
keeps the descriptor non-null, reports the existing mount error and
|
|
||||||
`EOPNOTSUPP` from config, and selects the decompress stub returning `-1`.
|
|
||||||
- Confirmed `WITH_ZSTDIO=1` adds `-DZSTDIO`, keeps the same descriptor and
|
|
||||||
config callback, and selects the existing ZSTD implementation with its
|
|
||||||
resource-release and error paths unchanged.
|
|
||||||
- `git diff --check` and `git diff --cached --check` were required for this
|
|
||||||
batch.
|
|
||||||
|
|
||||||
## Deferred validation
|
|
||||||
|
|
||||||
No build, QEMU, smoke, feature, or other dynamic validation was run for this
|
|
||||||
batch. Follow-up validation must build the FreeBSD KLD with both
|
|
||||||
`WITH_ZSTDIO=0` and `WITH_ZSTDIO=1`.
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# Pre-12 Batch 07: exact macro alignment
|
|
||||||
|
|
||||||
Date: 2026-08-13
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
- Renamed only `EROFS_ALL_SUPPORTED_INCOMPAT` to the Linux name
|
|
||||||
`EROFS_ALL_FEATURE_INCOMPAT` in its comment, definition, and sole source
|
|
||||||
use.
|
|
||||||
- Deleted only the zero-consumer compatibility alias
|
|
||||||
`EROFS_CHUNK_FORMAT_INDEXES_FLAG`.
|
|
||||||
|
|
||||||
## Static proof
|
|
||||||
|
|
||||||
- Before the edit, the target tree had exactly three source occurrences of
|
|
||||||
`EROFS_ALL_SUPPORTED_INCOMPAT`: its comment and definition in
|
|
||||||
`src/erofs_fs.h`, and the `src/super.c` unsupported-feature calculation.
|
|
||||||
The two additional target-tree matches were historical review prose, not
|
|
||||||
source or build consumers.
|
|
||||||
- After the edit, the old source name has zero occurrences and
|
|
||||||
`EROFS_ALL_FEATURE_INCOMPAT` has exactly the same comment, definition, and
|
|
||||||
sole `src/super.c` use.
|
|
||||||
- The macro continuation expression and its feature-bit operands are
|
|
||||||
unchanged. The unsupported calculation changes only the macro token.
|
|
||||||
- A tracked-tree exact-symbol search found
|
|
||||||
`EROFS_CHUNK_FORMAT_INDEXES_FLAG` only as identical definitions in retained
|
|
||||||
repository snapshots. The target tree had exactly one occurrence: the
|
|
||||||
definition being deleted.
|
|
||||||
- Exact searches of target-tree Makefiles, scripts, documentation, text
|
|
||||||
interfaces, and preprocessor `-D` flags found no consumer of the deleted
|
|
||||||
alias. Existing code continues to use `EROFS_CHUNK_FORMAT_INDEXES`;
|
|
||||||
`EROFS_CHUNK_FORMAT_ALL` and chunk decoding are unchanged.
|
|
||||||
- `git diff --check` and `git diff --cached --check` were required for this
|
|
||||||
batch.
|
|
||||||
|
|
||||||
## Deferred validation
|
|
||||||
|
|
||||||
No build, QEMU, smoke, feature, or other dynamic validation was run for this
|
|
||||||
batch. The final KLD and Plain/LZ4/LZMA validation remains deferred.
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# Pre-12 Batch 08: xattr helper order
|
|
||||||
|
|
||||||
Date: 2026-08-13
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
- Moved the complete `static erofs_listxattr_foreach` function block to
|
|
||||||
immediately precede `erofs_getxattr_foreach` in `src/xattr.c`.
|
|
||||||
- Made no changes to either function body, signature, visibility, callers, or
|
|
||||||
conditional-compilation context.
|
|
||||||
|
|
||||||
## Static proof
|
|
||||||
|
|
||||||
- The exact function block from `static int` through its closing brace had
|
|
||||||
SHA-256 `0541c211f78a19f39caeebdafe73bdd0a7064e996686a7b45c9c651160ed98ae`
|
|
||||||
before and after the move.
|
|
||||||
- The target remains one `static` definition with two call sites, in the
|
|
||||||
inline and shared xattr iterators.
|
|
||||||
- `erofs_getxattr_foreach` remains one definition with the same two call
|
|
||||||
sites; its complete block is unchanged.
|
|
||||||
- Both helpers remain in the same unconditional compilation region after
|
|
||||||
`struct erofs_xattr_iter` and before the iterator functions, so no forward
|
|
||||||
declaration or conditional boundary was introduced.
|
|
||||||
- The source diff is a pure block move; adjacent xattr and ACL logic is
|
|
||||||
unchanged.
|
|
||||||
- `git diff --check` and `git diff --cached --check` were required for this
|
|
||||||
batch.
|
|
||||||
|
|
||||||
## Deferred validation
|
|
||||||
|
|
||||||
No build, QEMU, smoke, feature, or other dynamic validation was run for this
|
|
||||||
batch. Final KLD and Plain/LZ4/LZMA validation remains deferred.
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
# Pre-12 Batch 09: compression header responsibility
|
|
||||||
|
|
||||||
Date: 2026-08-13
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
- Removed the direct `internal.h` include from `decompressor.c` and the four
|
|
||||||
`decompressor_*.c` backend consumers that already include `compress.h`.
|
|
||||||
- Made no declaration, definition, function, storage-duration, or public API
|
|
||||||
changes.
|
|
||||||
|
|
||||||
## Candidate source
|
|
||||||
|
|
||||||
Batch 04 created `compress.h` with a direct `internal.h` include and added
|
|
||||||
`compress.h` to these five translation units while retaining their direct
|
|
||||||
`internal.h` includes. Batch 06 then made LZMA, DEFLATE, and ZSTD backend
|
|
||||||
functions private and exposed only their descriptor objects through
|
|
||||||
`compress.h`. This left exactly five duplicate include edges attributable to
|
|
||||||
Batches 04/06.
|
|
||||||
|
|
||||||
## Static proof
|
|
||||||
|
|
||||||
- `compress.h` remains the sole owner of `z_erofs_decompress_req`,
|
|
||||||
`z_erofs_decompressor`, the LZ4 decompressor prototype, and the three
|
|
||||||
backend descriptor declarations.
|
|
||||||
- `internal.h` remains the sole public owner of `z_erofs_decompress` and
|
|
||||||
`z_erofs_parse_cfgs`; it does not include `compress.h`.
|
|
||||||
- The include graph remains acyclic: each affected translation unit includes
|
|
||||||
`compress.h`, and `compress.h` includes `internal.h`, which includes only
|
|
||||||
`erofs_fs.h` among project headers.
|
|
||||||
- Each affected consumer therefore still sees the same complete request,
|
|
||||||
descriptor, mount, map, and superblock types through one guarded include
|
|
||||||
path. No backend prototype or descriptor declaration is duplicated between
|
|
||||||
`internal.h` and `compress.h`.
|
|
||||||
- The source diff removes exactly one `#include "internal.h"` line from each
|
|
||||||
of five authorized files and changes no other token.
|
|
||||||
- `git diff --check` and `git diff --cached --check` were required for this
|
|
||||||
batch.
|
|
||||||
|
|
||||||
## Deferred validation
|
|
||||||
|
|
||||||
No build, QEMU, smoke, feature, or other dynamic validation was run under the
|
|
||||||
execution constraint. The required FreeBSD KLD `WITH_ZSTDIO=0/1` matrix and
|
|
||||||
final Plain/LZ4/LZMA validation remain deferred.
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# Pre-12 Batch 10: Makefile readability review
|
|
||||||
|
|
||||||
Date: 2026-08-13
|
|
||||||
|
|
||||||
## Result
|
|
||||||
|
|
||||||
No-op. `src/Makefile` was reviewed after Batches 04, 06, and 09, but no
|
|
||||||
non-redundant comment or blank-line grouping with clear maintenance value was
|
|
||||||
identified.
|
|
||||||
|
|
||||||
## Static proof
|
|
||||||
|
|
||||||
- The `SRCS` list already keeps the core filesystem sources, mapping and data
|
|
||||||
sources, and `decompressor_*.c` sources in readable contiguous regions.
|
|
||||||
- Adding labels would repeat names already visible in the short source list.
|
|
||||||
- `src/Makefile` is byte-for-byte unchanged.
|
|
||||||
- The `SRCS` elements, order, duplicate counts, `WITH_ZSTDIO` condition,
|
|
||||||
per-file CFLAGS, target, and `.include` line are unchanged.
|
|
||||||
- `git diff --check` and `git diff --cached --check` were required for this
|
|
||||||
documentation-only closeout.
|
|
||||||
|
|
||||||
## Validation
|
|
||||||
|
|
||||||
No build, QEMU, smoke, or feature test was run for this no-op review.
|
|
||||||
@@ -1,229 +0,0 @@
|
|||||||
# Pre12 Final Report
|
|
||||||
|
|
||||||
Date: 2026-08-13
|
|
||||||
|
|
||||||
## Conclusion and scope
|
|
||||||
|
|
||||||
Pre12 is complete for its deliberately limited scope. The final result is
|
|
||||||
**PASS** for the planned static review, both FreeBSD KLD build configurations,
|
|
||||||
KLD load/status/unload, and the ordinary Plain/LZ4/LZMA QEMU smoke cases.
|
|
||||||
|
|
||||||
This PASS is not a claim of complete EROFS feature validation. No feature
|
|
||||||
test, `test_all.py`, new fixture, ZSTD data test, DEFLATE data test, ACL runtime
|
|
||||||
test, explicit-extent test, or multi-device test was run. The included changes
|
|
||||||
were selected as low-side-effect maintenance work and did not require a full
|
|
||||||
feature suite after their static proofs and final build/smoke matrix. Deferred
|
|
||||||
behavior work remains unresolved and is listed below.
|
|
||||||
|
|
||||||
The validated device-under-test identity is:
|
|
||||||
|
|
||||||
| Identity | Value |
|
|
||||||
| --- | --- |
|
|
||||||
| Commit | `a55e42a117e504f6ece49be3c2a2d81603031ea3` |
|
|
||||||
| `repo-pre-12` tree | `9161671bd0e855faa52c37e24fe8efcd6ddd71e0` |
|
|
||||||
| `repo-pre-12/src` tree | `d63c45c7872dcf9dd84007c8883cf9fbe0f9467d` |
|
|
||||||
| Source archive SHA-256 | `bb7e7f0383be29102475575e130e0b19a48452d20520c94059dc6ef128d0c7ce` |
|
|
||||||
|
|
||||||
## Goals
|
|
||||||
|
|
||||||
Pre12 continued the staged effort to reduce unnecessary maintenance
|
|
||||||
differences from Linux EROFS without importing Linux-only memory, I/O, device,
|
|
||||||
or concurrency models into FreeBSD. Its concrete scope was nine core batches
|
|
||||||
and one conditional maintenance closeout:
|
|
||||||
|
|
||||||
1. Use existing semantic scalar aliases where their width and signedness are
|
|
||||||
exactly equivalent.
|
|
||||||
2. Use FreeBSD unaligned little-endian readers for raw on-disk bytes.
|
|
||||||
3. Use the FreeBSD POSIX.1e ACL mode conversion facility.
|
|
||||||
4. Introduce a Linux-comparable private compression header.
|
|
||||||
5. Remove an unreachable ZSTD lower-bound condition.
|
|
||||||
6. Align codec descriptor ownership while preserving FreeBSD behavior.
|
|
||||||
7. Align exact macro vocabulary and remove one zero-consumer alias.
|
|
||||||
8. Align one xattr helper's file order through a byte-identical block move.
|
|
||||||
9. Remove include duplication introduced by the compression-header work.
|
|
||||||
10. Review Makefile readability and make no change when no useful grouping
|
|
||||||
was found.
|
|
||||||
|
|
||||||
The work explicitly excluded broad file reordering, catch-all style cleanup,
|
|
||||||
Linux page/folio/bio/workqueue infrastructure, and behavior changes requiring
|
|
||||||
specialized feature fixtures.
|
|
||||||
|
|
||||||
## Batch results
|
|
||||||
|
|
||||||
| Batch | Commit | Result and summary |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| 01 | `bb28c47bdf4de777febde05ebb333c420ea1e9b9` | Replaced the planned NID, block-number, and byte-offset declarations with existing equal-width unsigned `erofs_nid_t`, `erofs_blk_t`, and `erofs_off_t` aliases. Field order, layout, ABI width, expressions, on-disk types, and control flow were unchanged. |
|
|
||||||
| 02 | `76a655788538f2270626cff1ca91b8c47700d536` | Replaced exactly three potentially unaligned typed loads with `le16dec`/`le32dec` in xattr, inode, and block-map decoding. |
|
|
||||||
| 03 | `35bde15f5242f84a6343cc9e96519fcce4eeca90` | Replaced three manual ACL mode shifts with `acl_posix1e_mode_to_perm` for owner, group, and other entries. |
|
|
||||||
| 04 | `b591751f90e62bc0ec54d3f34c724f698c99813d` | Added `src/compress.h` for private decompressor request, descriptor, and backend declarations; public entry points and runtime enum remained in `internal.h`. |
|
|
||||||
| 05 | `aaa3c5db40745ee558e6fcf6375d60e044217df9` | Removed only the unreachable `zstd_windowlog + 10 < 10` subcondition; the upper bound, zero-output check, disabled stub, errno behavior, and resource handling remained unchanged. |
|
|
||||||
| 06 | `6748d58f7e15927321f44a83d81a6c697c1185ae` | Moved LZMA, DEFLATE, and ZSTD descriptors into their backends, kept LZ4 and plain transforms central, and changed the central descriptor table to the pointer table `z_erofs_decomp`. All six normalized descriptor tuples and indices remained unchanged. |
|
|
||||||
| 07 | `292da21bd9288cac4a8b280bb67970c8b9058550` | Renamed `EROFS_ALL_SUPPORTED_INCOMPAT` to Linux's `EROFS_ALL_FEATURE_INCOMPAT` at its definition and sole source use, and removed zero-consumer `EROFS_CHUNK_FORMAT_INDEXES_FLAG`. |
|
|
||||||
| 08 | `0be5642d917104f1904bcfadaea803c9845c7a5c` | Moved the complete `erofs_listxattr_foreach` static function block before `erofs_getxattr_foreach`; the block SHA-256 remained `0541c211f78a19f39caeebdafe73bdd0a7064e996686a7b45c9c651160ed98ae`. |
|
|
||||||
| 09 | `e5315489eb5ed08884d5d5f2645264067e36838e` | Removed five direct `internal.h` includes made redundant by `compress.h`; declaration visibility and the acyclic include graph were preserved. |
|
|
||||||
| 10 | `a55e42a117e504f6ece49be3c2a2d81603031ea3` | Conditional Makefile readability closeout: honest no-op. The source list and Makefile remained byte-for-byte unchanged because no non-redundant grouping comment was justified. |
|
|
||||||
|
|
||||||
Batch 10 is not counted among the nine core source workflows. Batch 09 did
|
|
||||||
produce a precise cleanup diff, while Batch 10 records the required review
|
|
||||||
without manufacturing source churn.
|
|
||||||
|
|
||||||
## Static review
|
|
||||||
|
|
||||||
The final static review found no source-blocking issue. In particular, it did
|
|
||||||
not find a regression in declaration/definition matching, include ownership or
|
|
||||||
graph shape, descriptor indices and callback ownership, errno paths, resource
|
|
||||||
release, in-memory ABI/layout, endian decoding, ACL construction, macro values,
|
|
||||||
or the byte-identical xattr function move.
|
|
||||||
|
|
||||||
The important proofs were:
|
|
||||||
|
|
||||||
- The three semantic scalar aliases are direct unsigned 64-bit aliases; the
|
|
||||||
approved substitutions preserve size, alignment, signedness, structure
|
|
||||||
layout, parameter representation, and arithmetic width.
|
|
||||||
- The three `le16dec`/`le32dec` inputs are raw little-endian disk bytes of the
|
|
||||||
required length; the decoded values are equivalent while avoiding typed
|
|
||||||
unaligned loads.
|
|
||||||
- ACL owner/group/other conversion was exhaustively compared across modes
|
|
||||||
`0000` through `0777`: `1536/1536` tag/mode combinations were equivalent,
|
|
||||||
with zero mismatches.
|
|
||||||
- The compression include graph remained acyclic and each migrated or private
|
|
||||||
symbol retained one authoritative declaration/definition relationship.
|
|
||||||
- The six codec descriptor tuples, indices, names, config callbacks,
|
|
||||||
decompress callbacks, and ZSTD conditional ownership remained equivalent.
|
|
||||||
- The removed ZSTD lower bound is unreachable because the field is `uint8_t`;
|
|
||||||
its promoted value plus 10 cannot be less than 10.
|
|
||||||
- Macro expressions and values were unchanged, and the deleted chunk-format
|
|
||||||
alias had no source, build, documentation-interface, or preprocessor
|
|
||||||
consumer in the target tree.
|
|
||||||
- The moved xattr function block retained its exact SHA-256 and conditional
|
|
||||||
context.
|
|
||||||
|
|
||||||
The Batch 06 record originally used wording that could imply an actual
|
|
||||||
`WITH_ZSTDIO=0` build had already occurred during that batch. It has been
|
|
||||||
corrected to state that only the static conditional path was validated then.
|
|
||||||
Final validation subsequently built both configurations successfully.
|
|
||||||
|
|
||||||
## KLD build matrix
|
|
||||||
|
|
||||||
The valid final run used FreeBSD `15.0-RELEASE-p8`, amd64, with `/usr/src/sys`
|
|
||||||
and the in-tree FreeBSD ZSTD headers present. The extracted source archive
|
|
||||||
matched SHA-256
|
|
||||||
`bb7e7f0383be29102475575e130e0b19a48452d20520c94059dc6ef128d0c7ce`.
|
|
||||||
|
|
||||||
For each configuration, the guest executed:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
timeout -k 10s 120s make "WITH_ZSTDIO=<0-or-1>" clean
|
|
||||||
timeout -k 10s 600s make "WITH_ZSTDIO=<0-or-1>"
|
|
||||||
```
|
|
||||||
|
|
||||||
| Configuration | Clean exit | Build exit | Module SHA-256 |
|
|
||||||
| --- | ---: | ---: | --- |
|
|
||||||
| `WITH_ZSTDIO=0` | 0 | 0 | `96dc276c6c3f68943e68a144cc2ea138ffc215b62c7392cad9688ec45c9fc2fb` |
|
|
||||||
| `WITH_ZSTDIO=1` | 0 | 0 | `4d879c0b7ebc653e915a3e41863f74d6d5b5f18aa81c5178579368048d1b6ee3` |
|
|
||||||
|
|
||||||
The enabled build compiled `decompressor_zstd.c` with `-DZSTDIO` and linked
|
|
||||||
`erofs.ko`. These builds prove both compile-time configurations close and link;
|
|
||||||
they do not prove ZSTD or DEFLATE data-path correctness.
|
|
||||||
|
|
||||||
## KLD and smoke results
|
|
||||||
|
|
||||||
The valid run loaded the `WITH_ZSTDIO=1` artifact under the standard module
|
|
||||||
name `erofs.ko`.
|
|
||||||
|
|
||||||
| Check | Result |
|
|
||||||
| --- | --- |
|
|
||||||
| `kldload` | exit 0 |
|
|
||||||
| `kldstat -n erofs.ko` | present as `erofs.ko`, module id 5 |
|
|
||||||
| Loaded module SHA-256 | `4d879c0b7ebc653e915a3e41863f74d6d5b5f18aa81c5178579368048d1b6ee3` |
|
|
||||||
| `kldunload erofs.ko` | exit 0 |
|
|
||||||
| Post-unload `kldstat` | module absent, as expected |
|
|
||||||
|
|
||||||
All ordinary read cases matched their complete expected hashes:
|
|
||||||
|
|
||||||
| Case | Exit | Expected SHA-256 | Actual SHA-256 | Elapsed |
|
|
||||||
| --- | ---: | --- | --- | ---: |
|
|
||||||
| Plain | 0 | `056f8f7585667dc695e2edf936deaf84cfee0f88671ba6cd5be22ce890763433` | `056f8f7585667dc695e2edf936deaf84cfee0f88671ba6cd5be22ce890763433` | 593 ms |
|
|
||||||
| LZ4 | 0 | `3ff012b76087c4da65ce0b69813a76f47ea367e95782edf8b8cd6cd3ec4d1880` | `3ff012b76087c4da65ce0b69813a76f47ea367e95782edf8b8cd6cd3ec4d1880` | 6822 ms |
|
|
||||||
| LZMA | 0 | `ddda39737f0f6093e828a032ec161511fefbb1fa361bc6cbffdbc91e48e4c461` | `ddda39737f0f6093e828a032ec161511fefbb1fa361bc6cbffdbc91e48e4c461` | 3418 ms |
|
|
||||||
|
|
||||||
The dmesg delta was zero bytes and the suspect-filter output was zero bytes.
|
|
||||||
No new panic, trap, or EROFS error was observed.
|
|
||||||
|
|
||||||
## Evidence and invalid attempts
|
|
||||||
|
|
||||||
The only final valid evidence directory is:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/work/tests-dev/temp/pre12-smoke-direct-20260813T165639Z/
|
|
||||||
```
|
|
||||||
|
|
||||||
Its `final-summary.txt`, guest build logs, module hashes, case records, dmesg
|
|
||||||
files, and cleanup record form the accepted evidence set.
|
|
||||||
|
|
||||||
Two earlier infrastructure attempts are explicitly invalid and contribute no
|
|
||||||
source result and no test pass:
|
|
||||||
|
|
||||||
1. `/work/tests-dev/temp/pre12-build-20260813T154900Z/` is **INFRA-FAIL**.
|
|
||||||
The SSH password expanded to an empty string, so there were zero successful
|
|
||||||
SSH sessions and neither build began. Its QEMU and temporary resources were
|
|
||||||
cleaned. This is neither a DUT failure nor a test success.
|
|
||||||
2. `/work/tests-dev/temp/pre12-final-smoke-20260813T160957Z/` stopped while
|
|
||||||
redundantly hashing the 16 GB base image. Five nested Codex CLI sessions
|
|
||||||
were discovered and all were terminated or had exited; no QEMU, SSH,
|
|
||||||
guest build, KLD action, or smoke case started. Its partial files are not
|
|
||||||
test evidence and it is neither a DUT failure nor a test success.
|
|
||||||
|
|
||||||
The final accepted run was performed by a single direct execution layer and
|
|
||||||
did not start a nested agent or Codex process.
|
|
||||||
|
|
||||||
One intermediate runner revision attempted to query KLD using the renamed
|
|
||||||
artifact filename rather than the module's standard name. That was a
|
|
||||||
test-period runner issue, not a DUT issue. Only the temporary runner copy under
|
|
||||||
`tests-dev/temp` was corrected: the successful `WITH_ZSTDIO=1` artifact was
|
|
||||||
copied to `erofs.ko`, then the complete KLD and Plain/LZ4/LZMA sequence was
|
|
||||||
rerun. No `repo-pre-12` source or build file was modified to make the test
|
|
||||||
pass.
|
|
||||||
|
|
||||||
## Cleanup and repository state
|
|
||||||
|
|
||||||
The accepted run completed cleanup successfully:
|
|
||||||
|
|
||||||
- Owned QEMU stopped.
|
|
||||||
- SSH ControlMaster stopped.
|
|
||||||
- Test port `10048` released.
|
|
||||||
- Test overlay removed.
|
|
||||||
- Guest test mounts and `md70`/`md71`/`md72` devices were removed.
|
|
||||||
- The retained guard QEMU remained unchanged and reachable at PID `26318`,
|
|
||||||
port `9222`, with process start ticks `1102996924`.
|
|
||||||
- The base image remained mode `0444`, size `16515530752` bytes, and mtime
|
|
||||||
`1786418212`. Its retained SHA-256 record is
|
|
||||||
`67f359621f23a1d745f0889370cbb99a096cee3e99a0b2f3bb18fc7a91bf6fef`;
|
|
||||||
the final run intentionally did not repeat the expensive 16 GB hash.
|
|
||||||
- At validation completion, `HEAD` and `xdm/main` both identified
|
|
||||||
`a55e42a117e504f6ece49be3c2a2d81603031ea3`, and the worktree was clean.
|
|
||||||
|
|
||||||
This report is documentation-only and does not alter the validated DUT source
|
|
||||||
tree `d63c45c7872dcf9dd84007c8883cf9fbe0f9467d`.
|
|
||||||
|
|
||||||
## Deferred feature work
|
|
||||||
|
|
||||||
The following issues remain unresolved and require dedicated behavior design,
|
|
||||||
fixtures, or feature tests before any future implementation can be accepted:
|
|
||||||
|
|
||||||
- inode decode split or rewrite;
|
|
||||||
- map request interface conversion;
|
|
||||||
- directory/namei control flow, qstr, cookies, namecache, and lock behavior;
|
|
||||||
- metadata reader consolidation;
|
|
||||||
- rejection or handling of a non-directory root;
|
|
||||||
- `run_len == 0` behavior;
|
|
||||||
- header-only xattr behavior;
|
|
||||||
- duplicate or missing `device.N` behavior;
|
|
||||||
- `insmntque` race closure;
|
|
||||||
- explicit extent and explicit mapped-extent fixtures;
|
|
||||||
- `vnode_create_vobject` errno behavior.
|
|
||||||
|
|
||||||
No claim is made that these issues were fixed or covered by the ordinary
|
|
||||||
smoke run. The final PASS is limited to the Pre12 static review, both KLD build
|
|
||||||
configurations, KLD lifecycle, and the Plain/LZ4/LZMA smoke cases recorded in
|
|
||||||
the accepted evidence directory.
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# Pre13 Baseline
|
|
||||||
|
|
||||||
- Source commit: `35eb53c65a4f75ba580f64af043779b930e3bb78`
|
|
||||||
- `repo-pre-12` tree: `4ea4d7cfbf8b8a884b291f7433e19ce8e5af5a11`
|
|
||||||
- `repo-pre-12/src` tree: `d63c45c7872dcf9dd84007c8883cf9fbe0f9467d`
|
|
||||||
- `repo-pre-13/src` tree after copy: `d63c45c7872dcf9dd84007c8883cf9fbe0f9467d`
|
|
||||||
- Copy verification: 327 files, 43 directories, and 0 symbolic links matched by relative path, mode, link target, and SHA-256 content manifest before this document was added.
|
|
||||||
- Copy manifest SHA-256: `c6bdcee893a45a03308897715062aada41c591a82432f2c0008dbd316d10cf07`
|
|
||||||
|
|
||||||
Except for this baseline document, `repo-pre-13` is an exact copy of `repo-pre-12`.
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
# Pre13 Execution Status
|
|
||||||
|
|
||||||
## Final Status
|
|
||||||
|
|
||||||
Pre13 is **scoped PASS** for the planned and admitted Pre13 work at
|
|
||||||
`b804d7b77d1c76b8e844dc4a758c6ab3381ca006`. This is not a full feature-suite
|
|
||||||
PASS and does not claim V02 positive coverage.
|
|
||||||
|
|
||||||
At status backfill time, DUT `HEAD`, local `main`, fetched `xdm/main`, remote
|
|
||||||
`refs/heads/main`, and the DUT worktree all resolve to
|
|
||||||
`b804d7b77d1c76b8e844dc4a758c6ab3381ca006`; the DUT worktree is clean.
|
|
||||||
|
|
||||||
## Completed Source Work
|
|
||||||
|
|
||||||
- Low-risk alignment commits:
|
|
||||||
- L-A1 helper/guard alignment:
|
|
||||||
`2d0041ba3a195c184a52bdccae3bd00af520d4b7`
|
|
||||||
- L-A2 helper ordering:
|
|
||||||
`190a0b908d25e62b5c78ba82377f53d359fc5c4f`
|
|
||||||
- L-B semantic type alignment:
|
|
||||||
`f236836a55ad7ec7d536df483460ea394e38b6c3`
|
|
||||||
- L-C1 on-disk endian field typing:
|
|
||||||
`217b7a3032ec917c5ea63652b0f3cad734990d48`
|
|
||||||
- L-C2 flexible on-disk arrays:
|
|
||||||
`e72ecd7cc024047f0ce7c1855e6e44ae7f5350e1`
|
|
||||||
- L-D LZ4 endian helper:
|
|
||||||
`fe338f701059de8dfd6336dea7f9288bc0f12e9f`
|
|
||||||
- L-E localized private constants:
|
|
||||||
`9028b92343ec7f5bbc1b07477b8d4a669c436955`
|
|
||||||
- Stage0 decisions:
|
|
||||||
`8ed80c3ddbedc64b8b80daf1be16b28c4f24f10d`.
|
|
||||||
- H04 root-type validation:
|
|
||||||
`ee9dc4715436eeee21ae2d84eab2677b27d87ddd`.
|
|
||||||
- H03 qstr lookup alignment:
|
|
||||||
- H03a bounded qstr comparator:
|
|
||||||
`f51b0fe1ceb27cac641667aa5688d371a60d2d99`
|
|
||||||
- H03b lookup search propagation:
|
|
||||||
`3313d305a2193ef6ffa26c6a189e47187b9c0d70`
|
|
||||||
- H03c VOP adapter:
|
|
||||||
`83a5bef73b329c967bd8390a0966d30005295758`
|
|
||||||
- Build/test-input fixups:
|
|
||||||
`dc47e8f99c947d2929d3528a6c139a85eb4251d5`,
|
|
||||||
`b804d7b77d1c76b8e844dc4a758c6ab3381ca006`.
|
|
||||||
|
|
||||||
## Stage0 Decisions
|
|
||||||
|
|
||||||
- H04 ROOT-NONDIR: `READY`, then implemented and custom validated.
|
|
||||||
- H07 ZERO-RUN: `STOP/no-op`; 1,360 legal states showed no reachable
|
|
||||||
zero-progress path.
|
|
||||||
- H01a/b/c map request work: `STOP`; the tuple oracle lacked chunk,
|
|
||||||
multidevice, bounds, and overflow coverage.
|
|
||||||
- H03 comparator: `READY`; Python 11,562 cases and C 1,048,576 cases passed.
|
|
||||||
- Device-option probing: blocked/non-gating, no behavior claim.
|
|
||||||
|
|
||||||
## Validation Status
|
|
||||||
|
|
||||||
- Targeted build/layout/probe retry:
|
|
||||||
`/work/tests-dev/temp/pre13-targeted-final-runnerfix-retry-20260814T0138Z`.
|
|
||||||
`WITH_ZSTDIO=0` and `WITH_ZSTDIO=1` builds passed with module SHA256
|
|
||||||
`0b1244cf9b7fe70649bdcc1c6ef12e6151c77b10c2755b366f960b101ccb7220`
|
|
||||||
and `15db1fbf9450259d030e88602e1c5ba2e452a731c641b359bd5a2d7823da2735`.
|
|
||||||
Layout probe and four userspace probe builds passed.
|
|
||||||
- H04 custom fixture: PASS. Valid root mounted/remounted; non-directory root
|
|
||||||
returned exact `EINTEGRITY` (`97`); failed mount left the provider
|
|
||||||
detachable.
|
|
||||||
- H03 targeted feature cases: PASS for TC042, TC043, TC044, TC045, TC053,
|
|
||||||
TC054, TC123, TC141, and TC148. TC141's raw runner failure was an extra
|
|
||||||
empty `umount ''` false negative after 25 real commands passed. TC148
|
|
||||||
covered 320 files, 322 dirents, content, and empty suspect dmesg.
|
|
||||||
- Final smoke:
|
|
||||||
`/work/tests-dev/temp/pre13-missing-and-smoke-20260814T021330Z/final-summary.md`.
|
|
||||||
Plain, LZ4, and LZMA passed; KLD load/stat/unload and cleanup passed.
|
|
||||||
- V01 race:
|
|
||||||
`/work/tests-dev/temp/pre13-v01-race-20260814T031032Z/retry-fresh-20260814T032500Z`.
|
|
||||||
Raw runner FAIL was reclassified by the final offline analyzer at tests-dev
|
|
||||||
`22c0bea73b9b81cc44385d1ba7103fa820c56070` as
|
|
||||||
`DUT PASS / TEST false-negative-corrected`. The four offline analyzer unit
|
|
||||||
tests passed. Dmesg total delta was 24 lines / 1,266 bytes with suspect
|
|
||||||
bytes 0.
|
|
||||||
|
|
||||||
## Explicit Non-Claims
|
|
||||||
|
|
||||||
- No full feature suite was run.
|
|
||||||
- No V02 positive explicit-extent fixture was produced; V02 remains PARTIAL.
|
|
||||||
- TC004, TC011, TC143, TC144, TC145, TC150, and other unlisted feature cases
|
|
||||||
are not claimed as passing.
|
|
||||||
- H01, H07, H05, H06, H02, and H08 source changes were intentionally stopped,
|
|
||||||
rejected, or no-op as recorded in the final report.
|
|
||||||
|
|
||||||
Detailed evidence and limits are recorded in `pre13-final-report.md`.
|
|
||||||
@@ -1,344 +0,0 @@
|
|||||||
# Pre13 Final Report
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
Pre13 is **scoped PASS** for the planned and admitted Pre13 work:
|
|
||||||
|
|
||||||
- DUT baseline snapshot: `a587d489b829ef8e7fac94c87130b61d47aa3e44`.
|
|
||||||
- Final DUT commit: `b804d7b77d1c76b8e844dc4a758c6ab3381ca006`.
|
|
||||||
- At final report time, `HEAD`, local `main`, fetched `xdm/main`, remote
|
|
||||||
`refs/heads/main`, and the only DUT worktree all resolve to
|
|
||||||
`b804d7b77d1c76b8e844dc4a758c6ab3381ca006`.
|
|
||||||
- DUT working tree is clean.
|
|
||||||
|
|
||||||
This is **not** a full-filesystem certification. No full 161-case feature
|
|
||||||
suite was run, no positive V02 explicit-extent fixture was produced, and Pre13
|
|
||||||
does not claim that unrun cases such as TC004, TC011, TC143, TC144, TC145,
|
|
||||||
TC150, or other non-targeted feature cases passed.
|
|
||||||
|
|
||||||
## Commit Inventory
|
|
||||||
|
|
||||||
The audited DUT range is
|
|
||||||
`a587d489b829ef8e7fac94c87130b61d47aa3e44..b804d7b77d1c76b8e844dc4a758c6ab3381ca006`.
|
|
||||||
|
|
||||||
### Planning and Stage0
|
|
||||||
|
|
||||||
- `76a4c82`, `fd300cb`, `2f487f0`: Pre13 planning documents and low-risk batch
|
|
||||||
accounting.
|
|
||||||
- `8ed80c3ddbedc64b8b80daf1be16b28c4f24f10d`: recorded Stage0 gate decisions
|
|
||||||
in `repo-pre-13/docs/pre13-stage0-decisions.md` and the initial execution
|
|
||||||
status.
|
|
||||||
|
|
||||||
### Low-Risk Source Alignment
|
|
||||||
|
|
||||||
- `2d0041ba3a195c184a52bdccae3bd00af520d4b7`: L-A1 helper and guard alignment
|
|
||||||
across `compress.h`, `data.c`, `erofs_fs.h`, and `inode.c`, with
|
|
||||||
`pre13-low-a1.md`.
|
|
||||||
- `190a0b908d25e62b5c78ba82377f53d359fc5c4f`: L-A2 local helper ordering in
|
|
||||||
`decompressor.c` and `xattr.c`, with `pre13-low-a2.md`.
|
|
||||||
- `f236836a55ad7ec7d536df483460ea394e38b6c3`: L-B semantic `erofs_nid_t` and
|
|
||||||
`erofs_off_t` alignment across data, directory, inode, namei, super, xattr,
|
|
||||||
zdata, and zmap paths, with `pre13-low-b.md`.
|
|
||||||
- `217b7a3032ec917c5ea63652b0f3cad734990d48`: L-C1 on-disk `__leXX` field
|
|
||||||
alignment in `erofs_fs.h` and initial `pre13_ondisk_layout_probe.c`, with
|
|
||||||
`pre13-low-c1.md`.
|
|
||||||
- `e72ecd7cc024047f0ce7c1855e6e44ae7f5350e1`: L-C2 flexible on-disk arrays
|
|
||||||
and layout probe updates, with `pre13-low-c2.md`.
|
|
||||||
- `fe338f701059de8dfd6336dea7f9288bc0f12e9f`: L-D LZ4 offset endian helper in
|
|
||||||
`decompressor_lz4.c`, with `pre13-low-d.md`.
|
|
||||||
- `9028b92343ec7f5bbc1b07477b8d4a669c436955`: L-E localized private
|
|
||||||
constants, removed `erofs_defs.h`, and updated consumers/docs.
|
|
||||||
|
|
||||||
### Behavior Changes and Fixups
|
|
||||||
|
|
||||||
- `ee9dc4715436eeee21ae2d84eab2677b27d87ddd`: H04 rejects non-directory root
|
|
||||||
inodes during mount, with `pre13-h04-root-validation.md`.
|
|
||||||
- `f51b0fe1ceb27cac641667aa5688d371a60d2d99`: H03a introduced the bounded
|
|
||||||
qstr comparator.
|
|
||||||
- `3313d305a2193ef6ffa26c6a189e47187b9c0d70`: H03b passed qstr through block
|
|
||||||
and dirent lookup search.
|
|
||||||
- `83a5bef73b329c967bd8390a0966d30005295758`: H03c adapted VOP lookup to the
|
|
||||||
bounded qstr path.
|
|
||||||
- `dc47e8f99c947d2929d3528a6c139a85eb4251d5`: fixed const-correct build inputs
|
|
||||||
and the userspace layout probe `bool` include issue.
|
|
||||||
- `b804d7b77d1c76b8e844dc4a758c6ab3381ca006`: retired stale decompression test
|
|
||||||
harnesses that no longer matched the current module surface; this did not hide
|
|
||||||
a DUT test failure.
|
|
||||||
|
|
||||||
## Stage0 Gate Results
|
|
||||||
|
|
||||||
Stage0 was a mixed gate result, not an overall PASS:
|
|
||||||
|
|
||||||
- Gate A, ROOT-NONDIR: **READY**. The baseline accepted a non-directory root;
|
|
||||||
Pre13 froze the rejection as `EINTEGRITY` and allowed H04.
|
|
||||||
- Gate B, ZERO-RUN: **STOP/no-op**. The analysis covered 1,360 legal states and
|
|
||||||
found no reachable zero-progress state for H07.
|
|
||||||
- Gate C, map tuple oracle: **STOP**. The oracle covered only 26 plain,
|
|
||||||
inline, and hole tuples; it did not cover chunk, multidevice, bounds, or
|
|
||||||
overflow behavior, so H01a/H01b/H01c were not implemented.
|
|
||||||
- Gate D, qstr comparator: **PASS/READY**. The Python comparator corpus passed
|
|
||||||
11,562 cases and the independent C harness passed 1,048,576 cases.
|
|
||||||
- Gate E, device option probe: **blocked/non-gating**. It produced no runtime
|
|
||||||
behavior claim and did not block Pre13.
|
|
||||||
|
|
||||||
## Intentional Stops and Rejects
|
|
||||||
|
|
||||||
- H01 map objectization: **STOP** because the tuple oracle was incomplete for
|
|
||||||
chunk, multidevice, bounds, and overflow coverage.
|
|
||||||
- H07 zero-run: **STOP/no-op** because 1,360 legal states produced no reachable
|
|
||||||
zero-progress path.
|
|
||||||
- H05 header-only xattr: **rejected**; Linux treats the format as undefined and
|
|
||||||
BSD already returns `EOPNOTSUPP`.
|
|
||||||
- H06 duplicate `device.N`: **rejected/no-op** for source changes because
|
|
||||||
`vfs_sanitizeopts()` makes the EROFS duplicate-option check unreachable; any
|
|
||||||
probe is non-gating.
|
|
||||||
- H02 inode split: **rejected** because it would diverge from Linux's single
|
|
||||||
`erofs_read_inode()` switch and create low-value churn.
|
|
||||||
- H08 pager errno propagation: **rejected** because the target
|
|
||||||
`vnode_create_vobject()` path observably returns 0.
|
|
||||||
- V02 explicit extent positive coverage: **PARTIAL**. No positive mapped
|
|
||||||
fixture was available, and TC157 negative coverage is not a substitute.
|
|
||||||
|
|
||||||
## Build, Layout, and Probe Evidence
|
|
||||||
|
|
||||||
Primary evidence:
|
|
||||||
`/work/tests-dev/temp/pre13-targeted-final-runnerfix-retry-20260814T0138Z`.
|
|
||||||
|
|
||||||
After `dc47e8f` and `b804d7b`, the targeted retry produced:
|
|
||||||
|
|
||||||
- `WITH_ZSTDIO=0` build: PASS, module SHA256
|
|
||||||
`0b1244cf9b7fe70649bdcc1c6ef12e6151c77b10c2755b366f960b101ccb7220`.
|
|
||||||
- `WITH_ZSTDIO=1` build: PASS, module SHA256
|
|
||||||
`15db1fbf9450259d030e88602e1c5ba2e452a731c641b359bd5a2d7823da2735`.
|
|
||||||
- Loaded module in that targeted run: SHA256
|
|
||||||
`15db1fbf9450259d030e88602e1c5ba2e452a731c641b359bd5a2d7823da2735`.
|
|
||||||
- Userspace layout probe: build and run return code 0.
|
|
||||||
- Four userspace probe builds: `g3_vfs_probe`, `mount_errno_probe`,
|
|
||||||
`nfs_fh_tool`, and `readdir_probe` all returned 0.
|
|
||||||
|
|
||||||
The first targeted runner attempt still ended host-side FAIL because TC141
|
|
||||||
included an extra empty `umount ''` command. That was classified as a test
|
|
||||||
runner false negative, not a DUT failure: the 25 real TC141 commands all had
|
|
||||||
return code 0, and only the 26th synthetic empty unmount failed.
|
|
||||||
|
|
||||||
## H04 Root Validation
|
|
||||||
|
|
||||||
Evidence path:
|
|
||||||
`/work/tests-dev/temp/pre13-targeted-final-runnerfix-retry-20260814T0138Z/guest-evidence/cases/H04`.
|
|
||||||
|
|
||||||
H04 custom fixture result: **PASS**.
|
|
||||||
|
|
||||||
- Valid root fixture SHA256:
|
|
||||||
`d0baba501ae12fcdb8869a98908486473d2bcfb6b332a47cb6a6c1f856a3ab34`.
|
|
||||||
- Non-directory root fixture SHA256:
|
|
||||||
`60bf0d0d93baabdfa23b71f48283d317f6b7218852f3d19aee77575c41500db7`.
|
|
||||||
- Root proof payload SHA256:
|
|
||||||
`0ebc44a6c5a02ba458d1a115bc338fa4acb4d973a37804c9b926eafc0c53575f`.
|
|
||||||
- Valid root mounted, root mode was `040755`, payload matched, and unmount plus
|
|
||||||
`md` detach succeeded.
|
|
||||||
- Non-directory root returned exact `mount_errno=97` (`EINTEGRITY`) with message
|
|
||||||
`erofs: root inode nid=36 is not a directory`; the failed mount left the
|
|
||||||
provider detachable.
|
|
||||||
- The valid fixture remounted successfully after the non-directory failure.
|
|
||||||
- Per-case dmesg delta and suspect logs were empty.
|
|
||||||
|
|
||||||
TC011 and TC150 were not run and are not claimed as passing. They are not
|
|
||||||
Pre13 blockers because the dedicated H04 fixture directly exercised the actual
|
|
||||||
root-type change, including the valid control, exact errno, detach, and remount
|
|
||||||
properties.
|
|
||||||
|
|
||||||
## H03 Targeted Feature Evidence
|
|
||||||
|
|
||||||
H03 targeted cases exercised the qstr lookup changes and passed for:
|
|
||||||
TC042, TC043, TC044, TC045, TC053, TC054, TC123, TC141, and TC148.
|
|
||||||
|
|
||||||
Evidence:
|
|
||||||
|
|
||||||
- TC042/043/044/045/053/054/123 and TC141 raw evidence:
|
|
||||||
`/work/tests-dev/temp/pre13-targeted-final-runnerfix-retry-20260814T0138Z`.
|
|
||||||
- TC148 valid copied evidence and final smoke summary:
|
|
||||||
`/work/tests-dev/temp/pre13-missing-and-smoke-20260814T021330Z/final-summary.md`.
|
|
||||||
|
|
||||||
TC141 details:
|
|
||||||
|
|
||||||
- The runner logged 26 commands, but the last was the invalid empty
|
|
||||||
`umount ''` cleanup bug.
|
|
||||||
- The 25 real commands passed: valid-base and valid-padding cold lookup/read,
|
|
||||||
repeated missing lookups returning `ENOENT`, `entries=322` wide-directory
|
|
||||||
checks, and three corrupt lookup fixtures returning repeated
|
|
||||||
`EINTEGRITY` (`errno=97`).
|
|
||||||
- The only failure was the empty unmount runner command. Its stderr was
|
|
||||||
`statfs: No such file or directory` / `unknown file system`, with no DUT
|
|
||||||
dmesg delta.
|
|
||||||
|
|
||||||
TC148 details:
|
|
||||||
|
|
||||||
- Outcome: PASS.
|
|
||||||
- Fixture SHA256:
|
|
||||||
`9a94e9af2cab264b9c11975a20d78e615d6fe1e6f86267173cb5ac86aecb2b17`.
|
|
||||||
- Mount command return code: 0.
|
|
||||||
- Expected and actual regular-file count: 320.
|
|
||||||
- Directory oracle: 322 entries, with two directories and 320 regular files.
|
|
||||||
- `d_off` restart count and `seekdir` restart count: 322 each.
|
|
||||||
- Target content matched.
|
|
||||||
- Per-case dmesg delta and suspect log were empty.
|
|
||||||
|
|
||||||
## Final Smoke Evidence
|
|
||||||
|
|
||||||
Evidence path:
|
|
||||||
`/work/tests-dev/temp/pre13-missing-and-smoke-20260814T021330Z/final-summary.md`.
|
|
||||||
|
|
||||||
Final smoke outcome: **PASS**.
|
|
||||||
|
|
||||||
- DUT archive SHA256:
|
|
||||||
`d0c052bfef024d0acb40e107800cc8e8227fab6b691e8825af5cf01f19672fe4`.
|
|
||||||
- Assets SHA256:
|
|
||||||
`a9741ea468493bdc72d399615892d7f6269226467d09fa6613fa01352f011908`.
|
|
||||||
- Probe bundle SHA256:
|
|
||||||
`7b10d23c8a780fb35810fe85626305a8c49f196d270f98e5224045bd79f51066`.
|
|
||||||
- Clean tests-dev worktree commit used for the smoke:
|
|
||||||
`f86799654a37cdb81025b9e703635f7c7812fecb`.
|
|
||||||
- `WITH_ZSTDIO=0` build: PASS, module SHA256
|
|
||||||
`0b1244cf9b7fe70649bdcc1c6ef12e6151c77b10c2755b366f960b101ccb7220`.
|
|
||||||
- `WITH_ZSTDIO=1` build: PASS, module SHA256
|
|
||||||
`15db1fbf9450259d030e88602e1c5ba2e452a731c641b359bd5a2d7823da2735`.
|
|
||||||
- Loaded module for final smoke: `WITH_ZSTDIO=0`, SHA256
|
|
||||||
`0b1244cf9b7fe70649bdcc1c6ef12e6151c77b10c2755b366f960b101ccb7220`.
|
|
||||||
- `kldload`, `kldstat -n erofs.ko`, `kldunload`, and final KLD cleanup: PASS.
|
|
||||||
- Plain fixture SHA256:
|
|
||||||
`3785ca07e7bd16f6c611191596ae0314253c0ae9b7217a4b22de25799b0f08ac`;
|
|
||||||
payload SHA256 matched
|
|
||||||
`056f8f7585667dc695e2edf936deaf84cfee0f88671ba6cd5be22ce890763433`.
|
|
||||||
- LZ4 fixture SHA256:
|
|
||||||
`967cc1b625546f9f9f881472e71cc3d849c65feb4e98e67fbfdc9b90a4be6dda`;
|
|
||||||
payload SHA256 matched
|
|
||||||
`3ff012b76087c4da65ce0b69813a76f47ea367e95782edf8b8cd6cd3ec4d1880`.
|
|
||||||
- LZMA fixture SHA256:
|
|
||||||
`32107a084b27362a093768b88746c37c2e99a74b9f1301a9d4046988479defe9`;
|
|
||||||
payload SHA256 matched
|
|
||||||
`ddda39737f0f6093e828a032ec161511fefbb1fa361bc6cbffdbc91e48e4c461`.
|
|
||||||
- Every attach, mount, hash, unmount, and detach command returned 0.
|
|
||||||
- Per-case and global dmesg suspect logs were empty.
|
|
||||||
- Global mount, md, KLD, QEMU, ControlMaster, overlay, and ports
|
|
||||||
`10056`, `10057`, `10058` cleanup passed.
|
|
||||||
- Guard QEMU PID `26318` and port `9222` were unchanged and reachable.
|
|
||||||
- The main tests-dev worktree was dirty before and after with unchanged diff
|
|
||||||
SHA256 `92d3808ab33ff9b22fa2ee3f8a854c1fc36effecb4dd6c0917ae7e80c57fc23a`;
|
|
||||||
the clean tests worktree, not the dirty main worktree, was used as evidence.
|
|
||||||
|
|
||||||
The final summary explicitly states that no other TC, full feature suite,
|
|
||||||
TC004, TC143, TC144, or TC145 was run. Pre13 preserves that limitation.
|
|
||||||
|
|
||||||
## V01 Race Evidence
|
|
||||||
|
|
||||||
Raw evidence:
|
|
||||||
`/work/tests-dev/temp/pre13-v01-race-20260814T031032Z/retry-fresh-20260814T032500Z`.
|
|
||||||
|
|
||||||
tests-dev evidence commits were verified on `xdm/main`:
|
|
||||||
|
|
||||||
- `2269908cc3f721d57ae8138faef664a6bc4c7cc9`: added the V01 concurrent unmount
|
|
||||||
race runner.
|
|
||||||
- `374c9d8473e6638fa0c8e865fcfcfee141b13f0d`: fixed runner SSH command
|
|
||||||
execution.
|
|
||||||
- `22c0bea73b9b81cc44385d1ba7103fa820c56070`: corrected forced-unmount deadfs
|
|
||||||
errno classification and added the offline analyzer/unit tests. Fetched
|
|
||||||
`xdm/main` and remote `refs/heads/main` both resolve to this commit.
|
|
||||||
|
|
||||||
Original raw run:
|
|
||||||
|
|
||||||
- Raw host/guest outcome: FAIL, `guest race failed rc=41`.
|
|
||||||
- DUT commit: `b804d7b77d1c76b8e844dc4a758c6ab3381ca006`.
|
|
||||||
- Module SHA256:
|
|
||||||
`15db1fbf9450259d030e88602e1c5ba2e452a731c641b359bd5a2d7823da2735`.
|
|
||||||
- Fixture root-valid SHA256:
|
|
||||||
`d0baba501ae12fcdb8869a98908486473d2bcfb6b332a47cb6a6c1f856a3ab34`.
|
|
||||||
|
|
||||||
Normal group:
|
|
||||||
|
|
||||||
- Duration 90 seconds, 8 workers, 154 loops.
|
|
||||||
- `umount` returned accepted `EBUSY` 154 times; no successful unmount/remount.
|
|
||||||
- Worker read/stat/open/fstat success counts were each 79,164.
|
|
||||||
- Worker content mismatch, short reads, rejected errors, and dmesg suspect bytes
|
|
||||||
were all 0.
|
|
||||||
|
|
||||||
Forced group:
|
|
||||||
|
|
||||||
- Duration 90 seconds, 8 workers, 125 loops.
|
|
||||||
- Successful forced unmount/remount cycles: 125/125.
|
|
||||||
- `stat ENOENT`: 102,165; `open ENOENT`: 16.
|
|
||||||
- Raw rejected errors: 1,772, consisting of 882 `fstat EBADF` and 890
|
|
||||||
`read ENXIO`.
|
|
||||||
- The final mounted SHA matched the expected payload SHA in both normal and
|
|
||||||
forced groups.
|
|
||||||
|
|
||||||
Final analyzer result from
|
|
||||||
`scripts/analyze-pre13-v01-race-evidence.py` at
|
|
||||||
`22c0bea73b9b81cc44385d1ba7103fa820c56070`:
|
|
||||||
|
|
||||||
- `normal_verdict=PASS`.
|
|
||||||
- `forced_verdict=PASS`.
|
|
||||||
- `forced_expected_deadfs_errors=1772`.
|
|
||||||
- `forced_expected_deadfs_fstat_ebadf=882`.
|
|
||||||
- `forced_expected_deadfs_read_enxio=890`.
|
|
||||||
- `dut_verdict=PASS`.
|
|
||||||
- `test_verdict=false-negative-corrected`.
|
|
||||||
- `overall_verdict=DUT PASS / TEST false-negative-corrected`.
|
|
||||||
|
|
||||||
The `EBADF` and `ENXIO` results occur only after successful forced unmounts,
|
|
||||||
when existing descriptors are taken over by `deadfs`; that is standard FreeBSD
|
|
||||||
semantics and not a DUT instability.
|
|
||||||
|
|
||||||
The analyzer's four offline unit tests all passed:
|
|
||||||
|
|
||||||
- forced deadfs errors are corrected;
|
|
||||||
- normal deadfs errno is rejected;
|
|
||||||
- forced unrelated errno is rejected;
|
|
||||||
- count mismatch is rejected.
|
|
||||||
|
|
||||||
V01 cleanup and integrity:
|
|
||||||
|
|
||||||
- QEMU stopped, V01 port released, overlay removed.
|
|
||||||
- Base image mode, size, and mtime remained `444`, `16515530752`, and
|
|
||||||
`1786418212`.
|
|
||||||
- Guard VM was unchanged and reachable.
|
|
||||||
- Guest mount/md/KLD owned-resource cleanup passed.
|
|
||||||
- Total dmesg delta was 24 lines / 1,266 bytes, all known non-suspect
|
|
||||||
`mangled entry` lines; suspect bytes were 0. This is not a zero-total-delta
|
|
||||||
run.
|
|
||||||
- The dirty main tests-dev worktree was unchanged; the independent clean
|
|
||||||
worktree was clean.
|
|
||||||
|
|
||||||
## Static Review and Evidence Boundaries
|
|
||||||
|
|
||||||
Final static review of the Pre13 source delta found no production-source
|
|
||||||
blocker, test backdoor, out-of-bounds issue, ABI/layout issue,
|
|
||||||
lock/lifecycle issue, or errno issue requiring another DUT fix. The one
|
|
||||||
dynamic item that was pending at that review point was documentation/status
|
|
||||||
backfill; that was a reporting-sequence issue, not an unperformed test gate.
|
|
||||||
|
|
||||||
The source/test diff boundary was also reviewed:
|
|
||||||
|
|
||||||
- Production changes are limited to the planned low-risk alignment work, H04,
|
|
||||||
H03, and build-input fixups.
|
|
||||||
- The only new tracked test asset in the DUT repo is the userspace layout probe.
|
|
||||||
- The stale decompression harness removals in `b804d7b` were documented and do
|
|
||||||
not hide a failing Pre13 DUT test.
|
|
||||||
|
|
||||||
## Unrun or Non-Claimed Coverage
|
|
||||||
|
|
||||||
Pre13 deliberately does **not** claim:
|
|
||||||
|
|
||||||
- full feature-suite PASS;
|
|
||||||
- TC004 PASS;
|
|
||||||
- TC011 or TC150 PASS;
|
|
||||||
- TC143, TC144, or TC145 PASS;
|
|
||||||
- TC146/V02 positive explicit-extent PASS;
|
|
||||||
- H01 map objectization behavior;
|
|
||||||
- H07 zero-progress behavior;
|
|
||||||
- H05/H06/H02/H08 source behavior changes.
|
|
||||||
|
|
||||||
The custom H04 fixture directly covers the actual H04 source change, so the
|
|
||||||
absence of TC011/TC150 is not a blocker for the scoped Pre13 result. Likewise,
|
|
||||||
the final smoke covers Plain/LZ4/LZMA smoke only; Deflate, ZSTD, partial, and
|
|
||||||
other codec feature cases remain outside the Pre13 claim unless specifically
|
|
||||||
listed above.
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# Pre13 H03a: bounded qstr comparator carrier
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
- Added a private `struct erofs_qstr` to `src/namei.c` with explicit `name`
|
|
||||||
and `end` pointers.
|
|
||||||
- Converted `erofs_dirnamecmp()` to consume bounded qstr objects.
|
|
||||||
- Kept the existing search helpers on their original pointer/length interface
|
|
||||||
through a temporary local adapter. Block search, VOP lookup, vnode locking,
|
|
||||||
namecache timing, errno handling, readdir, and cookies are unchanged.
|
|
||||||
|
|
||||||
## Static equivalence
|
|
||||||
|
|
||||||
- Search and disk lengths are still derived from the same pointer ranges.
|
|
||||||
- `matched` is clamped to both ranges before comparison.
|
|
||||||
- Comparison remains unsigned byte ordering, supports non-NUL search keys and
|
|
||||||
embedded NUL bytes, and never assumes a trailing NUL at the disk boundary.
|
|
||||||
- The adapter performs no allocation, copying, normalization, or error mapping.
|
|
||||||
|
|
||||||
## Comparator gate
|
|
||||||
|
|
||||||
Tests baseline: `ce03c283e6e2cb8f1b69c8eff21f7d06098a4fbe`.
|
|
||||||
|
|
||||||
- Python deterministic corpus: PASS, 11,562 cases.
|
|
||||||
- Independent C harness: PASS, 1,048,576 cases.
|
|
||||||
|
|
||||||
These host comparator results prove the old and new comparison contracts are
|
|
||||||
equivalent for the generated corpus. They are not dynamic filesystem feature
|
|
||||||
test results. H03 still requires TC042, TC043, TC044, TC045, TC053, TC054,
|
|
||||||
TC123, TC141, and TC148, followed by the final smoke test.
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# Pre13 H03b: qstr block and dirent search
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
- Converted `find_target_dirent()` and `erofs_find_target_block()` to accept a
|
|
||||||
bounded `struct erofs_qstr` search key.
|
|
||||||
- Constructed bounded on-disk qstr objects from the same validated dirent name
|
|
||||||
offsets and block end pointers used before this change.
|
|
||||||
- Constructed a temporary search qstr inside `erofs_namei()` while retaining
|
|
||||||
its original pointer/length external interface for H03c.
|
|
||||||
- Removed the H03a legacy comparator adapter.
|
|
||||||
|
|
||||||
No changes were made to `dir.c`, readdir, cookies, buffer ownership, directory
|
|
||||||
validation, binary-search decisions, errno selection, cleanup, VOP lookup,
|
|
||||||
vnode locking, or namecache operations.
|
|
||||||
|
|
||||||
## Static evidence
|
|
||||||
|
|
||||||
- `erofs_dirnamecmp()` has exactly two call sites: the block-level first-name
|
|
||||||
comparison and the candidate block's dirent comparison.
|
|
||||||
- Both on-disk qstr end pointers use the same next `nameoff` or validated block
|
|
||||||
boundary as the previous pointer arguments.
|
|
||||||
- `erofs_find_target_block()` retains every `erofs_brelse()` path, candidate
|
|
||||||
replacement, `EINTEGRITY` assignment, and `ENOENT` distinction.
|
|
||||||
- `erofs_namei()` still releases the selected block once and returns `ENOENT`
|
|
||||||
only for a true miss.
|
|
||||||
- The `erofs_lookup()` control flow and all `cache_enter()`, `vn_vget_ino()`,
|
|
||||||
`erofs_vget()`, and `cn_lkflags` uses are outside this stage's diff.
|
|
||||||
|
|
||||||
## Comparator gate
|
|
||||||
|
|
||||||
Tests baseline: `ce03c283e6e2cb8f1b69c8eff21f7d06098a4fbe`.
|
|
||||||
|
|
||||||
- Python deterministic corpus: PASS, 11,562 cases.
|
|
||||||
- Independent C harness: PASS, 1,048,576 cases.
|
|
||||||
|
|
||||||
The comparator gates are host static-equivalence evidence, not dynamic feature
|
|
||||||
tests. H03 still requires TC042, TC043, TC044, TC045, TC053, TC054, TC123,
|
|
||||||
TC141, and TC148, followed by the final smoke test.
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# Pre13 H03c: qstr VOP lookup adapter
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
- Changed the private `erofs_namei()` interface to accept the bounded qstr
|
|
||||||
carrier directly.
|
|
||||||
- Moved search qstr construction to the `erofs_lookup()` FreeBSD VOP adapter,
|
|
||||||
using exactly `cn_nameptr` and `cn_namelen` after the existing length checks.
|
|
||||||
- Removed the temporary qstr construction from `erofs_namei()`.
|
|
||||||
|
|
||||||
No changes were made to `componentname` validation, mutation rejection, `.` or
|
|
||||||
`..` handling, vnode lock mode, `vn_vget_ino()`, `erofs_vget()`, namecache
|
|
||||||
timing, errno mapping, readdir, directory cookies, or directory UIO handling.
|
|
||||||
|
|
||||||
## Static evidence
|
|
||||||
|
|
||||||
- The qstr search range is `[cn_nameptr, cn_nameptr + cn_namelen)` and does not
|
|
||||||
require or inspect a trailing NUL.
|
|
||||||
- The only `erofs_namei()` caller remains `erofs_lookup()`.
|
|
||||||
- A true `ENOENT` remains the only result eligible for negative `cache_enter()`;
|
|
||||||
`EINTEGRITY` and all other errors still return directly.
|
|
||||||
- `ISDOTDOT` still selects `vn_vget_ino()` with the original `cn_lkflags`;
|
|
||||||
ordinary hits still select `erofs_vget()` with the same lock flags.
|
|
||||||
- The H03c diff does not modify any `cache_enter()`, vnode lookup, lock, cookie,
|
|
||||||
readdir, or UIO statement.
|
|
||||||
|
|
||||||
## Comparator gate
|
|
||||||
|
|
||||||
Tests baseline: `ce03c283e6e2cb8f1b69c8eff21f7d06098a4fbe`.
|
|
||||||
|
|
||||||
- Python deterministic corpus: PASS, 11,562 cases.
|
|
||||||
- Independent C harness: PASS, 1,048,576 cases.
|
|
||||||
|
|
||||||
The comparator gates are host static-equivalence evidence, not dynamic feature
|
|
||||||
tests. Dynamic H03 validation remains pending for TC042, TC043, TC044, TC045,
|
|
||||||
TC053, TC054, TC123, TC141, and TC148, followed by the final smoke test.
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
# Pre13 H04 Root Inode Validation
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
H04 adds one mount-time format check in `src/super.c`: the decoded root inode
|
|
||||||
must have FreeBSD vnode type `VDIR`.
|
|
||||||
|
|
||||||
The check runs after packed and metabox inode initialization and before xattr
|
|
||||||
prefix initialization or publication of `mp->mnt_data`. No vnode is created and
|
|
||||||
no permanent root inode reference is retained.
|
|
||||||
|
|
||||||
## Error Contract
|
|
||||||
|
|
||||||
A decodable non-directory root violates the EROFS filesystem structure. The
|
|
||||||
mount therefore fails with positive FreeBSD errno `EINTEGRITY`.
|
|
||||||
|
|
||||||
This intentionally differs from Linux's negative `EINVAL` return while keeping
|
|
||||||
the same format rejection. `EINTEGRITY` matches the existing FreeBSD EROFS
|
|
||||||
contract for decodable on-disk metadata that violates filesystem invariants.
|
|
||||||
|
|
||||||
## Ownership Review
|
|
||||||
|
|
||||||
- The temporary `struct erofs_node` is stack-owned and has no independent
|
|
||||||
allocations or vnode references.
|
|
||||||
- Decode failures and the type rejection use the existing `fail` path.
|
|
||||||
- `erofs_sb_free()` releases extent-cache state, internal inodes, external
|
|
||||||
devices, and the primary GEOM device in the established reverse order.
|
|
||||||
- The failure occurs before xattr prefixes, mount data, mount flags, or a root
|
|
||||||
vnode are published.
|
|
||||||
- The legal directory-root path is unchanged after the new check.
|
|
||||||
|
|
||||||
## Validation Gate
|
|
||||||
|
|
||||||
The required targeted QEMU validation is:
|
|
||||||
|
|
||||||
1. Build and load the current DUT module.
|
|
||||||
2. Mount the valid paired fixture, verify mode `040755`, read its proof file,
|
|
||||||
and unmount it.
|
|
||||||
3. Mount the non-directory-root fixture and require exact errno `EINTEGRITY`.
|
|
||||||
4. Verify mount, md, KLD, and GEOM resources return to zero, then remount the
|
|
||||||
valid fixture.
|
|
||||||
5. Verify the kernel log has no panic, trap, or lock warning.
|
|
||||||
|
|
||||||
No full feature suite is part of H04.
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# Pre13 L-A1
|
|
||||||
|
|
||||||
This batch aligns the remaining low-risk helper vocabulary with Linux:
|
|
||||||
|
|
||||||
- `compress.h` now uses the Linux include guard name.
|
|
||||||
- `erofs_inode_is_data_compressed()` replaces four equivalent FULL/COMPACT
|
|
||||||
tests that do not need to distinguish the two layouts.
|
|
||||||
- `erofs_addrmask()` directly uses the existing 48-bit feature helper.
|
|
||||||
|
|
||||||
Static proof:
|
|
||||||
|
|
||||||
- For every value from zero through `EROFS_INODE_DATALAYOUT_MAX`, the new
|
|
||||||
compressed-layout helper equals the replaced boolean expression.
|
|
||||||
- The helper was not substituted in `zmap.c`, where FULL and COMPACT remain
|
|
||||||
distinct cases.
|
|
||||||
- `erofs_is_48bit()` and `erofs_sb_has_48bit()` tested the same incompat bit;
|
|
||||||
address-mask values and control flow are unchanged.
|
|
||||||
- The old include guard and duplicate 48-bit helper have no remaining source
|
|
||||||
consumers.
|
|
||||||
|
|
||||||
No build, QEMU, smoke, or feature test was run for this batch.
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# Pre13 L-A2
|
|
||||||
|
|
||||||
This batch mechanically aligns two local declaration groups with Linux:
|
|
||||||
|
|
||||||
- The xattr prefix cleanup/init functions follow the public get/list entry
|
|
||||||
points and precede the ACL entry point.
|
|
||||||
- The shifted/interlaced decompressor descriptors precede the LZ4 descriptor.
|
|
||||||
|
|
||||||
Only complete blocks moved. No prototype, function body, callback, conditional
|
|
||||||
compilation, or indexed descriptor slot changed. Pre-move and post-move hashes
|
|
||||||
of both xattr functions and all three descriptor definitions are identical;
|
|
||||||
the indexed descriptor table is byte-identical.
|
|
||||||
|
|
||||||
No build, QEMU, smoke, or feature test was run for this batch.
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# Pre13 L-B
|
|
||||||
|
|
||||||
This batch completes the planned semantic aliases for internal EROFS NIDs and
|
|
||||||
byte offsets. Each changed object was selected from the Pre13 variable-level
|
|
||||||
whitelist.
|
|
||||||
|
|
||||||
The aliases remain unsigned 64-bit types. No expression, cast, format string,
|
|
||||||
error path, field order, or control flow changed. File sizes, lengths, chunk
|
|
||||||
and extent indexes/counts, directory cookies, media sizes, timestamps, disk
|
|
||||||
fields, and overflow-only temporaries retain their previous types.
|
|
||||||
|
|
||||||
Declarations and definitions were updated together. The resulting source diff
|
|
||||||
contains only type tokens, line wrapping required by those tokens, and this
|
|
||||||
record.
|
|
||||||
|
|
||||||
No build, QEMU, smoke, or feature test was run for this batch.
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# Pre13 L-C1
|
|
||||||
|
|
||||||
This batch aligns the endian type vocabulary of named multi-byte on-disk
|
|
||||||
fields with the corresponding Linux EROFS declarations.
|
|
||||||
|
|
||||||
Only fields for which the same Linux structure and field use `__le16`,
|
|
||||||
`__le32`, or `__le64` were changed. Byte fields, arrays, field order, unions,
|
|
||||||
packing, macros, and all read/conversion sites remain unchanged. The direct
|
|
||||||
disk-type parameter of `erofs_xattr_ibody_size()` was synchronized.
|
|
||||||
|
|
||||||
The FreeBSD compatibility aliases map each `__leXX` type to the exact previous
|
|
||||||
unsigned integer type. A host-side probe compared 119 structure/union
|
|
||||||
size/alignment and named-field offset entries before and after the batch; all
|
|
||||||
values were identical. `tests/pre13_ondisk_layout_probe.c` retains legacy
|
|
||||||
definitions and exhaustive assertions for every modified structure so the
|
|
||||||
same proof can be compiled with the final FreeBSD guest toolchain. Existing
|
|
||||||
kernel `_Static_assert` checks remain unchanged.
|
|
||||||
|
|
||||||
No KLD build, QEMU, smoke, or feature test was run for this batch.
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# Pre13 L-C2
|
|
||||||
|
|
||||||
The two planned zero-length on-disk tail arrays now use standard flexible array
|
|
||||||
declarators:
|
|
||||||
|
|
||||||
- `erofs_xattr_ibody_header::h_shared_xattrs`
|
|
||||||
- `erofs_xattr_long_prefix::infix`
|
|
||||||
|
|
||||||
The layout probe retains the previous `[0]` declarations and asserts equal
|
|
||||||
structure size/alignment and member offsets. Host Clang accepts both old and
|
|
||||||
new declarations with the same warning/error result and identical layouts.
|
|
||||||
The probe is also retained for the final FreeBSD guest compiler gate.
|
|
||||||
|
|
||||||
No KLD build, QEMU, smoke, or feature test was run for this batch.
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# Pre13 L-D
|
|
||||||
|
|
||||||
The LZ4 two-byte little-endian offset now uses FreeBSD's unaligned-safe
|
|
||||||
`le16dec()` helper. Boundary checks, input advancement, zero/back-reference
|
|
||||||
validation, partial decoding, padding validation, and error returns are
|
|
||||||
unchanged.
|
|
||||||
|
|
||||||
An exhaustive 65,536-value comparison proved `ip[0] | (ip[1] << 8)` and
|
|
||||||
`le16dec(ip)` equivalent for every possible encoded offset. The final FreeBSD
|
|
||||||
KLD and LZ4 smoke gates remain required later; this phase does not run them.
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# Pre13 L-E
|
|
||||||
|
|
||||||
The BSD-only miscellaneous `erofs_defs.h` has been removed. Its three owners
|
|
||||||
now keep their constants in the files responsible for those values:
|
|
||||||
|
|
||||||
- `super.c` owns the named private CRC32C seed.
|
|
||||||
- `dir.c` uses `sizeof(struct erofs_dirent)` directly.
|
|
||||||
- `decompressor_lz4.c` owns its private LZ4 format constants.
|
|
||||||
|
|
||||||
The former header had exactly these three production source consumers. All
|
|
||||||
constant values and use-site expressions remain equivalent. Two already
|
|
||||||
retired userspace decompression test files still referenced the removed header;
|
|
||||||
they were deleted because they also depended on obsolete userspace ABIs and did
|
|
||||||
not compile independently. No current source or test entry retains the old
|
|
||||||
include. The LZ4 macro names remain private to `decompressor_lz4.c`; the former
|
|
||||||
shared CRC and dirent macro names have no current consumers. The current
|
|
||||||
architecture file was updated; historical reports were not changed.
|
|
||||||
|
|
||||||
No KLD build, QEMU, smoke, or feature test was run for this batch.
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
# Pre13 Stage0 Gate Decisions
|
|
||||||
|
|
||||||
## Scope and Baseline
|
|
||||||
|
|
||||||
- DUT repository baseline: `9028b92343ec7f5bbc1b07477b8d4a669c436955`.
|
|
||||||
- Clean tests-dev baseline: `ce03c283e6e2cb8f1b69c8eff21f7d06098a4fbe`.
|
|
||||||
- Stage0 was a planning gate. Infrastructure fixes made in tests-dev are not DUT changes.
|
|
||||||
- The complete Stage0 runner result is `FAIL`, not `PASS`, because the H01 DTrace probe failed.
|
|
||||||
|
|
||||||
## Gate A: ROOT-NONDIR
|
|
||||||
|
|
||||||
Status: `READY`.
|
|
||||||
|
|
||||||
The baseline incorrectly mounts an image whose root NID points to a regular file. Pre13 freezes the expected rejection errno as `EINTEGRITY`. H04 may proceed with the dedicated fixture and its required targeted validation.
|
|
||||||
|
|
||||||
## Gate B: ZERO-RUN
|
|
||||||
|
|
||||||
Status: `BLOCKED/STOP`.
|
|
||||||
|
|
||||||
The analysis covered 1,360 legal states and found no zero-progress state. H07 must be recorded as a no-op and must not be implemented in Pre13.
|
|
||||||
|
|
||||||
## Gate C: Map Tuple Oracle
|
|
||||||
|
|
||||||
Status: `BLOCKED/STOP`.
|
|
||||||
|
|
||||||
The oracle reliably covers only 26 plain, inline, and hole tuples. It does not cover chunk, multidevice, bounds, or overflow behavior. H01a, H01b, and H01c must not be implemented in Pre13.
|
|
||||||
|
|
||||||
## Gate D: Comparator
|
|
||||||
|
|
||||||
Status: `READY`.
|
|
||||||
|
|
||||||
The Python comparator corpus passed all 11,562 cases. The independent C harness passed all 1,048,576 cases. H03 may proceed within the planned boundaries and with its targeted validation.
|
|
||||||
|
|
||||||
## Gate E: Device Options
|
|
||||||
|
|
||||||
Status: incomplete and non-gating.
|
|
||||||
|
|
||||||
The `device.N` runtime probe was not completed. Pre13 makes no runtime behavior claim from this gate.
|
|
||||||
|
|
||||||
## Integrity and Cleanup
|
|
||||||
|
|
||||||
- Stage0 must not be described as an overall pass.
|
|
||||||
- Stage0-owned QEMU, SSH, ports, overlays, and temporary runtime resources were cleaned up.
|
|
||||||
- The guard VM and read-only base image were not modified.
|
|
||||||
- The pre-existing dirty tests-dev working tree was unchanged.
|
|
||||||
- Tests-dev runner and infrastructure repairs are evidence support only; they are not EROFS DUT fixes.
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
# 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/`.
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
# 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`.
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
# 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`.
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
# 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`.
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
# 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/`.
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
# repo-pre-2 Maintenance Baseline
|
|
||||||
|
|
||||||
## Snapshot Identity
|
|
||||||
|
|
||||||
`repo-pre-2` was created from the tracked `repo-pre-1` tree without copying
|
|
||||||
working-tree-only files or build artifacts.
|
|
||||||
|
|
||||||
```text
|
|
||||||
planning baseline commit: ed47f1b5583a229e372f488b9492d1f6234aae98
|
|
||||||
snapshot creation parent: 109fe74d3fcef107db5869be1d030f4f12d1cfa6
|
|
||||||
snapshot creation commit: 73fa57924b549387400eeeb85354bbbbe770a962
|
|
||||||
repo-pre-1 source tree: 6a5a1a49d4a4e08f6ef1155de240500e63a15365
|
|
||||||
repo-pre-2 snapshot tree: 6a5a1a49d4a4e08f6ef1155de240500e63a15365
|
|
||||||
Linux comparison tree: b79b9a8b62f633e887a8b99075ff9412fabd7f83
|
|
||||||
```
|
|
||||||
|
|
||||||
The matching source and snapshot tree IDs establish byte-for-byte content,
|
|
||||||
file-mode, and path equivalence at snapshot creation. `repo-pre-1` and
|
|
||||||
`src-linux` are read-only references for pre2 work.
|
|
||||||
|
|
||||||
## Phase Scope
|
|
||||||
|
|
||||||
Pre2 phase 1 is L0 mechanical maintenance alignment. It permits only the
|
|
||||||
separately reviewed changes listed below:
|
|
||||||
|
|
||||||
1. Remove stale Linux-only declaration fragments from `src/xattr.h` while
|
|
||||||
preserving every active FreeBSD interface.
|
|
||||||
2. Remove six specified, unreferenced private constants from
|
|
||||||
`src/erofs_defs.h`.
|
|
||||||
3. Rename the private checksum helper in `src/super.c` without changing its
|
|
||||||
signature, body, call position, or behavior.
|
|
||||||
|
|
||||||
Each source change must remain an independent commit. This phase does not add
|
|
||||||
features, fix behavior, move responsibilities between files, reorder data
|
|
||||||
structures, alter ABI, or broadly reformat code.
|
|
||||||
|
|
||||||
## Required FreeBSD Differences
|
|
||||||
|
|
||||||
Linux and FreeBSD EROFS remain independent implementations. The following
|
|
||||||
platform boundaries are intentional and must not be replaced merely to make
|
|
||||||
the source look more similar:
|
|
||||||
|
|
||||||
- FreeBSD VFS, vnode, mount, namecache, pager, and NFS export interfaces.
|
|
||||||
- FreeBSD buffer/cache, GEOM provider, device I/O, locking, and allocation
|
|
||||||
APIs.
|
|
||||||
- FreeBSD xattr, ACL, errno, kernel-module, and `bsd.kmod.mk` conventions.
|
|
||||||
- FreeBSD build gates, including the current amd64 restriction and optional
|
|
||||||
`ZSTDIO` integration.
|
|
||||||
|
|
||||||
Linux naming and layout should be followed only when doing so preserves these
|
|
||||||
native contracts and makes cross-repository review easier.
|
|
||||||
|
|
||||||
## Excluded Work
|
|
||||||
|
|
||||||
This phase does not address vnode ownership after `insmntque()` failure,
|
|
||||||
large-run allocation and `uiomove()` limits, compact pblk validation, 48-bit
|
|
||||||
boundaries, decompressor descriptors, backend ABI, typed errno, xattr parsing,
|
|
||||||
ACL behavior, file splitting, build-system alignment, CI, or test tooling.
|
|
||||||
|
|
||||||
## Validation Status
|
|
||||||
|
|
||||||
Only static snapshot and Git allowlist checks were performed for the
|
|
||||||
initialization commits. No build, QEMU run, test script, smoke test, mount, or
|
|
||||||
runtime feature check was performed. All runtime capabilities therefore remain
|
|
||||||
`NOT RUN` for repo-pre-2 until a later, explicitly authorized validation phase.
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
# repo-pre-3 Maintenance Baseline
|
|
||||||
|
|
||||||
## Snapshot Identity
|
|
||||||
|
|
||||||
`repo-pre-3` was created exclusively from the Git-tracked `repo-pre-2` tree.
|
|
||||||
Untracked files, ignored files, build outputs, and working-tree-only content
|
|
||||||
were not copied.
|
|
||||||
|
|
||||||
```text
|
|
||||||
snapshot source commit: 034f409841d2edaf7f140fc7475a357c924a5930
|
|
||||||
snapshot creation commit: 865a702341a82e61ab5ca1d5708a28005277cc0a
|
|
||||||
repo-pre-2 source tree: c28e015c74f4d012dfd070f887fabf75d4d4cb16
|
|
||||||
repo-pre-3 snapshot tree: c28e015c74f4d012dfd070f887fabf75d4d4cb16
|
|
||||||
tracked files per tree: 281
|
|
||||||
```
|
|
||||||
|
|
||||||
The matching tree IDs establish path, file-mode, and blob equivalence at
|
|
||||||
snapshot creation. `repo-pre-2`, `repo-pre-1`, and `src-linux` are read-only
|
|
||||||
references for pre3 work.
|
|
||||||
|
|
||||||
## Phase Scope
|
|
||||||
|
|
||||||
Pre3 is an L1 mechanical naming-alignment stage. It contains four independent
|
|
||||||
source tasks:
|
|
||||||
|
|
||||||
1. Rename `erofs_init_xattr_prefixes` and
|
|
||||||
`erofs_cleanup_xattr_prefixes` to the Linux-like lifecycle names
|
|
||||||
`erofs_xattr_prefixes_init` and `erofs_xattr_prefixes_cleanup`.
|
|
||||||
2. Rename the private ACL helper `erofs_getacl` to `erofs_get_acl`.
|
|
||||||
3. Rename `erofs_close_device` to `erofs_release_device_info` while retaining
|
|
||||||
its FreeBSD implementation.
|
|
||||||
4. Rename the private mount-state destructor `erofs_free_mount` to
|
|
||||||
`erofs_sb_free` while retaining its complete FreeBSD cleanup body.
|
|
||||||
|
|
||||||
Only function names and their closed sets of declarations, definitions, and
|
|
||||||
call sites may change. Signatures, behavior, control flow, ordering, locking,
|
|
||||||
ownership, error handling, and file responsibilities must remain unchanged.
|
|
||||||
|
|
||||||
## Required FreeBSD Differences
|
|
||||||
|
|
||||||
- Xattr-prefix helpers continue to use `struct erofs_mount *`, not Linux
|
|
||||||
`struct super_block *`.
|
|
||||||
- ACL handling continues to use FreeBSD `struct vnode *`, `struct acl *`, and
|
|
||||||
integer errno conventions.
|
|
||||||
- Device teardown continues to release GEOM consumers, vnode references, and
|
|
||||||
cdev references in the existing order and under the existing locking rules.
|
|
||||||
It must not adopt the Linux callback signature or ownership model.
|
|
||||||
- Mount-state teardown continues to release all FreeBSD GEOM and private
|
|
||||||
filesystem state. A Linux-like name does not make the implementations or
|
|
||||||
lifecycle contracts interchangeable.
|
|
||||||
|
|
||||||
## Excluded Work
|
|
||||||
|
|
||||||
Pre3 does not include feature changes, correctness fixes, ABI changes, codec
|
|
||||||
work, xattr or ACL behavior changes, function reordering, structure layout
|
|
||||||
changes, file splitting, build-system changes, formatting cleanup, or repairs
|
|
||||||
to earlier planning and snapshot material.
|
|
||||||
|
|
||||||
## Git Workflow
|
|
||||||
|
|
||||||
The snapshot, this baseline document, and each of the four rename batches are
|
|
||||||
separate commits. Every commit must be pushed immediately to `xdm main` and
|
|
||||||
must not be squashed with another batch. Before each commit, its staged paths
|
|
||||||
must be checked against the task-specific allowlist. After each push, local
|
|
||||||
`HEAD`, `xdm/main`, and remote `main` must identify the same commit.
|
|
||||||
|
|
||||||
## Validation Status
|
|
||||||
|
|
||||||
Only static snapshot-equivalence, path-allowlist, Git-state, and documentation
|
|
||||||
checks were performed for pre3 initialization.
|
|
||||||
|
|
||||||
```text
|
|
||||||
build: NOT RUN
|
|
||||||
QEMU: NOT RUN
|
|
||||||
test scripts: NOT RUN
|
|
||||||
smoke tests: NOT RUN
|
|
||||||
mount/runtime: NOT RUN
|
|
||||||
feature validation: NOT RUN
|
|
||||||
```
|
|
||||||
|
|
||||||
No compile-time or runtime PASS is claimed by this document. Existing reports
|
|
||||||
copied from `repo-pre-2` are historical material and are not fresh validation
|
|
||||||
of `repo-pre-3`.
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
# Pre3 Smoke Test Report - 2026-08-12
|
|
||||||
|
|
||||||
## Result
|
|
||||||
|
|
||||||
The `repo-pre-3` plain/LZ4 differential smoke test **PASSed** within the scope documented below.
|
|
||||||
|
|
||||||
| Field | Value |
|
|
||||||
|---|---|
|
|
||||||
| Run ID | `20260812T110037.575683Z-693361-ac21acee` |
|
|
||||||
| Process exit code | `0` |
|
|
||||||
| Guest return code | `0` |
|
|
||||||
| Runner stages | `12/12 passed` |
|
|
||||||
| Elapsed time | `18m51s` |
|
|
||||||
| DUT outer commit | `1a2361bfae2f6b4e7fc4c89d97d05f44553a5ba7` (`1a2361b`) |
|
|
||||||
| DUT path tree | `902a32fbfc1274d4404174346953d19e41c61f1f` |
|
|
||||||
| DUT content SHA256 | `07aa856f0c0d9d0d084dbcb5d743cf4831a7f2ab884b51941db7d1840b248c60` |
|
|
||||||
| KLD SHA256 | `59650f03029afc31658dcf3386105d001122d7702b8144e7c5925d9d9ed4accb` |
|
|
||||||
| Base image SHA256 | `67f359621f23a1d745f0889370cbb99a096cee3e99a0b2f3bb18fc7a91bf6fef` |
|
|
||||||
| Base image mode | `0444`, unchanged before and after |
|
|
||||||
|
|
||||||
Primary evidence:
|
|
||||||
|
|
||||||
- [result.json](/work/tests-dev/erofsstress/demo-result/repo-pre-3-smoke-20260812/20260812T110037.575683Z-693361-ac21acee/result.json)
|
|
||||||
- [summary.txt](/work/tests-dev/erofsstress/demo-result/repo-pre-3-smoke-20260812/20260812T110037.575683Z-693361-ac21acee/summary.txt)
|
|
||||||
- [guest evidence directory](/work/tests-dev/erofsstress/demo-result/repo-pre-3-smoke-20260812/20260812T110037.575683Z-693361-ac21acee/guest-evidence)
|
|
||||||
- [guest-result.json](/work/tests-dev/erofsstress/demo-result/repo-pre-3-smoke-20260812/20260812T110037.575683Z-693361-ac21acee/guest-evidence/guest-result.json)
|
|
||||||
|
|
||||||
## Invocation
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./test.sh --dut /work/erofs-freebsd-pre/repo-pre-3 \
|
|
||||||
--base-image /work/tests-dev/lfs/freebsd-15-dev-src-20260811.bp \
|
|
||||||
--duration 10 \
|
|
||||||
--output demo-result/repo-pre-3-smoke-20260812
|
|
||||||
```
|
|
||||||
|
|
||||||
Evidence root:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/work/tests-dev/erofsstress/demo-result/repo-pre-3-smoke-20260812/20260812T110037.575683Z-693361-ac21acee/
|
|
||||||
```
|
|
||||||
|
|
||||||
## PASS Scope
|
|
||||||
|
|
||||||
The successful run covered:
|
|
||||||
|
|
||||||
- FreeBSD guest boot and SSH readiness.
|
|
||||||
- DUT build with `WITH_ZSTDIO=0` and loading the exact generated `erofs.ko`.
|
|
||||||
- Creation and use of plain and LZ4 EROFS fixtures.
|
|
||||||
- Attach, mount, differential workload, unmount, and fixture cleanup.
|
|
||||||
- Four workers per fixture for five seconds each.
|
|
||||||
- Differential random, aligned, unaligned, full-file, and EOF reads.
|
|
||||||
- Directory enumeration, symbolic-link reads, and `fadvise` operations.
|
|
||||||
- Host and guest resource cleanup after the workload.
|
|
||||||
|
|
||||||
The guest-side stages and fixture identities are recorded in [stages.txt](/work/tests-dev/erofsstress/demo-result/repo-pre-3-smoke-20260812/20260812T110037.575683Z-693361-ac21acee/guest-evidence/stages.txt) and [scenarios.txt](/work/tests-dev/erofsstress/demo-result/repo-pre-3-smoke-20260812/20260812T110037.575683Z-693361-ac21acee/guest-evidence/scenarios.txt). Per-worker evidence is available in the same guest evidence directory.
|
|
||||||
|
|
||||||
## SKIPPED And Non-Claims
|
|
||||||
|
|
||||||
The following tests were **SKIPPED** and have no execution evidence in this run:
|
|
||||||
|
|
||||||
| Test | Area | Status |
|
|
||||||
|---|---|---|
|
|
||||||
| `TC079` | xattr prefix initialization, lookup, and cleanup | `SKIPPED` |
|
|
||||||
| `TC138` | ACL parsing and error paths | `SKIPPED` |
|
|
||||||
| `TC099` | multidevice mount and release paths | `SKIPPED` |
|
|
||||||
|
|
||||||
This report therefore does **not** claim that xattr prefix handling, ACL behavior, multidevice behavior, ZSTD, LZMA, DEFLATE, or the full feature/regression suite passed. The PASS result is limited to the plain/LZ4 differential smoke scope listed above.
|
|
||||||
|
|
||||||
## Integrity And Cleanup
|
|
||||||
|
|
||||||
- The DUT content hash, commit, and tree were identical before and after the run; the test did not modify `repo-pre-3`.
|
|
||||||
- The read-only base image remained mode `0444` with the same SHA256 before and after the run.
|
|
||||||
- New QEMU PID `693836` exited gracefully.
|
|
||||||
- Test port `10000` was released.
|
|
||||||
- The qcow2 overlay was deleted and the port lock became available.
|
|
||||||
- Guard PID `26318` and guard port `9222` retained the same process identity, start time, and command hash.
|
|
||||||
- The generated result directory under `tests-dev` is evidence only and was not committed.
|
|
||||||
|
|
||||||
## Honesty Review
|
|
||||||
|
|
||||||
The post-run honesty audit **PASSed**. It found no concealed source fix, result substitution, or exaggerated coverage claim. The guest log filename `repo22-build.txt` and related `repo22` stage labels are inherited labels in the test harness; they do not identify the DUT. The DUT is independently bound to `repo-pre-3` by the recorded commit, path tree, content hash, archived source, and generated KLD hash.
|
|
||||||
|
|
||||||
The complete machine-readable record remains authoritative for details not reproduced here: [result.json](/work/tests-dev/erofsstress/demo-result/repo-pre-3-smoke-20260812/20260812T110037.575683Z-693361-ac21acee/result.json).
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
# Pre5 Extraction Baseline
|
|
||||||
|
|
||||||
## Repository Baseline
|
|
||||||
|
|
||||||
- Outer starting commit: `6421919003ecfab5317dfa70959ab81cd9bbc990`
|
|
||||||
- Starting `repo-pre-5` tree: `f99462eee8898af209332ef202f8da07f2dd567e`
|
|
||||||
- Starting `repo-pre-5/src/super.c` blob: `c150d795df42ae4136fbd6e74c3b88903341b05a`
|
|
||||||
- Execution target: the existing `repo-pre-5` directory
|
|
||||||
- Source allowlist for the later extraction commits: `repo-pre-5/src/super.c`
|
|
||||||
|
|
||||||
The fixed tree and blob identifiers above were read from Git before this
|
|
||||||
document was created. Pre5 works directly on `repo-pre-5`; it does not create
|
|
||||||
another snapshot.
|
|
||||||
|
|
||||||
## Stage Scope
|
|
||||||
|
|
||||||
Pre5 is an L2-S private cleanup responsibility extraction stage. It has two
|
|
||||||
source tasks:
|
|
||||||
|
|
||||||
1. Extract the existing extra-device cleanup from `erofs_sb_free()` into
|
|
||||||
`static void erofs_free_dev_context(struct erofs_mount *em)`.
|
|
||||||
2. Extract the existing metabox and packed-inode cleanup from
|
|
||||||
`erofs_sb_free()` into
|
|
||||||
`static void erofs_drop_internal_inodes(struct erofs_mount *em)`.
|
|
||||||
|
|
||||||
Both tasks are statement movement only. They must preserve FreeBSD GEOM,
|
|
||||||
vnode, allocation, and ownership semantics. They must not change behavior,
|
|
||||||
ABI, features, error handling, locking, logging, conditions, release calls, or
|
|
||||||
object ownership.
|
|
||||||
|
|
||||||
## Protected Paths
|
|
||||||
|
|
||||||
The following paths must remain unchanged during Pre5 execution:
|
|
||||||
|
|
||||||
- `repo-pre-3/`
|
|
||||||
- `repo-pre-2/`
|
|
||||||
- `repo-pre-1/`
|
|
||||||
- `src-linux/`
|
|
||||||
- `planning/reject/`
|
|
||||||
- existing reports and other planning stages
|
|
||||||
|
|
||||||
Except for this baseline document, no path outside
|
|
||||||
`repo-pre-5/src/super.c` belongs in the Pre5 source commits.
|
|
||||||
|
|
||||||
## Cleanup-Order Invariant
|
|
||||||
|
|
||||||
The effective cleanup order must remain exactly:
|
|
||||||
|
|
||||||
```text
|
|
||||||
xattr prefixes
|
|
||||||
-> metabox
|
|
||||||
-> packed inode
|
|
||||||
-> extra devices in reverse order
|
|
||||||
-> primary device
|
|
||||||
-> mount state
|
|
||||||
```
|
|
||||||
|
|
||||||
The extraction must not add pointer clearing, conditions, assertions, logs,
|
|
||||||
locks, return values, error handling, or header declarations.
|
|
||||||
|
|
||||||
## Commit and Push Discipline
|
|
||||||
|
|
||||||
Each Pre5 commit must contain one planned logical task and must be pushed
|
|
||||||
immediately to `xdm main`. The commits must not be squashed. Execution must
|
|
||||||
stop if a push fails or if local, tracking, and remote commit identities
|
|
||||||
diverge.
|
|
||||||
|
|
||||||
## Validation Status at Baseline
|
|
||||||
|
|
||||||
| Validation item | Status |
|
|
||||||
|---|---|
|
|
||||||
| Static Git baseline capture | RECORDED |
|
|
||||||
| Source extraction tasks | NOT RUN |
|
|
||||||
| Build with `WITH_ZSTDIO=0` | NOT RUN |
|
|
||||||
| Build with `WITH_ZSTDIO=1` | NOT RUN |
|
|
||||||
| QEMU smoke testing | NOT RUN |
|
|
||||||
| Manual or automated tests | NOT RUN |
|
|
||||||
|
|
||||||
No build, QEMU run, feature validation, regression test, or runtime result is
|
|
||||||
claimed by this document.
|
|
||||||
@@ -1,268 +0,0 @@
|
|||||||
# Pre5 Completion Report
|
|
||||||
|
|
||||||
Date: 2026-08-12
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
| Area | Result | Notes |
|
|
||||||
|---|---|---|
|
|
||||||
| Planned source extraction | PASS | Both private cleanup helpers are present in `repo-pre-5/src/super.c`. |
|
|
||||||
| Static correctness review | PASS | No High or Medium findings; statement order and FreeBSD cleanup behavior are preserved. |
|
|
||||||
| Commit recoverability | PASS after correction | The initial split commits were non-destructively reverted and replaced by one independently revertible atomic source commit. |
|
|
||||||
| `WITH_ZSTDIO=0` build | PASS | Exit code 0, zero warnings, zero errors. |
|
|
||||||
| Module load | NOT RUN | The produced `erofs.ko` was not loaded. |
|
|
||||||
| QEMU functional testing | NOT RUN | No functional or regression test was run for Pre5. |
|
|
||||||
| Pre5 smoke test | DEFERRED | Deferred for a combined Pre5/Pre6 smoke run. |
|
|
||||||
|
|
||||||
Pre5 is complete for its planned source changes, static review, and required
|
|
||||||
build gate. This report does not claim runtime, feature, regression, or smoke
|
|
||||||
test coverage.
|
|
||||||
|
|
||||||
The final Pre5 source commit is
|
|
||||||
`4535cccaf1ca1837f0a2d1cca526e5f138a23c6d`. This report is created after that
|
|
||||||
commit and, when committed, its documentation commit will therefore follow the
|
|
||||||
final source commit.
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
Pre5 directly modified `repo-pre-5`; no new repository snapshot was created.
|
|
||||||
The starting planning commit was:
|
|
||||||
|
|
||||||
```text
|
|
||||||
6421919003ecfab5317dfa70959ab81cd9bbc990
|
|
||||||
docs: plan repo-pre-5 cleanup extraction phase
|
|
||||||
```
|
|
||||||
|
|
||||||
The baseline documentation commit was:
|
|
||||||
|
|
||||||
```text
|
|
||||||
0666800fa529a8869757da85f2e69b8e1dd2c9f6
|
|
||||||
docs: record pre5 extraction baseline
|
|
||||||
```
|
|
||||||
|
|
||||||
The baseline recorded the following source identity:
|
|
||||||
|
|
||||||
```text
|
|
||||||
repo-pre-5/src/super.c blob:
|
|
||||||
c150d795df42ae4136fbd6e74c3b88903341b05a
|
|
||||||
```
|
|
||||||
|
|
||||||
The source scope was limited to extracting two existing cleanup regions from
|
|
||||||
`erofs_sb_free()` into private helpers. No feature, ABI, error handling,
|
|
||||||
locking, logging, ownership, or cleanup policy change was intended.
|
|
||||||
|
|
||||||
## Final Implementation
|
|
||||||
|
|
||||||
The final implementation is in [`src/super.c`](../src/super.c).
|
|
||||||
|
|
||||||
### Extra-device cleanup
|
|
||||||
|
|
||||||
`erofs_free_dev_context()` is a `static void` helper with exactly one
|
|
||||||
definition and one call. It contains only the existing extra-device cleanup:
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void
|
|
||||||
erofs_free_dev_context(struct erofs_mount *em)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (em->devs != NULL) {
|
|
||||||
for (i = em->extra_devices; i > 0; --i)
|
|
||||||
erofs_release_device_info(&em->devs[i - 1]);
|
|
||||||
free(em->devs, M_EROFS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The reverse close order is unchanged. The primary device remains outside this
|
|
||||||
helper and is still released separately by `erofs_sb_free()`.
|
|
||||||
|
|
||||||
### Internal-inode cleanup
|
|
||||||
|
|
||||||
`erofs_drop_internal_inodes()` is a `static void` helper with exactly one
|
|
||||||
definition and one call. It contains only the existing metabox and packed
|
|
||||||
inode releases:
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void
|
|
||||||
erofs_drop_internal_inodes(struct erofs_mount *em)
|
|
||||||
{
|
|
||||||
if (em->metabox_en != NULL)
|
|
||||||
free(em->metabox_en, M_EROFS);
|
|
||||||
if (em->packed_inode != NULL)
|
|
||||||
free(em->packed_inode, M_EROFS);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This remains a FreeBSD allocation cleanup path. It does not copy Linux
|
|
||||||
`iput()` or Linux inode-lifecycle semantics.
|
|
||||||
|
|
||||||
### Preserved cleanup order
|
|
||||||
|
|
||||||
The effective cleanup order remains:
|
|
||||||
|
|
||||||
```text
|
|
||||||
xattr prefixes
|
|
||||||
-> metabox
|
|
||||||
-> packed inode
|
|
||||||
-> extra devices in reverse order
|
|
||||||
-> primary device
|
|
||||||
-> mount state
|
|
||||||
```
|
|
||||||
|
|
||||||
The final caller is:
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void
|
|
||||||
erofs_sb_free(struct erofs_mount *em)
|
|
||||||
{
|
|
||||||
if (em == NULL)
|
|
||||||
return;
|
|
||||||
erofs_xattr_prefixes_cleanup(em);
|
|
||||||
erofs_drop_internal_inodes(em);
|
|
||||||
erofs_free_dev_context(em);
|
|
||||||
erofs_release_device_info(&em->dif0);
|
|
||||||
free(em, M_EROFS);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Static expansion of both helpers produces the baseline statement sequence.
|
|
||||||
No condition, loop direction, release function, pointer clearing, lock, errno,
|
|
||||||
log message, return value, or ownership rule was added or changed.
|
|
||||||
|
|
||||||
## Commit Timeline
|
|
||||||
|
|
||||||
| Commit | Purpose | Result |
|
|
||||||
|---|---|---|
|
|
||||||
| `6421919` | Establish the Pre5 execution plan | Baseline planning point. |
|
|
||||||
| `0666800` | Record the source baseline and validation status | Documentation only. |
|
|
||||||
| `52dca2e` | Initially extract `erofs_free_dev_context()` | Static behavior correct. |
|
|
||||||
| `e9b9fb2` | Initially extract `erofs_drop_internal_inodes()` | Static behavior correct. |
|
|
||||||
| `c406813` | Revert `e9b9fb2` | Non-destructively removed the second helper first. |
|
|
||||||
| `20733bd` | Revert `52dca2e` | Restored the exact baseline `super.c` blob. |
|
|
||||||
| `4535ccc` | Atomically introduce both cleanup helpers | Final source implementation. |
|
|
||||||
|
|
||||||
The initial two source commits were behaviorally correct. The static audit
|
|
||||||
found a commit-organization defect: after `e9b9fb2`, the earlier `52dca2e`
|
|
||||||
could not be independently reverted from the final HEAD without conflict
|
|
||||||
because both commits edited the same tightly coupled `erofs_sb_free()` region.
|
|
||||||
|
|
||||||
No history rewrite or destructive reset was used. The correction was:
|
|
||||||
|
|
||||||
1. Revert `e9b9fb2` with `c406813`.
|
|
||||||
2. Revert `52dca2e` with `20733bd`.
|
|
||||||
3. Confirm that `super.c` returned to baseline blob
|
|
||||||
`c150d795df42ae4136fbd6e74c3b88903341b05a`.
|
|
||||||
4. Reintroduce both helpers in atomic commit `4535ccc`.
|
|
||||||
|
|
||||||
The final `super.c` blob is:
|
|
||||||
|
|
||||||
```text
|
|
||||||
03b92560bb5ef01f322b0d052f84bc3c577ef829
|
|
||||||
```
|
|
||||||
|
|
||||||
This is byte-for-byte identical to the correct source state at `e9b9fb2`.
|
|
||||||
The final commit `4535ccc` can be reverted without conflict and restores the
|
|
||||||
baseline blob.
|
|
||||||
|
|
||||||
The original plan preferred one source task per commit. That rule was adjusted
|
|
||||||
because the two extractions share one cleanup sequence and one caller region;
|
|
||||||
separate commits weakened independent rollback despite preserving behavior.
|
|
||||||
One atomic source commit provides a clearer and mechanically verifiable
|
|
||||||
rollback boundary without changing the planned source result.
|
|
||||||
|
|
||||||
## Static Review Evidence
|
|
||||||
|
|
||||||
The final independent static review result was PASS with no High or Medium
|
|
||||||
findings.
|
|
||||||
|
|
||||||
Verified properties:
|
|
||||||
|
|
||||||
- Only `repo-pre-5/src/super.c` differs from the source baseline.
|
|
||||||
- Both helpers are `static void` and each has one definition and one call.
|
|
||||||
- Extra devices are still released in reverse order before `em->devs` is
|
|
||||||
freed.
|
|
||||||
- Metabox cleanup still precedes packed-inode cleanup.
|
|
||||||
- The primary device remains a separate release after the extra-device
|
|
||||||
context.
|
|
||||||
- The mount state remains the final allocation released.
|
|
||||||
- Expanding both helpers recovers the original cleanup statement sequence.
|
|
||||||
- No header, exported interface, ABI, feature, condition, lock, errno, log, or
|
|
||||||
ownership change was introduced.
|
|
||||||
- No deferred correctness, codec, descriptor, formatting, or feature work was
|
|
||||||
mixed into Pre5.
|
|
||||||
- `repo-pre-1/`, `repo-pre-2/`, `repo-pre-3/`, `src-linux/`, planning files,
|
|
||||||
reject records, and earlier reports remained protected from source changes.
|
|
||||||
|
|
||||||
The source result therefore satisfies the intended L2-S responsibility
|
|
||||||
extraction while preserving the necessary FreeBSD cleanup implementation.
|
|
||||||
|
|
||||||
## Build Evidence
|
|
||||||
|
|
||||||
The required build gate was executed in the existing FreeBSD 15 VM with PID
|
|
||||||
`26318`. No new VM was started for this build.
|
|
||||||
|
|
||||||
Command:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
FREEBSD_SRC=/root/pre5-build-gate-20260812T125645Z/freebsd-src \
|
|
||||||
WITH_ZSTDIO=0 ./build.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Result:
|
|
||||||
|
|
||||||
| Evidence | Value |
|
|
||||||
|---|---|
|
|
||||||
| Exit code | `0` |
|
|
||||||
| Compiler warnings | `0` |
|
|
||||||
| Compiler errors | `0` |
|
|
||||||
| Build log | `repo-pre-5/build/pre5-zstdio0-20260812T125645Z/build.log` |
|
|
||||||
| Module | `repo-pre-5/build/pre5-zstdio0-20260812T125645Z/erofs.ko` |
|
|
||||||
| Module size | `78,248` bytes |
|
|
||||||
| Module SHA256 | `0a2928a711715a22dfe243a536f514395acd52af3cec5515bd4bb003e42a14ac` |
|
|
||||||
|
|
||||||
The build artifacts are under the ignored `repo-pre-5/build/` directory and
|
|
||||||
must not be committed. The module was not loaded, and the build result alone
|
|
||||||
does not establish runtime behavior.
|
|
||||||
|
|
||||||
## Not Run And Deferred
|
|
||||||
|
|
||||||
| Item | Status | Meaning |
|
|
||||||
|---|---|---|
|
|
||||||
| Load produced `erofs.ko` | NOT RUN | Module load and unload behavior were not checked. |
|
|
||||||
| QEMU functional testing | NOT RUN | No functional test VM run was performed for Pre5. |
|
|
||||||
| Feature or regression suite | NOT RUN | No feature-completeness claim is made. |
|
|
||||||
| Pre5 standalone smoke test | DEFERRED | Deferred by user direction and risk assessment. |
|
|
||||||
| Combined Pre5/Pre6 smoke test | REQUIRED LATER | Must be performed after Pre6 before claiming runtime coverage. |
|
|
||||||
|
|
||||||
The Pre5 changes only extract existing private cleanup statements, and the
|
|
||||||
static review plus build gate found no source or compiler issue requiring an
|
|
||||||
immediate standalone smoke run. To avoid duplicating a relatively expensive VM
|
|
||||||
cycle, the smoke test is deferred and will be combined with Pre6.
|
|
||||||
|
|
||||||
The combined Pre5/Pre6 smoke run must cover at least:
|
|
||||||
|
|
||||||
1. Plain and LZ4 basic build, module load, mount, read, readdir, unmount, and
|
|
||||||
cleanup.
|
|
||||||
2. `TC099` multi-device success, missing-device failure, and device cleanup.
|
|
||||||
3. A packed-inode/metabox fixture mount and unmount path that exercises
|
|
||||||
internal-inode cleanup.
|
|
||||||
|
|
||||||
None of these deferred checks is claimed as passed by this report.
|
|
||||||
|
|
||||||
## Residual Risk
|
|
||||||
|
|
||||||
- The compiled module has not been loaded, so loader, symbol-resolution, and
|
|
||||||
unload behavior remain unverified for the final source commit.
|
|
||||||
- Failure and partial-initialization paths have only been reviewed statically.
|
|
||||||
- Multi-device cleanup has not been exercised at runtime after extracting
|
|
||||||
`erofs_free_dev_context()`.
|
|
||||||
- Packed-inode and metabox cleanup has not been exercised at runtime after
|
|
||||||
extracting `erofs_drop_internal_inodes()`.
|
|
||||||
- `WITH_ZSTDIO=1` was not built in this stage.
|
|
||||||
- No QEMU smoke, feature suite, stress test, or regression test has been run
|
|
||||||
specifically against the final Pre5 source state.
|
|
||||||
|
|
||||||
These risks are accepted for the current stage and are carried into the
|
|
||||||
combined Pre5/Pre6 smoke gate. Until that gate runs, Pre5 should be described
|
|
||||||
as static-review PASS and `WITH_ZSTDIO=0` build PASS, not runtime PASS.
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
# Pre6 Initialization Baseline
|
|
||||||
|
|
||||||
## Repository Baseline
|
|
||||||
|
|
||||||
- Outer starting commit: `bfed0431693e7798bdecacd78b7e6258c2d93c5a`
|
|
||||||
- Starting `repo-pre-6` tree: `b4a40164394b378adc947d6ad14dc7c845e79b2c`
|
|
||||||
- Starting `repo-pre-6/src/super.c` blob: `03b92560bb5ef01f322b0d052f84bc3c577ef829`
|
|
||||||
- Execution target: the existing `repo-pre-6` directory
|
|
||||||
- Source allowlist for later extraction commits: `repo-pre-6/src/super.c`
|
|
||||||
|
|
||||||
The tree and blob identities above were read from Git before this document was
|
|
||||||
created. Pre6 works directly on `repo-pre-6`; it does not create another source
|
|
||||||
snapshot.
|
|
||||||
|
|
||||||
## Stage Scope
|
|
||||||
|
|
||||||
Pre6 is an L2-I private mount-initialization responsibility extraction stage.
|
|
||||||
It contains three helper tasks:
|
|
||||||
|
|
||||||
1. Extract one decoded external-device initialization block into
|
|
||||||
`static int erofs_init_device(...)`.
|
|
||||||
2. Extract packed-carrier initialization into
|
|
||||||
`static int erofs_init_packed_inode(struct erofs_mount *em)`.
|
|
||||||
3. Extract metabox initialization into
|
|
||||||
`static int erofs_init_metabox_inode(struct erofs_mount *em)`.
|
|
||||||
|
|
||||||
These tasks move existing statements into private helpers. They must not change
|
|
||||||
features, behavior, public interfaces, error handling, allocation, cleanup,
|
|
||||||
logging, locking, GEOM operations, or object ownership.
|
|
||||||
|
|
||||||
## Source Commit Strategy
|
|
||||||
|
|
||||||
The source work is delivered in two commits:
|
|
||||||
|
|
||||||
1. One independent commit for `erofs_init_device()`.
|
|
||||||
2. One atomic commit for `erofs_init_packed_inode()` and
|
|
||||||
`erofs_init_metabox_inode()`.
|
|
||||||
|
|
||||||
Packed and metabox initialization remain one ownership unit because their
|
|
||||||
blocks are adjacent and a fragment-backed metabox can depend on the packed
|
|
||||||
carrier. No intermediate commit may contain only one internal-inode helper.
|
|
||||||
|
|
||||||
Each commit, including this baseline commit, must be pushed immediately to
|
|
||||||
`xdm main`. Execution must stop if local HEAD, `xdm/main`, and remote `main`
|
|
||||||
do not agree after a push.
|
|
||||||
|
|
||||||
## Protected Paths
|
|
||||||
|
|
||||||
The following paths must remain unchanged during Pre6 execution:
|
|
||||||
|
|
||||||
- `repo-pre-1/`
|
|
||||||
- `repo-pre-2/`
|
|
||||||
- `repo-pre-3/`
|
|
||||||
- `repo-pre-5/`
|
|
||||||
- `src-linux/`
|
|
||||||
- `planning/reject/`
|
|
||||||
- `1-code-similarity-review/`
|
|
||||||
- existing planning documents and reports
|
|
||||||
|
|
||||||
Except for Pre6 documents under `repo-pre-6/docs/`, no path outside
|
|
||||||
`repo-pre-6/src/super.c` belongs in the planned source commits.
|
|
||||||
|
|
||||||
## Behavior-Preservation Invariants
|
|
||||||
|
|
||||||
- Preserve the order of every moved statement and every helper call.
|
|
||||||
- Preserve all conditions, loop direction, values, types, casts, and return
|
|
||||||
values.
|
|
||||||
- Preserve every errno and log message without translation or normalization.
|
|
||||||
- Preserve allocations, frees, NULL assignments, and failure paths.
|
|
||||||
- Preserve the current owner and lifetime of every buffer, device, inode, and
|
|
||||||
mount resource.
|
|
||||||
- Keep `erofs_open_device()` unchanged as the FreeBSD GEOM open transaction.
|
|
||||||
- Keep external-device slot lookup and ascending iteration in
|
|
||||||
`erofs_scan_devices()`.
|
|
||||||
- Keep packed inode initialization before metabox inode initialization.
|
|
||||||
- Keep `erofs_mountfs()` as the common failure owner that calls
|
|
||||||
`erofs_sb_free()`.
|
|
||||||
- Add no rollback, validation, cleanup, logging, locking, or defensive changes.
|
|
||||||
- Keep all new helpers private and add no header declarations.
|
|
||||||
|
|
||||||
If an extraction requires a behavior, ownership, ordering, or errno change,
|
|
||||||
execution must stop instead of expanding Pre6 scope.
|
|
||||||
|
|
||||||
## Validation Status at Baseline
|
|
||||||
|
|
||||||
| Validation item | Status |
|
|
||||||
|---|---|
|
|
||||||
| Static Git baseline capture | RECORDED |
|
|
||||||
| Device initialization extraction | NOT RUN |
|
|
||||||
| Packed and metabox initialization extraction | NOT RUN |
|
|
||||||
| Static equivalence and independent revert gates | NOT RUN |
|
|
||||||
| Build with `WITH_ZSTDIO=0` | NOT RUN |
|
|
||||||
| Plain/LZ4 smoke test | NOT RUN |
|
|
||||||
| Complete `TC099` multi-device smoke test | NOT RUN |
|
|
||||||
| Positive `TC142` metabox smoke test | NOT RUN |
|
|
||||||
| Other build, QEMU, or runtime tests | NOT RUN |
|
|
||||||
|
|
||||||
No source extraction, build, QEMU run, feature validation, regression test, or
|
|
||||||
runtime result is claimed by this baseline document.
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
# Pre7 Helper-Alignment Baseline
|
|
||||||
|
|
||||||
## Repository Baseline
|
|
||||||
|
|
||||||
- Execution-start commit: `3f5f783b9f316af6d3887421251cc79909aed934`
|
|
||||||
- Starting `repo-pre-7` tree: `909ffaa0f586a51933f4220a8fe67d963d5b1dff`
|
|
||||||
- Starting `repo-pre-6` tree: `909ffaa0f586a51933f4220a8fe67d963d5b1dff`
|
|
||||||
- Starting `repo-pre-7/src/internal.h` blob: `253a30a595f9740ce97de865cc6f255f8eda2b74`
|
|
||||||
- Starting `repo-pre-7/src/inode.c` blob: `c753c14fdc48ae53e6dd2554cb9dc4a5b8a6c569`
|
|
||||||
- Starting `repo-pre-7/src/xattr.c` blob: `cef4db2a8d03be028c0344941cea60def9cd84ce`
|
|
||||||
- Execution target: the existing `repo-pre-7` directory
|
|
||||||
|
|
||||||
The tracked `repo-pre-7` baseline is an exact snapshot of `repo-pre-6` at the
|
|
||||||
execution-start commit. The identities above were read from Git objects at
|
|
||||||
that commit, not inferred from the live worktree.
|
|
||||||
|
|
||||||
Uncommitted changes were already present in `repo-pre-7/src/internal.h` and
|
|
||||||
`repo-pre-7/src/inode.c` when this document was written. This baseline does
|
|
||||||
not assess, validate, or claim completion of those changes.
|
|
||||||
|
|
||||||
## Exact Source Scope
|
|
||||||
|
|
||||||
Pre7 contains exactly two source tasks:
|
|
||||||
|
|
||||||
1. Rename the private inode-location helper from
|
|
||||||
`erofs_nid_to_offset()` to `erofs_iloc()` in
|
|
||||||
`repo-pre-7/src/internal.h` and `repo-pre-7/src/inode.c`. This is an
|
|
||||||
identifier-only alignment; the FreeBSD signature, implementation,
|
|
||||||
callers, metabox handling, overflow checks, and failure behavior remain
|
|
||||||
unchanged.
|
|
||||||
2. Extract the private `erofs_xattr_prefix()` mapping helper from
|
|
||||||
`erofs_xattr_namespace_prefix()` in `repo-pre-7/src/xattr.c`. The existing
|
|
||||||
wrapper retains FreeBSD namespace validation, namespace matching, errno
|
|
||||||
selection, and all existing get/list call sites.
|
|
||||||
|
|
||||||
No other source file, helper cleanup, behavior change, public interface
|
|
||||||
change, formatting pass, or deferred planning item belongs in Pre7.
|
|
||||||
|
|
||||||
## Validation Status
|
|
||||||
|
|
||||||
Per the current execution instruction, this baseline-recording step performs
|
|
||||||
no build or test activity. Historical Pre6 evidence is not a Pre7 result.
|
|
||||||
|
|
||||||
| Validation item | Status |
|
|
||||||
|---|---|
|
|
||||||
| Pre7 source implementation validation | NOT RUN |
|
|
||||||
| Static reference and behavior-matrix checks | NOT RUN |
|
|
||||||
| Independent source-commit revert checks | NOT RUN |
|
|
||||||
| `WITH_ZSTDIO=0` build | NOT RUN |
|
|
||||||
| QEMU smoke testing | NOT RUN |
|
|
||||||
| Manual or automated runtime tests | NOT RUN |
|
|
||||||
| CI testing | SKIPPED |
|
|
||||||
|
|
||||||
This is an implementation baseline only. It is not a completion report and
|
|
||||||
does not claim that either Pre7 source task is complete or correct.
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
# Pre8 Responsibility-Alignment Baseline
|
|
||||||
|
|
||||||
## Repository Identity
|
|
||||||
|
|
||||||
The following identities were read directly from Git objects at execution-start
|
|
||||||
commit `475b62437f89a8a98e0e3a1d1628481768525cb2`:
|
|
||||||
|
|
||||||
```text
|
|
||||||
execution-start commit: 475b62437f89a8a98e0e3a1d1628481768525cb2
|
|
||||||
execution-start tree: 3f0bc6be8324446440ce578f03d892c95f73591c
|
|
||||||
repo-pre-7 tree: b8f9af2cd55225c4348b79ff5910ae6fc83cd517
|
|
||||||
repo-pre-8 tree: b8f9af2cd55225c4348b79ff5910ae6fc83cd517
|
|
||||||
```
|
|
||||||
|
|
||||||
The equal `repo-pre-7` and `repo-pre-8` tree identities establish that
|
|
||||||
`repo-pre-8` is an exact tracked snapshot of `repo-pre-7` at the execution
|
|
||||||
start. This relationship is based on Git object identities, not a live
|
|
||||||
worktree comparison.
|
|
||||||
|
|
||||||
Relevant source identities at the same commit are:
|
|
||||||
|
|
||||||
```text
|
|
||||||
mode blob path
|
|
||||||
100644 e06822e363d9122a39256494bde7d12cfea1f7c9 repo-pre-8/src/decompressor.c
|
|
||||||
100644 ff595fe009679a4e950eb3743b2f152fac4aad31 repo-pre-8/src/decompressor_lzma.c
|
|
||||||
100644 f3e48cd2016608aaf84ed5e80151782a6c5513f7 repo-pre-8/src/decompressor_deflate.c
|
|
||||||
100644 23756af263ceb148ca50fbb8cd1ae80ba3fac4cd repo-pre-8/src/decompressor_zstd.c
|
|
||||||
100644 cac9ee15f81a1607a03fbab3466cf89c588872c8 repo-pre-8/src/internal.h
|
|
||||||
100644 2257a2299b3bcf3ab15978d723843f26d0b4b346 repo-pre-8/src/xattr.c
|
|
||||||
```
|
|
||||||
|
|
||||||
These values define the immutable comparison baseline for Pre8. Concurrent
|
|
||||||
or later worktree changes are not assessed by this document.
|
|
||||||
|
|
||||||
## Execution Scope
|
|
||||||
|
|
||||||
Pre8 is limited to the following private responsibility-alignment tasks:
|
|
||||||
|
|
||||||
1. Move `z_erofs_load_lzma_config()` from the core decompressor file to the
|
|
||||||
LZMA backend without changing its name, signature, validation order,
|
|
||||||
state updates, or error behavior.
|
|
||||||
2. Move `z_erofs_load_deflate_config()` to the DEFLATE backend with its
|
|
||||||
existing format checks, window-bit limits, state updates, and errors
|
|
||||||
preserved.
|
|
||||||
3. Move `z_erofs_load_zstd_config()` to the ZSTD backend while preserving the
|
|
||||||
availability check, configuration checks, window-log limit, diagnostics,
|
|
||||||
and `WITH_ZSTDIO` behavior.
|
|
||||||
4. Replace the duplicated inline and shared xattr traversal paths with shared
|
|
||||||
private iterator helpers while preserving lookup priority, list order,
|
|
||||||
namespace and errno timing, validation differences, output accounting, and
|
|
||||||
buffer ownership.
|
|
||||||
|
|
||||||
The source allowlist is restricted to the six files identified above. This
|
|
||||||
baseline file is the only documentation path used by the baseline step.
|
|
||||||
|
|
||||||
Pre8 does not include superblock extraction, a new `compress.h` contract,
|
|
||||||
descriptor tables, decode callback ABI changes, codec primitive renaming,
|
|
||||||
typed errno conversion, Linux page or folio abstractions, broad function
|
|
||||||
reordering, or any item already recorded under `planning/reject/`.
|
|
||||||
|
|
||||||
## Initial Validation Status
|
|
||||||
|
|
||||||
This document records the execution baseline only. No implementation,
|
|
||||||
correctness, build, or runtime conclusion is made here.
|
|
||||||
|
|
||||||
| Validation item | Initial status |
|
|
||||||
|---|---|
|
|
||||||
| Pre8 source implementation | NOT RUN |
|
|
||||||
| Source allowlist and protected-path audit | NOT RUN |
|
|
||||||
| `git diff --check` | NOT RUN |
|
|
||||||
| Loader definition, declaration, reference, and body-equivalence checks | NOT RUN |
|
|
||||||
| Xattr iterator invariant and behavior review | NOT RUN |
|
|
||||||
| Direct-parent restoration checks for source commits | NOT RUN |
|
|
||||||
| Final-HEAD inverse-patch compatibility checks | NOT RUN |
|
|
||||||
| `WITH_ZSTDIO=0` build | NOT RUN |
|
|
||||||
| `WITH_ZSTDIO=1` build | NOT RUN |
|
|
||||||
| Basic plain/LZ4 QEMU mount, read, readdir, and unmount smoke | NOT RUN |
|
|
||||||
| Pre7 deferred QEMU coverage | NOT RUN |
|
|
||||||
| Pre8 xattr QEMU coverage | NOT RUN |
|
|
||||||
| Pre8 codec QEMU coverage | NOT RUN |
|
|
||||||
| QEMU cleanup and zero-residual-state checks | NOT RUN |
|
|
||||||
| Completion and evidence-honesty review | NOT RUN |
|
|
||||||
|
|
||||||
Historical evidence from an earlier snapshot is not a Pre8 result. Every
|
|
||||||
status above remains `NOT RUN` until supported by fresh evidence from the
|
|
||||||
final Pre8 DUT. This file must not be interpreted as a completion report.
|
|
||||||
@@ -1,314 +0,0 @@
|
|||||||
# Pre8 Completion and Validation
|
|
||||||
|
|
||||||
## Final Verdict
|
|
||||||
|
|
||||||
Pre8 overall status is **FAIL**.
|
|
||||||
|
|
||||||
The required implementation, static review, revert review, build matrix, basic
|
|
||||||
plain/LZ4 smoke, and selected test suite were all executed. The selected suite
|
|
||||||
did not pass its required gate. In particular, TC004 produced a definite DUT
|
|
||||||
failure while twelve other DUT verdicts were blocked by test-harness defects or
|
|
||||||
prior test residue. Under the status definition in `planning/pre8`, a required
|
|
||||||
action that ran and failed a gate is `FAIL`, not `PASS` or `PARTIAL`.
|
|
||||||
|
|
||||||
This overall verdict does not erase the narrower successful results:
|
|
||||||
|
|
||||||
| Validation layer | Verdict | Scope |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Source implementation | PASS | Planned loader placement and xattr iterator work is present in the final source tree. |
|
|
||||||
| Static source review | PASS | Allowlist, token-equivalence, references, xattr invariants, and protected paths passed review. |
|
|
||||||
| Revert and history review | PASS | Accepted replacement commits passed their defined direct-parent and final-HEAD checks; historical failures remain disclosed. |
|
|
||||||
| Four build configurations | PASS | `default`, `debug`, `zstdio0`, and `zstdio1` built and passed module load/unload smoke. |
|
|
||||||
| Basic plain/LZ4 smoke | PASS | Independent run `20260812T210345.913633Z-770842-a2868dd9`. |
|
|
||||||
| Selected 19-case suite | FAIL | Automation: 5 PASS / 9 FAIL / 4 ERROR / 1 NOT_RUN. Audited DUT: 6 PASS / 1 FAIL / 12 BLOCKED. |
|
|
||||||
| Pre8 overall | **FAIL** | A required selected-suite gate ran and failed. |
|
|
||||||
|
|
||||||
No claim is made that Pre8, repo22, the LZMA issue, or the test harness was
|
|
||||||
fixed by this validation work.
|
|
||||||
|
|
||||||
## Final DUT Identity
|
|
||||||
|
|
||||||
The final repository identity used by both selected-suite and basic-smoke
|
|
||||||
evidence is:
|
|
||||||
|
|
||||||
```text
|
|
||||||
parent repository commit: d1f5b686e8945d06b6e8c0a0188b2262de0b4ac2
|
|
||||||
parent repository tree: 19f450085cad49d06f6fe05d180313f13d4347f0
|
|
||||||
repo-pre-8 tree: 497736695fcc4285760b24c5954c34d32b8af49f
|
|
||||||
repo-pre-8/src tree: cbf93a19df8d1ce2fb66e2aeb7276a4ea6d4dcc2
|
|
||||||
```
|
|
||||||
|
|
||||||
Selected-suite DUT archive:
|
|
||||||
|
|
||||||
```text
|
|
||||||
bbcfd8a6a28faba3f7c5c7e827bde5578774be6e08b83d05485d58ee16a7fb6f
|
|
||||||
```
|
|
||||||
|
|
||||||
Basic-smoke DUT archive:
|
|
||||||
|
|
||||||
```text
|
|
||||||
402459ba6a6f55696d06474f7494a69ef1a5fe49063d565cacadece37e8b9ce1
|
|
||||||
```
|
|
||||||
|
|
||||||
The different archive hashes belong to different runners and archive
|
|
||||||
procedures. Both reports bind their run to the same final repository commit
|
|
||||||
and `repo-pre-8/src` tree.
|
|
||||||
|
|
||||||
## Source Delivery
|
|
||||||
|
|
||||||
### Accepted implementation
|
|
||||||
|
|
||||||
The final accepted source changes are:
|
|
||||||
|
|
||||||
1. `3d28d96fc48753231b1899fce6189e586cf988c6`
|
|
||||||
(`erofs: unify inline and shared xattr iteration`)
|
|
||||||
2. `aac1412056f9ae7269f7c0f85c0233ade8cc662a`
|
|
||||||
(`erofs: move codec config loaders atomically`)
|
|
||||||
|
|
||||||
The xattr commit introduces common private inline/shared iteration while
|
|
||||||
preserving the reviewed lookup order, list order, namespace and errno timing,
|
|
||||||
inline/shared validation differences, buffer ownership, and output accounting.
|
|
||||||
|
|
||||||
The atomic loader replacement moves the LZMA, DEFLATE, and ZSTD configuration
|
|
||||||
loaders to their backend files. The loader bodies remain token-equivalent to
|
|
||||||
the baseline, dispatch calls remain in the core, decode functions are not
|
|
||||||
changed, and no Linux page/folio or descriptor ABI was introduced.
|
|
||||||
|
|
||||||
### Superseded split-loader history
|
|
||||||
|
|
||||||
The following pushed commits remain in history and must not be described as
|
|
||||||
accepted independent delivery units:
|
|
||||||
|
|
||||||
| Commit | Historical final-HEAD inverse result | Final disposition |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| `dd7f2483d468ec4397a863c7a871391ea1bc2c4c` | FAIL: conflict in `decompressor.c`; `internal.h` auto-merged as staged content | Superseded by `aac1412`; failure permanently retained. |
|
|
||||||
| `0dba0ea223bee8626b8cd3371562f87ed975a99f` | FAIL: conflict in `decompressor.c`; `internal.h` auto-merged as staged content | Superseded by `aac1412`; failure permanently retained. |
|
|
||||||
| `7c47f6d` | PASS | Superseded with the split-loader group by `aac1412`. |
|
|
||||||
|
|
||||||
All three split commits passed direct-parent restoration at the point where
|
|
||||||
they were introduced. That fact does not overwrite the two final-HEAD inverse
|
|
||||||
failures. The split group was reverted by `96f041f`, then replayed as the one
|
|
||||||
accepted atomic commit `aac1412`. Commit `3d28d96` was not superseded.
|
|
||||||
|
|
||||||
### Static and revert verdict
|
|
||||||
|
|
||||||
Final static and revert status is **PASS**:
|
|
||||||
|
|
||||||
- the implementation remained within the planned source allowlist;
|
|
||||||
- protected trees and unrelated paths were unchanged;
|
|
||||||
- all three moved loader bodies matched their baseline implementations;
|
|
||||||
- declaration, definition, and dispatch-call closure was correct;
|
|
||||||
- the ZSTD availability and `windowlog > 10` rejection order was preserved;
|
|
||||||
- codec decode bodies were unchanged;
|
|
||||||
- the xattr iterator behavior and ownership matrix passed independent review;
|
|
||||||
- `aac1412` restored its direct parent exactly when reverted;
|
|
||||||
- `aac1412` independently reverted from final HEAD without changing xattr;
|
|
||||||
- `3d28d96` independently reverted from final HEAD without changing the
|
|
||||||
accepted loader layout;
|
|
||||||
- final `repo-pre-8/src` matched the reviewed functional source tree;
|
|
||||||
- `git diff --check` and worktree cleanliness checks passed at static handoff.
|
|
||||||
|
|
||||||
The detailed history record is
|
|
||||||
`repo-pre-8/docs/pre8-loader-history-correction.md`.
|
|
||||||
|
|
||||||
## Build Validation
|
|
||||||
|
|
||||||
The selected-suite runner built four module configurations. Every
|
|
||||||
configuration passed build completion, SHA256 recording, unresolved-symbol
|
|
||||||
checks, and an actual `kldload`/`kldunload` smoke before case execution.
|
|
||||||
|
|
||||||
| Configuration | Verdict | SHA256 | Size |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| `default` | PASS | `348cb1f5a91d47e1412747d285c795c49375a61a66cfb3d35d22f38ecfde6ea0` | 47,272 bytes |
|
|
||||||
| `debug` | PASS | `274189804511d249b34fbb3c223e9525b07c7c6266ec39d016ad2f33185001c7` | **UNKNOWN**; the harness did not persist size evidence before VM destruction |
|
|
||||||
| `zstdio0` | PASS | `348cb1f5a91d47e1412747d285c795c49375a61a66cfb3d35d22f38ecfde6ea0` | 47,272 bytes; byte-identical to `default` |
|
|
||||||
| `zstdio1` | PASS | `6cdb8e01fdac7805cb7ae12a9d1804b00d3e5cf37ef8b2f583137d36ee70426e` | 51,368 bytes |
|
|
||||||
|
|
||||||
The missing debug size is not reconstructed or inferred. No KLD or other
|
|
||||||
binary was committed.
|
|
||||||
|
|
||||||
## Basic Plain/LZ4 Smoke
|
|
||||||
|
|
||||||
Independent basic smoke run:
|
|
||||||
|
|
||||||
```text
|
|
||||||
run ID: 20260812T210345.913633Z-770842-a2868dd9
|
|
||||||
automation: PASS
|
|
||||||
runner exit: 0
|
|
||||||
DUT result: PASS for plain and LZ4 basic differential scope
|
|
||||||
guest: FreeBSD 15.0-RELEASE-p8 amd64
|
|
||||||
KLD SHA256: 527fe80ad7307d0200cfc4fec84c6fb86b914e89889e4a42ff0613fc24465015
|
|
||||||
KLD size: 47,272 bytes
|
|
||||||
```
|
|
||||||
|
|
||||||
All twelve runner stages passed. The run created a deterministic corpus with
|
|
||||||
256 regular files, 9 symlinks, and 43 directories. Both the plain and LZ4
|
|
||||||
images mounted read-only, passed a 307-entry differential preflight, completed
|
|
||||||
all four workers, and unmounted cleanly. The test QEMU exited gracefully, its
|
|
||||||
overlay and large temporary data were removed, and ports 10000 and 10001 were
|
|
||||||
released.
|
|
||||||
|
|
||||||
This result covers only plain/LZ4 basic mount, traversal, read, differential,
|
|
||||||
unmount, and cleanup behavior. It does not override the selected-suite
|
|
||||||
failures or blocked verdicts.
|
|
||||||
|
|
||||||
Evidence:
|
|
||||||
|
|
||||||
- `/work/tests-dev/erofsstress/demo-result/repo-pre-8-smoke-20260812/20260812T210345.913633Z-770842-a2868dd9/audit-report.md`
|
|
||||||
- `/work/tests-dev/erofsstress/demo-result/repo-pre-8-smoke-20260812/20260812T210345.913633Z-770842-a2868dd9/result.json`
|
|
||||||
- tests-dev commit `374b8e3ab4b0df24d6761802b70c694e2896d5fd`
|
|
||||||
|
|
||||||
## Selected Suite
|
|
||||||
|
|
||||||
Primary run:
|
|
||||||
|
|
||||||
```text
|
|
||||||
run ID: pre8-required-20260812T194817Z
|
|
||||||
cases: 19
|
|
||||||
automation: 5 PASS / 9 FAIL / 4 ERROR / 1 NOT_RUN
|
|
||||||
runner exit: 3
|
|
||||||
duration: 1892.44 seconds
|
|
||||||
audited DUT: 6 PASS / 1 FAIL / 12 BLOCKED
|
|
||||||
```
|
|
||||||
|
|
||||||
The automation status is the runner's result. The DUT status is a separate
|
|
||||||
evidence audit. An automation failure caused by a harness defect is not changed
|
|
||||||
to automation PASS. Likewise, a positive command observed before a missing
|
|
||||||
negative check does not make the full DUT case PASS.
|
|
||||||
|
|
||||||
### Per-case matrix
|
|
||||||
|
|
||||||
| Case | Automation | DUT | Audited observation |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| TC005 | FAIL | BLOCKED | Inline listing and both requested user xattr values succeeded. The missing-xattr `ENOATTR` assertion was never invoked because the truss output directory did not exist. |
|
|
||||||
| TC013 | PASS | PASS | Invalid NID returned `EINTEGRITY` (`ERR#97`) twice; mount, unmount, and zero-state checks passed. |
|
|
||||||
| TC079 | PASS | PASS | Packed user and trusted prefix values matched expected data and cleanup passed. |
|
|
||||||
| TC080 | FAIL | BLOCKED | Four packed-prefix values were correct. The missing-suffix `ENOATTR` assertion was not invoked because the truss output directory was absent. |
|
|
||||||
| TC082 | FAIL | BLOCKED | ACL bytes and ordering were observed, but automation compared spaced hex against an unspaced prefix; the user-namespace negative assertion also was not invoked. |
|
|
||||||
| TC067 | FAIL | PASS | Both shared files, the local xattr, and listing matched the fixture. Automation incorrectly expected one additional trailing `!`. |
|
|
||||||
| TC068 | FAIL | BLOCKED | Shared listing succeeded. The nonexistent lookup was not invoked because truss could not create its output file. |
|
|
||||||
| TC069 | PASS | PASS | Three shared xattrs were listed and all exact values were read; cleanup passed. |
|
|
||||||
| TC081 | PASS | PASS | Metabox shared, shared-prefix, and packed-prefix xattrs were listed and read from both files; cleanup passed. |
|
|
||||||
| TC117 | FAIL | BLOCKED | Both corrupt fixtures mounted and valid local shared data remained readable. Corrupt-entry errno assertions were not invoked because truss failed first. |
|
|
||||||
| TC135 | PASS | PASS | Metabox, packed, and primary-prefix fallback values matched expected data. |
|
|
||||||
| TC138 | FAIL | BLOCKED | Valid unordered and empty-header ACLs were read. Three malformed ACL assertions were not invoked because the scratch directory was absent. |
|
|
||||||
| TC140 | FAIL | BLOCKED | Positive compressed and fragment metabox carrier hashes and xattrs passed. Four negative mount commands were not invoked because truss failed opening its trace. |
|
|
||||||
| TC142 | FAIL | BLOCKED | Positive fragment-backed compressed metabox hash and xattrs passed. Four negative mount commands were not invoked for the same reason. |
|
|
||||||
| TC004 | ERROR | **FAIL** | LZMA image mounted, but SHA256 of the mounted 8 MiB `level.dat` timed out after 30 seconds. The process remained running and left the mount and `md0` busy. |
|
|
||||||
| TC084 | ERROR; follow-up FAIL | BLOCKED | Primary run was contaminated by TC004 residue. Fresh follow-up mounted LZ4 and found the target, but guest `dump.erofs` was absent before content verification. |
|
|
||||||
| TC102 | ERROR; follow-up FAIL | BLOCKED | Primary run was contaminated by TC004 residue. Fresh follow-up mounted DEFLATE, but missing guest `dump.erofs` prevented algorithm and content verification. |
|
|
||||||
| TC105 | ERROR; follow-up FAIL | BLOCKED | Primary run was contaminated by TC004 residue. Fresh follow-up mounted ZSTD with `zstdio1`, but missing guest `dump.erofs` prevented verification. |
|
|
||||||
| TC145 | NOT_RUN; follow-up ERROR | BLOCKED | Both zstdio modules built and initial load smoke passed. The follow-up queried and unloaded module name `erofs` instead of the loaded artifact name, so functional mount/read gates were not reached. |
|
|
||||||
|
|
||||||
### Definite DUT failure
|
|
||||||
|
|
||||||
TC004 is a definite observed DUT failure for this test run:
|
|
||||||
|
|
||||||
1. `lzma-level6.erofs` attached as `md0`.
|
|
||||||
2. The read-only EROFS mount succeeded.
|
|
||||||
3. The mounted `level.dat` existed.
|
|
||||||
4. SHA256 of the source file completed and returned
|
|
||||||
`ddda39737f0f6093e828a032ec161511fefbb1fa361bc6cbffdbc91e48e4c461`.
|
|
||||||
5. SHA256 of the mounted 8 MiB file did not finish within 30 seconds.
|
|
||||||
6. The timed-out `sha256` process remained alive.
|
|
||||||
7. Unmount and `mdconfig -d` returned `Device busy`.
|
|
||||||
|
|
||||||
This evidence does **not** prove that Pre8 introduced the problem. No matching
|
|
||||||
Pre7 or pre-change comparison run with the same image, guest, module build,
|
|
||||||
and command is available. The issue is recorded separately in
|
|
||||||
`issues/pre8-lzma-read-timeout.md` without an attribution claim.
|
|
||||||
|
|
||||||
### Codec follow-up
|
|
||||||
|
|
||||||
Fresh follow-up run:
|
|
||||||
|
|
||||||
```text
|
|
||||||
run ID: pre8-codec-followup-20260812T202059Z
|
|
||||||
cases: TC084, TC102, TC105, TC145
|
|
||||||
automation: 3 FAIL / 1 ERROR
|
|
||||||
runner exit: 1
|
|
||||||
duration: 1136.92 seconds
|
|
||||||
audited DUT: 4 BLOCKED
|
|
||||||
```
|
|
||||||
|
|
||||||
The follow-up isolated these cases from TC004 residue, but it did not produce
|
|
||||||
codec functional PASS verdicts. TC084, TC102, and TC105 were blocked by absent
|
|
||||||
guest `dump.erofs`. TC145 was blocked by incorrect module-name lookup/unload
|
|
||||||
and cleanup behavior in the harness. These results remain FAIL/ERROR in
|
|
||||||
automation and BLOCKED for the DUT.
|
|
||||||
|
|
||||||
The harness findings are recorded in
|
|
||||||
`issues/pre8-test-harness-blockers.md`. No harness modification is part of
|
|
||||||
Pre8 source delivery.
|
|
||||||
|
|
||||||
Selected-suite evidence:
|
|
||||||
|
|
||||||
- `/work/tests-dev/demo-result/repo-pre-8-smoke-20260812/summary.md`
|
|
||||||
- `/work/tests-dev/demo-result/repo-pre-8-smoke-20260812/summary.json`
|
|
||||||
- `/work/tests-dev/demo-result/repo-pre-8-smoke-20260812/pre8-required-20260812T194817Z/summary.json`
|
|
||||||
- `/work/tests-dev/demo-result/repo-pre-8-smoke-20260812/pre8-required-20260812T194817Z/evidence/`
|
|
||||||
- `/work/tests-dev/demo-result/repo-pre-8-smoke-20260812/pre8-codec-followup-20260812T202059Z/summary.json`
|
|
||||||
- `/work/tests-dev/demo-result/repo-pre-8-smoke-20260812/pre8-codec-followup-20260812T202059Z/evidence/`
|
|
||||||
- tests-dev commit `46e6840f1b8918414af76c9a5731322c697eee8b`
|
|
||||||
|
|
||||||
## Fixtures and Immutable Inputs
|
|
||||||
|
|
||||||
The common base image was not modified:
|
|
||||||
|
|
||||||
```text
|
|
||||||
path: /work/tests-dev/lfs/freebsd-15-dev-src-20260811.bp
|
|
||||||
format: qcow2
|
|
||||||
mode: 0444
|
|
||||||
size: 16,515,530,752 bytes
|
|
||||||
SHA256: 67f359621f23a1d745f0889370cbb99a096cee3e99a0b2f3bb18fc7a91bf6fef
|
|
||||||
```
|
|
||||||
|
|
||||||
Selected primary fixture deployment identities:
|
|
||||||
|
|
||||||
| Group | Manifest SHA256 | Checksum-list SHA256 |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| G1 | `9ffe9e695a6544cb010a5d4ba1e0c2c09d7455e6d7e28cc81da54d2dd954f2f2` | `db416004ff6b00ad286e50da506168b35a544a7da5619042225198843e4c741c` |
|
|
||||||
| G4 | `6200842757dae30f3a5b0683d726d339a24e55dff98cd084597462289a9308aa` | `229c84c5436cf9b5b659ded375097fba13621c20a2cf2d845f146df737836622` |
|
|
||||||
| G5 | `c9540baafb53b3783233c3950f4d8548c28585cd32335dadc14db613692a8978` | `d08138b1bd51579cbf5461a73abce9d7fddc9cdb8ace1329c9f1581d41e1095f` |
|
|
||||||
|
|
||||||
Follow-up G5 deployment identities:
|
|
||||||
|
|
||||||
```text
|
|
||||||
manifest: 9be85e48115f2dd2cae058f2a4ea7438512f28e647c30476d049d6b8025b02fd
|
|
||||||
checksum list: 7513425c98400f641523083bf0d06b2d548aa3163dfcdfe980dca2b0e1900acd
|
|
||||||
```
|
|
||||||
|
|
||||||
Deployment hashes can include run-specific metadata. Image, source, generator,
|
|
||||||
and checksum evidence remains beneath each run's `fixture-evidence/` and
|
|
||||||
per-case evidence directories.
|
|
||||||
|
|
||||||
## Cleanup and Guard Integrity
|
|
||||||
|
|
||||||
- The selected primary and follow-up QEMUs were force-destroyed by the runner
|
|
||||||
after their final errors.
|
|
||||||
- Their run-owned overlays were deleted.
|
|
||||||
- Ports 10000 and 10001 were released and closed.
|
|
||||||
- The independent basic-smoke QEMU shut down gracefully and its overlay was
|
|
||||||
removed.
|
|
||||||
- Guard PID 26318 retained its identity and TCP port 9222 remained active.
|
|
||||||
- Base-image SHA256, mode, and size were unchanged before and after the runs.
|
|
||||||
- The DUT commit and source tree remained unchanged and clean.
|
|
||||||
- No DUT source, repo22 source, base image, test source, fixture generator, or
|
|
||||||
`oldtests` content was modified during validation.
|
|
||||||
|
|
||||||
Cleanup of the disposable VM does not change TC004's case-level cleanup result:
|
|
||||||
the case itself failed to terminate its read process and could not unmount or
|
|
||||||
detach `md0`. VM destruction only removed the run environment afterward.
|
|
||||||
|
|
||||||
## Final Handoff
|
|
||||||
|
|
||||||
Pre8 delivers the planned source-responsibility changes and passes static,
|
|
||||||
revert, build, and basic plain/LZ4 smoke validation. It does not satisfy the
|
|
||||||
full required validation gate because the selected suite contains one definite
|
|
||||||
DUT failure and twelve blocked DUT cases. The honest final status is therefore
|
|
||||||
**FAIL**.
|
|
||||||
|
|
||||||
Open follow-up records:
|
|
||||||
|
|
||||||
- `issues/pre8-lzma-read-timeout.md`
|
|
||||||
- `issues/pre8-test-harness-blockers.md`
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
# Pre8 Loader History Correction
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This record corrects the commit organization of the Pre8 codec configuration
|
|
||||||
loader moves. It does not report a source behavior defect and does not rewrite,
|
|
||||||
amend, squash, or hide any pushed commit.
|
|
||||||
|
|
||||||
The affected historical commits are:
|
|
||||||
|
|
||||||
```text
|
|
||||||
dd7f2483d468ec4397a863c7a871391ea1bc2c4c LZMA loader move
|
|
||||||
0dba0ea223bee8626b8cd3371562f87ed975a99f DEFLATE loader move
|
|
||||||
7c47f6d ZSTD loader move
|
|
||||||
3d28d96fc48753231b1899fce6189e586cf988c6 xattr iterator change
|
|
||||||
```
|
|
||||||
|
|
||||||
## Recorded Results
|
|
||||||
|
|
||||||
Each of the three loader commits restores its direct parent's complete tree
|
|
||||||
when reverted at the commit where it was introduced. Those direct-parent
|
|
||||||
revert checks are `PASS`.
|
|
||||||
|
|
||||||
When each commit is reverted independently from final functional commit
|
|
||||||
`3d28d96`, the results are:
|
|
||||||
|
|
||||||
| Commit | Final-HEAD independent revert | Result |
|
|
||||||
|---|---|---|
|
|
||||||
| `dd7f248` | Unmerged conflict in `decompressor.c`; `internal.h` auto-merged as a staged modification | FAIL |
|
|
||||||
| `0dba0ea` | Unmerged conflict in `decompressor.c`; `internal.h` auto-merged as a staged modification | FAIL |
|
|
||||||
| `7c47f6d` | Applies without conflict | PASS |
|
|
||||||
| `3d28d96` | Applies without conflict | PASS |
|
|
||||||
|
|
||||||
The two failures are caused by overlapping patch context in `decompressor.c`.
|
|
||||||
In both cases, `internal.h` is automatically merged as a staged modification,
|
|
||||||
not left as an unmerged conflict. This is a commit organization problem, not
|
|
||||||
evidence of a codec implementation or xattr behavior problem.
|
|
||||||
|
|
||||||
The `dd7f248` and `0dba0ea` final-HEAD results remain permanently recorded as
|
|
||||||
`FAIL`. The `7c47f6d` result remains `PASS`, but that commit is superseded with
|
|
||||||
the other two loader commits so the loader responsibility change has one
|
|
||||||
atomic acceptance unit.
|
|
||||||
|
|
||||||
## Correction Strategy
|
|
||||||
|
|
||||||
The three split loader commits will be reverted in reverse order without
|
|
||||||
rewriting history. Their exact combined five-path change will then be replayed
|
|
||||||
as one atomic replacement commit. The replacement is limited to:
|
|
||||||
|
|
||||||
```text
|
|
||||||
repo-pre-8/src/decompressor.c
|
|
||||||
repo-pre-8/src/decompressor_lzma.c
|
|
||||||
repo-pre-8/src/decompressor_deflate.c
|
|
||||||
repo-pre-8/src/decompressor_zstd.c
|
|
||||||
repo-pre-8/src/internal.h
|
|
||||||
```
|
|
||||||
|
|
||||||
Commit `3d28d96` remains accepted and is not superseded. Its `xattr.c` content
|
|
||||||
must remain unchanged through the correction.
|
|
||||||
|
|
||||||
The new acceptance objects are:
|
|
||||||
|
|
||||||
1. the atomic replacement loader commit, which must restore its direct parent
|
|
||||||
exactly when reverted and must independently revert from final `HEAD`
|
|
||||||
without affecting xattr content; and
|
|
||||||
2. existing xattr commit `3d28d96`, which must independently revert from final
|
|
||||||
`HEAD` without affecting the final loader layout.
|
|
||||||
|
|
||||||
## Validation Status
|
|
||||||
|
|
||||||
This document records static Git evidence only. No build or QEMU test has been
|
|
||||||
run for this history correction. Build and runtime validation remain
|
|
||||||
`NOT RUN` until later Pre8 validation produces fresh evidence from the final
|
|
||||||
DUT.
|
|
||||||
@@ -1,191 +0,0 @@
|
|||||||
# Pre9 LZMA Diagnostic Implementation Baseline
|
|
||||||
|
|
||||||
## Baseline Meaning
|
|
||||||
|
|
||||||
The Pre9 planning phase ended when the planning documents were committed at
|
|
||||||
`d1ee2e05b82b5e8a8927861f1e981710532f2f23`. This file starts the
|
|
||||||
implementation phase and records identities only. It does not claim that the
|
|
||||||
TC004 root cause is known, that Pre8 introduced the observed timeout, or that
|
|
||||||
any source or test-harness fix has been selected or implemented.
|
|
||||||
|
|
||||||
All values below were read from Git objects or the named evidence files on
|
|
||||||
2026-08-13 UTC. Historical Pre8 evidence is context for controlled Pre9
|
|
||||||
diagnosis, not a Pre9 test result.
|
|
||||||
|
|
||||||
## Main Repository Identity
|
|
||||||
|
|
||||||
Repository: `/work/erofs-freebsd-pre`
|
|
||||||
|
|
||||||
```text
|
|
||||||
branch: main
|
|
||||||
execution-start commit: d1ee2e05b82b5e8a8927861f1e981710532f2f23
|
|
||||||
execution-start tree: 95a55ff912d007ca40bd578057e8a4cc6a21bbd9
|
|
||||||
xdm/main: d1ee2e05b82b5e8a8927861f1e981710532f2f23
|
|
||||||
remote xdm main: d1ee2e05b82b5e8a8927861f1e981710532f2f23
|
|
||||||
initial dirty entries: 0
|
|
||||||
```
|
|
||||||
|
|
||||||
Snapshot identities at the execution-start commit:
|
|
||||||
|
|
||||||
```text
|
|
||||||
snapshot subtree src tree
|
|
||||||
repo-pre-7 b8f9af2cd55225c4348b79ff5910ae6fc83cd517 dc203534d7b5721905f8538026e4c59346106020
|
|
||||||
repo-pre-8 1e24c992a5b071e6fdabfdc42d342b6ed5a91cf5 cbf93a19df8d1ce2fb66e2aeb7276a4ea6d4dcc2
|
|
||||||
repo-pre-9 1e24c992a5b071e6fdabfdc42d342b6ed5a91cf5 cbf93a19df8d1ce2fb66e2aeb7276a4ea6d4dcc2
|
|
||||||
```
|
|
||||||
|
|
||||||
The equal Pre8 and Pre9 object identities establish that Pre9 starts as an
|
|
||||||
exact tracked snapshot of Pre8. Pre7 is intentionally different and remains
|
|
||||||
the earlier controlled comparison point.
|
|
||||||
|
|
||||||
## Conditional Source Allowlist Identity
|
|
||||||
|
|
||||||
The primary conditional allowlist is `zdata.c`, `decompressor_lzma.c`, and
|
|
||||||
`internal.h`. The remaining three files require the additional decision gates
|
|
||||||
defined by the plan. Their baseline modes and blobs are:
|
|
||||||
|
|
||||||
```text
|
|
||||||
gate mode blob path
|
|
||||||
primary 100644 54c1c88e5c368e7b5f6a16188c48406767850821 repo-pre-9/src/zdata.c
|
|
||||||
primary 100644 688acd704e28daa46369fa2e63e895bce5262774 repo-pre-9/src/decompressor_lzma.c
|
|
||||||
primary 100644 9821fe3a8b5fcaaeb3939d191f15e9ce637cc8d1 repo-pre-9/src/internal.h
|
|
||||||
extra 100644 ca5d33cd42145159d71e153f115128ac75258708 repo-pre-9/src/inode.c
|
|
||||||
extra 100644 b233f138d036a2b37394946b382034955dc2a1df repo-pre-9/src/erofs_vnops.c
|
|
||||||
extra 100644 51170741a0fb5eced814db898c1a233e8a23088a repo-pre-9/src/zmap.c
|
|
||||||
```
|
|
||||||
|
|
||||||
This identity table authorizes no source change by itself. Source edits remain
|
|
||||||
conditional on controlled evidence and the applicable decision gate.
|
|
||||||
|
|
||||||
## tests-dev and Base Image Identity
|
|
||||||
|
|
||||||
The external test repository was inspected without modification:
|
|
||||||
|
|
||||||
```text
|
|
||||||
repository: /work/tests-dev
|
|
||||||
branch: main
|
|
||||||
current commit: 374b8e3ab4b0df24d6761802b70c694e2896d5fd
|
|
||||||
current tree: c438e72ebe94a6f10801999bfbdd36b43134d471
|
|
||||||
xdm/main: 374b8e3ab4b0df24d6761802b70c694e2896d5fd
|
|
||||||
initial dirty entries: 27 untracked paths
|
|
||||||
dirty inventory SHA256: bca9ca20e85698d04dad820a11bd0bbb117492c967d6fd338e7acf61bb8fa957
|
|
||||||
```
|
|
||||||
|
|
||||||
The pre-existing tests-dev dirty inventory was:
|
|
||||||
|
|
||||||
```text
|
|
||||||
demo-result/FINAL-REPORT.md
|
|
||||||
demo-result/audit-checklist.md
|
|
||||||
demo-result/audit-findings.md
|
|
||||||
demo-result/current-status.md
|
|
||||||
demo-result/fix-plan.md
|
|
||||||
demo-result/fix-verification-report.json
|
|
||||||
demo-result/progress-report.md
|
|
||||||
demo-result/repo-pre-6-smoke-20260812/
|
|
||||||
demo-result/repo22-full-20260811T065312Z/
|
|
||||||
demo-result/repo22-full-20260811T071634Z/
|
|
||||||
demo-result/repo22-full-20260811T073716Z/
|
|
||||||
demo-result/repo22-full-20260811T082907Z/
|
|
||||||
demo-result/repo22-full-20260811T095621Z/
|
|
||||||
demo-result/test-execution-summary.md
|
|
||||||
erofsstress/demo-result/repo-pre-3-smoke-20260812/
|
|
||||||
erofsstress/demo-result/repo-pre-6-smoke-20260812/
|
|
||||||
guest/setup-build-env.sh
|
|
||||||
lfs/FreeBSD-15.0-RELEASE-src.txz
|
|
||||||
scripts/check-kernel-src.sh
|
|
||||||
scripts/complete-setup-and-test.py
|
|
||||||
scripts/install-kernel-sources.py
|
|
||||||
scripts/manual-fix.sh
|
|
||||||
scripts/quick-install-src.py
|
|
||||||
scripts/run-final-test.sh
|
|
||||||
scripts/setup-build-env-simple.py
|
|
||||||
scripts/setup-build-env.py
|
|
||||||
scripts/simple-install-kernel-src.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
These paths are not owned by this baseline step and must not be staged,
|
|
||||||
modified, or removed as part of it.
|
|
||||||
|
|
||||||
Immutable base image identity:
|
|
||||||
|
|
||||||
```text
|
|
||||||
path: /work/tests-dev/lfs/freebsd-15-dev-src-20260811.bp
|
|
||||||
format: QEMU QCOW2 Image (v3)
|
|
||||||
mode: 0444
|
|
||||||
size: 16,515,530,752 bytes
|
|
||||||
SHA256: 67f359621f23a1d745f0889370cbb99a096cee3e99a0b2f3bb18fc7a91bf6fef
|
|
||||||
```
|
|
||||||
|
|
||||||
The base image is an input only. It must not be modified during Pre9 testing.
|
|
||||||
|
|
||||||
## Historical TC004 Evidence Identity
|
|
||||||
|
|
||||||
The prior observation is preserved by tests-dev evidence commit
|
|
||||||
`46e6840f1b8918414af76c9a5731322c697eee8b`, tree
|
|
||||||
`7178de49f3f429796d6de71a910d71bfccd5745a`, with subject
|
|
||||||
`evidence: record repo-pre-8 required smoke`.
|
|
||||||
|
|
||||||
```text
|
|
||||||
run ID: pre8-required-20260812T194817Z
|
|
||||||
case: TC004 - LZMA Compressed File Read
|
|
||||||
historical DUT commit: d1f5b686e8945d06b6e8c0a0188b2262de0b4ac2
|
|
||||||
historical DUT src tree: cbf93a19df8d1ce2fb66e2aeb7276a4ea6d4dcc2
|
|
||||||
DUT archive SHA256: bbcfd8a6a28faba3f7c5c7e827bde5578774be6e08b83d05485d58ee16a7fb6f
|
|
||||||
module SHA256: 348cb1f5a91d47e1412747d285c795c49375a61a66cfb3d35d22f38ecfde6ea0
|
|
||||||
fixture image: G5/images/lzma-level6.erofs
|
|
||||||
fixture image SHA256: 32107a084b27362a093768b88746c37c2e99a74b9f1301a9d4046988479defe9
|
|
||||||
source file: G5/sources/levels/level.dat
|
|
||||||
source file SHA256: ddda39737f0f6093e828a032ec161511fefbb1fa361bc6cbffdbc91e48e4c461
|
|
||||||
deployment manifest: c9540baafb53b3783233c3950f4d8548c28585cd32335dadc14db613692a8978
|
|
||||||
fixture checksum hash: d08138b1bd51579cbf5461a73abce9d7fddc9cdb8ace1329c9f1581d41e1095f
|
|
||||||
TC004 evidence SHA256: de6982a11fa368fbaad7d837586daa899789cd4cd8b9f698974a3ef4e251811f
|
|
||||||
```
|
|
||||||
|
|
||||||
Evidence paths:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/work/tests-dev/demo-result/repo-pre-8-smoke-20260812/pre8-required-20260812T194817Z/summary.json
|
|
||||||
/work/tests-dev/demo-result/repo-pre-8-smoke-20260812/pre8-required-20260812T194817Z/evidence/TC004/TC004_evidence.json
|
|
||||||
/work/tests-dev/demo-result/repo-pre-8-smoke-20260812/summary.md
|
|
||||||
/work/erofs-freebsd-pre/issues/pre8-lzma-read-timeout.md
|
|
||||||
```
|
|
||||||
|
|
||||||
The historical automation verdict was `ERROR` and the audited DUT verdict was
|
|
||||||
`FAIL`: mount and lookup succeeded, but hashing the mounted 8 MiB `level.dat`
|
|
||||||
did not finish within 30 seconds. PID 95693 remained active, and the mount and
|
|
||||||
`md0` stayed busy until the disposable VM was destroyed. Attribution remains
|
|
||||||
`UNKNOWN`. These facts neither prove a Pre8 regression nor select a Pre9 fix.
|
|
||||||
|
|
||||||
## Initial Implementation Status
|
|
||||||
|
|
||||||
| Item | Status |
|
|
||||||
|---|---|
|
|
||||||
| Pre9 planning | COMPLETE |
|
|
||||||
| Pre9 implementation baseline | RECORDED |
|
|
||||||
| tests-dev TC004 prerequisite corrections | NOT RUN |
|
|
||||||
| tests-dev remaining full-suite prerequisites | NOT RUN |
|
|
||||||
| Controlled Pre7 reproduction | NOT RUN |
|
|
||||||
| Controlled Pre8 reproduction | NOT RUN |
|
|
||||||
| Controlled unchanged Pre9 reproduction | NOT RUN |
|
|
||||||
| Manual SSH diagnosis | NOT RUN |
|
|
||||||
| Hypothesis decision gates | NOT RUN |
|
|
||||||
| Source decision | NOT RUN |
|
|
||||||
| Optional diagnostic instrumentation | NOT RUN |
|
|
||||||
| Pre9 source implementation | NOT RUN |
|
|
||||||
| Source static review | NOT RUN |
|
|
||||||
| Source direct-parent revert gate | NOT RUN |
|
|
||||||
| Source final-HEAD inverse gate | NOT RUN |
|
|
||||||
| `WITH_ZSTDIO=0` build | NOT RUN |
|
|
||||||
| `WITH_ZSTDIO=1` build | NOT RUN |
|
|
||||||
| TC004 | NOT RUN |
|
|
||||||
| Extended LZMA matrix | NOT RUN |
|
|
||||||
| Plain/LZ4 smoke | NOT RUN |
|
|
||||||
| Full regression | NOT RUN |
|
|
||||||
| QEMU cleanup and zero-residual-state checks | NOT RUN |
|
|
||||||
| Pre9 completion and evidence-honesty review | NOT RUN |
|
|
||||||
| Pre9 overall | NOT RUN |
|
|
||||||
|
|
||||||
No diagnostic command, tests-dev prerequisite, controlled comparison, source
|
|
||||||
change, build, QEMU run, or manual SSH investigation has been performed for
|
|
||||||
Pre9 at this baseline. Fresh evidence is required before any status above can
|
|
||||||
advance or any root-cause or repair claim can be made.
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user