560 lines
19 KiB
Markdown
560 lines
19 KiB
Markdown
# repo22 FreeBSD 15 NFS export manual test report
|
|
|
|
Date: 2026-08-08 20:08-20:37 UTC
|
|
|
|
Baseline: `4ef680df6dcbfad329c0b2b1c0af8fcb21cbed4a` plus this NFS export batch
|
|
|
|
Guest: FreeBSD 15.0-RELEASE-p8 amd64,
|
|
`releng/15.0-n281036-53054229dcb3`, QEMU TCG, 4 vCPUs, 6144 MB RAM
|
|
|
|
Host tools: erofs-utils 1.8.6, clang cross-target build
|
|
|
|
## Result
|
|
|
|
**PASS** for the implementation and all reasonably executable NFS tests.
|
|
|
|
FreeBSD mountd installed real EROFS exports through export-only `MNT_UPDATE`;
|
|
NFSv3 clients resolved 16-byte EROFS handles for regular files, directories,
|
|
symlinks, FIFOs, metabox bit-63 inodes, and multidevice files. Handle mutation,
|
|
same-md remount stability, nfsd restart, 12,050-entry READDIRPLUS pagination,
|
|
cold remounts, concurrent traversal/read/stat load, read-only enforcement, and
|
|
device-boundary errors all behaved as required.
|
|
|
|
The only non-code issue was a cleanup-order mistake after the completed test
|
|
matrix: one hard loopback NFS mount remained while nfsd and the direct EROFS
|
|
mount were stopped. This blocked `mount -p` and later produced five client
|
|
`fileid changed` messages when nfsd was temporarily restarted without the
|
|
underlying export. The functional-test dmesg snapshot taken before that cleanup
|
|
mistake was byte-identical to its baseline. The VM was rebooted to clear the
|
|
blocked cleanup process, and a final correctly ordered NFS rerun completed with
|
|
byte-identical pre/post dmesg and zero remaining resources.
|
|
|
|
## Repository and build
|
|
|
|
Initial verification:
|
|
|
|
```sh
|
|
git -C /work/repo-community/repo22 fetch xdm main
|
|
git -C /work/repo-community/repo22 rev-parse HEAD
|
|
git -C /work/repo-community/repo22 rev-parse xdm/main
|
|
git -C /work/repo-community/repo22 diff --quiet
|
|
git -C /work/repo-community/repo22 diff --cached --quiet
|
|
```
|
|
|
|
Both revisions were:
|
|
|
|
```text
|
|
4ef680df6dcbfad329c0b2b1c0af8fcb21cbed4a
|
|
```
|
|
|
|
Tracked files were clean. Existing untracked `repo22/build`,
|
|
`tests/results/manual/2026-08-08T1800Z-namei/artifacts`, and files outside
|
|
repo22 were not deleted, modified, staged, or committed.
|
|
|
|
To execute the required `./build.sh` without overwriting the pre-existing
|
|
untracked build products, the current source was copied to an isolated build
|
|
directory:
|
|
|
|
```sh
|
|
BUILD_ROOT=$(mktemp -d /work/build/repo22-nfs-build.XXXXXX)
|
|
mkdir -p "$BUILD_ROOT/src"
|
|
cp repo-community/repo22/build.sh "$BUILD_ROOT/build.sh"
|
|
cp repo-community/repo22/src/* "$BUILD_ROOT/src/"
|
|
chmod +x "$BUILD_ROOT/build.sh"
|
|
cd "$BUILD_ROOT"
|
|
./build.sh
|
|
nm -u build/erofs.ko | \
|
|
awk '$NF == "bcmp" { found = 1 } END { if (found) exit 1 }'
|
|
sha256sum build/erofs.ko
|
|
```
|
|
|
|
Result:
|
|
|
|
```text
|
|
==> SUCCESS: /work/build/repo22-nfs-build.eFulVf/build/erofs.ko
|
|
48776485d1679f00100bc7b2be5f891c8f03a3e8b53ac7c00da8c2fd5f74cc70 erofs.ko
|
|
```
|
|
|
|
There was no unresolved `bcmp` reference.
|
|
|
|
The FreeBSD helper compiled without warnings:
|
|
|
|
```sh
|
|
cc -O2 -Wall -Wextra -std=c17 nfs_fh_tool.c -o nfs_fh_tool
|
|
```
|
|
|
|
## Fixtures
|
|
|
|
The primary fixture was generated with:
|
|
|
|
```sh
|
|
mkdir -p plain-src/basic/subdir plain-src/bigdir plain-src/concurrent
|
|
printf 'repo22-nfs-regular\nline-two\n' > plain-src/basic/regular.txt
|
|
printf 'nested-directory-file\n' > plain-src/basic/subdir/nested.txt
|
|
ln -s regular.txt plain-src/basic/link-to-regular
|
|
mkfifo plain-src/basic/test.fifo
|
|
for i in $(seq -w 0 12049); do
|
|
printf 'entry-%s\n' "$i" > plain-src/bigdir/file-$i
|
|
done
|
|
for i in $(seq -w 0 255); do
|
|
awk -v n="$i" 'BEGIN {
|
|
for (j = 0; j < 256; j++)
|
|
printf "worker-%s-line-%03d-abcdefghijklmnopqrstuvwxyz0123456789\\n", n, j
|
|
}' > plain-src/concurrent/file-$i.dat
|
|
done
|
|
awk 'BEGIN {
|
|
for (i = 0; i < 262144; i++)
|
|
printf "throughput-%08d-abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\\n", i
|
|
}' > plain-src/throughput.dat
|
|
mkfs.erofs -T0 --all-root --ignore-mtime -x-1 -Uclear \
|
|
plain-nfs.erofs plain-src
|
|
```
|
|
|
|
Fixture and manifest hashes:
|
|
|
|
| Object | SHA256 |
|
|
|---|---|
|
|
| `plain-nfs.erofs` | `6928f05b58ce462596f9c7bf1d3442ad50d555dc5c31ed01d28e1a921a448bf2` |
|
|
| `metabox-nfs.erofs` | `8f493ed70d4be8096ab1adf8208622734d61a64903cf96a1ca1a1cc1854b1985` |
|
|
| multidevice primary | `fa2f35f59f63cc4a56d230ba960a6c1d27748506fccce081447cab0dc0d540fd` |
|
|
| multidevice blob 1 | `3aeb19c519636b61dc3ebd47c6286098deaa0990ff618ce3facbff4fd65907cd` |
|
|
| source manifest | `0eda6f88c3b6c4b7c8d81d940a237d1f63c958a7f6fe7bdd4f77d6b293736fa9` |
|
|
| `basic/regular.txt` | `93e7f327676f582356e9de2fcca7b714910227008fa1c5e7820e942c471edb6f` |
|
|
| `basic/subdir/nested.txt` | `6da159d7ea19e9d1253ccb0f2c67586e6e075459954e740ff8405546683d87c3` |
|
|
| `concurrent/file-000.dat` | `8435866622642b6dadf502b09f95af32cb01907ba3376e4f1fe96278e5ada692` |
|
|
| `throughput.dat` (21,757,952 bytes) | `0841effed82d1adf394b6834ce30d4d9eb5fc9427527e854ec1cb6bb4b86c119` |
|
|
| expected 12,050-name sorted list | `4fbf1b6103e8884223629c3fd03f4ec36061e65cd2a1becfc96670daa96f9d71` |
|
|
|
|
The metabox image was the previously qualified compressed-metabox fixture. The
|
|
multidevice fixture was the previously qualified primary-plus-one-blob image.
|
|
|
|
## FreeBSD 15 setup commands
|
|
|
|
The artifacts were copied to the existing VM through SSH port 9222. Password
|
|
material and askpass script contents were neither printed nor recorded.
|
|
|
|
```sh
|
|
scp -P 9222 erofs.ko plain-nfs.erofs metabox-nfs.erofs \
|
|
tests/nfs_fh_tool.c [email protected]:/tmp/repo22-nfs-test/
|
|
ssh -p 9222 [email protected]
|
|
cd /tmp/repo22-nfs-test
|
|
sha256 erofs.ko plain-nfs.erofs metabox-nfs.erofs
|
|
cc -O2 -Wall -Wextra -std=c17 nfs_fh_tool.c -o nfs_fh_tool
|
|
```
|
|
|
|
The guest hashes matched the host hashes.
|
|
|
|
EROFS and NFS setup:
|
|
|
|
```sh
|
|
kldload /tmp/repo22-nfs-test/erofs.ko
|
|
mdconfig -a -t vnode -f /tmp/repo22-nfs-test/plain-nfs.erofs -u 42
|
|
mkdir -p /mnt/repo22-erofs
|
|
mount -t erofs -o ro /dev/md42 /mnt/repo22-erofs
|
|
mount -v | grep /mnt/repo22-erofs
|
|
|
|
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-erofs
|
|
```
|
|
|
|
Before mountd reload the EROFS line did not contain `NFS exported`. Afterwards:
|
|
|
|
```text
|
|
/dev/md42 on /mnt/repo22-erofs (erofs, NFS exported, local, read-only, acls, ...)
|
|
```
|
|
|
|
NFSv2/v3 and mountd were registered over TCP and UDP. NFS components are built
|
|
into this GENERIC kernel: `kldload nfsd` and `kldload nfscl` reported
|
|
`already loaded or in kernel`, while rpcbind/mountd/nfsd operated normally.
|
|
|
|
## File-handle validation commands
|
|
|
|
Normal vnode types:
|
|
|
|
```sh
|
|
./nfs_fh_tool capture /mnt/repo22-erofs/basic/regular.txt regular.before.fh
|
|
./nfs_fh_tool capture /mnt/repo22-erofs/basic/subdir directory.fh
|
|
./nfs_fh_tool lcapture /mnt/repo22-erofs/basic/link-to-regular symlink.fh
|
|
./nfs_fh_tool capture /mnt/repo22-erofs/basic/test.fifo fifo.fh
|
|
./nfs_fh_tool describe regular.before.fh
|
|
./nfs_fh_tool describe directory.fh
|
|
./nfs_fh_tool describe symlink.fh
|
|
./nfs_fh_tool describe fifo.fh
|
|
./nfs_fh_tool stat regular.before.fh
|
|
./nfs_fh_tool stat directory.fh
|
|
./nfs_fh_tool stat symlink.fh
|
|
./nfs_fh_tool stat fifo.fh
|
|
./nfs_fh_tool cat regular.before.fh regular.fhopen.out
|
|
```
|
|
|
|
Observed handles:
|
|
|
|
| Type | NID | Generation | Result |
|
|
|---|---:|---:|---|
|
|
| regular | `0x74` | 1 | `fhstat` and `fhopen` PASS |
|
|
| directory | `0x76` | 1 | `fhstat` PASS |
|
|
| symlink (`lgetfh`) | `0x72` | 1 | `fhstat` PASS |
|
|
| FIFO | `0x79` | 1 | `fhstat` PASS |
|
|
|
|
All had `len=16` and `pad=0`. The regular full-handle SHA256 was:
|
|
|
|
```text
|
|
fb1778fc6bdc979e10d003dd6131a961e7532baa16273c5465935a665bf990f6
|
|
```
|
|
|
|
Malformed and stale classification:
|
|
|
|
```sh
|
|
./nfs_fh_tool mutate regular.before.fh bad-len.fh len 15
|
|
./nfs_fh_tool mutate regular.before.fh bad-pad.fh pad 1
|
|
./nfs_fh_tool mutate regular.before.fh bad-gen.fh gen 2
|
|
./nfs_fh_tool mutate regular.before.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
|
|
```
|
|
|
|
All eight checks passed. `fhstat` exercised the shared-lock `VFS_FHTOVP` path;
|
|
`fhopen` exercised the exclusive-lock path.
|
|
|
|
Same explicit md-unit remount:
|
|
|
|
```sh
|
|
umount /mnt/repo22-erofs
|
|
mdconfig -d -u 42
|
|
mdconfig -a -t vnode -f plain-nfs.erofs -u 42
|
|
mount -t erofs -o ro /dev/md42 /mnt/repo22-erofs
|
|
./nfs_fh_tool capture /mnt/repo22-erofs/basic/regular.txt regular.after.fh
|
|
./nfs_fh_tool compare regular.before.fh regular.after.fh
|
|
./nfs_fh_tool cat regular.before.fh regular.remount.out
|
|
```
|
|
|
|
The complete handles were byte-identical and the pre-remount handle still read
|
|
the correct file after remount.
|
|
|
|
Non-export mount update rejection:
|
|
|
|
```sh
|
|
mount -u -o noexec /mnt/repo22-erofs
|
|
```
|
|
|
|
Result: `Operation not supported`; the mount remained exported, local,
|
|
read-only, and did not gain `noexec`.
|
|
|
|
## NFSv3 basic and restart tests
|
|
|
|
Four NFSv3 TCP READDIRPLUS clients were mounted:
|
|
|
|
```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 clamped the requested 512/1024/4096 values to an effective
|
|
`readdirsize=8192`; the default client used 65536. This was recorded as a client
|
|
environment limit, not a failure.
|
|
|
|
For each client:
|
|
|
|
```sh
|
|
cmp NFS/basic/regular.txt DIRECT/basic/regular.txt
|
|
test -d NFS/basic/subdir
|
|
test "$(readlink NFS/basic/link-to-regular)" = regular.txt
|
|
test -p NFS/basic/test.fifo
|
|
test "$(stat -f %i NFS/basic/regular.txt)" = \
|
|
"$(stat -f %i DIRECT/basic/regular.txt)"
|
|
! touch NFS/write-must-fail
|
|
```
|
|
|
|
All passed. Writes failed with `Read-only file system`.
|
|
|
|
nfsd restart with an open descriptor:
|
|
|
|
```sh
|
|
exec 3< /mnt/repo22-nfs-default/basic/regular.txt
|
|
service nfsd onerestart
|
|
cat <&3 > open-fd-after-nfsd-restart.out
|
|
exec 3<&-
|
|
cmp open-fd-after-nfsd-restart.out /mnt/repo22-erofs/basic/regular.txt
|
|
```
|
|
|
|
The open descriptor and subsequent path reopen both passed. Direct file handles
|
|
captured before and after restart were byte-identical.
|
|
|
|
## Metabox bit-63 test
|
|
|
|
Commands:
|
|
|
|
```sh
|
|
mdconfig -a -t vnode -f metabox-nfs.erofs -u 43
|
|
mount -t erofs -o ro /dev/md43 /mnt/repo22-metabox
|
|
./nfs_fh_tool capture /mnt/repo22-metabox/long/file1.txt metabox.before.fh
|
|
./nfs_fh_tool describe metabox.before.fh
|
|
./nfs_fh_tool stat metabox.before.fh
|
|
./nfs_fh_tool cat metabox.before.fh metabox.fhopen.out
|
|
./nfs_fh_tool mutate metabox.before.fh metabox.bad-nid.fh \
|
|
nid_lo 0xffffffff
|
|
./nfs_fh_tool expect-stat metabox.bad-nid.fh ESTALE
|
|
./nfs_fh_tool expect-open metabox.bad-nid.fh ESTALE
|
|
```
|
|
|
|
Observed handle:
|
|
|
|
```text
|
|
len=16 pad=0 nid=800000000000010a gen=1
|
|
ino=9223372036854776074
|
|
```
|
|
|
|
The metabox mount was exported with mountd and mounted over NFSv3. Direct,
|
|
`fhopen`, and NFS contents had SHA256:
|
|
|
|
```text
|
|
661b22d2a7bd94a7da35834d4cc3647eb527d48eb08acc75bde2e3a7691ed45e
|
|
```
|
|
|
|
The NFS and direct inode numbers matched. The out-of-range metabox mutation
|
|
returned `ESTALE` through both shared and exclusive paths.
|
|
|
|
## Multidevice boundary test
|
|
|
|
Normal NFS commands:
|
|
|
|
```sh
|
|
mdconfig -a -t vnode -f primary.img -u 44
|
|
mdconfig -a -t vnode -f blob1.img -u 45
|
|
mount -t erofs -o ro -o device.1=/dev/md45 /dev/md44 \
|
|
/mnt/repo22-multidev
|
|
mount_nfs -o nfsv3,tcp,rdirplus,readdirsize=512 \
|
|
127.0.0.1:/mnt/repo22-multidev /mnt/repo22-nfs-multidev
|
|
cmp /mnt/repo22-nfs-multidev/alpha.bin /mnt/repo22-multidev/alpha.bin
|
|
cmp /mnt/repo22-nfs-multidev/small.txt /mnt/repo22-multidev/small.txt
|
|
```
|
|
|
|
Normal multidevice NFS reads passed. Representative hashes:
|
|
|
|
```text
|
|
f779dbe3aeaa609beb32212579f3aea441f244621d13c977cb8b52d7ec3016d9 alpha.bin
|
|
5990b055a3c6d27681185a25e15ff21ba3cbdca7632faf4332233238e5f45aad small.txt
|
|
001bcf4626e7d52f1bd76dee9a6c6e7d3a718c03602c5f9b07840a6c98b8fdc3 tree/beta.bin
|
|
```
|
|
|
|
Cold detached-provider test:
|
|
|
|
```sh
|
|
umount /mnt/repo22-multidev
|
|
mdconfig -d -u 44
|
|
mdconfig -a -t vnode -f primary.img -u 44
|
|
mdconfig -a -t vnode -f blob1.img -u 45
|
|
mount -t erofs -o ro -o device.1=/dev/md45 /dev/md44 \
|
|
/mnt/repo22-multidev
|
|
./nfs_fh_tool capture /mnt/repo22-multidev/tree/beta.bin multidev-beta.fh
|
|
./nfs_fh_tool stat multidev-beta.fh
|
|
mdconfig -d -o force -u 45
|
|
! ./nfs_fh_tool cat multidev-beta.fh beta.after-orphan
|
|
```
|
|
|
|
The handle resolved to NID `0x36`, then the cold read returned:
|
|
|
|
```text
|
|
Device not configured
|
|
```
|
|
|
|
This preserved the multidevice `ENXIO` boundary error instead of converting it
|
|
to `ESTALE`, reading past the provider, or panicking.
|
|
|
|
## READDIRPLUS and stress
|
|
|
|
Every one of the four initial listings returned exactly 12,050 unique expected
|
|
names. The expected list and all four sorted outputs had SHA256:
|
|
|
|
```text
|
|
4fbf1b6103e8884223629c3fd03f4ec36061e65cd2a1becfc96670daa96f9d71
|
|
```
|
|
|
|
Dot handling:
|
|
|
|
```sh
|
|
ls -a1 /mnt/repo22-nfs-default/bigdir > nfs-dot-list
|
|
test "$(wc -l < nfs-dot-list)" -eq 12052
|
|
test "$(grep -cx '\.' nfs-dot-list)" -eq 1
|
|
test "$(grep -cx '\.\.' nfs-dot-list)" -eq 1
|
|
```
|
|
|
|
All passed.
|
|
|
|
Cold pagination used five unmount/remount/list/compare cycles on the small
|
|
client. Concurrency then used eight workers, three complete 12,050-entry rounds
|
|
each, distributed across the four mounts. All 29 cold/concurrent sorted outputs
|
|
had one unique SHA256 value, matching the expected list.
|
|
|
|
Parallel data/metadata load:
|
|
|
|
```sh
|
|
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 &
|
|
find /mnt/repo22-nfs-$M/concurrent -type f -maxdepth 1 -print0 | \
|
|
xargs -0 -n 1 -P 8 stat -f '%i %z' > /dev/null &
|
|
done
|
|
wait
|
|
```
|
|
|
|
All jobs completed successfully.
|
|
|
|
Final stress counters:
|
|
|
|
| Counter | Client | Server |
|
|
|---|---:|---:|
|
|
| requests / cache misses | 270,854 | 271,174 |
|
|
| lookup | 264,989 | 265,109 |
|
|
| read | 1,360 | 1,360 |
|
|
| READDIRPLUS | 2,512 | 2,512 |
|
|
| write | 0 | 0 |
|
|
| timed out | 0 | n/a |
|
|
| retries | 0 | n/a |
|
|
|
|
There were no READDIR RPCs because the clients negotiated READDIRPLUS.
|
|
|
|
Informational throughput:
|
|
|
|
```text
|
|
21757952 bytes transferred in 5.843937 seconds
|
|
3723167 bytes/second
|
|
```
|
|
|
|
No fixed throughput threshold was used.
|
|
|
|
## Test matrix
|
|
|
|
| Test | Actual | Status |
|
|
|---|---|---|
|
|
| isolated `./build.sh` | success; module hash recorded | PASS |
|
|
| unresolved `bcmp` | none | PASS |
|
|
| FreeBSD helper compile | `-Wall -Wextra`, no warnings | PASS |
|
|
| final `kldload` / `kldunload` | load, unload, reload, unload succeeded | PASS |
|
|
| initial mount export flag | absent before mountd | PASS |
|
|
| export-only `MNT_UPDATE` | mountd installed export | PASS |
|
|
| non-export `MNT_UPDATE` | `EOPNOTSUPP`, flags unchanged | PASS |
|
|
| regular file | direct, `fhopen`, NFS content match | PASS |
|
|
| directory | handle and NFS traversal | PASS |
|
|
| symlink | `lgetfh`, target and NFS lookup | PASS |
|
|
| FIFO | handle metadata and NFS type | PASS |
|
|
| read-only behavior | direct and all NFS mounts rejected writes | PASS |
|
|
| 16-byte handle ABI | len/pad/NID hi/NID lo/gen observed | PASS |
|
|
| generation | `1`, matching `va_gen` | PASS |
|
|
| shared/exclusive lock contract | `fhstat` and `fhopen` passed | PASS |
|
|
| malformed len/pad | `EINVAL` | PASS |
|
|
| stale generation/NID | `ESTALE` | PASS |
|
|
| same `md42` remount | complete handle byte-identical | PASS |
|
|
| nfsd restart | open descriptor and reopen passed | PASS |
|
|
| metabox bit 63 | real `0x800000000000010a` round-trip | PASS |
|
|
| metabox boundary mutation | `ESTALE` | PASS |
|
|
| multidevice NFS | external-data reads matched | PASS |
|
|
| detached external device | cold handle read preserved `ENXIO` | PASS |
|
|
| 12,050-entry listings | exact count and names on four clients | PASS |
|
|
| cookie pagination | five cold remounts, no duplicate/omission | PASS |
|
|
| dot omitted | one `.` and one `..`, 12,052 total | PASS |
|
|
| concurrent traversal | 8 workers x 3 rounds, all hashes equal | PASS |
|
|
| concurrent read/stat | all jobs completed | PASS |
|
|
| READDIRPLUS | client/server 2,512 | PASS |
|
|
| NFS timeouts/retries | 0 / 0 | PASS |
|
|
| successful NFS writes | 0 | PASS |
|
|
| throughput | 3,723,167 B/s, informational | INFO |
|
|
|
|
## dmesg and cleanup
|
|
|
|
The functional matrix captured dmesg before loading the test module and after
|
|
all functional tests plus a load/unload cycle. Both files contained the same
|
|
two pre-existing historical lines and compared byte-for-byte equal:
|
|
|
|
```text
|
|
interface erofs.1 already present in the KLD 'erofs-repo22-xattrfix.ko'!
|
|
md0: truncating fractional last sector by 14 bytes
|
|
```
|
|
|
|
No EROFS error, stale-handle message, trap, panic, or new kernel line occurred
|
|
during the functional matrix.
|
|
|
|
The first cleanup attempt used the wrong order: it stopped nfsd and unmounted
|
|
the direct EROFS mounts before one hard loopback client was fully gone. This
|
|
left a `mount -p` process in uninterruptible NFS wait. When rpcbind/nfsd were
|
|
temporarily restarted without the underlying EROFS export to release those
|
|
clients, the NFS client logged five `fileid changed` messages. These messages
|
|
occurred after the byte-identical functional dmesg snapshot and are classified
|
|
as **environment cleanup artifact**, not an EROFS functional failure.
|
|
|
|
The VM was rebooted to remove the blocked cleanup process. Post-reboot audit:
|
|
|
|
```text
|
|
erofs_mounts=0
|
|
nfs_mounts=0
|
|
md_units=0
|
|
erofs_modules=0
|
|
nfsd_pids=0 mountd_pids=0 rpcbind_pids=0
|
|
exports_exists=no
|
|
```
|
|
|
|
A final correctly ordered clean rerun then performed:
|
|
|
|
```sh
|
|
kldload erofs.ko
|
|
mdconfig -a -t vnode -f plain-nfs.erofs -u 42
|
|
mount -t erofs -o ro /dev/md42 /mnt/repo22-erofs
|
|
service rpcbind onestart
|
|
service mountd onestart
|
|
service nfsd onestart
|
|
mount_nfs -o nfsv3,tcp,rdirplus,readdirsize=512 \
|
|
127.0.0.1:/mnt/repo22-erofs /mnt/repo22-nfs-clean
|
|
cmp /mnt/repo22-nfs-clean/basic/regular.txt \
|
|
/mnt/repo22-erofs/basic/regular.txt
|
|
test "$(find /mnt/repo22-nfs-clean/bigdir -type f -maxdepth 1 | wc -l)" \
|
|
-eq 12050
|
|
umount /mnt/repo22-nfs-clean
|
|
: > /etc/exports
|
|
service mountd onereload
|
|
service nfsd onestop
|
|
service mountd onestop
|
|
service rpcbind onestop
|
|
umount /mnt/repo22-erofs
|
|
mdconfig -d -u 42
|
|
kldunload erofs
|
|
```
|
|
|
|
The clean rerun's pre/post dmesg files compared byte-for-byte equal. Final
|
|
state after that rerun:
|
|
|
|
```text
|
|
clean_rerun_erofs=0 nfs=0 md=0 module=0 services=0 exports=absent
|
|
```
|
|
|
|
## Limitations
|
|
|
|
- **ENVIRONMENT-LIMIT**: FreeBSD clamped requested readdir sizes 512, 1024, and
|
|
4096 to an effective minimum of 8192. The test still exercised a much smaller
|
|
value than the 65536 default and produced 2,512 real READDIRPLUS calls.
|
|
- **ENVIRONMENT-CLEANUP-ARTIFACT**: the five post-test `fileid changed` lines
|
|
were caused by the explicitly documented wrong cleanup order. A reboot and a
|
|
correctly ordered rerun left no new dmesg lines or resources.
|
|
- **KERNEL-FAIL**: none.
|
|
- **NOT RUN**: none of the required functional cases were omitted.
|