Transport / network filesystem protocol

Preview

NFS

NFS is the current native macOS path and a Linux option when the host client and mount permissions are available. Its server and wire sessions can also be tested over loopback without mounting anything.

Platform requirements

macOS uses /sbin/mount_nfs and can run the owned temporary mountpoint rootlessly under the documented privacy policy. Linux needs the distribution NFS client tools and normally CAP_SYS_ADMINor root for a kernel mount.

Mount vs mount-free

Rootless TCP/XDR tests exercise NFSv3, MOUNTv3, and the implemented NFSv4.1 session service. mount_nfs is a separate lifecycle bridge; the native test must be explicitly enabled and hard-fails when prerequisites are missing.

Preview — scoped evidence

Native macOS NFSv3 plus job-scoped hosted macOS/Linux NFSv3 and Linux NFSv4.1 checkpoints are evidenced; shared v3/v4 session and connection views, rootless reconnect, bounded pipelining, and v4 channel/state knobs pass, while the current workstream remains NO-GO pending full stateful/member, hosted lifecycle, and crash/durability qualification. Current-tree Rust and N-API checks retain backend handles across NFSv3 unlink and NFSv4 rename, expose shared v3/v4 state, and exercise live connection/client close and wait behavior. The current complete locked NFS target passed 40 unit, rootless wire 1, transport concurrency 3, transport-error 4, lifecycle 5, v4 barrier 1, and v4 wire 7 cases; release build/typecheck/live server integration and strict Clippy also pass. Rootless NFSv4.1 survives an orderly TCP reconnect while the server remains alive, and eight pipelined NFSv3 MOUNT NULL calls pass with max_in_flight=4. Dynamic v4 owner and clock callbacks are exercised through the live N-API sequence, and bounded real-TCP close cancellation passes 2/2 cases. Recorded hosted native-NFS run35650924001 was cancelled, so it is not acceptance. A restart-boundary test confirms the old v4 session is rejected with NFS4ERR_BADSESSION by a replacement server, proving that session/lease state is process-local rather than crash-durable; the pre-crash root handle also returnsNFS4ERR_STALE. The v4 state packet now covers lease, session, fore-slot, COMPOUND, replay-cache, open/lock, and reclaim ceilings, including NFS4ERR_TOOSMALL,NFS4ERR_NOSPC, refused-session replay, and per-file lock enforcement. Static NFSv4 identity maps now qualify mapped user and group names with numeric fallback and reject other domains withNFS4ERR_BADOWNER; reclaim ordering returnsNFS4ERR_GRACE until RECLAIM_COMPLETE, and deterministic lease expiry releases sessions, locks, open state, and pinned handles. The refreshed opt-in macOS native NFSv3 loopback mount passed 1/1 in 0.11s with filesystem round trips and bounded cleanup. The latest N-API session/member packet also exposes the server-owned read-only driver wrapper, effective scalar options, configured ID-map presence, write verifier, shared v3 routing, and shared handle/counter/destroy state; ./nfs exportsNfs3Session. Hosted runs35656252661, 35657100915, and35657445618 were cancelled before native-NFS jobs ran, so they are not acceptance evidence. The later hosted run35658285441 completed both named native-NFS jobs: macOS passed native NFSv3, CLI persistence/cleanup, and SQLite-over-NFS, while Ubuntu passed privileged native NFSv3/NFSv4.1 and SQLite-over-NFS. The surrounding workflow was not wholly green, so this remains job-scoped platform evidence rather than release acceptance. A focused process-restart target writes aFILE_SYNC file, force-terminates the server, and recovers the bytes through a replacement HostFs server; the pre-crash handle returns NFS3ERR_STALE. This is host-backed NFSv3 process-restart evidence, not power-loss or NFSv4 lease/replay recovery. A bounded rootless NFSv4.1 target also runs two independent sessions with concurrent distinct-file OPEN/WRITE/READ and passes 7/7; hosted run 35663954461 was cancelled before jobs were created, so it supplies no hosted concurrency result. The latest terminal-close oracle at published commit90e130b8 passes 266 pinned NFSv3/MOUNT and NFSv4.1 TCP cases with 18 explicit capability/root skips and zero mismatches; hosted run 35670416469 cancelled both native-NFS jobs before any steps ran, so it adds no hosted native acceptance. The current userspace packet also qualifies completion-order replies, 32 concurrent close waiters plus a late waiter, terminal relisten rejection, and a max_in_flight=1 dispatch bound; those are rootless protocol/lifecycle boundaries, not native-client or production durability evidence. The same pinned oracle also covers 266 NFSv3/MOUNT and NFSv4.1 TCP cases with 18 capability/root skips; bounded maxHandles LRU and NFSv4 open-state pinning are covered. The full stateful/member matrix, hosted lifecycle, and crash/concurrency/durability remain external gates. The latest terminal CI packet 35698854392 at source116e9ed4 also passed the native NFSv3 jobs on macOS and Ubuntu, including the Ubuntu NFSv4.1 lane; the surrounding workflow failed in provider/W26, Windows, and native-FUSE lanes, so this remains job-scoped platform evidence rather than release acceptance. The current source packet at commit96df991f adds a forced NFSv4.1 process-restart case: it deletes a seeded host file through wire REMOVE, kills the server without async shutdown, then verifies a replacement session returns NFS4ERR_NOENT and the host path remains absent. The direct process-restart target passed 2/2 and the full locked NFS target passed its 20 v4 wire cases with strict Clippy. This is one-host process-crash namespace evidence, not directory-fsync, physical power-loss durability, durable session/lease/replay/handle state, native-client ordering, hosted acceptance, or production acceptance. A follow-up source commit 6d520dd2 extends the same forced-process-restart lane with a successful NFSv4.1 wireRENAME: the replacement session seesNFS4ERR_NOENT for the old name and the new host path keeps the exact seeded bytes. Direct process restart passed 2/2 and the full locked NFS target passed 41 unit and all applicable integrations, including 20 v4 wire cases, with strict Clippy, formatting, and diff checks green. This is same-directory, one-host process-crash namespace evidence, not directory-fsync, physical power-loss durability, persistent NFSv4 state, native-client ordering, hosted acceptance, or production acceptance. The macOS 27 release-profile repair at sourceb7ba3806 also produces a loadable N-API addon without a profile override; the complete NFS server integration and direct unsupported-version assertion pass locally. This qualifies local addon loading and runtime reachability only, not hosted ordering, crash durability, or production readiness. The current shared-target CLI also passes a local macOS host-backed NFS smoke at source be382691: a fresh source directory mounted through --transport nfs, the kernel reported127.0.0.1:/, and create, append, read, stat, and list through the mounted folder matched the 34-byte backing file. Ctrl-C exited 0 with unmounted, the mount-table entry disappeared, the mount folder was empty, and the backing bytes persisted. This is local macOS CLI-to-folder and lifecycle evidence only; the negotiated NFS version was not captured, and Linux/v4.1 ordering, durable state, power-loss, hosted acceptance, and production readiness remain open. A real-TCP HostFs regression at source 512ef958 also fixes NFSv4.1 same-owner OPEN access upgrades: a read-only to read/write upgrade now retains a write-capable backend descriptor instead of producing NFS4ERR_IO on WRITE, while write-only to read upgrades and cross-client share denial remain covered. Focused wire coverage passed 1/1, the locked NFS target passed 42 unit and all applicable integrations including 21 v4 cases, and pinned parity passed 266 cases with 18 explicit skips. This repairs a one-server userspace access-upgrade boundary; native v4.1 client ordering, cross-process recovery, power-loss durability, hosted acceptance, and production readiness remain open. The same immutable candidate's native NFS macOS job106701527843 in run 35714144497 also passed. This is a candidate-scoped native NFSv3 result alongside the existing current-main evidence; it does not close Linux/v4.1 ordering, cross-process recovery, power-loss durability, or production readiness. The latest NFS source at commit ff4b091c now validates complete AUTH_SYS bodies before shared-router or v3/v4 dispatch. Its real-TCP regression denies five malformed credential cases across MOUNTv3, NFSv3, NFSv4, an unsupported NFS version, and trailing AUTH_SYS bytes while accepting three controls, including nonempty AUTH_NONE; the full locked target passed 42 unit tests and the pinned oracle remained 266 passed with 18 explicit skips. Malformed AUTH_SYS bodies receiveAUTH_BADCRED, while unsupported flavors retainAUTH_TOOWEAK. RFC 5531 leaves opaque AUTH_NONEbytes undefined while recommending a zero length. This is fail-closed protocol parsing; AUTH_SYS remains client-asserted identity rather than cryptographic authentication, and native ordering, crash durability, hosted acceptance, and production readiness remain open. The latest symmetric namespace-ordering regression at source3884c194 pauses a v3 LOOKUP after backend stat but before handle binding, then proves a v4.1 REMOVE waits until that handle is bound. The v3 handle becomes NFS3ERR_STALE, a fresh name lookup returns NFS3ERR_NOENT, and the focused case passes ten reruns; the locked target passes 42 unit and 24 v4-wire cases with strict Clippy. This is same-server reverse cross-version namespace ordering, not cross-process arbitration, native-client ordering, crash/power-loss durability, hosted acceptance, or production readiness. The follow-up rename-over-open fix at source 350c0357preserves a pinned destination handle when v3 RENAME replaces its name: the old v4 handle remains pathless and readable, while a fresh v3 LOOKUP receives a distinct replacement handle. The focused wire case passed ten reruns; the locked target passed 43 unit and 25 v4-wire cases with warning-denied NFS/N-API Clippy and formatting. This covers same-process cross-version handle lifetime, not native v4 ordering, cross-process recovery, crash/power-loss durability, hosted acceptance, or production readiness. The current HostFs requalification at source 6aa043b4upgrades that case to a real backing directory: v3 RENAME replaces the destination bytes, the held v4 OPEN still reads the original bytes, CLOSE retires the old pathless handle, and the replacement handle stays valid. The focused case passed ten reruns, the locked target remained green at 43 unit and 25 v4-wire cases, and the opt-in macOS native NFSv3 loopback passed 1/1. The preceding exact-tip hosted run was cancelled before jobs, so native v4.1 ordering and hosted acceptance remain open.

