# G6 Chunk and Multi-Device Manual Setup This setup applies only to `TC006`, `TC093` through `TC101`, and `TC118`. There are exactly 11 test cases. The commands below generate new inputs; no fixture or result from an earlier run is an input. ## Host prerequisites - Linux host with erofs-utils 1.8.6 (`mkfs.erofs` and `fsck.erofs`). - Python 3.11 or newer. - QEMU with qcow2 support. - A clean FreeBSD 15 amd64 base disk used only as the backing file for a new per-run overlay. Set a new run directory and generate the fixtures twice: ```sh REPO=/path/to/worktree/repo-community/repo22 RUN=/work/build/repo22-g6-$(date -u +%Y%m%dT%H%M%SZ) mkdir -p "$RUN" cd "$REPO" python3 -B tests/g6_multidev_fixtures.py generate \ --output "$RUN/fixtures-a" python3 -B tests/g6_multidev_fixtures.py generate \ --output "$RUN/fixtures-b" cmp "$RUN/fixtures-a/manifest.json" "$RUN/fixtures-b/manifest.json" cmp "$RUN/fixtures-a/SHA256SUMS" "$RUN/fixtures-b/SHA256SUMS" python3 -B tests/g6_multidev_fixtures.py verify "$RUN/fixtures-a" ``` `generate` refuses an existing output directory, fixes source bytes, UUIDs, timestamps, worker count, and every binary transformation, and asserts the old field before each patch. `verify` checks every artifact size and SHA256, then reparses superblock, device-table, and chunk-index fields from disk. The manifest records two erofs-utils 1.8.6 limitations. Its fsck qualifies the mkfs split image, single-index image, explicit 2/3-slot images, table-at-0, `uniaddr=0`, fragment image, and original two-block LZ4 pcluster. Flatdev and device-ID-0 unified relocation are qualified by the FreeBSD kernel reads in TC094 and TC101 because this fsck release does not implement those mappings. ## Dedicated FreeBSD 15 VM Create a new overlay and use only SSH port 9226 for this run: ```sh qemu-img create -f qcow2 -F qcow2 \ -b /work/build/vm-freebsd-dev-base.qcow2 \ "$RUN/freebsd15-overlay.qcow2" qemu-system-x86_64 -accel tcg,thread=multi -cpu qemu64 \ -m 6144 -smp 4 \ -drive file="$RUN/freebsd15-overlay.qcow2",if=virtio,format=qcow2 \ -netdev user,id=net0,hostfwd=tcp:127.0.0.1:9226-:22 \ -device virtio-net-pci,netdev=net0 -display none \ -serial file:"$RUN/freebsd15-serial.log" -monitor none \ -pidfile "$RUN/freebsd15-qemu.pid" \ -D "$RUN/freebsd15-qemu.log" -daemonize ``` Record the guest identity before installing test artifacts: ```sh uname -a freebsd-version -ku sysctl -n kern.osreldate sha256 /boot/kernel/kernel mdconfig -l mount -p | awk '$3 == "erofs"' ``` The initial `mdconfig` and EROFS mount outputs must be empty. ## Exact-source KLD On the host, record and archive the exact worktree source: ```sh git rev-parse HEAD | tee "$RUN/source.commit" git status --short git archive --format=tar HEAD repo-community/repo22 | \ gzip -n > "$RUN/repo22-source.tar.gz" git archive --format=tar HEAD dev-freebsd-releng/sys | \ gzip -n > "$RUN/freebsd-sys-source.tar.gz" tar -C "$RUN/fixtures-a" -czf "$RUN/g6-fixtures.tar.gz" \ SHA256SUMS manifest.json images sources ``` Transfer both archives to the new guest. Authentication details remain outside the repository: ```sh scp -O -P 9226 "$RUN/repo22-source.tar.gz" \ "$RUN/freebsd-sys-source.tar.gz" \ "$RUN/g6-fixtures.tar.gz" root@127.0.0.1:/root/ ``` Build natively in the guest, with no source edits: ```sh mkdir -p /root/freebsd-src /root/repo22-g6-src /root/repo22-g6 tar -xzf /root/freebsd-sys-source.tar.gz -C /root/freebsd-src \ --strip-components 1 tar -xzf /root/repo22-source.tar.gz -C /root/repo22-g6-src \ --strip-components 2 tar -xzf /root/g6-fixtures.tar.gz -C /root/repo22-g6 cd /root/repo22-g6-src grep -E '^(REVISION|BRANCH)=' /root/freebsd-src/sys/conf/newvers.sh env WITH_ZSTDIO=1 FREEBSD_SRC=/root/freebsd-src ./build.sh sha256 build/erofs.ko file build/erofs.ko cp build/erofs.ko /root/repo22-g6/erofs.ko ``` At baseline `6b33b4afb490be7d6fec70e499469c306a58435d`, the tracked sys tree is 15.0-RELEASE-p9 and the clean guest is p8; both report OSREL 1500068. Record this source/guest distinction rather than claiming they are the same patch level. Also record `source.commit`, `WITH_ZSTDIO=1`, FreeBSD source archive SHA256, KLD SHA256, kernel SHA256, and all guest values in the report. ## Manual evidence rules Run the commands in each TC Markdown directly. Do not use a runner, CI job, or test wrapper. Before each test: ```sh mkdir -p /mnt/g6 kldload /root/repo22-g6/erofs.ko dmesg | tail -40 > /tmp/g6-dmesg-before ``` For a negative mount or read, capture the syscall result with `truss` and record the named errno, not only command exit status: ```sh truss -f -o /tmp/operation.truss command arguments tail -20 /tmp/operation.truss ``` After every TC, unmount first, detach external providers in descending slot order, detach the primary, and unload the module. All four checks must report zero: ```sh mount -p | awk '$3 == "erofs" { print }' mdconfig -l kldstat -n erofs 2>/dev/null || true sysctl -n kern.geom.conftxt | \ awk '/Geom name: md9[0-3]$|Consumers:|Providers:|erofs/ { print }' ``` Also compare the new dmesg suffix and reject any panic, trap, assertion, watchdog, or EROFS error not expected by the current negative operation. ## FreeBSD and Linux behavior Linux EROFS accepts a device table at byte offset zero and excludes a slot whose `uniaddr` is zero from device-ID-0 unified lookup; a nonzero device ID still selects that slot. FreeBSD uses explicit `device.=/dev/` mount options because GEOM providers are not discovered from Linux block device tags. FreeBSD also holds one read-only GEOM consumer per provider, so normal `mdconfig -d` returns `EBUSY` while mounted. A forced GEOM orphan makes later cold I/O return `ENXIO`; unmount must still release vnode, cdev, and GEOM references. These lifecycle details have no direct Linux loop-device equivalent and are checked in TC006 and TC118.