POSIX vs flock on Network File Systems in Linux
The Linux operating system manages file locking across networked file
systems by translating local kernel primitives—specifically POSIX record
locks (fcntl/lockf) and BSD-style locks
(flock)—into network protocol operations. While POSIX locks
natively map to standard network lock protocols like NFS and SMB to
provide cross-client synchronization, flock historically
functioned only on local filesystems. Modern Linux kernels reconcile
these differences by emulating flock as whole-file POSIX
locks over network mounts, a mechanism that unifies distributed locking
but introduces distinct semantic caveats and configuration
dependencies.
Fundamental Divergence in Linux Locking Semantics
Locally, Linux handles POSIX and flock locks using
fundamentally different structures in the Virtual Filesystem (VFS)
layer:
- POSIX Locks (
fcntl,lockf): Associated with a specific process (pid) and aninode. They support byte-range locking and are automatically released when the process closes any file descriptor pointing to that file. - BSD Locks (
flock): Associated with the open file description (struct file), not the process. They apply exclusively to whole files, survivefork()calls, and remain active until explicitly unlocked or until the last duplicated descriptor is closed.
Because network protocols like NFS were designed around POSIX-like, byte-range semantics, native support for BSD-style whole-file descriptor locks does not exist at the wire-protocol level.
POSIX Locks Over the Network
When an application calls fcntl() on a network-mounted
file, the VFS invokes the filesystem driver’s .lock() hook
rather than using the local VFS lock list:
- NFSv3: Relies on the external Network Lock Manager
(NLM) protocol. The Linux kernel uses
rpc.lockdto negotiate locks with the server's lock manager, whilerpc.statdtracks client and server reboot statuses through the Network Status Monitor (NSM) protocol to handle lock recovery. - NFSv4: Replaces NLM by integrating locking directly into the stateful NFSv4 protocol. Locks are associated with a server-side state ID and client-managed leases. If the client misses lease renewals due to network partitions, the server drops the locks, and the Linux client must recover them during a server grace period.
- SMB/CIFS: Translates POSIX lock requests into native SMB byte-range lock packets. Depending on the mount parameters, Linux can map POSIX advisory locks into SMB mandatory locks, causing the server to reject unauthorized read/write operations from other nodes.
The Network Evolution of
flock
Historically, flock calls on network mounts were purely
client-local; a lock taken on Client A was invisible to Client B. Modern
Linux kernels (since version 2.6.12) resolve this by delegating
flock to the network file system:
- Protocol Emulation: The network filesystem driver
implements a
.flock()hook that translates an incomingflock()call into a whole-file POSIX byte-range lock (spanning byte 0 to the maximum possible offset). - Transmission: The lock is transmitted over the wire as an ordinary POSIX lock using NLM, NFSv4, or SMB.
- Semantic Blurring: Locally, Linux treats
flockand POSIX locks as independent namespaces that do not conflict with one another. However, on a network mount whereflockis emulated as a POSIX lock, a localflockwill conflict directly with a POSIX lock on the same node or across the cluster, altering local application behavior.
Mount Options and Behavioral Control
Because translating flock to POSIX network locks can
cause performance overhead or break legacy applications, Linux provides
mount options to alter locking behavior:
local_flock(NFS): Disables over-the-wire lock requests forflock(). BSD locks are handled entirely inside the local client's VFS, providing legacy BSD semantics between processes on the same node while keeping them invisible to other cluster nodes.flock/noflock(SMB/CIFS): Determines whether the CIFS client attempts to pass whole-file locks to the remote server or falls back to internal emulation.nordirplus/nolock(NFS): Completely disables client-side over-the-wire locking, converting all POSIX andflockrequests to purely local locks. This is common in single-client architectures to eliminate RPC latency.
State Recovery and Partition Handling
Distributed locking requires strict synchronization between the client VFS and remote state handlers. On network partitions or server crashes:
- POSIX/NFSv4: The Linux kernel detects expired leases via state renewal errors. Once the connection is re-established, the kernel enters an internal recovery loop, attempting to reclaim previously held POSIX locks before processing new I/O requests.
- Emulated
flock: Because these locks are represented on the wire as POSIX states, they participate in the same recovery loops as standardfcntllocks, but failure to reclaim the lock invalidates the file handle and surfaces errors to the application layer.