What the transport exposes

The common filesystem/session path includes handles, namespace I/O, stateids, and selected byte-range locks. Held backend handles retain object identity across unlink/rename. The N-API views now expose shared v3/v4 session state, sorted BigInt handle snapshots, active connection counts, and stable live client peer/session objects with close/wait lifecycle. The server does not start rpcbind; it uses an explicitly selected loopback TCP port.

Run the platform-specific native test only when prepared

Evidence-oriented check
# macOS or Linux, NFSv3:
MOUNT_RS_NFS_NATIVE_TEST=1   cargo test -p mount-rs-nfs --test native_mount   -- --ignored --exact native_loopback_mount_round_trip --nocapture

# Linux only, NFSv4.1:
MOUNT_RS_NFS_NATIVE_V4_TEST=1   cargo test -p mount-rs-nfs --test native_mount   -- --ignored --exact native_loopback_mount_v4_1_round_trip --nocapture

Safe use and lifecycle

Use an ephemeral loopback port and an empty temporary mountpoint. For SQLite's single-host profile, opt in explicitly and prefer DELETE journaling; the profile is not cross-host locking or power-loss proof.

Current limitations

NFSv4.1 is not full RFC parity, macOS remains v3-only in the current path, and lock state is process-local/advisory. UDP, portmapper/NLM, persistent cross-process recovery, distributed SQLite locking, and universal WAL support are not claimed.

← Back to transports