C++ / a working model

153 / 163   ·   C11   ·   8 min

Network File System (NFS)

Keep this sentence

This chapter introduces the early successful distributed file system NFS, focusing on how the client-server model enables data sharing and transparent access, and how NFSv2 achieves instant recovery after server crashes via a completely stateless protocol.

In this lesson
  1. Why Remote File Service
  2. Transparent Client File System
  3. Stateless Design for Fast Recovery
  4. Ecosystem from an Open Specification
  5. Example
  6. Exercise

Official chapter PDF

Why Remote File Service

When each workstation has only local disks, users cannot easily see the same files from different machines. Placing data on a few servers that clients reach over the network automatically gives a unified view. Backups, permissions and physical security can also be handled centrally instead of being repeated on every machine.

Transparent Client File System

Applications still invoke ordinary system calls such as open, read and write. The client-side file system translates those calls into network requests; the server performs the disk or cache operation and returns the result. To the programmer remote files look almost identical to local ones, except perhaps for higher latency.

Stateless Design for Fast Recovery

The server deliberately remembers nothing about clients: no open-file table, no current offsets, no knowledge of cached blocks. Every protocol message carries all parameters needed to finish the operation, such as a file handle, offset and length. After a restart the server can immediately accept new requests; a client at worst retransmits the last message.

Ecosystem from an Open Specification

Sun published the exact message formats rather than shipping a closed product, so any vendor could implement a compatible server. Competition drove continual improvements in performance and reliability and helped NFS become a de-facto standard.

Pitfalls

  • Sending a local file descriptor in a network request so the server cannot identify the file after a crash
  • Treating a transient network partition as a permanent server death and giving up retries
  • Caching dirty data on the client for a long time without write-back, producing inconsistent views across clients

Run an example

Minimum C11 · complete program · Download .c

#include <stdio.h>
#include <string.h>
#include <stdint.h>

typedef uint32_t nfs_fh_t;

static const char file_data[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const size_t file_len = 26;

int nfs_read(nfs_fh_t fh, uint64_t offset, uint32_t count, char *buf, uint32_t *nread) {
    printf("NFS-REQ READ fh=%u off=%llu cnt=%u\n", (unsigned)fh, (unsigned long long)offset, count);
    if (fh != 7) {
        printf("NFS-ERR stale handle\n");
        return -1;
    }
    if (offset >= file_len) {
        *nread = 0;
        printf("NFS-REP 0 bytes (EOF)\n");
        return 0;
    }
    size_t remain = file_len - (size_t)offset;
    uint32_t copy = count < remain ? count : (uint32_t)remain;
    memcpy(buf, file_data + (size_t)offset, copy);
    *nread = copy;
    printf("NFS-REP %u bytes\n", copy);
    return 0;
}

int main(void) {
    char buf[32];
    uint32_t got;
    nfs_fh_t fh = 7;
    printf("Client starts using NFS file handle 7\n");
    if (nfs_read(fh, 0, 5, buf, &got) == 0) {
        buf[got] = '\0';
        printf("DATA: %s\n", buf);
    }
    if (nfs_read(fh, 10, 5, buf, &got) == 0) {
        buf[got] = '\0';
        printf("DATA: %s\n", buf);
    }
    printf(">>> simulated server crash and restart <<<\n");
    if (nfs_read(fh, 20, 10, buf, &got) == 0) {
        buf[got] = '\0';
        printf("DATA: %s\n", buf);
    }
    nfs_read(fh, 30, 4, buf, &got);
    printf("EOF reached as expected\n");
    return 0;
}

Compile locally

gcc -std=c11 -Wall -Wextra -Wpedantic -Werror ostep-49-nfs.c -o example && ./example

Expected result

Client starts using NFS file handle 7
NFS-REQ READ fh=7 off=0 cnt=5
NFS-REP 5 bytes
DATA: ABCDE
NFS-REQ READ fh=7 off=10 cnt=5
NFS-REP 5 bytes
DATA: KLMNO
>>> simulated server crash and restart <<<
NFS-REQ READ fh=7 off=20 cnt=10
NFS-REP 6 bytes
DATA: UVWXYZ
NFS-REQ READ fh=7 off=30 cnt=4
NFS-REP 0 bytes (EOF)
EOF reached as expected

CHECK YOUR UNDERSTANDING

Close the answer. Explain it.

If the NFS protocol included an open call that returned an integer descriptor, what difficulty would the next read encounter after a server crash? How does the stateless design avoid that difficulty?

Show a reference answer

The in-memory mapping from descriptor to file would be lost, so the read would not know which file to access. A stateless protocol makes every read carry its own file handle and offset, so the server needs no prior state to complete the operation.

Check the sources

Drafts and official chapters change. The version mark is only the example’s minimum.

Back to the catalog