3.7 KiB
Test Case: FreeBSD NFS File-Handle Stability and Image Replacement
Test ID: TC132-nfs-file-handle-stability Category: NFS Export Priority: Critical Regression: Constant generation could resolve an old handle in a replacement image
Objective
Verify 16-byte EROFS FIDs with full 64-bit NIDs and stable superblock-seeded
per-inode generations. The same image remounted on the same explicit md unit
must preserve the complete fhandle_t; a different image with the same device
number and NID must reject the old handle with ESTALE. Verify va_gen and
handle generation are identical.
Preconditions
- FreeBSD 15 and
tests/nfs_fh_tool.ccompiled asnfs_fh_tool. - Deterministic
nfs-a.erofsandnfs-b.erofsfrom the metadata/VFS fixture generator. They contain the same NIDs/content but different UUIDs. - Use one explicit md unit for every remount/replacement step because FreeBSD stores the filesystem ID outside the filesystem-private FID.
Direct Handle Procedure
Perform these steps before starting NFS clients, so the direct EROFS mount
can be unmounted and replaced without EBUSY.
-
Attach
nfs-a.erofsto md80 and mount it. -
Capture regular, directory, symlink (
lcapture), and FIFO handles. For the regular file:./nfs_fh_tool describe a.fh ./nfs_fh_tool stat a.fh stat -f 'gen=%v ino=%i' /mnt/repo22-erofs/basic/regular.txtAssert
len=16,pad=0, full NID preservation, nonzero generation, anddescribe gen == stat st_gen. -
Verify malformed versus stale classification:
./nfs_fh_tool mutate a.fh bad-len.fh len 15 ./nfs_fh_tool mutate a.fh bad-pad.fh pad 1 ./nfs_fh_tool mutate a.fh bad-gen.fh gen_xor 1 ./nfs_fh_tool mutate a.fh bad-nid.fh nid_hi 0xffffffff ./nfs_fh_tool expect-stat bad-len.fh EINVAL ./nfs_fh_tool expect-open bad-len.fh EINVAL ./nfs_fh_tool expect-stat bad-pad.fh EINVAL ./nfs_fh_tool expect-open bad-pad.fh EINVAL ./nfs_fh_tool expect-stat bad-gen.fh ESTALE ./nfs_fh_tool expect-open bad-gen.fh ESTALE ./nfs_fh_tool expect-stat bad-nid.fh ESTALE ./nfs_fh_tool expect-open bad-nid.fh ESTALE -
Unmount, detach, reattach the same image to md80, remount, capture
a-remount.fh, compare complete handle bytes, and read through the old handle. -
Unmount/detach, attach
nfs-b.erofsto the same md80, and remount. Captureb.fh; it must have the same NID and fsid but a different generation. Bothfhstat(a.fh)andfhopen(a.fh)must returnESTALE, whileb.fhsucceeds.
NFS Restart Procedure
After the replacement test is cleaned up, mount/export the qualified NFS fixture and mount the NFS client. Keep a client descriptor open across nfsd restart, but prevent the restarted daemon from inheriting the test descriptor:
exec 3< /mnt/repo22-nfs/basic/regular.txt
service nfsd onerestart 3<&-
cat <&3 > open-after-restart.out
exec 3<&-
cmp open-after-restart.out /mnt/repo22-erofs/basic/regular.txt
Without 3<&- on the service command, nfsd inherits the NFS-client descriptor
and can keep the client mount busy during cleanup.
Metabox and Multidevice Regression
- Capture/resolve a metabox bit-63 NID and mutate it beyond the metabox backing
range; expect
ESTALEonly for invalid NID/generation. - For an external-data file, a valid handle must still resolve after the data
provider is detached; the subsequent read preserves
ENXIO/I/O error rather than rewriting it toESTALE.
Cleanup
Unmount NFS clients first while rpcbind/mountd/nfsd still run. Then clear and
reload /etc/exports, stop nfsd, mountd, and rpcbind, unmount EROFS, detach md
providers, and unload the module. Assert every mount, md, module, service PID,
and export entry is gone.