DF-2550 / verify_fix.sh
#!/bin/sh # DF-2550 fix-verification driver. Run on the PATCHED (single-fix) kernel. # Same NFS repro as run.sh, but the expected outcome is the NEGATION: # - on baseline (#0): guest PANICS ("locking against myself") after the # failing VOP_GETATTR leaks the vnode lock. # - on patched (#1): NO panic; the fchown loop keeps returning the # VOP_GETATTR error (e.g. EINTR/EIO) cleanly for many iterations, # because vput(vp) now releases the lock on the error path. Guest stays up. set -u DIR=$(cd "$(dirname "$0")" && pwd) ROOT=$(cd "$DIR/../../.." && pwd) SSH="ssh -F $ROOT/dfbsd-qemu/config -o BatchMode=yes -o ConnectTimeout=8" VM="$ROOT/dfbsd-qemu/vm.sh" MNT=/mnt/nfs; EXP=/export LOG="$DIR/fix_run.log" echo "[fix] patched kernel:" | tee "$LOG" $VM run_root 'sysctl -n kern.version | head -1' 2>&1 | tee -a "$LOG" echo "[fix] NFS server up" | tee -a "$LOG" $VM run_root 'umount -f '"$MNT"' 2>/dev/null pkill -9 nfsd 2>/dev/null; pkill -9 mountd 2>/dev/null; pkill -9 rpcbind 2>/dev/null; sleep 1 mkdir -p '"$EXP"' '"$MNT"'; echo "nfs repro" > '"$EXP"'/f; chown 1001 '"$EXP"'/f; chmod 644 '"$EXP"'/f echo "'"$EXP"' -alldirs -maproot=0 127.0.0.1" > /etc/exports /usr/sbin/rpcbind; sleep 1; /sbin/mountd; sleep 1; /sbin/nfsd -t -u -n 4; sleep 2 mount_nfs -3 -U -s -t 1 -x 1 -o acregmin=0,acregmax=0 127.0.0.1:'"$EXP"' '"$MNT"' && echo MOUNT_OK ls -l '"$MNT"'/f' 2>&1 | grep -E "MOUNT_OK|maxx" | tee -a "$LOG" rm -f "$DIR/trigger_fix.out" ( $SSH dfbsd-maxx /bin/sh <<EOF cd poc/DF-2550 && exec ./trigger $MNT/f EOF ) > "$DIR/trigger_fix.out" 2>&1 & TPID=$! sleep 4 echo "[fix] steady state:" | tee -a "$LOG"; tail -2 "$DIR/trigger_fix.out" | tee -a "$LOG" echo "[fix] kill NFS server" | tee -a "$LOG" $VM run_root 'pkill -9 nfsd; sleep 1; pgrep nfsd || echo nfsd_dead' 2>&1 | grep -E "dead" | tee -a "$LOG" echo "[fix] wait 90s; on patched kernel the guest must STAY UP" | tee -a "$LOG" i=0 while [ $i -lt 45 ]; do if ! $VM run_root 'true' >/dev/null 2>&1; then echo "[fix] !!! guest went DOWN at +$((i*2))s (PANIC = fix FAILED)" | tee -a "$LOG"; break fi sleep 2; i=$((i+1)) done echo "===== trigger_fix.out (tail) =====" | tee -a "$LOG" tail -10 "$DIR/trigger_fix.out" | tee -a "$LOG" echo "===== guest status (expect up) =====" | tee -a "$LOG" $VM status 2>&1 | tee -a "$LOG" echo "===== serial panic check (expect none) =====" | tee -a "$LOG" $VM log 2000 2>/dev/null | grep -iE "panic:|locking against myself" | tail -5 | tee -a "$LOG" if $VM run_root 'true' >/dev/null 2>&1; then echo "[fix] RESULT: guest still UP after NFS failure -> NO PANIC -> FIX VALIDATED" | tee -a "$LOG" exit 0 else echo "[fix] RESULT: guest DOWN -> fix did NOT prevent the panic" | tee -a "$LOG" exit 1 fi |