#!/bin/sh
# DF-2621 trigger v1: plain MASTER+MASTER same-pfs_clid merge (dd clone, NO
# forged bytes).  Exercises hammer2_xop_helper_create() being called twice on
# the same pmp:
#   mount1: hammer2_mount_helper                -> helper_create #1 (array A)
#   mount2: hammer2_pfsalloc (pmp->mp set)      -> helper_create #2 (array B,
#                                                  array A + 36 threads leaked)
#           mount fails EBUSY (vfsops.c:1454)
#   umount: helper_cleanup tears down array B; array A threads are orphaned;
#           pmp later kfree'd in hammer2_pfsfree (vfsops.c:722) while the
#           orphans still hold thr->pmp -> 30s poll loop writes pmp->xop_spin.
# Everything logged to run.log.  Standalone (nohup-safe).
D=/root/poc/df2621
LOG=$D/run.log
exec > $LOG 2>&1
set -x

vnconfig -u vn0 2>/dev/null
vnconfig -u vn1 2>/dev/null

# fresh images each run (identical bytes => identical pfs_clid)
rm -f $D/base.img $D/clone.img
truncate -s 64M $D/base.img
newfs_hammer2 -L testvol $D/base.img
dd if=$D/base.img of=$D/clone.img bs=1m 2>/dev/null

vnconfig -c vn0 $D/base.img
vnconfig -c vn1 $D/clone.img
mkdir -p /mnt/h2 /mnt/h2b

memstat() {
	vmstat -m 2>/dev/null | grep -E '^hammer2|HAMMER2' || true
	ps axlw | grep "h2xop-testvol" | grep -v grep | wc -l
}

echo "=== 0. baseline ==="
echo -n "T0="; memstat
vmstat -m | grep -i hammer2 > $D/m.base
cat $D/m.base

echo "=== 1. mount MASTER vn0 (clindex 0) ==="
mount -t hammer2 -o ro /dev/vn0@testvol /mnt/h2
echo MOUNT1_RC=$?
echo -n "T1="; memstat
vmstat -m | grep -i hammer2 > $D/m.t1
cat $D/m.t1

echo "=== 2. same-clid MASTER vn1: merge then EBUSY ==="
mount -t hammer2 -o ro /dev/vn1@testvol /mnt/h2b
echo "MOUNT2_RC=$? (expect 1 'PFS already mounted')"
echo -n "T2="; memstat
vmstat -m | grep -i hammer2 > $D/m.t2
cat $D/m.t2

echo "=== 3. umount (plain) -> array B torn down; array A orphaned ==="
date
umount /mnt/h2
echo UMOUNT_RC=$?
date
echo -n "T3="; memstat
vmstat -m | grep -i hammer2 > $D/m.t3
cat $D/m.t3

echo "=== 4. orphan poll window (orphan wakes every 30s touch freed pmp) ==="
i=0
while [ $i -lt 12 ]; do
	echo -n "w$i t="; memstat
	i=$((i+1))
	sleep 10
done
echo "=== 5. unbind devices (releases hmps; pmp freed in pfsfree_scan) ==="
vnconfig -u vn0
vnconfig -u vn1
echo -n "T5="; memstat

echo "=== 6. post-free orphan window (pmp kfreed; orphans write freed heap) ==="
i=0
while [ $i -lt 12 ]; do
	echo -n "p$i t="; memstat
	i=$((i+1))
	sleep 10
done
echo TRIGGER_V1_DONE
