# 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: ```sh 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: ```sh 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`: ```sh 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. ```sh umount /mnt/g6 mdconfig -d -u 91 mdconfig -d -u 90 ``` ## Concurrent mount ownership ```sh 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. ```sh umount /mnt/g6 mdconfig -d -u 92 mdconfig -d -u 91 mdconfig -d -u 90 ``` ## Pathname preservation ```sh 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 ```sh 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.