test code v1
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
# 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.c` compiled as `nfs_fh_tool`.
|
||||
- Deterministic `nfs-a.erofs` and `nfs-b.erofs` from 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`.
|
||||
|
||||
1. Attach `nfs-a.erofs` to md80 and mount it.
|
||||
2. Capture regular, directory, symlink (`lcapture`), and FIFO handles. For the
|
||||
regular file:
|
||||
|
||||
```sh
|
||||
./nfs_fh_tool describe a.fh
|
||||
./nfs_fh_tool stat a.fh
|
||||
stat -f 'gen=%v ino=%i' /mnt/repo22-erofs/basic/regular.txt
|
||||
```
|
||||
|
||||
Assert `len=16`, `pad=0`, full NID preservation, nonzero generation, and
|
||||
`describe gen == stat st_gen`.
|
||||
3. Verify malformed versus stale classification:
|
||||
|
||||
```sh
|
||||
./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
|
||||
```
|
||||
|
||||
4. Unmount, detach, reattach **the same image** to md80, remount, capture
|
||||
`a-remount.fh`, compare complete handle bytes, and read through the old
|
||||
handle.
|
||||
5. Unmount/detach, attach `nfs-b.erofs` to the same md80, and remount. Capture
|
||||
`b.fh`; it must have the same NID and fsid but a different generation.
|
||||
Both `fhstat(a.fh)` and `fhopen(a.fh)` must return `ESTALE`, while `b.fh`
|
||||
succeeds.
|
||||
|
||||
## 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:
|
||||
|
||||
```sh
|
||||
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 `ESTALE` only 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 to `ESTALE`.
|
||||
|
||||
## 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.
|
||||
Reference in New Issue
Block a user