#!/bin/sh
# DF-5550 live xpt-path run: free a periph that is still scheduled on
# device->drvq, exactly like a surprise-removed busy disk does.
#
# Requires: ptsim2.ko loaded (fresh boot), stock (unfixed) kernel.
set -e
cd /root/df5550
sysctl debug.debugger_on_panic=0 >/dev/null 2>&1 || true

if ! kldstat -v 2>/dev/null | grep -q ptsim2; then
	kldload ./ptsim2/ptsim2.ko
fi
i=0
while [ $i -lt 30 ]; do [ -e /dev/da7 ] && break; sleep 1; i=$((i+1)); done
echo "attached: $(ls /dev/da[0-9] 2>/dev/null | wc -l) da nodes on ptsim20"

# 1. jam the shared devq: 56 readers, 100ms completions
sysctl debug.ptsim2.delay=5
for n in 0 1 2 3 4 5 6 7; do
	for j in 1 2 3 4 5 6 7; do
		(dd if=/dev/da$n of=/dev/null bs=8k count=1000000 2>/dev/null &)
	done
done
sleep 5
echo "jam: $(sysctl -n debug.ptsim2.deferred) ccbs deferred (openings exhausted)"

# 2. freeze the openings: periphs park on drvq indefinitely
sysctl debug.ptsim2.hold=1

# 3. kill all targets and rescan -> AC_LOST_DEVICE frees pass periphs,
#    marks da periphs INVALID (still open, still parked on drvq)
sysctl debug.ptsim2.ntargets=0
sysctl debug.ptsim2.rescan=1
echo "removal triggered; waiting for invalidate..."
sleep 12

# 4. close the readers: last cam_periph_release of an INVALID periph ->
#    camperiphfree -> xpt_remove_periph -> camq_resize(drvq, -1) with the
#    dying periph still counted in drvq.entries
echo "killing readers (last close frees parked da periphs)..."
date
pkill dd || true
sleep 20
echo "still alive after 20s -- no panic this run"
