4.3 KiB
Test Case: FreeBSD NFSv3 Export Basic Functionality
Test ID: TC131-nfs-export-basic
Category: NFS Export
Priority: Critical
Regression: EROFS VOP_VPTOFH / VFS_FHTOVP / export updates
Objective
Verify that FreeBSD 15 mountd can install an export on a read-only EROFS mount, that nfsd can resolve EROFS file handles, and that regular files, directories, symlinks, and FIFOs are visible through a real NFSv3 client.
Preconditions
- FreeBSD 15 amd64 server/client, optionally the same host over loopback.
- Root privilege for module, md, NFS service,
getfh, andfhopenoperations. erofs.ko,test-nfs.erofs, andtests/nfs_fh_tool.cavailable in the guest.- The fixture contains
basic/regular.txt,basic/subdir,basic/link-to-regular, andbasic/test.fifo.
Procedure
-
Build the module and helper:
./build.sh cc -O2 -Wall -Wextra -std=c17 tests/nfs_fh_tool.c -o nfs_fh_tool -
Load and mount EROFS on a fixed md unit:
kldload ./erofs.ko mdconfig -a -t vnode -f test-nfs.erofs -u 42 mkdir -p /mnt/repo22-erofs mount -t erofs -o ro /dev/md42 /mnt/repo22-erofs mount -v | grep /mnt/repo22-erofsThe line must show
read-onlyand must not showNFS exportedbefore mountd processes/etc/exports. -
Configure the real FreeBSD mountd/nfsd flow:
cp -p /etc/exports /tmp/exports.before 2>/dev/null || true printf '%s\n' \ '/mnt/repo22-erofs -ro -maproot=root -network 127.0.0.0 -mask 255.0.0.0' \ > /etc/exports service rpcbind onestart service mountd onestart service nfsd onestart service mountd onereload rpcinfo -p 127.0.0.1 showmount -e 127.0.0.1 mount -v | grep /mnt/repo22-erofsAfter reload, the EROFS mount line must show
NFS exported. The flag is installed by the generic FreeBSD export layer after the filesystem accepts the export-onlyMNT_UPDATE; EROFS must not set it during the initial mount. -
Mount the export through NFSv3 and confirm the negotiated options:
mkdir -p /mnt/repo22-nfs mount_nfs -o nfsv3,tcp,rdirplus 127.0.0.1:/mnt/repo22-erofs \ /mnt/repo22-nfs nfsstat -m -
Verify all required vnode types and read-only behavior:
cmp /mnt/repo22-nfs/basic/regular.txt \ /mnt/repo22-erofs/basic/regular.txt test -d /mnt/repo22-nfs/basic/subdir test "$(readlink /mnt/repo22-nfs/basic/link-to-regular)" = regular.txt test -p /mnt/repo22-nfs/basic/test.fifo test "$(stat -f %i /mnt/repo22-nfs/basic/regular.txt)" = \ "$(stat -f %i /mnt/repo22-erofs/basic/regular.txt)" ! touch /mnt/repo22-nfs/write-must-fail -
Exercise both shared- and exclusive-lock file-handle resolution locally:
./nfs_fh_tool capture /mnt/repo22-erofs/basic/regular.txt regular.fh ./nfs_fh_tool stat regular.fh ./nfs_fh_tool cat regular.fh regular.out cmp regular.out /mnt/repo22-erofs/basic/regular.txtfhstatrequests a shared lock andfhopenrequests an exclusive lock. -
Confirm that NFSv3 used READDIRPLUS and did not issue writes:
nfsstat -c nfsstat -s
Expected Results
- mountd accepts the EROFS export-only update.
showmount -elists the EROFS path andmount -vshowsNFS exportedonly after mountd reloads exports.- NFSv3 regular reads, directory traversal, symlink lookup, FIFO metadata, and inode numbers match the direct EROFS mount.
- Writes fail with
EROFS/Read-only file system. fhstatandfhopenboth resolve the same 64-bit EROFS NID.- NFS statistics show READDIRPLUS traffic and zero successful write RPCs.
Cleanup
Always remove clients before stopping the loopback server:
umount /mnt/repo22-nfs
: > /etc/exports
service mountd onereload
service nfsd onestop
service mountd onestop
service rpcbind onestop
umount /mnt/repo22-erofs
mdconfig -d -u 42
kldunload erofs
rm -f /etc/exports
Restore a pre-existing /etc/exports instead of removing it when applicable.
Notes
- The EROFS FreeBSD file-handle payload is 16 bytes:
len,pad,nid_hi,nid_lo, and a nonzero superblock-seeded per-inode generation matchingva_gen. - Do not use Linux
exportfs; FreeBSD mountd installs exports through a mount update carrying theexportoption. - Throughput is recorded for information only; correctness has no fixed MB/s threshold.