# 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.