Β§49.10–49.12Assessing NFS Cache Consistency, Server Write Buffering, and Summary

Part III OSTEP pp. 633–636 Β· ~6 min read

  • virtual file system

Two loose ends remain: how good NFS’s caching really is, and a subtle server-side correctness rule.

49.10 Assessing NFS Cache Consistency

NFS’s cache consistency is an engineering solution, and it shows. Flush-on-close does the right thing but over-works: a short-lived temp file, created and quickly deleted, is still forced all the way to the server. And the attribute cache means you sometimes get the latest version and sometimes a stale one β€” depending only on whether a timeout has elapsed. It’s a striking case where the details of an implementation end up defining the user-observable semantics, rather than the other way around.

49.11 Implications on Server-Side Write Buffering

Clients aren’t the only ones that cache β€” servers do too. Reads are easy to cache. Writes are the trap: a server must not report a WRITE as successful until the data is on stable storage. Watch what happens if it acks from memory instead:

Why a server must never ack a WRITE it hasn't persisted. Three writes overwrite three blocks with a's, b's, c's β€” but the server buffers the middle one, acks it, then crashes.
xxxxxxxxblk 0yyyyyyyyblk 1zzzzzzzzblk 2three writes issued: a's, then b's, then c's

1Start: a 3-block file

The file holds x's, y's, z's. A client issues three writes: block 0 β†’ a's, block 1 β†’ b's, block 2 β†’ c's. Expected result: aaa / bbb / ccc.

step 1 / 5

Because the client treats β€œsuccess” as β€œpersisted”, it never retries the lost middle write β€” leaving a silent hole. So NFS servers force each write to disk before replying. That made write speed a bottleneck, which spawned an industry: NetApp and others built fast NFS servers using battery-backed memory (so a reply is safe without an immediate disk write) plus an LFS-style file system tuned to write quickly.

Aside: Innovation Breeds Innovation β€” the VFS/vnode Interface

Bringing NFS into the OS required another lasting invention: the virtual file system (VFS/vnode) interface. VFS operations act on a whole file system (mount, unmount, sync all dirty writes); vnode operations act on one file (open, close, read, write). Implement those methods and the framework connects system calls to your file system and handles generic work like caching β€” letting many file systems coexist. Some form now lives in Linux, the BSDs, macOS, and Windows.

system calls (open, read, write)VFS / vnode layer (common interface)local FS (ext)NFSothers…implement the vnode methods and the framework wires your file system in
The VFS/vnode layer sits between the system-call API and the individual file systems, so NFS, a local FS, and others plug into the same interface.

49.12 Summary

NFS is built around simple, fast crash recovery, achieved through careful protocol design. The whole chapter in one table:

NFS in one table β€” the ideas that make simple, fast crash recovery work.
ideawhat it does
statelessstateless protocolthe server tracks nothing about clients β†’ after a crash it just restarts and serves; the client, at worst, retries
idempotentidempotent operationsrepeating an op equals doing it once β†’ a client can safely retry, unifying lost-message and server-crash recovery
cachingclient caching + write bufferingcache data/metadata for performance β†’ but this introduces the cache consistency problem
consistencyflush-on-close + attribute cacheengineering fixes: flush dirty pages on close; a GETATTR check softened by a ~3 s attribute-cache timeout
server-writesserver forces writes to stable storagenever ack a WRITE until it is persisted β†’ otherwise a crash silently loses acknowledged data
vfsVFS / vnode interfacethe pluggable file-system layer Sun added so many file systems can coexist in one OS
Dotted-underlined cells have explanations β€” click one.

A stateless protocol plus idempotent operations means recovery is just β€œrestart and retry”. Caching is essential for performance but brings the cache consistency problem, which NFS solves in a slightly ad hoc way β€” occasionally producing observably weird behavior. Server writes must reach stable storage before success is reported. One thing we glossed over is security: early NFS was famously lax (any user could masquerade as another), later shored up with services like Kerberos. Next, AFS takes a very different approach to the same problems.

Check yourself: server write buffering, VFS, and the NFS recap

1.Why must an NFS server force a WRITE to stable storage BEFORE replying success?

2.In the a/b/c example (three writes overwriting three blocks), the server buffers the 2nd write, acks it, then crashes. What's the final file?

3.Forcing writes to disk before acking made write performance a bottleneck. How did vendors like NetApp address it?

4.What's a downside of flush-on-close, and what does the attribute cache reveal about NFS semantics?

5.What is the VFS/vnode interface, introduced by Sun to support NFS?

6.Which pair of ideas is the core of NFS's fast, simple crash recovery?

6 questions