Files
erofs-freebsd-out-tree/tests/TC118-device-not-found.md
T
2026-08-18 09:20:44 +02:00

4.1 KiB

Test Case: Missing, Invalid, and Orphaned External Device

Test ID: TC118-device-not-found
Category: Multi-Device / Error Handling Priority: Critical

Objective

Verify exact missing/short/duplicate/path errors, forced GEOM orphan behavior, concurrent provider ownership, and complete vnode/cdev/consumer cleanup.

Fixture qualification

Use the fresh multi2 set. The manifest must show /cold-slot2.bin has one chunk with device ID 2; do not read it before the orphan step. multi2-slot2-short.blob is exactly one block below slot 2's declared size.

Mount-time errors

Set up the test directory and load the exact KLD once:

I=/root/repo22-g6/images
mkdir -p /mnt/g6 /mnt/g6b
kldload /root/repo22-g6/erofs.ko

Run each case separately with truss, detaching all attached md units after each failure:

  1. Split primary with no device.N: ENXIO.
  2. Only device.1: ENXIO.
  3. Valid slot 1 plus multi2-slot2-short.blob: ENXIO.
  4. The same md91 assigned to slots 1 and 2: EINVAL.
  5. Primary md90 also assigned as slot 1, with valid md92 for slot 2: EINVAL.

The short-media command is:

mdconfig -a -t vnode -f "$I/multi2-primary.erofs" -u 90
mdconfig -a -t vnode -f "$I/multi2-slot1.blob" -u 91
mdconfig -a -t vnode -f "$I/multi2-slot2-short.blob" -u 92
truss -f -o /tmp/tc118-short.truss mount -t erofs -o ro \
  -o device.1=/dev/md91 -o device.2=/dev/md92 /dev/md90 /mnt/g6
tail -20 /tmp/tc118-short.truss
mdconfig -d -u 92
mdconfig -d -u 91
mdconfig -d -u 90

After every case, mount -p | awk '$3 == "erofs"' and matching kern.geom.conftxt consumer output must be empty.

Forced orphan

Attach fresh providers and mount without reading cold-slot2.bin:

mdconfig -a -t vnode -f "$I/multi2-primary.erofs" -u 90
mdconfig -a -t vnode -f "$I/multi2-slot1.blob" -u 91
mdconfig -a -t vnode -f "$I/multi2-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/tc118-ebusy.truss mdconfig -d -u 92
tail -20 /tmp/tc118-ebusy.truss
mdconfig -d -u 92 -o force
truss -f -o /tmp/tc118-orphan-read.truss sha256 \
  /mnt/g6/cold-slot2.bin
tail -20 /tmp/tc118-orphan-read.truss

Normal detach must return EBUSY; forced detach must complete; the first cold slot-2 read must return exactly ENXIO without panic, hang, or leaked vnode.

umount /mnt/g6
mdconfig -d -u 91
mdconfig -d -u 90

Concurrent mount ownership

mdconfig -a -t vnode -f "$I/multi2-primary.erofs" -u 90
mdconfig -a -t vnode -f "$I/multi2-slot1.blob" -u 91
mdconfig -a -t vnode -f "$I/multi2-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/tc118-concurrent.truss mount -t erofs -o ro \
  -o device.1=/dev/md91 -o device.2=/dev/md92 /dev/md90 /mnt/g6b
tail -20 /tmp/tc118-concurrent.truss
sha256 /mnt/g6/tc006.bin

The second mount must return exactly EBUSY, and the first mount must remain readable. Record a kernel failure and do not edit src/ if FreeBSD permits a second mount of an already-open provider set.

umount /mnt/g6
mdconfig -d -u 92
mdconfig -d -u 91
mdconfig -d -u 90

Pathname preservation

truss -f -o /tmp/tc118-primary-enoent.truss mount -t erofs -o ro \
  /no/such/repo22-g6-primary /mnt/g6
tail -20 /tmp/tc118-primary-enoent.truss
mdconfig -a -t vnode -f "$I/multi2-primary.erofs" -u 90
mdconfig -a -t vnode -f "$I/multi2-slot1.blob" -u 91
truss -f -o /tmp/tc118-slot-enoent.truss mount -t erofs -o ro \
  -o device.1=/dev/md91 -o device.2=/no/such/repo22-g6-slot2 \
  /dev/md90 /mnt/g6
tail -20 /tmp/tc118-slot-enoent.truss

Both operations must preserve exactly ENOENT; the external failure must also release the already-open slot-1 consumer.

Cleanup and zero-state check

mdconfig -d -u 91
mdconfig -d -u 90
kldunload erofs
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
dmesg | tail -120

All four final lifecycle outputs must be empty. The dmesg suffix must contain no panic, trap, assertion, watchdog, or unexpected EROFS error.