Transport / lightweight TCP filesystem protocol
Experimental9P2000.L
9P is a mount-free-friendly transport: the server and per-connection fid state run over Tokio TCP, while native Linux mounting is a separate kernel capability. macOS has no built-in 9P client in this project.
Rootless TCP tests run on macOS and Linux. Native Linux needs the9p, 9pnet, and 9pnet_tcp kernel modules plus mount capability, normally CAP_SYS_ADMIN. macOS would require an external userspace client.
The standard path is mount-free: start P9Server and test frames or a loopback client. A Linux mount is an explicit host test, not something the Rust transport wrapper silently provides.
Rootless protocol/server, attached Node Duplex, hosted Rust plus N-API Linux lifecycle, and root-gated upstream conformance now pass for the supported scope; macOS is rootless-only, Windows is compile-qualified only, public parity remains partial, and crash/reset/half-close recovery is supervisor-owned rather than a library guarantee. The current attached-stream/session packet passed focused Rust/N-API lifecycle and fault tests, strict Clippy, generated typechecks, and the pinned 44-case 9P codec differential. Dedicated hosted run35628187344 at the exact published revision passed9p/9pnet_fd probing and all four ignored native tests: eight-worker concurrent mounted I/O, server-close/kernel- connection release, ordinary mount/unmount, and external umount. This closes the supported Linux lifecycle scope; automatic recovery after a process crash, arbitrary kernel reset, or half-close remains outside the library contract and needs supervisor-level evidence. Exact SHA Exact SHA 0d520a1d passed hosted N-API run35671509538, including automatic, direct./9p (with a non-empty mounted source), and structural-driver mounted I/O/cleanup, plus direct native session/lock optional-shape assertions; the Rust job also passed all four ignored native tests. The corrected member-boundary packet at exact SHA81cc6596 and run 35670279904 confirms nativestream: undefined and the transport-source peer string. The later wire-framing packet at exact SHAc42030c1 passed hosted run 35687955065, covering a deterministic 256 KiB payload split across negotiated 8 KiB frames, oversized-frame rejection, and continued service for a second session. The subsequent backpressure teardown packet at exact SHA1179d9e3 passed hosted run 35685073733, covering bounded pending replies while observing orderly EOF, TCP reset, and paused-peer half-close cleanup. These remain scoped native/API and transport qualifications; process-crash, arbitrary kernel-reset, broader parity, and production acceptance remain open. The platform-probe packet at run 35672845113 also passes synthetic Linux/Darwin override checks. The same pinned packet checks all 124 constants and 274 runtime ./9p barrel exports. The current packet adds live P9Session.driver, debug-gated assertion readback/counters, request-error and assertion callbacks with Node error revival, and root/./9p factory identity. Release build, generated typecheck, focused N-API tests, formatting, strict Clippy, and 31 ordinary 9P tests passed. The public barrel now differentially checks all 124 upstream constants and the 44-codec surface, alongside live session fids, cursor/open state, hardlink identity, clunk snapshots, and retained open handles.P9Server.clients is now a live property-shaped view,P9ServerOptions.locks accepts a sharedP9LockTable, and the bounded ./9p facade exposes probe/refusal/option helpers plus named mount9pdelegation and mounted server/connection views. A configuredP9Server can be adopted when the Linux client probe is usable. The latest N-API packet now preservesP9Session.stats.messages as aMap<string, number>; exact SHAe8c6043 passed hosted run 35673543701 with mounted-I/O and cleanup checks in both the N-API and Rust jobs. The subsequent fid-view packet at exact SHA ba20d29 and run35674581481 also passed the Linux probe and automatic, direct, and structural mounted-I/O checks, with writableFid.iounit/Fid.cursor and array-shaped cursor offsets. Automatic signal ownership and broader upstream parity remain open. The newer direct ./9p facade now returns a synchronous Array<P9Mount> fromlive9pMounts(), with a process-local registry that prunes inactive and closed mounts; exact SHA 56291e3 passed hosted run 35679754417 for automatic, direct, and structural mounted I/O and cleanup. The typed-reader helpers also preserve the oracle-compatible optional maximum forreadRread, readTwrite, andreadRreaddir; exact SHA 4ecdb63 passed run35678757675 with bounded success and oversized-body error coverage. The follow-up packets also export the directP9Platform type alias and preserve P9User.uidas an own undefined field when no numeric uid is available. Hosted run 35683716217 at exact SHAd43f5ea4 passed the isolated server/attached-stream lifecycle and Unix-listener policy checks, including private-directory refusal, explicit shared-directory opt-in, 0600 socket mode, peer/path reporting, socket removal, and path/port exclusivity, alongside the Linux mounted-I/O and cleanup checks. These are scoped native/API qualifications, not broader upstream parity or crash/reset recovery; overall production status remains NO-GO. The latest structural-session packet at exact SHA496ed42b passed hosted run 35691732267: the N-API job passed the Linux probe, addon build, isolated server/attach selector, direct native/structural session lifecycle, and automatic/direct/structural mounted-I/O cleanup, while the Rust job passed the Linux probe and all four ignored native lifecycle tests. This extends direct P9Session construction to structuralFsDriver input and releases the retained adapter exactly once on destroy; process-crash, arbitrary kernel-reset, broader parity, and production acceptance remain open. The follow-up direct-session state-machine packet at exact SHAc6277617 passed hosted run 35693518562: an in-flight Tgetattr is counted and released byTflush, Tversion reset clears negotiated state/fids/users and invalidates the stale request withEIO, and destroy() wakes pending work and invalidates it with ENODEV. Generation invalidation wins over a late adapter error while the caller-owned structural source remains alive; both the N-API and Rust jobs passed their Linux probe and mounted-I/O cleanup suites. The attached-connection parity packet at exact SHA1c791cf6 adds the declaredP9Connection.waitClosed() member to theserver.attach() wrapper, and the metadata teardown regression now awaits it after close(). Local metadata, direct-session, observability, fid, mount-helper, generated typecheck, syntax, diff, and elevated server-selector checks passed. Hosted run35696071202 then completed successfully: the N-API job passed addon build, server/attach, direct-session, automatic/direct/ structural mounted-I/O and cleanup checks, while the Rust job passed the Linux 9P probe and all four native lifecycle tests. This is scoped lifecycle evidence; broader upstream parity and crash/reset recovery remain open. The newer supported-scope closure at exact source86b88c32 passed hosted run 35703805373: the N-API job covered direct mounted I/O, cleanup, and the adjacent server/connection lifecycle, while the Rust job passed the Linux probe and all four ignored native lifecycle tests. The packet records the supported P9Session and server/connection member surface, attached Node Duplex behavior, client identity/order/close semantics, direct and automatic mount-option mapping, and mounted identity. Legacy message families, extended attributes, rootless macOS native kernel mounting, and process-crash/reset/half-close recovery remain explicit outside-scope or supervisor-owned boundaries; this is not broader upstream parity or production acceptance. The newest hosted pinned-oracle conformance at exact sourced11f458d passed run 35711056768: the baseline job reported 144/146 with the two explicit root-gated ownership skips, while the privileged root job passed 146/146. The companion N-API and Rust native lifecycle jobs also passed. This closes the previously root-gated symlink-ownership cases for the pinned oracle; legacy/auth/xattr gaps, non-Linux native-mount scope, Windows runtime/N-API scope, and supervisor-owned crash/reset recovery remain open.
What the transport exposes
The implementation covers 9P2000.L attach/walk, open/create, I/O, metadata, links, rename/unlink, locks, and session state. The N-API facade exposes direct P9Session.handleCall/destroy, attached stream identity/peer/closed state, ownership and duplicate attach handling, bounded backpressure, and write-fault reporting. Native Tokio connections deliberately expose no Node stream and report a transport-source peer string when available (Unix socket path or TCPaddress:port), with null only when the source is absent. Callers needing a Node Duplex useserver.attach, which retains the supplied stream and peer metadata. Effective callback hooks remain omitted from serializable option snapshots. Authentication, xattr messages, legacy message families, and several unsupported driver capabilities return explicit unsupported errors.
Exercise the portable wire surface first
cargo test -p mount-rs-9p --locked
cargo clippy -p mount-rs-9p --all-targets --locked -- -D warnings
# Prepared Linux host only:
sudo mount -t 9p -o trans=tcp,version=9p2000.L,port=<PORT> 127.0.0.1 /mnt/mount-rs-9pSafe use and lifecycle
Bind the server to the intended address, choose a unique test mountpoint, and unmount explicitly. Keep any authentication or service credentials in the host environment; the transport tests themselves do not create credentials.
Current limitations
The bounded ./9p/mount9p helper is a native Linux mount seam, but it requires the host kernel client and mount privilege; there is no built-in macOS client. The protocol does not claim legacy 9P families, xattrs, authentication, or full upstream parity; rootless success is not a kernel mount result.
Sources: 9P transport README · W01 9P progress tracker · Porting status · Hosted Linux 9P lifecycle CI · Latest hosted Native 9P lifecycle · Latest hosted Native 9P structural session · Latest hosted Native 9P state machine · Previous hosted Native 9P attached waitClosed parity · Previous hosted Native 9P supported-scope closure · Latest hosted Native 9P root conformance · Hosted 9P wire-framing qualification · Hosted 9P Unix-listener qualification · Hosted N-API Native 9P qualification · Latest hosted 9P stats qualification · Latest hosted 9P fid qualification · Latest hosted 9P live-mount qualification · Hosted 9P typed-reader qualification · Hosted 9P platform-probe qualification · Hosted 9P member-boundary qualification