Storage Systems / Under the Hood

NFSv3 Under the Hood: RPC, XDR, File Handles, and Statelessness

Understand the NFSv3 mount and request path, XDR encoding, file handles, stable writes, and the limits of statelessness. Compare the right boundaries with NFSv4.

Palash Vij / Published / 3 min read
Source-backed explainer NFSv3 RPC XDR Storage

NFS makes remote filesystem operations look local, but it does not turn a network into a disk cable. A pathname must become a server-recognizable object, an operation must become an RPC, and a reply must be interpreted under caching and failure rules.

NFSv3 is often called stateless. That is useful only if you specify which state you mean. Clients cache data, TCP connections have state, servers may cache duplicate replies, and locking can involve companion protocols. “Stateless” is not “nothing needs recovery.”

From an export to a file handle

The NFSv3 MOUNT protocol helps a client obtain a file handle for an exported directory. Service discovery may involve rpcbind, depending on configuration. Mounting and subsequent filesystem operations are distinct activities; successfully contacting a mount service does not prove every NFS operation will work.

The file handle is opaque to the client. It identifies an object in the server’s filesystem context; it is not a portable pathname that the client can reconstruct after a server change. NFS operations carry handles and arguments rather than relying on a previously opened server-side file descriptor.

export path -> MOUNT result -> root file handle
root handle + name -> LOOKUP -> object handle
object handle + offset + count -> READ -> data and status

This sequence is conceptual. Caches, compound application behavior, and client implementation choices affect the actual request trace.

RPC chooses the procedure; XDR defines the bytes

RPC identifies a program, version, procedure, and request transaction. XDR defines the wire representation of values such as integers, variable-length arrays, strings, and discriminated unions. Its purpose is interoperability across machines, not compression or encryption.

A C++ struct’s in-memory layout is not an XDR encoding. Padding, endianness, length fields, and alignment must follow the protocol. Copying a native struct into a TCP buffer is not a correct generic RPC encoder.

TCP provides an ordered byte stream, not RPC message boundaries. RPC over TCP uses record marking, and a record can span network segments. That is why counting captured TCP packets is not the same as counting NFS operations.

What statelessness buys—and what it does not

The core protocol does not require the server to maintain a client’s open-file session to service ordinary handle-based operations. That simplifies some recovery scenarios. It does not make a retried mutation harmless in every situation or give the client certainty about an operation whose reply disappeared.

NFSv3 includes unstable and stable write semantics. A server can acknowledge data that still needs a later COMMIT to meet the required persistence semantics. Write verifiers help a client recognize changes relevant to recovery. An application-visible write return, a server reply, and durable storage are therefore different boundaries.

NFSv4 integrates more functionality and has stateful mechanisms for opens, locking, leases, and recovery. Version 4.1 adds sessions. Describing “v4” as simply v3 on one port hides meaningful differences between minor versions and deployments.

Inspect the negotiated protocol

On an authorized Linux client with an existing lab mount:

findmnt -t nfs,nfs4
nfsstat -m
nfsstat -c

Record the version, transport, mount options, and operation counters. Confirm server configuration separately. If you inspect a capture, correlate RPC transaction IDs and procedure names rather than inferring one operation per segment. Do not expose file handles, paths, or payloads from private systems.

The directory-listing walkthrough makes this distinction concrete: one ls -l can involve directory entries, attributes, and client-side work, rather than one obvious remote call.

Compare semantics before performance

A useful v3/v4 comparison records the specific minor version, security flavor, transport, caching, server backing store, concurrency, and workload. Comparing different durability or caching behavior and attributing the result solely to the version number is misleading.

Finally, endpoint continuity is not object continuity. A failover target must honor the relevant handles, data, and recovery semantics. DNS or NAT can influence where traffic travels, but they cannot independently recreate remote filesystem identity or guarantee that an in-flight write completed once.

Further reading

Primary references behind this explanation. Consult documentation for the version and environment you actually run.

  1. RFC 1813: NFS version 3 protocol
  2. RFC 5531: Remote Procedure Call protocol
  3. RFC 4506: XDR data representation
  4. RFC 7530: NFS version 4 protocol
Follow the thread

Related reading

Search the notebook

Search articles, projects, and experiments. Everything stays on your device.

palash / notebook

A small doorway into the site. No shell, no remote execution.

Welcome. Type help to find your way around.

lab →experience →contact →Ctrl / Cmd + K