Subject: resend: Re: "indivisible lock" semantics

From: Mike Kupfer <[email-masked]>
Date: Tue, 11 Jan 2000 14:29:46 -0800

(This is a resend of a message that bounced, just to make sure the
entire WG gets to see it.  I'm currently waiting to hear back from our
local standards gurus.  --mike)

>>>>> "Dave" == Noveck, Dave <[email-masked]> writes:

    Dave> I'm curious about the adjective "rare" as opposed to
    Dave> "non-existent".  I'm not saying that such programs don't
    Dave> exist, but I've never seen one.  Has anybody else?

I can't point to a specific program that expects indivisible locks,
but

1. Mr. Murphy says that as soon as we declare that nobody does that,
someone will come along and do it.

2. I do remember being surprised at some of the locking calls CAD
programs make.

3. I can imagine someone wanting to process a UNIX mail file by
initially read-locking the entire file, then obtaining write locks as
necessary to process user edits.

    Dave> It wouldn't necessarily know.  It could be that another
    Dave> client got a conflicting lock and gave it up before you got
    Dave> around to getting the second locked region.  The result
    Dave> would be that you wouldn't have the atomicity guarantee and
    Dave> you wouldn't know about the conflicting lock.

Gack, you're right.  To be safe, a UNIX v4 client would have to
disallow any locking operations that open a window for a conflicting
lock.

    Dave> I want to be clear about the details here.  Let's suppose
    Dave> that region Z consists of two abutting sub-regions: X and Y.

    Dave> In your example, process A has a read lock on Z and is
    Dave> attempting to upgrade his lock on the sub-region X to a
    Dave> write lock.

    Dave> The overall transition [read(Z)] -> [write(X)+read(Y)] is
    Dave> *not* atomic in the UNIX locking implementations that I've
    Dave> seen.  If there were two processes trying to do this, they
    Dave> would either have to wait forever or get EDEADLCK and I
    Dave> don't think that happens.

The implementation is not the API spec.  My reading of the UNIX '98
spec <http://www.opengroup.org/onlinepubs/007908799/xsh/fcntl.html> is
that if process A attempts such an upgrade (using F_SETLKW) while
process B has region Z read-locked, process A will sleep until process
B releases its lock.  If both processes A and B attempt such an
upgrade, you'll get a deadlock, which the OS might or might not
detect.

    Dave> The question of upgrade poses some issues even apart form
    Dave> the divisiblity issue.  If you simplify your example to a
    Dave> single region and say that two processes are trying to
    Dave> upgrade a lock for the region X from read to write.  With
    Dave> the spec as it is, what happens?  A and B both keeps sending
    Dave> upgrade reequests which are denied.  They continue to poll
    Dave> and maybe do it slower after a while but they don't make any
    Dave> progress.

    Dave> There is no way that the server can ever grant A's request
    Dave> for upgrade without revoking B's lock.  The conclusion that
    Dave> I draw is that upgrade should be done by the client using an
    Dave> unlock followed by getting a write lock.  This is not atomic
    Dave> but I don't think UNIX has atomicity in this regard now
    Dave> (don't know about Windows).  

The UNIX '98 spec is less clear here.  "Atomic" does not appear in the
fcntl documentation.  What it does say is "the previous lock type for
each byte ... will be replaced by the new lock type".  I will contact
our local standards gurus for an interpretation of that phrase.

    Mike> "The byte range of a lock is indivisible.  A range may be
    Mike> locked or unlocked between read and write but may not have

    Dave> locked or unlocked or changed between read and write

Right, thanks.

    Mike> subranges unlocked or changed between read and write.  These
    Mike> are the semantics provided by the Win32 environment but only
    Mike> a subset of the semantics provided by Unix environment.
    Mike> This means that Unix clients may need to emulate a single
    Mike> locking request with multiple NFS calls.  For example, if a
    Mike> subrange is unlocked, the client will need to unlock the
    Mike> entire range and lock the new regions.  This creates a
    Mike> window during which a conflicting lock can be taken by
    Mike> another client.  If this happens, the server will reject the
    Mike> client's attempt to create the new regions, and the client
    Mike> will notify the application that the lock has been lost."

    Dave> I would replace the last sentence with the following:

    Dave>       Thus, atomically unlocking a subrange (as provided
    Dave> locally by UNIX systems) may not be possible under NFS
    Dave> version 4.
 
Yeah, let me see what our Standards folks say about atomicity
requirements.  Then we figure out what to tell UNIX clients they need
to do.

mike