A new and very robust method for doing file locking over NFS?

Ben Hutchings do-not-spam-ben.hutchings at businesswebsoftware.com
Thu Apr 24 16:47:47 CEST 2003


In article <lcu1cw525a.fsf at gaffa.mit.edu>, Douglas Alan wrote:
> I'd like to do file locking over NFS without using lockd.  The reason
> I want to avoid using lockd is because many lockd implementations are
> too buggy.
> 
> It is fairly easy to avoid using lockd -- just avoid using lockf() to
> lock a file.  Instead of using lockf(), lock a file by creating a lock
> file that you open with the O_CREAT | O_EXCL flags.
<snip>

O_EXCL doesn't work with NFS prior to version 3, and maybe not even
then.

The usual solution for creating a lock file in an NFS-safe way is:

1. Create a file in the target directory with a unique name (usually
   involving hostname and pid).
2. Attempt to link the lock file name to this file (using the temporary
   file name).  Ignore whether this succeeds or fails, as the result is
   not reliable.
3. stat() the target file name and record the number of links.
4. Unlink the original file name.
5. If the number of links recorded in step 3 was 2, continue, else fail.
   (Or try again, up to some maximum number of times.)

A cleaner solution would be to use a client-server protocol instead of
synchronising through the file system, but that's not so easy to do.

In Python:

    hostname = socket.gethostname().split('.')[0]
    unique_name = '%s.%s-%d' % (lock_name, hostname, os.getpid())
    for i in range(5):
        os.close(os.open(unique_name, os.O_CREAT|os.O_WRONLY))
        try:
            try:
                os.link(lock_name, unique_name)
            except OSError:
                pass
            if os.stat(lock_name).st_nlink == 2:
                break
        finally:
            os.unlink(unique_name)
    else:
        raise OSError((errno.EEXIST, os.strerror(errno.EEXIST), lock_name))




More information about the Python-list mailing list