Files
erofs-freebsd-out-tree/tests/TC101-unified-address-mapping.md
T
2026-08-13 10:44:59 +02:00

5.4 KiB

Test Case: Unified Address and Flatdev Mapping

Test ID: TC101-unified-address-mapping
Category: Multi-Device
Priority: Critical

Objective

Verify both EROFS mapping forms and fail-closed complete-extent checks:

  1. device ID 0 plus a block in a nonzero slot uniaddr range selects that explicit provider and subtracts the range base;
  2. a nonzero device ID in flatdev mode adds uniaddr and reads the combined primary provider;
  3. gaps, cross-slot chunks/pclusters, and out-of-range 48-bit addresses return EINTEGRITY before physical I/O fallback.

Positive explicit unified mapping

I=/root/repo22-g6/images
S=/root/repo22-g6/sources/chunk
mkdir -p /mnt/g6
kldload /root/repo22-g6/erofs.ko
mdconfig -a -t vnode -f "$I/multi2-unified-primary.erofs" -u 90
mdconfig -a -t vnode -f "$I/multi2-unified-slot1.blob" -u 91
mdconfig -a -t vnode -f "$I/multi2-unified-slot2.blob" -u 92
mount -t erofs -o ro -o device.2=/dev/md92 -o device.1=/dev/md91 \
  /dev/md90 /mnt/g6
sha256 "$S/unified-address.bin" /mnt/g6/unified-address.bin
cmp "$S/unified-address.bin" /mnt/g6/unified-address.bin
dd if="$S/unified-address.bin" of=/tmp/tc101.unified.src bs=1 skip=61440 count=8192 2>/dev/null
dd if=/mnt/g6/unified-address.bin of=/tmp/tc101.unified.mnt bs=1 skip=61440 count=8192 2>/dev/null
cmp /tmp/tc101.unified.src /tmp/tc101.unified.mnt
umount /mnt/g6
mdconfig -d -u 92
mdconfig -d -u 91
mdconfig -d -u 90

The manifest must show that this index is device ID 0 and pblk equals slot-1 uniaddr + local_pblk, not a local primary address.

Positive flatdev mappings

First test nonzero chunk device IDs in one combined provider:

mdconfig -a -t vnode -f "$I/multi2-flatdev.erofs" -u 90
mount -t erofs -o ro /dev/md90 /mnt/g6
sha256 "$S/cross-device.bin" /mnt/g6/cross-device.bin
cmp "$S/cross-device.bin" /mnt/g6/cross-device.bin
dd if="$S/cross-device.bin" of=/tmp/tc101.flat.src bs=1 skip=126976 count=139264 2>/dev/null
dd if=/mnt/g6/cross-device.bin of=/tmp/tc101.flat.mnt bs=1 skip=126976 count=139264 2>/dev/null
cmp /tmp/tc101.flat.src /tmp/tc101.flat.mnt
umount /mnt/g6
mdconfig -d -u 90

Then test device-ID-0 unified addressing in the combined provider:

mdconfig -a -t vnode -f "$I/multi2-unified-flatdev.erofs" -u 90
mount -t erofs -o ro /dev/md90 /mnt/g6
cmp "$S/unified-address.bin" /mnt/g6/unified-address.bin
umount /mnt/g6
mdconfig -d -u 90

The 139264-byte range spans the slot-1/slot-2 transition. erofs-utils 1.8.6 cannot qualify these flatdev forms; the kernel full/range comparisons are the qualification.

Positive 48-bit high mapping

mdconfig -a -t vnode -f "$I/multi2-unified48-primary.erofs" -u 90
mdconfig -a -t vnode -f "$I/multi2-unified48-slot1.blob" -u 91
mdconfig -a -t vnode -f "$I/multi2-unified48-slot2.blob" -u 92
mount -t erofs -o ro -o device.1=/dev/md91 -o device.2=/dev/md92 \
  /dev/md90 /mnt/g6
cmp "$S/unified-address.bin" /mnt/g6/unified-address.bin
umount /mnt/g6
mdconfig -d -u 92
mdconfig -d -u 91
mdconfig -d -u 90

This requires nonzero uniaddr_hi and startblk_hi; zero-high truncation would read the wrong bytes.

Fail-closed extent cases

Each primary below is checksum-valid. Mount succeeds, and the named cold read must return exactly EINTEGRITY in truss:

Primary and providers Mode Read target
bad-unified-gap-* explicit and bad-unified-gap-flatdev.erofs unified-address.bin
bad-cross-slot-explicit-* explicit indexed.bin
bad-cross-slot-unified-* explicit and bad-cross-slot-unified-flatdev.erofs indexed.bin
bad-lz4-cross-slot-* explicit and bad-lz4-cross-slot-flatdev.erofs external-pcluster.bin
bad-unified48-out-of-range-* explicit unified-address.bin

For an explicit chunk case, use this direct command shape with the matching prefix and target:

PREFIX=bad-cross-slot-explicit
TARGET=indexed.bin
mdconfig -a -t vnode -f "$I/$PREFIX-primary.erofs" -u 90
mdconfig -a -t vnode -f "$I/$PREFIX-slot1.blob" -u 91
mdconfig -a -t vnode -f "$I/$PREFIX-slot2.blob" -u 92
mount -t erofs -o ro -o device.1=/dev/md91 -o device.2=/dev/md92 \
  /dev/md90 /mnt/g6
truss -f -o "/tmp/tc101-$PREFIX.truss" dd if="/mnt/g6/$TARGET" \
  of=/dev/null bs=131072 count=1
tail -20 "/tmp/tc101-$PREFIX.truss"
umount /mnt/g6
mdconfig -d -u 92
mdconfig -d -u 91
mdconfig -d -u 90

For a flatdev row, attach only its *-flatdev.erofs as md90 and use no device.N options. For the LZ4 explicit row, use its two one-block slot providers. Execute every row and mode separately; do not use a runner.

The explicit crossing providers are physically only as long as their declared slots. Therefore both declared range and physical media would be exceeded; EINTEGRITY must win before a possible ENXIO from I/O. The largest non-NULL 48-bit address (0xfffffffffffe; all ones is the hole sentinel) is representable in 64-bit arithmetic but belongs to no declared range, so it also returns EINTEGRITY.

Cleanup and zero-state check

umount /mnt/g6 2>/dev/null || true
mdconfig -d -u 92 2>/dev/null || true
mdconfig -d -u 91 2>/dev/null || true
mdconfig -d -u 90 2>/dev/null || true
kldunload erofs
rm -f /tmp/tc101.*.src /tmp/tc101.*.mnt
mount -p | awk '$3 == "erofs" { print }'
mdconfig -l
kldstat -n erofs 2>/dev/null || true
sysctl -n kern.geom.conftxt | grep -E 'md9[0-2]|erofs' || true

All four final outputs must be empty, with no panic, trap, or hang.