Summary

  • RFC 3010 separated a stable client name from a particular running incarnation: a changing verifier, negotiated clientid and authenticated confirmation prevented a remembered name from silently inheriting old locks.
  • After a server lost state, one lease-length grace period normally admitted reclaims while refusing new conflicting locks and protected I/O, making continuity a bounded recovery procedure rather than a permanent claim.

A file server can return from a reboot before its memory of ownership does. The disks may be present, the names may resolve and the network may accept calls, while the volatile table that said which client held which lock is gone. If the server immediately grants a conflicting lock, it can betray the client that still believes its earlier exclusion is valid. If it waits forever, a dead client can immobilize a live system.

RFC 3010, the first NFS version 4 protocol specification published in December 2000, treated that interval as a protocol problem rather than an administrative mood. NFSv4 integrated locking into a design whose earlier versions had been famous for minimizing server state. Once locks, opens and delegations mattered across calls, recovery needed its own evidence, clock and order.

The first separation was between a client and a client incarnation. A client supplied an opaque identifier that could remain stable, plus a verifier that was expected to change when the client restarted and lost its prior volatile state. A host name or network address might answer “which machine?”, but it could not answer “which boot?”. The verifier made the second question visible.

That distinction was negotiated through SETCLIENTID. The server associated the proposed identity with the authenticated principal in the RPC request, returned a short 64-bit clientid and supplied a confirmation verifier. SETCLIENTID_CONFIRM completed the exchange. The clientid then served as an efficient server-local reference for later state, not as a global identity, property title or bearer credential.

The handshake also exposed collision. Two machines could acquire the same opaque client name through misconfiguration, cloned high-availability settings or hostile behavior. RFC 3010 did not tell the server to merge them. It could return NFS4ERR_CLID_INUSE and identify where the existing claimant could be reached. Equality of the name was evidence of a conflict to resolve, not proof of a shared principal.

When the same authenticated client returned with a changed verifier, the server could infer that a new incarnation no longer possessed the old in-memory lock state. It could then release locks associated with the previous clientid. The security qualifier was essential: an unauthenticated stranger must not be able to claim a reboot on someone else's behalf and cause valid locks to disappear. The verifier detected an epoch change; the RPC principal bounded whose epoch it could change.

Time supplied the second boundary. RFC 3010 defined a server-chosen lease interval for locking state. Ordinary operations that created or used state could renew the common client deadline implicitly, and an otherwise idle client could send RENEW. Renewal applied to the client's state set, so a thousand locks did not require a thousand keepalives.

A lease was a temporary protection against conflicting grants, not ownership in perpetuity. If a client remained silent beyond the interval, the server could free its state and let others proceed. After a long partition, the returning client could receive NFS4ERR_EXPIRED when it tried to use an old stateid. The correct response was not to pretend the former lock still governed the server. The application had to learn that exclusion had been lost.

Server failure created the opposite asymmetry. Clients might still remember valid-looking stateids while the restarted server recognized neither those stateids nor their clientid. NFS4ERR_STALE_STATEID and NFS4ERR_STALE_CLIENTID were therefore epoch evidence. They told the client to establish a new clientid and enter recovery rather than simply resubmit ordinary work under an obsolete namespace.

The recovery mechanism was the grace period. For a duration normally equal to the lease interval, returning clients could issue reclaim-form LOCK and OPEN requests, including CLAIM_PREVIOUS. The simple safe server behavior was to reject new locks, new opens, reads and writes with NFS4ERR_GRACE. The server was running, but a part of its authority surface was deliberately closed.

That temporary refusal is the design's most important act. It protected clients that were not yet present. A former holder might be reconnecting, discovering the reboot or rebuilding its state. Allowing a new conflicting grant first would turn arrival order after failure into ownership. Grace made the new claimant wait while old claims received a finite opportunity to be reconstructed.

The pause was not absolute. RFC 3010 allowed a server to process new work during grace when it could guarantee that no later reclaim would conflict and no legitimate reclaim would be rejected because of the new operation. Stable storage could provide such evidence: retained lock counts or records might show that a particular file had no outstanding claim left to recover. Optimization was permitted only after proof, not merely because service pressure made waiting inconvenient.

Nor was grace an endless amnesty. A reclaim submitted after the window could succeed only if the server could guarantee that it had granted no conflicting lock or I/O since restart. Once new facts entered the state machine, an unrecorded old claim could no longer displace them safely. The deadline converted uncertainty into a bounded operational cost.

RFC 2624 had described the design pressures behind NFSv4: stronger security, integrated locking, Internet operation and fewer round trips. RFC 3010 supplied the first complete protocol. RFC 3530 later replaced it, and RFC 7530 became the subsequent NFSv4.0 specification. The vocabulary and edge cases evolved, so RFC 3010 is a historical source, not today's implementation manual.

NFSv4.1 went further. RFC 5661 introduced EXCHANGE_ID, sessions and a more explicit recovery architecture. Its replacement, RFC 8881, explains an enduring trade-off: the more generously a server wants to honor reclaims after awkward failures, the more durable evidence about clients and state it must retain. Tolerance is purchased with custody.

That later detail does not erase the original insight. A stable label is not stable authority. A client name can remain the same while its process, memory and obligations have changed. A server endpoint can remain the same while its lock table belongs to a new epoch. Continuity has to be demonstrated by the receipts that cross those discontinuities.

Through Lu Heng's Running-Code Primacy lens, the operative right is the one the restarted server can validate locally: authenticated client incarnation, recognized recovery mode, eligible prior state, unexpired recovery window and absence of a later conflict. The minimum common rule is not that an institution remembers a claim forever. It is that executable recovery ordering prevents a new claimant from winning merely because failure made it arrive first.

The Stability Fallacy appears when a familiar name or uninterrupted filesystem view is treated as proof that the old exclusion still exists. RFC 3010 did something harder. It admitted that state could disappear, exposed the loss with stale identifiers, froze new conflicts for a measured interval and demanded that continuity be rebuilt before normal competition resumed.

The lock did not survive because the client remembered it. The client received a chance to reconstruct it because the protocol remembered how uncertainty should be ordered. That is a smaller promise than permanence, and a much more defensible one.

Sources