# repo22 TC060 pathconf fix manual test report Execution window: 2026-08-09 11:20-11:35 UTC Exact source commit: `cdba7e54fb9e9d82980a06f178e68d0bbc1663ac` Guest: FreeBSD 15.0-RELEASE-p8 amd64, QEMU TCG, port 9222 ## Scope and Result TC060 is **PASS**. The original six-key helper returned the required values with errno 0, compatibility queries retained their previous values, an unknown name returned EINVAL, mount/read/read-only smoke passed, dmesg did not change, and final mount/md/KLD/artifact counts were zero. This was a direct manual run. No CI, result wrapper, or historical PASS supplied the result. `WITH_ZSTDIO=1` was build-verified; runtime TC060 used `WITH_ZSTDIO=0` because pathconf is compression-independent and this avoids an unnecessary optional runtime dependency. ## Implementation Basis FreeBSD 15 `sys/kern/vfs_default.c` shows that `vop_stdpathconf()` handles generic `_PC_ASYNC_IO`, `_PC_PATH_MAX`, and several zero-valued optional features, then returns EINVAL for other names. The same source tree's UFS, tmpfs, and ext2fs vnode operations explicitly return 1 for `_PC_CHOWN_RESTRICTED` and `_PC_NO_TRUNC` before delegating the remaining names to `vop_stdpathconf()`. The EROFS fix adds only those two switch labels and retains the existing default delegation. `src/namei.c` rejects components longer than `EROFS_NAME_LEN` with ENAMETOOLONG, while `src/erofs_vnops.c` rejects uid/gid mutation with EROFS. Linux EROFS's 255-byte name limit and ENAMETOOLONG lookup check were reviewed only for maintenance similarity; FreeBSD VOP behavior was authoritative. ## Exact Build The repo22 subtree was exported directly from the exact source commit. Later `current/`-only reporting changes did not alter `src/`. | Item | Value | |---|---| | Source archive SHA256 | `a4c871ca7cefc49470ef0003f876792380a8d8db6cbeaefb96456d06ad946d53` | | FreeBSD source path | `/tmp/repo22-freebsd15-src` | | Compiler | FreeBSD clang 19.1.7 | | Build command | `FREEBSD_SRC=/tmp/repo22-freebsd15-src WITH_ZSTDIO=N ./build.sh` | Both clean-object builds completed with kernel `-Werror`: | Configuration | Module SHA256 | Size | Undefined-symbol audit | Result | |---|---|---:|---|---| | `WITH_ZSTDIO=0` | `68536e03ce93c6c04aab9cf29dab81ee5802d4b94401bd1a4bd752de40c0e504` | 73896 | no `bcmp`, no `ZSTD_*` | PASS | | `WITH_ZSTDIO=1` | `598f171d355af78c64407a6d513d20f053530620da92df7f8ccfdf9a804e463d` | 78728 | no `bcmp`; only five expected FreeBSD `ZSTD_*` APIs | PASS | The enabled module referenced `ZSTD_DCtx_setParameter`, `ZSTD_createDCtx_advanced`, `ZSTD_decompressStream`, `ZSTD_freeDCtx`, and `ZSTD_isError`. ## Fixture and Probes | Artifact | SHA256 | |---|---| | `vfs-plain.erofs` | `79f0b5f4aa8e7ea532b711ee8fb466f14f35d0952446d41ba4bbc4d6e008b8ff` | | tracked `g3_vfs_probe` binary | `08fe3999600dd1826805c00a17af3d893d247a593c0812f767d85a2633302068` | | one-run `pathconf_audit` source | `c2cc69297848cad8c806d47585ef670ae5b378827450110e2cf47cf82ed527b3` | | one-run `pathconf_audit` binary | `17aa9d738871ac424900ed7a928cb72cc2e5a288f2c2f9744906fa139a78835b` | Both probes compiled natively with `-O2 -Wall -Wextra -Werror -std=c17`. The one-run helper was kept outside the repository and only printed each value/errno plus assertions for unknown-name and overlong-component behavior. ## TC060 Values The exact original command was: ```text ./g3_vfs_probe pathconf /tmp/repo22-tc060-fix/mnt/testdir ``` It exited 0 and printed: ```text name_max=255 path_max=1024 filesizebits=64 link_max=2147483647 no_trunc=1 chown_restricted=1 ``` The expanded value/errno capture was: | Query | Actual value | errno | |---|---:|---:| | `_PC_NAME_MAX` | 255 | 0 | | `_PC_PATH_MAX` | 1024 | 0 | | `_PC_FILESIZEBITS` | 64 | 0 | | `_PC_LINK_MAX` | 2147483647 | 0 | | `_PC_NO_TRUNC` | 1 | 0 | | `_PC_CHOWN_RESTRICTED` | 1 | 0 | | `_PC_ASYNC_IO` | 200112 | 0 | | `_PC_ACL_EXTENDED` | 1 | 0 | | `_PC_ACL_PATH_MAX` | 254 | 0 | | `_PC_ACL_NFS4` | 0 | 0 | | unknown name `INT_MAX` | -1 | 22 (`EINVAL`) | A lookup using a 256-byte path component returned -1 with errno 63 (`ENAMETOOLONG`), confirming the reported no-truncation behavior. ## Mount and Read Smoke The module loaded as KLD file ID 20, module `erofs`, and the fixture attached as dynamic `md0`. The mount line was: ```text /dev/md0 on /tmp/repo22-tc060-fix/mnt (erofs, local, read-only, acls) ``` `testdir` reported inode 44, mode `drwxr-xr-x`, and size 1039. Reading `testdir/file.txt` produced `repo22 G3 file payload` and SHA256 `523af4c899ba3b8f4fa4d854fe609590be271905b63932cf067ca9630e612687`. Opening the same file with `O_RDWR` returned errno 30 (`EROFS`) as expected. ## Dmesg and Cleanup The qualified run's dmesg had 131 lines before and after, with identical SHA256 `91bf74a3607f432b4802f143bcf9d050c2f9e741da0a54f3e6a1b47bcc996a06`. There was no new EROFS diagnostic, assertion, trap, panic, or resource warning. Qualified cleanup returned zero for umount, md detach, and KLD unload. After removing the transferred archive and test directory, the final guest audit was: ```text erofs_mounts=0 md_units= erofs_klds=0 guest_artifacts=0 ``` ## Discarded Attempt The first otherwise successful runtime pass loaded the KLD from the non-canonical filename `erofs-zstdio0.ko`. Its explicit `kldunload erofs` command could not resolve that filename, so the run stopped before final dmesg and cleanup qualification. Its mount and md were already clean; KLD file ID 20 was then unloaded directly and the guest returned to zero resources. The full test was repeated with canonical `erofs.ko`, and only that rerun is counted. ## Independent Review The post-test review found no lock, resource, or error-path issue: - `VOP_PATHCONF` is called with the vnode shared-locked; the function does not change lock state. - The new constant-return branches allocate nothing and acquire no references. - Both normal and FIFO vnode vectors use the same filesystem-wide result. - Existing value branches are unchanged, and unsupported names still reach `vop_stdpathconf()` and return EINVAL. - The syscall copies `retval` only on error 0, so the unknown-name error path cannot expose a stale value.