Files
nfs/CHANGELOG.md
T
petrbalvin a9b8039ef7
Test / test (push) Successful in 2m4s
Release / gates (push) Successful in 2m5s
Release / build (amd64, freebsd) (push) Successful in 1m27s
Release / build (amd64, linux) (push) Successful in 1m22s
Release / build (amd64, netbsd) (push) Successful in 1m19s
Release / build (amd64, openbsd) (push) Successful in 1m20s
Release / build (arm64, darwin) (push) Successful in 1m21s
Release / build (arm64, freebsd) (push) Successful in 1m26s
Release / build (arm64, linux) (push) Successful in 1m25s
Release / build (arm64, netbsd) (push) Successful in 1m31s
Release / build (arm64, openbsd) (push) Successful in 1m27s
Release / build (loong64, linux) (push) Successful in 1m37s
Release / build (riscv64, linux) (push) Successful in 1m21s
Release / release (push) Successful in 40s
feat: full NFSv4.2 server and client in pure Go
Assisted-by: GLM 5.3 Flash
2026-09-21 18:51:17 +02:00

135 lines
8.1 KiB
Markdown

# Changelog
All notable changes to **nfs** are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [development]
### Added
-
## [1.0.0] - 2026-09-21
### Added
The first release of a full NFSv4.2 implementation in pure Go: server and client,
minor version 2 on the wire only, no portmapper, no mountd, no separate locking
protocol.
- **Wire foundation**: the XDR codec of RFC 4506, ONC RPC record marking of
RFC 5531 with fragment reassembly, the call and reply headers, AUTH_SYS, and
the NFSv4.2 operation, error and attribute numbers verified against the
standards and the Linux client header.
- **Stateless operations**: PUTROOTFH, PUTFH, SAVEFH, RESTOREFH, GETFH, LOOKUP,
LOOKUPP, PUTPUBFH, GETATTR, ACCESS, READ, READDIR, WRITE, CREATE, REMOVE,
RENAME, SETATTR, LINK, READLINK, COMMIT, VERIFY, NVERIFY, SECINFO and
SECINFO_NO_NAME, over a virtual filesystem with a local directory backend.
- **Sessions**: EXCHANGE_ID, CREATE_SESSION, DESTROY_SESSION, BIND_CONN_TO_SESSION
and SEQUENCE with a slot table, a reply cache per slot, and client reboot
detection that drops the state of the previous life.
- **Open state**: OPEN and CLOSE with real stateids, share reservations enforced
across opens of the same file, OPEN_DOWNGRADE, and regular file creation
through the unchecked, guarded and exclusive forms, where an exclusive create
replays by its verifier.
- **Ownership**: every object a client creates carries the identity the client
presented, and the server answers the owner and owner group of every object,
so ownership reads correctly on any conformant client.
- **Byte range locking**: LOCK, LOCKT and LOCKU with per owner conflict
detection, range splitting on unlock, and RELEASE_LOCKOWNER.
- **Lease and recovery**: lease renewal on every SEQUENCE, DESTROY_CLIENTID,
RECLAIM_COMPLETE inside the grace window, CLAIM_PREVIOUS reclamation, and
persistent file handle maps that survive a server restart.
- **Delegations**: read and write delegations granted on the only open of a
file, recalled over the back channel on a conflicting open, returned through
DELEGRETURN.
- **Directory delegations**: GET_DIR_DELEGATION with CB_NOTIFY on create,
rename and remove, and CB_NOTIFY_LOCK when a released range frees a denied
lock.
- **Back channel**: CB_COMPOUND over the same TCP connection, CB_SEQUENCE,
CB_RECALL, and callback delivery that the client demultiplexes from replies.
- **Optional operations of RFC 7862**: SEEK, ALLOCATE, DEALLOCATE, IO_ADVISE,
READ_PLUS, WRITE_SAME, COPY, CLONE, COPY_NOTIFY, OFFLOAD_CANCEL,
OFFLOAD_STATUS, LAYOUTERROR and LAYOUTSTATS.
- **Extended attributes**: GETXATTR, SETXATTR, LISTXATTR and REMOVEXATTR of
RFC 8276 over the user namespace of the local backend.
- **Named attributes**: OPENATTR with create, lookup, read, write and remove
over the synthetic attribute directory of an object.
- **pNFS**: the metadata server role with LAYOUTGET, LAYOUTCOMMIT,
LAYOUTRETURN, GETDEVICEINFO and GETDEVICELIST, and layout bodies for
flexfiles (RFC 8435), files, block volumes, objects and SCSI, all over one
emulated device that is the metadata server itself. The flexfiles version 2
body of draft-haynes-nfsv4-flex-filesv2-00 (layout type 0x6) is served the
same way.
- **Migration and referrals**: the fs_locations and fs_locations_info
attributes, referral stubs whose other operations answer NFS4ERR_MOVED.
- **Kerberos**: RPCSEC_GSS with the krb5, krb5i and krb5p service levels, the
AES profiles of RFC 3961 and RFC 3962 and the tokens of RFC 4121 implemented
in pure Go, plus the version three credential of RFC 7861 with CREATE, LIST
and assertion binding.
- **RPC-with-TLS**: the AUTH_TLS probe and in place TLS upgrade of RFC 9289.
- **RPC-over-RDMA framing**: the chunk lists and message assembly of RFC 8166
over a stream transport; the verbs transport itself sits outside pure Go.
- **The nfsd command**: the `-export` directory and the `-addr` listen
address, a TOML configuration file through `-config` carrying the listen
address, the operation log, the state directory, the connection cap, the
TLS key pair and one `[[export]]`, with the flags overriding the file and a
broken file ending the start up with the file and the line named; a read
only export with `-ro`; RPC-with-TLS through `-tls-cert` and `-tls-key`,
where a client that skips STARTTLS is refused with auth too weak for every
procedure but the NULL of the probe; the operation log of `-log-ops`; the
connection cap of `-max-connections`; persistent recovery state through
`-state-dir`, where file handles and opens are written as they change, a
restart loads them back and the grace window lets clients reclaim their
opens with CLAIM_PREVIOUS; root squash with `-root-squash` or `root-squash`
in the export, mapping a client claiming uid 0 onto nobody (65534);
`READY=1` on $NOTIFY_SOCKET once the listener is up, so a `Type=notify`
unit starts on real readiness; version reporting; and a clean shutdown on
SIGINT and SIGTERM.
- **The nfs command**: ls, cat, put, get, rm, mkdir and stat against a running
server; the whole operation matrix as `nfs selftest`, one line per check
plus a summary and a nonzero exit when a check fails; transfers spread over
several session slots with `-concurrency`, measured on loopback at a 64 MiB
put dropping from 77 ms sequential to 32 ms at four; a session owner id
unique to the process, so two clients of the command beside each other are
two clients, not one rebooting; and the version report.
- **Kernel interop**: the server is verified end to end against the Linux
kernel NFSv4.2 client, which mounts the tree over `mount -t nfs4` and reads,
writes, creates and removes through it, with correct ownership, as root and
non root callers alike.
- **Interoperability stance**: strict conformance as the rule, a documented
tolerance layer confined to the deviations of real clients, and the server
and client pair as the strict reference of the stack.
- **Performance**: the server answers a COMPOUND from one buffer instead of
copying every operation result twice, READ fills the reply in place, WRITE
hands the request's own bytes to the storage and the wire buffers recycle;
the local backend keeps open descriptors of regular files in a bounded
cache and revalidates the file identity on every use; READDIR pages cost
the page against a cached sorted order of the directory; COPY and CLONE run
through copy_file_range and the reflink of the filesystem with a fallback
to the userspace copy; the session store locks per session instead of one
server wide mutex and the lease check runs lock free against an atomic
renewal stamp, six clients beside each other measured at 4.8 times the
sequential throughput. Measured numbers: 11 percent faster reads, 19
percent fewer allocations per COMPOUND, 27 percent fewer bytes per read,
16.9 percent faster reads and 11.0 percent faster writes of 64 KiB chunks,
and a READDIR page of 64 entries in a 10 000 entry directory measured 30
times faster; the reports live in docs/_results/.
- **Operations**: docs/DEPLOYMENT.md carries the production picture, the
hardened systemd unit with Type=notify and the two capability model, the
firewall note and the upgrade and monitoring story; docs/CONFIGURATION.md
lists every configuration key; docs/BENCHMARKING.md states the measurement
method.
- **Platforms**: Linux on amd64, arm64, loong64 and riscv64; FreeBSD, OpenBSD
and NetBSD on amd64 and arm64, all three verified live on amd64, OpenBSD
and NetBSD with both ends of the project running inside the system and
across to the Linux server because their kernel clients speak only NFSv3;
darwin on arm64 as a cross compiled build without runtime testing. Extended
attributes and the sparse operations answer not supported on OpenBSD,
NetBSD and darwin, whose local backends have no system interface an
arbitrary attribute name could use. The stack is pure Go end to end, and
the module ships the two commands only: there is no importable package and
no library surface.