DF-4063 / run.log
DF-4063 baseline (UNPATCHED kernel, DragonFly 6.5-DEVELOPMENT #0 built 20:25 UTC,
fdc0+fd0 attached on QEMU ISA floppy, 6 vCPU):
RUN 1 (readers=128):
readers=128 running; letting the queue build...
fdform#1(timeout-expected): FD_FORM cyl=2 -> rc=-1 errno=5 (Input/output error) in 20.010 s
(fdform#2 + stress never got to flush: kernel panicked ~60 s later)
serial console (dfbsd-qemu/boot.log, captured in panic.txt):
tsleep error biowait 35
panic: Bad link elm 0xfffff8004f415908 next->prev != elm
cpuid = 0
fdstate() at fdstate+0xdfb
fdstate() at fdstate+0xdfb
fdc_intr() at fdc_intr+0x18
ithread_handler() at ithread_handler+0x2fe
Debugger("panic") / db>
RUN 2 (readers=128, fresh boot, same kernel):
readers=128 running; letting the queue build...
fdform#1(timeout-expected): FD_FORM cyl=2 -> rc=-1 errno=5 (Input/output error) in 20.014 s
serial console (panic.txt):
tsleep error biowait 35
panic: Bad link elm 0xfffff8004f41fcc0 next->prev != elm
fdstate() at fdstate+0xdfb
fdc_intr() at fdc_intr+0x18
ithread_handler() at ithread_handler+0x2fe
NOTE: /tmp is tmpfs on the guest, so the PoC's own log after fdform#1 was lost
when the panic rebooted the box; the two lines above were captured live over
ssh before the crash (same for both runs). Deterministic: 2/2 panics.
Interpretation:
- fdform#1 returns EIO at exactly the 20*hz biowait_timeout while 128 reader
threads keep the fdc queue deep -> the driver still owns the bio.
- fdformat() then does biodone(&bp->b_bio1) + relpbuf(bp) itself; the freed
pbuf is immediately recycled by fdform#2 (getpbuf), which re-queues the SAME
bio (bp->b_bio1 address) via bioq_insert_tail while the stale entry is still
linked in fdc->bio_queue -> double-linked TAILQ element.
- When the machine finally dequeues into the corrupted region:
panic "Bad link elm ... next->prev != elm" from TAILQ_REMOVE in fdstate.
"tsleep error biowait 35" is the collateral damage to the recycled pbuf's
biowait.