# Test Case: Invalid Device Table **Test ID**: TC097-device-table-invalid **Category**: Multi-Device / Error Handling **Priority**: Critical ## Objective Verify fail-closed table validation and complete cleanup after parse failure or after slot 1 has opened and slot 2 fails. ## Deterministic negative fixtures The G6 generator makes one asserted change per checksum-valid image: | Image | Exact expected errno | | --- | --- | | `bad-table-oob.erofs` | `EINTEGRITY` | | `bad-slot-zero-blocks.erofs` | `EINTEGRITY` | | `bad-slot-inside-primary.erofs` | `EINTEGRITY` | | `bad-slot-overlap.erofs` | `EINTEGRITY` | | `bad-slot-32bit-limit.erofs` | `EINTEGRITY` | | `bad-slot-48bit-limit.erofs` | `EINTEGRITY` | An on-disk slot has only 48-bit `blocks` and `uniaddr`; their sum cannot overflow a 64-bit C integer. Therefore an alleged uint64-add-overflow fixture is not representable. The last image tests the real format boundary: a 48-bit range ending above `2^48`. `devt_slotoff=0` and `uniaddr=0` are legal TC096 positives, not invalid fixtures. ## Manual procedure for each structural image For each row above, execute the following commands directly, replacing `IMAGE` with that row. Do not put the rows in a runner or shell loop. ```sh I=/root/repo22-g6/images IMAGE=bad-table-oob.erofs mkdir -p /mnt/g6 kldload /root/repo22-g6/erofs.ko mdconfig -a -t vnode -f "$I/$IMAGE" -u 90 mdconfig -a -t vnode -f "$I/multi2-slot1.blob" -u 91 mdconfig -a -t vnode -f "$I/multi2-slot2.blob" -u 92 truss -f -o "/tmp/tc097-$IMAGE.truss" mount -t erofs -o ro \ -o device.1=/dev/md91 -o device.2=/dev/md92 /dev/md90 /mnt/g6 tail -20 "/tmp/tc097-$IMAGE.truss" mount -p | awk '$3 == "erofs" { print }' mdconfig -d -u 92 mdconfig -d -u 91 mdconfig -d -u 90 kldunload erofs mdconfig -l kldstat -n erofs 2>/dev/null || true sysctl -n kern.geom.conftxt | grep -E 'md9[0-2]|erofs' || true ``` Each mount must return exactly `EINTEGRITY`. After each individual failure, the mount, md, KLD, and matching GEOM consumer outputs must all be empty before proceeding to the next image. ## Reverse-open cleanup This valid table opens slot 1 and then fails the slot-2 pathname lookup: ```sh kldload /root/repo22-g6/erofs.ko 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/tc097-reverse.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/tc097-reverse.truss mdconfig -d -u 91 mdconfig -d -u 90 kldunload erofs ``` The mount returns `ENOENT`, and immediate detach of md91 proves reverse-order cleanup released the already-open consumer. ## Final zero-state check ```sh 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 outputs must be empty, with no panic, trap, hang, leaked mount, or stale GEOM consumer.