# TC060 Standard pathconf Values

Status: **RESOLVED - standard FreeBSD pathconf values validated**

Last updated: 2026-08-09

Resolved: 2026-08-09

Priority: High

Implementation status: Fixed by `cdba7e54fb9e9d82980a06f178e68d0bbc1663ac`
and dynamically validated

## Problem

The exact repo22 9ae22009f KLD returns EINVAL for two standard pathconf names on
an otherwise valid mounted EROFS directory:

- _PC_NO_TRUNC
- _PC_CHOWN_RESTRICTED

The same call correctly returns NAME_MAX=255, PATH_MAX=1024,
FILESIZEBITS=64, and LINK_MAX=2147483647. TC060 therefore fails at the kernel
behavior level; this is not a missing guest tool or fixture limitation.

## Trigger and Evidence

Environment:

- FreeBSD 15.0-RELEASE-p8 amd64 guest on port 9222.
- Exact source commit: 9ae22009f23a65320730072a780998e80aa9b728.
- KLD SHA256:
  19ad086bd2508cbb4c57b1a51f38c93057d438b84fbcfa2e637ff2519f5bc590.
- Fixture: vfs-plain.erofs SHA256
  79f0b5f4aa8e7ea532b711ee8fb466f14f35d0952446d41ba4bbc4d6e008b8ff.

Direct command:

    /tmp/repo22-g3/g3_vfs_probe pathconf \
      /tmp/repo22-g3/mnt/testdir

Observed output and process status:

    name_max=255 path_max=1024 filesizebits=64 link_max=2147483647 \
    no_trunc=error:22 chown_restricted=error:22
    g3_vfs_probe: unexpected EROFS pathconf values
    probe_status=1

The test used a fresh dynamic md0, a read-only EROFS mount, and the exact KLD.
After capture, umount and md detach both returned zero. Final guest state was
zero EROFS mounts, zero md units, and no loaded EROFS KLD.

## Analysis

erofs_pathconf() handles NAME_MAX, PATH_MAX, FILESIZEBITS, LINK_MAX, and ACL
queries directly, then delegates other names to vop_stdpathconf(). In this
FreeBSD 15 configuration the delegation returns EINVAL for both names above.
The mounted filesystem is immutable and enforces 255-byte names, so reporting
NO_TRUNC=1 and CHOWN_RESTRICTED=1 is consistent with the implemented behavior
and with the TC contract.

This failure affects applications that use pathconf(2) to discover pathname
truncation and ownership-change restrictions. It does not affect the four
values that repo22 already handles directly.

## Original Required Resolution

Add explicit FreeBSD vnode pathconf handling for both standard names, then
rerun TC060 with the direct syscall helper. Acceptance requires both values to
be 1, all six queries to have errno 0, unchanged mount/read behavior, no new
dmesg diagnostics, and complete mount/md/KLD cleanup.

## Resolution

FreeBSD 15's `vop_stdpathconf()` intentionally provides only generic values
such as `_PC_ASYNC_IO`, `_PC_PATH_MAX`, and zero-valued optional features; its
default case returns `EINVAL`. UFS, tmpfs, and ext2fs therefore implement
`_PC_CHOWN_RESTRICTED` and `_PC_NO_TRUNC` in their filesystem pathconf methods
before delegating all remaining names to `vop_stdpathconf()`.

EROFS now follows that FreeBSD pattern: the two names return 1, while the
existing NAME_MAX, PATH_MAX, FILESIZEBITS, LINK_MAX, and ACL cases remain
unchanged and the default branch still calls `vop_stdpathconf()`. This matches
the implemented filesystem behavior: uid/gid mutation is rejected with EROFS,
and lookup of a component longer than `EROFS_NAME_LEN` returns ENAMETOOLONG.
No lock, allocation, reference, or cleanup path was added.

Linux EROFS was used only as a maintenance comparison for the 255-byte name
limit and ENAMETOOLONG behavior. FreeBSD 15 VOP and syscall semantics were the
authority for the returned values and errno behavior.

## Qualified Retest

The exact source archive for the fix commit built natively on FreeBSD
15.0-RELEASE-p8 with kernel `-Werror` in both configurations:

- `WITH_ZSTDIO=0`: KLD SHA256
  `68536e03ce93c6c04aab9cf29dab81ee5802d4b94401bd1a4bd752de40c0e504`.
- `WITH_ZSTDIO=1`: KLD SHA256
  `598f171d355af78c64407a6d513d20f053530620da92df7f8ccfdf9a804e463d`.

The dependency-minimal `WITH_ZSTDIO=0` KLD and the original TC060 helper
reported:

```text
name_max=255 path_max=1024 filesizebits=64 link_max=2147483647
no_trunc=1 chown_restricted=1
```

All six queries had errno 0. Additional direct checks returned ASYNC_IO=200112,
ACL_EXTENDED=1, ACL_PATH_MAX=254, and ACL_NFS4=0 with errno 0. An unknown name
returned `-1/EINVAL(22)`, and a 256-byte component returned
`ENAMETOOLONG(63)`. The mounted file hash and read-only EROFS behavior were
unchanged, dmesg was byte-identical before and after, and final mount/md/KLD
and guest artifact counts were zero.

Complete build, value, smoke, discarded-attempt, review, and cleanup evidence
is in
`tests/results/manual/2026-08-09T1120Z-tc060-fix/manual-test-report.md`.
