#!/bin/sh
# DF-4760 v2 — the infinite variant: VF_DAEMONOPEN set by a bare holder,
# with NO vinum daemon alive (no `vinum` command has been issued since
# kldload, so no thread is blocked in the VINUM_DAEMON ioctl to answer
# daemonrq_return). Expect:
#   * `timeout 25 kldunload vinum` -> rc 124 (hung in free_vinum loop)
#   * ps wchan of the kldunload process == "vstop" while hung
#   * devbuf in-use/alloc count grows ~linearly at ~hz allocations/sec
#   * when the holder closes at t=40, the (SIGTERMed) kldunload syscall
#     completes and the module unloads; all queued daemonq nodes leaked
set -x
date
uname -a
sysctl kern.hz
kldunload vinum 2>/dev/null; sleep 1
kldload vinum; sleep 1
kldstat -v 2>/dev/null | grep -ci vinum

cc -O -o /tmp/hold_daemon /tmp/hold_daemon.c

vmstat -m | grep -i devbuf
/tmp/hold_daemon 40 > /tmp/holder2.log 2>&1 &
sleep 2

(timeout 25 kldunload vinum; echo "TIMEOUT_KLDUNLOAD_RC=$?" > /tmp/unload2.rc) &
sleep 6
echo '==== t=8: expect kldunload alive, wchan vstop ===='
ps -ax -o pid,stat,wchan,command | grep '[k]ldunload'
vmstat -m | grep -i devbuf
sleep 8
echo '==== t=16 ===='
ps -ax -o pid,stat,wchan,command | grep '[k]ldunload'
vmstat -m | grep -i devbuf
sleep 8
echo '==== t=24 ===='
ps -ax -o pid,stat,wchan,command | grep '[k]ldunload'
vmstat -m | grep -i devbuf
sleep 20
echo '==== t=44: holder closed at t=42; kldunload syscall should have completed ===='
ps -ax -o pid,stat,wchan,command | grep '[k]ldunload' || echo "kldunload process gone"
cat /tmp/unload2.rc
kldstat | grep -i vinum || echo "vinum module gone"
vmstat -m | grep -i devbuf
cat /tmp/holder2.log
dmesg | tail -4
