Β§49.1–49.4A Basic Distributed File System and the Key to Recovery: Statelessness

Part III OSTEP pp. 621–624 Β· ~6 min read

  • distributed file system
  • network file system
  • transparent access
  • client-side file system
  • file server
  • stateless protocol
  • stateful protocol
  • distributed state

Distributed computing’s first great use was the distributed file system : many client machines, one server (or a few) that holds the disks, and files accessed over a network.

Client 0Client 1Client 2Client 3NetworkServerRAID
Figure 49.1: a generic client/server system. Clients reach the server’s disks (a RAID) over the network.

Why centralize like this instead of using local disks? Chiefly sharing β€” you get the same view of your files from any client β€” plus centralized administration/backup and security (lock the servers in a room). The catch is a new challenge that runs through the whole chapter: failure.

The Crux: How To Build A Distributed File System

How do you build one? What are the key aspects to think about, what’s easy to get wrong, and what can we learn from existing systems?

49.1 A Basic Distributed File System

A DFS has two software halves. The client-side file system fields the application’s ordinary syscalls (open, read, write, close, mkdir, …) and turns them into protocol messages; the file server stores the data and answers those messages (reading from its disk or in-memory cache). Together they define the system’s behavior:

CLIENTSERVERClient ApplicationClient-side File SystemNetworking LayerFile ServerNetworking LayerDisksnetwork
Figure 49.2: the architecture. The client stack (app β†’ client-side FS β†’ networking) talks over the network to the server stack (networking β†’ file server β†’ disks).

A crucial goal is transparent access : the DFS presents the same POSIX API as a local file system, so to applications it looks no different (except, perhaps, in performance). A cached re-read might even generate no network traffic at all.

49.2 On to NFS

Sun’s Network File System (NFS) was one of the earliest and most successful. Sun’s clever move: instead of a proprietary product, they defined an open protocol β€” just the exact message formats clients and servers exchange. Anyone could build an NFS server, so a competitive market grew (Oracle/Sun, NetApp, EMC, IBM, …), and interoperability held. We study the classic NFSv2.

49.3 Focus: Simple and Fast Server Crash Recovery

NFSv2’s overriding design goal is simple, fast server crash recovery. In a many-client, single-server world, every minute the server is down idles every client β€” β€œas the server goes, so goes the entire system.” So recovery had to be trivial.

Aside: Why Servers Crash

Plenty of reasons: a power outage; a bug in the millions of lines of server code (even good code has a few bugs per thousand lines); a memory leak that slowly exhausts RAM. And in a distributed system the network itself can partition β€” a perfectly healthy server can look crashed simply because it’s unreachable.

49.4 Key to Fast Crash Recovery: Statelessness

NFSv2’s answer is a stateless protocol : the server tracks nothing about clients β€” not which files are open, not file offsets, not which blocks a client caches. Every request carries all the information needed to complete it.

Contrast a stateful protocol . Consider ordinary open(), which returns a file descriptor used by later reads:

char buffer[MAX];
int fd = open("foo", O_RDONLY);  // get descriptor "fd"
read(fd, buffer, MAX);           // read MAX from foo via "fd"
read(fd, buffer, MAX);           // read MAX again
...
close(fd);                       // close file

If the server tracked that fd, it would be distributed state (Ousterhout’s term) β€” shared between client and server β€” and that is exactly what makes recovery hard:

Why a stateful open()/fd hurts crash recovery. The descriptor's meaning is distributed state β€” shared between client and server β€” and a server crash wipes the server's half.
Clientfd = 3app holds descriptor 3read(fd=3, …)Serverfd 3 β†’ "foo"tracks the open filedistributed statethe fd's meaning lives on BOTH sides β€” shared, and fragile

1Normal: the server tracks the open file

A stateful open() returns fd = 3; the server records "fd 3 β†’ foo" in its open-file table. Subsequent read(fd) requests rely on the server remembering that mapping.

step 1 / 2

It’s worse still with client crashes: a client that open()s a file and then dies never sends close(), so the server’s open descriptor leaks until it somehow notices. For all these reasons NFS went stateless β€” each request self-contained, no recovery protocol, the server just restarts and clients (at worst) retry.

Check yourself: a stateless distributed file system

1.Why route file access through a central server instead of letting each client use its local disk?

2.What does 'transparent access' mean for a distributed file system?

3.What are the two software pieces of a client/server distributed file system?

4.NFSv2's overriding design goal is simple, fast server crash recovery. What protocol property achieves it?

5.Why does a stateful design β€” where open() makes the server track a file descriptor β€” complicate crash recovery?

5 questions