#!/bin/sh
# DF-3061 reproduction (run inside the DragonFly guest as root)
# Baseline expectation: kernel panic ("nfs - retry rename" then
# "Fatal trap 12 ... lockmgr_release+0x11") within ~1-3 minutes.
set -x
mkdir -p /export /mnt/nfs
echo "/export -maproot=root localhost" > /etc/exports
rpcbound=$(pgrep rpcbind); [ -z "$rpcbound" ] && rpcbind
pgrep nfsd >/dev/null || /sbin/nfsd -t -u -n 4
sleep 1
pgrep mountd >/dev/null || /sbin/mountd &
sleep 2
mount | grep -q /mnt/nfs || mount localhost:/export /mnt/nfs

cat > /tmp/cl.c <<'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char **argv){
  const char *d = argv[1];
  char a[512], b[512];
  snprintf(a,sizeof(a),"%s/src",d);
  snprintf(b,sizeof(b),"%s/dst",d);
  for(;;){
    int fd=open(a,O_CREAT,0666); if(fd>=0) close(fd);
    rename(a,b);
    rename(b,a);
    unlink(a);
  }
}
EOF
cat > /tmp/rc4.c <<'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sched.h>
int main(int argc, char **argv){
  const char *d=argv[1]; char a[512],b[512]; int i=0,fd;
  snprintf(a,sizeof(a),"%s/src",d); snprintf(b,sizeof(b),"%s/dst",d);
  if((fd=open(a,O_CREAT,0666))>=0) close(fd);
  for(;;){
    i++;
    if ((i & 63)==0) unlink(a);
    else if ((i & 63)==1) { fd=open(a,O_CREAT,0666); if(fd>=0) close(fd); }
    rename(b,a);
    rename(a,b);
    sched_yield();
  }
}
EOF
cc -O2 -o /tmp/cl /tmp/cl.c || exit 1
cc -O2 -o /tmp/rc4 /tmp/rc4.c || exit 1

pkill rc4 2>/dev/null; pkill cl 2>/dev/null; sleep 1
rm -f /export/* /mnt/nfs/*
for i in 1 2; do /tmp/rc4 /export >/dev/null 2>&1 & done
for i in 1 2 3 4 5 6; do /tmp/cl /mnt/nfs >/dev/null 2>&1 & done
sleep 300
pkill rc4; pkill cl
dmesg | grep -c "nfs - retry rename"
# baseline: guest panics before this point; patched: prints count and exits 0
