# Test Case: FreeBSD NFSv3 READDIRPLUS and Export Stress **Test ID**: TC133-nfs-export-stress **Category**: NFS Export **Priority**: High **Regression**: directory cookies, EOF, concurrency, and export stability ## Objective Stress the FreeBSD NFSv3 export with a 10,000+ entry directory, small negotiated readdir sizes, repeated cookie pagination, multiple concurrent traversals, and parallel reads/stat operations. Verify no duplicates, omissions, premature EOF, stale handles, panic, or resource leak. ## Preconditions - Complete TC131 server setup. - A fixture with at least 12,050 deterministically named files in `bigdir`, a `concurrent` file set, and a larger sequential-read file. - Four client mount points are available. ## Procedure 1. Mount four NFSv3 client views with READDIRPLUS. Request small readdir sizes on three mounts and record the effective values: ```sh mount_nfs -o nfsv3,tcp,rdirplus,readdirsize=512 \ 127.0.0.1:/mnt/repo22-erofs /mnt/repo22-nfs-512 mount_nfs -o nfsv3,tcp,rdirplus,readdirsize=1024 \ 127.0.0.1:/mnt/repo22-erofs /mnt/repo22-nfs-1024 mount_nfs -o nfsv3,tcp,rdirplus,readdirsize=4096 \ 127.0.0.1:/mnt/repo22-erofs /mnt/repo22-nfs-4096 mount_nfs -o nfsv3,tcp,rdirplus \ 127.0.0.1:/mnt/repo22-erofs /mnt/repo22-nfs-default nfsstat -m ``` FreeBSD may clamp very small requests to its client minimum. Record both the requested and effective values; a clamp is an environment characteristic, not a test failure. 2. Traverse each mount and verify exact names, counts, and uniqueness: ```sh jot -w file-%05d 12050 0 > expected.names for M in 512 1024 4096 default; do find /mnt/repo22-nfs-$M/bigdir -type f -maxdepth 1 | \ sed 's#.*/##' > names.$M test "$(wc -l < names.$M)" -eq 12050 sort names.$M | uniq -d > duplicates.$M test ! -s duplicates.$M sort names.$M > sorted.$M cmp expected.names sorted.$M done sha256 expected.names sorted.* ``` 3. Verify `.` and `..` are each returned exactly once and EOF is reached only after all real entries: ```sh ls -a1 /mnt/repo22-nfs-default/bigdir > dot-list test "$(wc -l < dot-list)" -eq 12052 test "$(grep -cx '\.' dot-list)" -eq 1 test "$(grep -cx '\.\.' dot-list)" -eq 1 ``` 4. Force cold cookie pagination by repeatedly unmounting/remounting the small client and comparing every complete listing: ```sh for round in 1 2 3 4 5; do umount /mnt/repo22-nfs-512 mount_nfs -o nfsv3,tcp,rdirplus,readdirsize=512 \ 127.0.0.1:/mnt/repo22-erofs /mnt/repo22-nfs-512 find /mnt/repo22-nfs-512/bigdir -type f -maxdepth 1 | \ sed 's#.*/##' | sort > cold-$round.sorted cmp expected.names cold-$round.sorted done ``` 5. Run at least eight traversal workers, three rounds each, distributed across the four mounts. Save every PID and wait for every PID individually; a bare final `wait` does not prove that all background jobs succeeded: ```sh pids="" worker=0 for round in 1 2 3; do for M in 512 1024 4096 default; do worker=$((worker + 1)) (find /mnt/repo22-nfs-$M/bigdir -type f -maxdepth 1 | \ sed 's#.*/##' | sort | cmp expected.names -) \ > walk-$worker.log 2>&1 & pids="$pids $!" done done status=0 for pid in $pids; do wait "$pid" || status=1 done test "$status" -eq 0 ``` 6. Run parallel data and metadata operations: ```sh pids="" for M in 512 1024 4096 default; do (find /mnt/repo22-nfs-$M/concurrent -type f -maxdepth 1 -print0 | \ xargs -0 -n 1 -P 8 cat > /dev/null) > cat-$M.log 2>&1 & pids="$pids $!" (find /mnt/repo22-nfs-$M/concurrent -type f -maxdepth 1 -print0 | \ xargs -0 -n 1 -P 8 stat -f '%i %z' > /dev/null) \ > stat-$M.log 2>&1 & pids="$pids $!" done status=0 for pid in $pids; do wait "$pid" || status=1 done test "$status" -eq 0 ``` 7. Record throughput as information only: ```sh /usr/bin/time -p dd if=/mnt/repo22-nfs-default/throughput.dat \ of=/dev/null bs=1m ``` 8. Record NFS and kernel state: ```sh nfsstat -c nfsstat -s vmstat -H dmesg ``` READDIRPLUS must be non-zero. Timed-out RPCs, retries, successful write RPCs, stale-handle messages, traps, and panics must be zero. ## Expected Results - Every listing contains exactly 12,050 unique expected names. - Cold remount and concurrent listings have identical SHA256 values. - Cookie pagination has no duplicate or missing entry and no premature EOF. - Dot-omitted EROFS directories expose one `.` and one `..` through NFS. - Concurrent reads and stats complete without stale handles or deadlock. - READDIRPLUS activity is visible in client/server statistics. - Throughput is reported without a fixed pass/fail threshold. ## Cleanup Unmount every NFS client while nfsd is still running, then reload an empty export list, stop services, unmount EROFS, detach md, and unload the module: ```sh for M in 512 1024 4096 default; do umount /mnt/repo22-nfs-$M done : > /etc/exports service mountd onereload service nfsd onestop service mountd onestop service rpcbind onestop umount /mnt/repo22-erofs mdconfig -d -u 42 kldunload erofs ``` Final EROFS/NFS mount counts, md units, loaded EROFS modules, service PIDs, and unexpected new dmesg lines must all be zero. Do not stop NFS services before client unmounts; hard localhost NFS mounts can otherwise become uninterruptible.