#!/bin/sh
# DF-2940 — minimal deterministic-ish reproducer (validated on the guest).
#
# stack: vn(4) file-backed -> dm-delay(10ms) 'slow' -> dm-crypt 'vol'
# load : 24 parallel dd streams (mixed read/write) through /dev/mapper/vol
# kill : repeated suspend -> load(linear) -> resume  (table switch destroys
#        the crypt table while bios hold write_mpipe buffers)
#
# Baseline (unfixed): dmtc_destroy entered with 1..12 write buffers checked
# out; guest wedges (resume stuck in-kernel, 26+ unkillable D-state procs)
# within a few cycles.
set -x
kldload dm 2>/dev/null
kldload dm_target_delay 2>/dev/null
kldload dm_target_linear 2>/dev/null
kldload dm_target_crypt 2>/dev/null

dd if=/dev/urandom of=/root/img bs=1m count=64 2>/dev/null
vnconfig -c -S 64m -T vn0 /root/img
dmsetup create slow --table "0 131072 delay /dev/vn0 0 10"

KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
CTABLE="0 131072 crypt aes-cbc-plain $KEY 0 /dev/mapper/slow 0"
dmsetup create vol --table "$CTABLE"

rm -f /tmp/dd.pids
i=0
while [ $i -lt 24 ]; do
    if [ $((i % 2)) -eq 0 ]; then
        ( while :; do dd if=/dev/zero of=/dev/mapper/vol bs=128k 2>/dev/null; done ) &
    else
        ( while :; do dd if=/dev/mapper/vol of=/dev/null bs=128k 2>/dev/null; done ) &
    fi
    echo $! >> /tmp/dd.pids
    i=$((i+1))
done
sleep 2

a=0
while [ $a -lt 15 ]; do
    dmsetup suspend vol
    dmsetup load vol --table "0 131072 linear /dev/vn0 0"
    dmsetup resume vol
    a=$((a+1))
    dmsetup suspend vol
    dmsetup load vol --table "$CTABLE"
    dmsetup resume vol
done
echo SURVIVED
