NFS: Consistency, State, and Recovery of Remote Files
On this page
A client may time out, yet the server might have already created the file; a WRITE may succeed, yet the content may not yet be stable. NFS needs to track request identity, cache validation, and persistence acknowledgments separately before deciding how to retry.
| Phenomenon to Explain | Reading Location |
|---|---|
| If multiple operations are bundled into a single RPC, are they rolled back together? | Sections 1–2: Versions and COMPOUND |
| When will another client see modifications? | Section 3: Caching and delegation |
| After a crash, is data retransmitted or is it a re-acknowledgment? | Section 4: WRITE/COMMIT Deduction |
| How to locate timeouts, recovery, and security? | Sections 5–7: Waiting, Layouts, and Read-Only Observations |
1. VFS, RPC, and the Backend Filesystem
The Linux client fs/nfs/ interfaces with VFS; net/sunrpc/ provides ONC RPC facilities; the kernel server fs/nfsd/ handles remote operations and accesses the exported backend. ONC RPC is a remote invocation framework, with XDR defining data encoding; TCP, UDP, or RPC-over-RDMA are its transport mechanisms. SUNRPC should not be treated as a transport protocol at the same level as TCP.
An NFS filehandle identifies the server-side file object; it is not a client-side file descriptor, nor merely an absolute path string. A rename can change the name while preserving the object's identity; deletion and recreation, or changes in exports, may invalidate old handles and return ESTALE. Upon encountering ESTALE, one should analyze the object and export lifecycles rather than simply increasing the retry count.
| Version | Key Mechanisms | Boundaries |
|---|---|---|
| v3 | Basic operations like read/write and attributes; typically obtains the initial handle via the auxiliary MOUNT protocol | The core protocol is relatively stateless; this does not imply the server has no cache, no lock service, or no recovery needs |
| v4.0 | OPEN/LOCK, leases and delegation, COMPOUND, unified export view | Stateful; requires handling recovery and revocation |
| v4.1 | Sessions, slots/sequences, pNFS, etc. | Replay protection has specific session and cache boundaries |
| v4.2 | Adds server-side replication, sparse files, and other capabilities | Negotiated versions do not imply all optional operations are available |
v4 typically traverses directly from the protocol export root, eliminating the need for the v3 auxiliary MOUNT protocol; the path seen by the client is the server's export view, which may not equal the server's local path. New configurations should use -t nfs and specify vers= as needed; the old nfs4 filesystem type syntax is no longer recommended. See Linux nfs(5).
2. COMPOUND Reduces Round Trips but Does Not Provide Database Transactions
Bundling multiple operations such as "locate object, open, read attributes" into a COMPOUND reduces network round trips. The server executes according to the protocol and reports results; a failure later in the sequence does not automatically roll back effects already produced earlier. Therefore, multiple operations within a single RPC should not be treated as an all-or-nothing business transaction.
v4.1 sessions use slot and sequence information to identify retries and reuse results, reducing the risk of redundant execution; it does not mean that arbitrarily resending requests in a new session will automatically deduplicate them, nor can it replace business-level deduplication outside the filesystem. Restarts, state loss, and response cache limitations must still be handled according to the protocol. See the updated specification for v4.1 at RFC 8881, which obsoletes RFC 5661.
How a Session Distinguishes Retries from New Requests After a Single Response Loss
Assume a client sends sequence 8 in slot 3 of a valid v4.1 session. Request R intends to create a file and caches the response as required by the protocol. The server executes successfully, records the result for this slot, but the response is lost in transit. The client experiences a timeout, even though the file has already been created.
| Client Subsequent Action | How the Server Should Differentiate |
|---|---|
| Retransmit identical R in the same session, slot 3, sequence 8 | Identify as a retry; return the previously cached result if conditions are met |
| After accepting the result, advance to sequence 9 in slot 3 | The next task for this slot |
| Send a request in another slot | Can concurrently occupy another request slot |
Slots provide concurrent positions, and sequences distinguish requests before and after at each position. They are not infinite deduplication databases that permanently store all business IDs.
If the client re-establishes the session, or if the original response was not retained under the required conditions, one cannot assume the same replay protection applies based on the same filename. Related errors must enter the recovery procedures defined by the protocol. This explains the gap between "RPC has retry mechanisms" and "any business operation can be safely retransmitted."
Partial Success: Changing Attributes After Creation May Still Fail
Another boundary of COMPOUND can be understood via creating then changing attributes: if the preceding OPEN succeeds in creating the file, but the subsequent SETATTR fails due to permissions, the return values must be interpreted item by item. The file may already exist; one cannot simply translate the final error of the entire COMPOUND into "nothing was done." The replay cache saves the result of this execution, which is a different capability from rolling back previously completed operations. See Session and COMPOUND Semantics in RFC 8881.
3. Cache Consistency: Who Validates What and When
Clients can cache file contents, attributes, and name lookup results. The attribute cache lifetime controls when re-validation occurs; whether data is stale is also influenced by change attributes and other judgments. The typical intent of close-to-open is: the writer advances modifications before closing, and then another client checks for changes upon opening. It does not mean that all open file descriptors and mmap mappings share the same memory in real-time.
Two Clients: Re-opening vs. Continuously Holding an FD
| Sequence | What Can Be Analyzed |
|---|---|
| A writes, completing necessary sync/close | A advances modifications |
| B re-opens afterward, validating according to normal policies | B has the opportunity to see updates via change detection |
| B continuously holds the fd and repeatedly reads the cache | One cannot infer that B will definitely see updates next time solely based on A's write success |
Multiple writers overlapping in writes must still jointly adhere to locks or application protocols. NFS clients may also simulate O_APPEND; concurrent appends involve races between positioning and writing, so local append intuitions cannot be directly applied.
"The necessity of sending a GETATTR for every open" is also too absolute: caching, delegation, protocol combinations, and mount options all affect actual requests. noac is not a universal switch to disable all page caching; reducing the attribute cache lifetime does not magically create multi-operation transactions.
Delegation is a Revocable Right
The server may grant read or write delegations under suitable conditions, allowing the client to handle more operations locally within the permitted scope. A read delegation does not imply there is only one global reader; a write delegation does not mean all content is cached or that all local accesses will forever incur zero RPCs.
When conflicts occur, the server typically issues a recall first; the client completes necessary write-backs and returns the delegation; revocation and recovery are only involved when normal return is not possible. Leases, callback channels, and server state participate in this process; it cannot be simplified to "another client accesses, so immediate revoke occurs, and the old client naturally syncs."
4. WRITE Success Depends on Stability Level
WRITE can report different stability levels. UNSTABLE indicates that the server has not yet made the required stable storage commitment; the client usually still needs to retain data for retransmission and subsequently request COMMIT; if WRITE has already been stabilized as required, an additional COMMIT may not be necessary. Therefore, fsync is not a fixed alias for "only execute COMMIT"; it may also need to send dirty data, wait for results, and handle state.
The write verifier is used to determine if the server's related write state has changed across restarts. If the server loses unstable data, the client cannot assume content is recovered by simply submitting a COMMIT without data again; it should retransmit the data according to the protocol. Definitions for stable writes can be found in WRITE/COMMIT in RFC 1813 and the v4.1 specification.
Client success still depends on the server honoring its commitments. Exporting async, backend synchronization policies, and volatile device caches may alter actual fault guarantees; the client's mount sync options and the server's exports sync options are different control points. NFS will not automatically fix incorrect persistence commitments made by the backend.
Deduction of Two Crashes: Why the Client Must Retain Unstable Data
Assume the file content on the server disk is the old version O, and the client prepares to write a certain range to N. Ignoring other writers for now, assume the server strictly honors stable storage commitments and the underlying device is not damaged.
| Time | What the Client Knows | Server State | Recovery Required at This Moment |
|---|---|---|---|
| t0: WRITE Sent | N has not been acknowledged | May not have received the request yet | Client retains N |
| t1: Receives UNSTABLE, verifier V₁ | Server received N, but did not commit to stability | N may only be in volatile buffer; disk remains O | Client must still be able to retransmit N |
| t2: Server Crashes Before COMMIT | Client may only see temporary unresponsiveness | After restart, only O remains; write state verifier changes to V₂ | Detect V₂ ≠ V₁, re-write N |
| t3: Retransmit and Complete Stable Confirmation | N's recovery commitment finally holds | N is now stable | Only then can the corresponding stabilization responsibility end |
The key is at t2: COMMIT does not carry the complete new content. If the client discards the only copy of N at t1, sending COMMIT again cannot allow the server to guess N back from O. The verifier turns "is this still the same volatile write period as last time?" into a checkable condition; the client retaining data provides the actual recovery material.
Suppose disk has O and the client sends N. UNSTABLE with verifier V₁ confirms receipt, not stable storage. If the server restarts before COMMIT, disk may still contain O and verifier becomes V₂. Detecting the change requires resending N; COMMIT contains no full new data from which O could become N. Only stable confirmation resolves the client's obligation. NFSv3 WRITE/COMMIT
After an UNSTABLE reply, the client retains retransmission data. If the verifier changes, COMMIT alone cannot restore lost contents; data must be sent again.
Contrast: Data Already Stable, Only COMMIT Response Lost
Consider a different crash point: the server has already stabilized N, but the COMMIT response is lost. At this point, re-querying/recovering according to the protocol is to eliminate client uncertainty; the disk has not reverted to O. Both scenarios may appear as timeouts to the client, but handling cannot assume the write never occurred based on "not receiving success." This difference is also why applications need to consider result uncertainty after fsync returns an error. The above is protocol deduction, excluding configurations where the server intentionally fails to honor stability commitments.
5. Timeouts, hard/soft, and Task Waiting
Request timeouts only indicate that the client did not receive a usable response in time; they do not prove the server did not execute. Reliable TCP transmission does not eliminate the window for server execution followed by response loss or restart.
| Setting | Controls | How Not to Interpret |
|---|---|---|
| hard | Usually continuously retries recoverable requests | retrans is not the total retry limit for all requests |
| soft and other policies | May return errors to the application earlier | Returning an error does not prove the server did not partially execute |
| timeo | Timeout parameter in tenths of a second | Not necessarily the total deadline for the entire system call |
Shortening waits changes the failure modes encountered by the application; it should not be treated as an unconditional optimization to eliminate hanging.
Some waits can be interrupted by fatal signals, while others remain subject to uninterruptible resource waits. TASK_KILLABLE existed before 5.x; one cannot assert from a process showing D state that it "can never be killed, only restarted," nor can one guarantee that SIGKILL immediately completes all NFS cleanup. Analysis should be combined with kernel stacks, specific wait points, and server recovery states.
Server Recovery: Leases and Locks Require Re-coordination
v4 server restarts may also enter a grace period, requiring clients to reassert previous opens and locks. Persistent clients tracking data aids recovery decisions, but this does not mean writing all runtime lock objects verbatim to a fixed path. The number of nfsd workers is configurable and is not forced to be exactly one thread per CPU.
6. pNFS and Security Model
pNFS provides layout information via a metadata server; clients access data servers or related storage targets according to the layout used, thereby dispersing the data path. It does not cancel metadata coordination, nor does it guarantee that arbitrary directory access bypasses the MDS; layout types, revocations, failure fallbacks, and device capabilities determine the actual path.
| Security Method | Provides | Does Not Provide |
|---|---|---|
AUTH_SYS / sec=sys | Passes identity information such as UID/GID for permission checks | Encryption, nor verification of the authenticity of remote host user claims by itself |
sec=krb5 | RPCSEC_GSS authentication | Content privacy equivalent to krb5p |
sec=krb5i | Authentication and integrity protection | Encryption of operation content |
sec=krb5p | Authentication, integrity, and privacy | Replacement for export authorization, file permissions, and key management |
root_squash maps the client's root identity; it is not complete protection against arbitrary untrusted client identity forgery. NFSv4 does not mean the current mount necessarily uses Kerberos; one should check the actually negotiated sec=; standard implementations require this and cannot be directly treated as a runtime configuration fact.
7. Read-Only Positioning of the Current NFS View
= False
, , =
=
= True
The output preserves the escaped format of mountinfo to avoid mistakenly splitting paths containing spaces into ordinary strings. Further reading of /proc/self/mountstats, nfsstat -c, or nfsstat -s distinguishes RPC counts, retransmissions, and service times; these metrics should be calculated as differentials over the same time window. Full rpcdebug modifies debug state and may generate large amounts of logs, and should not be used as the default read-only observation step.