Files
erofs-freebsd-out-tree/tests/results/manual/2026-08-08T2114Z-multidev-review/manual-test-report.md
T
2026-08-18 09:20:44 +02:00

6.3 KiB

repo22 multi-device review findings manual test report

Date: 2026-08-08 21:14 UTC Baseline: 2354b4487c84458c1e447f4d0bb7b55daebcca26 plus this review fix Guest: FreeBSD 15.0-RELEASE-p8 amd64, QEMU TCG Linux reference: 7.1-rc1 /work/dev-src-linux/fs/erofs Host tools: erofs-utils 1.8.6

Result

PASS. All five multi-device review findings were fixed and exercised with deterministic positive and negative fixtures. A real two-block LZ4 pcluster was read from an external provider and the complete 1 MiB output matched the source SHA256. Multi-device NFS reads and forced-device-removal behavior also passed.

Source changes validated

  • Non-zero device IDs accept a slot with uniaddr=0; unified device-ID-0 lookup skips such slots.
  • devt_slotoff=0 reads the table from byte offset zero, as Linux 7.1 does.
  • Device mapping carries the requested extent length. Flatdev reads must fit wholly in the primary range or one non-zero unified slot; gaps, adjacent-slot crossings, and pcluster crossings fail closed.
  • Declared image and slot bounds are checked before physical media size, so format corruption is EINTEGRITY and a genuinely short provider is ENXIO.
  • Primary and external namei() failures preserve ENOENT; omitted required device.N options still return ENXIO.

The NFS file-handle ABI, VFS_FHTOVP, inode bounds, readdir cookies, and GEOM orphan lifecycle from 2354b448 were not changed.

Build

Commands:

git diff --check
./build.sh
nm -u build/erofs.ko | awk '$NF == "bcmp" {bad=1} END {exit bad}'
sha256sum build/erofs.ko

Results:

  • Cross-build: PASS.
  • git diff --check: PASS.
  • Unresolved bcmp: none.
  • Module SHA256: b85c429fa73e6cebc10e6e3941575a6ca170306ab4fa9ccca4006c922971acb8.
  • FreeBSD kldload and kldunload: PASS.

Fixture construction

The chunk fixtures derive from the checksum-valid TC094 images recorded in the 19:37 multi-device report. The patcher asserted the original table values slot1=(blocks=19, uniaddr=2), slot2=(blocks=25, uniaddr=21), and the first 32 KiB chunk index (device_id=2, startblk=9) before each change.

The compressed baseline was generated from the deterministic shape.dat:

mkfs.erofs -T0 -U00000000-0000-0000-0000-000000000000 \
    --all-root -E legacy-compress -zlz4 -C65536 \
    lz4-full-64k.erofs src-big64k
dump.erofs --path=/shape.dat -e lz4-full-64k.erofs

The baseline contains one 1 MiB logical extent backed by an 8192-byte physical pcluster. Its HEAD pblk was changed from block 1 to unified block 4; the two compressed blocks were copied to a two-block external provider and zeroed in the primary image. A checksum-valid device table declared slot1=(blocks=2, uniaddr=4).

For the crossing negative, the same pcluster was placed across adjacent slot1=[4,5) and slot2=[5,6). The flatdev contains both real compressed blocks, proving that failure is caused by the declared slot boundary rather than absent data.

erofs-utils 1.8.6 parses the external compressed extent but its userspace compressed read path does not propagate the unified slot ID to erofs_dev_read; therefore userspace extraction of this layout is tool-unavailable. The FreeBSD kernel full-file SHA256 is the authoritative read validation.

Fixture hashes

Fixture SHA256
zero-uniaddr primary d38935291fb2ee756e0c192d1b0d39b4f4f5b4047aa37c2de44cad91a55fa018
zero-uniaddr device-ID-0 control fac9db7631cd06d17212cbe3e7b1d681766f031d1e41e443f71f1bad39f9b960
slotoff-zero primary 39e3e8c60bea962f1200550316be87ec7da7b15c0ba11c6e5edf05f0715db451
cross-slot primary edd0cba92a26bc9a7a59561732fb8e045b2e1565d18d9f9b3143f86f64649dee
cross-slot flatdev 6e2834450081d778cee37fa3e050249f04927def205d6816aab814a2912744bc
gap flatdev 5bc07b66f7b0f83e9568ba781dcc78a08d45e617dc27bb365ed3ee2c12353218
external-compressed primary 5625612426d68624c77dd94b09754da583fc6bd90767e9e9d958e4fc89131a4d
external-compressed blob 0d71102ce471af0a30d4d61a1fbeef1fc33437c85651d7c7f9c60ebd305ec9d0
cross-pcluster primary 2bce4a91c1aedc4bab2e65582ef9cb465094f825a051c0203d52b3d18bb17ed8
cross-pcluster flatdev bc07fb06ca5c6bb60ef1a989eecbd3d714450092ba756f85f5b060c8b8b2ec3a

Source shape.dat SHA256: 370eb0a8df86868c4842ca535ed64670f0277ea2ed47a703f089bbb13ee4ac52.

FreeBSD result matrix

Test Actual Status
slot 1 uniaddr=0, explicit device ID 1 complete striped and second-file SHA256 matched PASS
slot 1 uniaddr=0, device ID 0 control slot skipped; primary-bound EINTEGRITY PASS
devt_slotoff=0 mount and complete striped SHA256 matched PASS
nonexistent primary path ENOENT / No such file or directory PASS
nonexistent external path ENOENT / No such file or directory PASS
omitted slot option ENXIO / Device not configured PASS
flatdev chunk crosses adjacent slots read returned EINTEGRITY PASS
device-ID-0 chunk starts in a gap read returned EINTEGRITY PASS
explicit chunk exceeds declared slot and media EINTEGRITY, not ENXIO PASS
real external 64 KiB LZ4 pcluster complete 1 MiB SHA256 matched PASS
flatdev pcluster crosses adjacent slots read returned EINTEGRITY PASS
explicit pcluster crosses two providers read returned EINTEGRITY PASS

NFS smoke

The external-compressed image was exported read-only over local NFSv3/TCP. The NFS client read the complete shape.dat; SHA256 matched the source.

The zero-uniaddr two-slot image was then exported. The client obtained stable inode and size data for a cold slot-2 file, slot 2 was forcibly orphaned, and the same NFS pathname still resolved to identical metadata. Its first cold data read failed with the underlying device error. This preserves the 2354b448 contract: file-handle resolution is not misreported as ESTALE, while missing external data remains an I/O/device failure.

Cleanup

All EROFS and NFS mounts were unmounted, NFS services stopped, /etc/exports cleared, md providers detached, and the module unloaded. No image, overlay, fixture, or build artifact is part of this commit.

A final representative rerun covered the external-compressed positive, the flatdev-gap negative, and the offset-zero table positive. The dmesg SHA256 was unchanged before and after: 897003051a6a50875d49715bfa27907611cedac9e42e0a06ca7377105ac695ae.