Skip to content

NFS

NFS shares a directory from a server to clients over the network, mounted so it looks like a local filesystem. It is the default network filesystem on Linux, and a hung NFS mount is a classic cause of high load with idle CPUs.

Track: Core · Interview weight: Med


Must-Know Facts

Fact Value Verify with
Server package nfs-utils (RHEL), nfs-kernel-server (Ubuntu) rpm -q nfs-utils
Client package nfs-utils (RHEL), nfs-common (Ubuntu) mount.nfs -V
Exports file /etc/exports defines shared directories and who may mount cat /etc/exports
Apply exports Re-read and show the export table exportfs -rav
Current exports What the server is exporting now exportfs -s
List from client Show a server's exports showmount -e SERVER
Default version NFSv4.2 over TCP on modern distros findmnt -o FSTYPE,OPTIONS
Port NFSv4 uses a single port, 2049 ss -tlnp | grep 2049
hard mount Retries forever if the server stops; process blocks in D mount option hard
soft mount Fails I/O after retries; risks data corruption mount option soft
Hang signature D state, WCHAN rpc_wait_bit_killable, load rising ps -o stat,wchan
Boot-safe mount _netdev and nofail in /etc/fstab man nfs

Exporting a Directory

The server lists shared directories in /etc/exports, each with the clients allowed to mount it and the options. exportfs -rav re-reads the file and applies it, and exportfs -s shows what is exported now.

echo '/srv/nfs/shared 172.16.0.0/16(rw,sync,no_subtree_check)' | sudo tee /etc/exports
sudo systemctl enable --now nfs-server
sudo exportfs -rav
sudo exportfs -s

Output:

exporting 172.16.0.0/16:/srv/nfs/shared
/srv/nfs/shared  172.16.0.0/16(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,root_squash,no_all_squash)

The server filled in defaults, including root_squash, which maps a client's root to nobody so a remote root cannot own server files. sync makes the server commit writes before replying, which is safer than async but slower.

root_squash is on by default for a reason

With root_squash, a client's root becomes nobody on the export, so a compromised client cannot write files as root on the server. Turning it off with no_root_squash hands remote root real root on the share, and is rarely correct.


Mounting on the Client

The client lists a server's exports with showmount -e, then mounts one like any filesystem. findmnt shows the negotiated protocol version and options.

showmount -e 172.16.1.3
sudo mount -t nfs 172.16.1.3:/srv/nfs/shared /mnt/nfs
findmnt -no FSTYPE,OPTIONS /mnt/nfs

Output:

Export list for 172.16.1.3:
/srv/nfs/shared 172.16.0.0/16
nfs4 rw,relatime,vers=4.2,hard,proto=tcp,timeo=600,retrans=2,sec=sys

The mount negotiated NFSv4.2 over TCP with hard and timeo=600 (a 60-second retransmit timeout). For a permanent mount, an /etc/fstab line with _netdev and nofail keeps a slow or absent server from blocking boot, covered in Mounting and fstab.


hard vs soft, and the Hang

A hard mount retries indefinitely if the server stops responding, so no data is lost but a process doing I/O blocks in uninterruptible sleep (D). A soft mount gives up after retrans retries and returns an error, which avoids the hang but can corrupt data mid-write.

When a hard-mounted server becomes unreachable, the writing process goes to D, load average climbs, yet the CPUs stay idle because a D task consumes no CPU.

# server unreachable; a write to the mount blocks
ps -o pid,stat,wchan:20,comm -p <writer-pid>
cat /proc/<writer-pid>/stack | head -3

Output:

    PID STAT WCHAN                COMMAND
   1576 D    rpc_wait_bit_killabl dd
[<0>] rpc_wait_bit_killable+0x11/0x80
[<0>] __rpc_execute+0x17e/0x320
[<0>] nfs4_call_sync_sequence+0x74/0xb0 [nfsv4]

The D state, the rpc_wait_bit_killable wait channel, and the NFS frames in the kernel stack together name the cause: the process is blocked waiting for an NFS RPC to complete. This is the signature behind the High Load, Low CPU scenario.

A D-state NFS process cannot be killed, even with SIGKILL

A process in uninterruptible sleep on NFS ignores every signal until the RPC completes or the server returns. The fix is to restore the server or the network, or reboot; kill -9 does nothing while it waits.


Install Differences

sudo dnf install -y nfs-utils          # server and client both
sudo systemctl enable --now nfs-server # server side
sudo apt install -y nfs-kernel-server  # server
sudo apt install -y nfs-common         # client only
sudo systemctl enable --now nfs-server

Common Errors

clnt_create: RPC: Program not registered from showmount

Cause: the NFS server service is not running, or a firewall blocks the NFS port.

Fix: start nfs-server on the server, and allow the nfs service through the firewall (port 2049 for NFSv4).

mount.nfs: access denied by server while mounting

Cause: the client's address does not match any entry in /etc/exports, or exports were not re-applied after an edit.

Fix: correct the client range in /etc/exports and run sudo exportfs -rav; confirm with exportfs -s.


Interview Checkpoints

L1: What is the difference between a hard and a soft NFS mount?

Say first: a hard mount retries forever if the server stops, blocking the process but never losing data; a soft mount fails I/O after a few retries, risking corruption.

Proof: the mount options hard and soft; a hard-mounted hang shows processes in D state.

Follow-up: which is the safe default for data? (hard, with _netdev and nofail in fstab.)

L1: How does root_squash protect an NFS server?

Say first: it maps a client's root to nobody on the export, so a remote root cannot own or overwrite files as root on the server.

Proof: it is on by default; exportfs -s shows root_squash in the options.

Follow-up: when would you disable it? (rarely, for a trusted management host, with the risk understood.)

L2: Export a directory read-write to one subnet and apply it.

Say first: add the line to /etc/exports and re-read it.

Proof:

echo '/data 10.0.0.0/24(rw,sync)' | sudo tee -a /etc/exports
sudo exportfs -rav

Follow-up: how does the client see the export? (showmount -e SERVER.)

L3: Load average is climbing but every CPU is idle. What do you check first, and why NFS?

Say first: look for processes in D state, because uninterruptible sleep counts toward load but uses no CPU, and a hung hard NFS mount is a common cause.

Proof: ps -eo stat,wchan,comm | grep '^D'; rpc_wait_bit_killable in WCHAN or the kernel stack points at NFS.

Follow-up: why can you not kill the process? (it is in uninterruptible sleep until the RPC returns.)

L4: Why does a process on a hung hard NFS mount ignore SIGKILL?

Say first: it is in uninterruptible sleep (D) inside a kernel RPC wait, and the kernel does not deliver signals until that wait completes, to avoid leaving the filesystem in an inconsistent state.

Proof: /proc/PID/stack shows rpc_wait_bit_killable; the state clears only when the server responds or the mount is forced down.

Don't say: that kill -9 will free it; only restoring the server or a reboot will.

L2: Make an NFS mount safe to have in fstab when the server may be down at boot.

Say first: mark it as a network device that must not block boot.

Proof: add _netdev,nofail (and often x-systemd.automount) to the fstab options.

Follow-up: what does nofail change? (a failed mount no longer drops boot to emergency.)


Captured on Rocky Linux 10.2 servers on an iximiuz Labs FlexBox microVM, kernel 6.1.167, 2026-09. The hang was produced by dropping NFS traffic to the server.