135 lines
8.1 KiB
Markdown
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.
|