138 lines
4.1 KiB
Markdown
138 lines
4.1 KiB
Markdown
# 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.
|