#!/bin/sh
# DF-3093 verification: unsynchronized msdosfs free-cluster allocator
# (MSDOSFS_LOCK_MP is an empty macro, msdosfsmount.h:216-218).
#
# Per cycle: fresh newfs_msdos volume, mounted via vn0; race2 fires
# nprocs barrier-synchronized single write(2)s of chunk bytes per round
# (all files pre-created); then unmount and run the offline FAT
# in-degree scanner (fat_scan) which deterministically detects any
# cluster claimed by two chains.
#
# usage: run2.sh [cycles] [procs] [rounds] [chunk]
set -u
ID=DF-3093
MNT=/mnt/df3093
VND=vn0
IMG=/root/df3093.img
CYCLES=${1:-20}
PROCS=${2:-8}
ROUNDS=${3:-3}
CHUNK=${4:-2097152}
SZ=64m
DIR="$(dirname "$0")"

cleanup() {
	umount $MNT 2>/dev/null || true
	vnconfig -u $VND 2>/dev/null || true
}
trap cleanup EXIT

cd "$DIR" || exit 1
echo "=== $ID build ==="
cc -O2 -o race2 race2.c || exit 1
cc -O2 -o fat_scan fat_scan.c || exit 1

c=1
hits=0
while [ $c -le $CYCLES ]; do
	echo "--- cycle $c/$CYCLES: ${PROCS}p x ${ROUNDS}r x ${CHUNK}B ---"
	cleanup
	rm -f $IMG
	newfs_msdos -C $SZ $IMG >/dev/null 2>&1 || { echo newfs fail; exit 1; }
	vnconfig -c $VND $IMG
	mkdir -p $MNT
	mount_msdos -m 644 /dev/$VND $MNT || { echo mount fail; exit 1; }
	./race2 $MNT $PROCS $ROUNDS $CHUNK
	sync
	umount $MNT
	vnconfig -u $VND
	if ./fat_scan $IMG; then
		:
	else
		echo "=== CYCLE $c: FAT SCAN FOUND CROSS-LINKS ==="
		hits=$((hits + 1))
		cp $IMG /root/df3093-hit-$c.img
		break
	fi
	# incidental kernel-side signal: unsynchronized frees
	dmesg | tail -30 | grep -i "Freeing unused sector" && {
		echo "=== kernel noticed 'Freeing unused sector' ==="; hits=$((hits+1)); break; }
	c=$((c + 1))
done
echo
if [ $hits -gt 0 ]; then
	echo "RESULT $ID: REPRODUCED (see cycle output above + saved image)"
else
	echo "RESULT $ID: no cross-link detected in $((c - 1)) cycles"
fi
