v0.2.0
Adds an experimental NFSv4.0 package. Operating-system clients can now mount a facetfs.FileSystem directly, with no portmapper and no mountd.
nfs4 (experimental)
nfs4.Server serves NFSv4.0 (RFC 7530) on a listener you bind. The exported surface is one struct and two methods:
server := &nfs4.Server{FileSystem: facetfs.Dir("/srv/data")}
log.Fatal(server.Serve(ctx, listener))Implemented: ONC RPC with record marking and bounded XDR; the COMPOUND engine; HMAC-sealed volatile filehandles; the client-identity and lease machinery; open state with sequence-id replay, share reservations, and OPEN_CONFIRM; byte-range locks with split, merge, and conflict reporting; and the file, directory, and attribute operations. Delegations are never granted and reclaim is refused, since in-memory state leaves nothing to reclaim.
Optional interfaces unlock features: SymlinkFS for symlinks, SetStatFS for SETATTR, StatVFSFS for space attributes, LinkFS for LINK, and a Sync() error method on File for COMMIT and stable writes.
Root package
- New optional interface
LinkFS(Link), implemented byDir. TheFileSystemcontract itself is unchanged and remains frozen; optional interfaces may be added, existing ones do not change. - The optional
Sync() errormethod onFileis now documented.
Fixes found by review
Six defects were found and fixed before this release, each with a regression test:
- A LOCK could name one owner through both stateid slots and make the server lock a single mutex twice, hanging that owner permanently. A LOCK open_stateid now resolves only against live opens.
- A LOCK that repeated one sequence id while advancing the other was answered from the replay cache, reporting a byte range the client never held. Replay now requires both sequence ids to repeat.
- A WRITE at the advertised
maxwriteexceeded the record cap and closed the connection, so no full-size write could succeed. The cap is now derived frommaxwrite. - RENAME applied no type rules, so a file could replace a directory and a directory could replace a file, destroying the target.
- COMMIT and stable WRITE returned NFS4ERR_NOTSUPP on any backend whose
FilelacksSync, which left such a backend unable to complete a write. COMMIT also flushed a fresh handle rather than the file the client wrote through. - Lock and share state were keyed by path and did not follow a rename, so a second client could lock the same file under its new name.
Verification
Unit, state-machine, and in-process protocol tests; the race detector; and fuzz targets over both the XDR primitives and whole connections (4.4M executions, no crashes or hangs). Tested on Linux, macOS, and Windows.
Status
The nfs4 package is experimental and has not yet passed the real-client mount profile. AUTH_SYS carries an unverified identity, so serve it on a trusted network or behind your own authentication. Filehandles and protocol state do not survive a restart, and byte-range locks are advisory.
webdav and sftp are unchanged from v0.1.0. smb remains a stub.