flock(2) versus fcntl(2) over a NFS

I'm pretty sure that you are looking at legacy concerns. Recall that the Perl5 manual was released in 1994 and that it was just an edit of Perl4's manual from 1991. In those days it could probably be said about the oft-named Nightmare File System that "it isn't how well the bear dances that amazes, but that it dances at all".

NFS2 in the 1991 epoch was slowly crawling out of Sun into other platforms and was relatively crude. The security model was essentially non-existent (root on a client machine could read the full contents of an NFS mount) and locking - via nfs.lockd - was this side of experimental. You would have been foolish to expect flock semantics to work properly if at all between two different allegedly interoperable implementations. Coax was the dominant Ethernet PHY at the time which many network users have never had the displeasure of using (what do you mean you forgot to put the 50 termination resistor on?) if that gives you a better grip on the state of intranets then.

Larry Wall and crew had every reason to make pessimistic assumptions about the correctness of NFS locks at the time, and this is the sort of defensive programming that future code jockeys are loathe to remove because it is so hard to prove the absence of a defect by removing old code which is re-introduced in interoperability with a legacy system that you never even heard of.

Since then, NFS has improved considerably, and lockd has migrated in time to a feature of the Linux 2.6 kernel. For a collection of 2003+ systems, NFS file locking can probably be trusted, especially if tested well within your application across the many platforms it may be running on.

All of the above was cribbed from memory, and could likely be substantiated through research (e.g. http://nfs.sourceforge.net/) but the proof - as they say - is in the locking, and if you didn't test it, it is presumed broken.


Lennart Poettering recently did some digging into linux filesystem locking behaviour, which doesn't paint a particularly rosy picture for locking over NFS (especially the follow-up he links to at the bottom of the post).

http://0pointer.net/blog/projects/locking.html


Another one, straight from Linux-NFS FAQ: nfs.sf.net

I'm trying to use flock()/BSD locks to lock files used on multiple clients, but the files become corrupted. How come? A. flock()/BSD locks act only locally on Linux NFS clients prior to 2.6.12. Use fcntl()/POSIX locks to ensure that file locks are visible to other clients.

Here are some ways to serialize access to an NFS file.

Use the fcntl()/POSIX locking API. This type of locking provides byte-range locking across multiple clients via the NLM protocol, or via NFSv4. Use a separate lockfile, and create hard links to it. See the description in the O_EXCL section of the creat(2) man page. It's worth noting that until early 2.6 kernels, O_EXCL creates were not atomic on Linux NFS clients. Don't use O_EXCL creates and expect atomic behavior among multiple NFS client unless you are running a kernel newer than 2.6.5.

It's a known issue that Perl uses flock()/BSD locking by default. This can break programs ported from other operating systems, such as Solaris, that expect flock/BSD locks to work like POSIX locks.

On Linux, using file locking instead of a hard link has the added benefit of checkpointing the client's cache with the server. When a file lock is acquired, the client will flush the page cache for that file so that any subsequent reads get new data from the server. When a file lock is released, any changes to the file on that client are flushed back to the server before the lock is released so that other clients waiting to lock that file can see the changes.

The NFS client in 2.6.12 provides support for flock()/BSD locks on NFS files by emulating the BSD-style locks in terms of POSIX byte range locks. Other NFS clients that use the same emulation mechanism, or that use fcntl()/POSIX locks, will then see the same locks that the Linux NFS client sees.

On local Linux filesystems, POSIX locks and BSD locks are invisible to one another. Thus, due to this emulation, applications running on a Linux NFS server will still see files locked by NFS clients as being locked with a fcntl()/POSIX lock, whether the application on the client is using a BSD-style or a POSIX-style lock. If the server application uses flock()BSD locks, it will not see the locks the NFS clients use.