Subject: What does paragraph 1 of Section 8.9 mean?

From: "Noveck, Dave" <[email-masked]>
Date: Mon, 12 Mar 2001 08:27:51 -0800

Does anybody out there know what the first paragraph of
section 8.9 is supposed to mean?  The more I look at it,
the more difficult (i.e. impossible) I find it to come up 
with an interpretation that makes any sense in the context 
of the rest of the spec.

The paragraph in question reads:

   To provide correct share semantics, a client MUST use the OPEN
   operation to obtain the initial filehandle and indicate the desired
   access and what if any access to deny.  Even if the client intends to
   use a stateid of all 0's or all 1's, it must still obtain the
   filehandle for the regular file with the OPEN operation so the
   appropriate share semantics can be applied.  For clients that do not
   have a deny mode built into their open programming interfaces, deny
   equal to NONE should be used.

Two interpretations have been suggested, which differ mainly in 
how the introductory phrase is related to the rest of the text.

What I'll call interpretation A, treats the introductory phrase
as a condition, (severely) qualifying what comes after.  It can 
be paraphrased as follows:

   If a client implementation intends to provide correct share
   semantics, it is necessary that it use the OPEN operation 
   to obtain the initial filehandle and indicate the desired
   access and what if any access to deny.  Even if the client 
   intends to use a stateid of all 0's or all 1's, it would still
   need to obtain the filehandle for the regular file with the OPEN
   operation so the appropriate share semantics could be applied.  
   For clients that do not have a deny mode built into their open
   programming interfaces, deny equal to NONE should be used.

It seems to me that this interpretation is a very strange one as
it essentially says that the client really really really has to
use OPEN, unless ... it doesn't want to.  This doesn't make
sense, particularly given the capital MUST in the original.
Interpretation A would treat the must as indicating (non-normative)
practical necessity, which isn't the same thing at all.

Also, the nature of the protocol means that no client could
depend on "correct share semantics" if there were other clients
(who presumably did not care about share semantics) not using
OPEN.  In fact, the last sentence refers to clients without 
a deny mode in their open (e.g. UNIX clients), without suggesting
that they would do anything but do an OPEN, in essentially
the same way as other clients.

I conclude that interpretation A is untenable.

Interpretation B treats the introductory phrase as explaining
the background of the requirement and not qualifying it.  It 
can be paraphrased as follows.

   In order to provide correct share semantics, the NFS-v4 protocol
   requires a client to use the OPEN operation to obtain the initial
   filehandle and indicate the desired access and what if any access 
   to deny.  Even if the client intends to use a stateid of all 0's 
   or all 1's, it must still obtain the filehandle for the regular 
   file with the OPEN operation so the appropriate share semantics 
   can be applied.  Clients that do not have a deny mode built into
   their open programming interfaces and which normally do not 
   internally implement share smantics must nevertheless use 
   OPEN, with deny equal to NONE specified.

The biggest problem with interpretation B is the fourth paragraph
of Section 8.9 which discusses a client doing precisely what 
interpretation B says it MUST not do: accessing a file without 
doing an OPEN.  It doesn't express condemnation or even mild
disapproval; it just indicates how the server will respond to 
the situation and that certainly isn't to return an indication of 
a protocol error.  The paragraph in question reads:

   The LOOKUP operation will return a filehandle without establishing
   any lock state on the server.  Without a valid stateid, the server
   will assume the client has the least access.  For example, a file
   opened with deny READ/WRITE cannot be accessed using a filehandle
   obtained through LOOKUP because it would not have a valid stateid
   (i.e. using a stateid of all bits 0 or all bits 1).

By the way, the last sentence seems incorrect as applied to a 
stateid of all bits 1.  Those are supposed to bypass locking 
checks at least for READ.  So I would think, READS with an all-1's
stateid would be allowed, any active OPEN's denying READ not-
withstanding.  Otherwise, how are stateids of all 0's and 
stateids of all 1's different?

The very existence of special stateid's seems to contradict
interpretation B or at least make it dubious.  First, what is
the point of the all-zero stateid.  If the client is supposed
to do an OPEN, none.  He will get a stateid from the OPEN and
can use it.  Adding another way of reading and writing the 
file (stateid zero), adds no function, only complexity.  If
interpretation B is correct, the protocol has created a special
stateid, whose most common use is to do what is not supposed to
be allowed.

The case of stateid of all 1's is different, but just as 
troublesome.  The all-1's stateid is presumably for operations
such as backup that don't wish to be inhibited by (share or
byte-range) locks.  However, any such advantage would be 
vitiated if the client has to do an OPEN first.  A READ with
a stateid of all 1-s would be allowed when someone else has
the file opened DENY=READ, but an open for read would not,
making the stateid of all 1's pretty useless.

All of the above seems to make interpretation B untenable as
well, leaving me without any way to make sense of section 8.9.

Also I should note that section 8.1.4 has some text that is
relevant here.  It seems to contradict interpretation B by
discussing use of state of all 0's when "no state is
established by the client".  It also seems to indicate that
if the client has done an OPEN, it cannot use a special stateid,
although the text refers confusingly to doing an IO on a
range of bytes within a locked range, which makes it sounds
like byte-range locks only are being discussed, but then refers
to the "appropriate lock (record or share)", which indicates 
otherwise.  In any case, it is unclear whether a normal 
UNIX OPEN (i.e with DENY=NONE) is covered as something that
*requires* you to use the stateid you got (as opposed to
a special stateid).  However, if it is covered, then this
seems to contradict the second sentence of the first paragraph
of section 8.9 on almost any interpretation.  That sentence talks 
about doing an OPEN then using one of the special stateid's, which
seems to be contradicted by sectin 8.1.4.

I guess all things considered, the weight of evidence is
that interpretation A, which makes the first paragraph a
no-op is what was intended, but if it is a no-op, what is 
it doing in the spec?  Or is there some way of reading this
(or modifying it, or some other part of the spec) so that 
things make more sense? 

It might help to know if there is any clients out there using 
or intending to use special stateids for any purpose other 
than as a temporary hack until OPEN is fully implemented.
Anybody?

---

From: David Robinson <[email-masked]>
Date: Mon, 12 Mar 2001 15:23:25 -0800

Here is my interpretation of what the spec should be saying.

A file handle is required to perform both I/O and non-I/O
operations on a file.  In order to perform an I/O operation,
an OPEN call MUST first be made to establish the correct
access and deny modes.  A file handle obtained via a LOOKUP
operation MUST NOT be used for an I/O operation unless an
OPEN has also been performed. This requirement is independant
of any byte range locking desired.

The use of magic stateids is a seperate issue. Given that an OPEN
returns back a stateid it is questionable why we even need
magic stateid values.  The original intent was to allow
clients to opt out of the mandatory locking semantics, reading
a file locked exclusively and writing a file locked shared/exclusive
(if the server allows it). If we simply allowed a new OPEN
flag to indicate "advisory locking" we could dispense with
the magic stateids.  In fact, the only way the client could
perform I/O operations would be to have a valid stateid
which would make the requirement to use OPEN implicit.

The magic stateids were introduced before OPEN was added,
they have probably lived past their useful life.

To do I/O you MUST have a valid stateid, to get a valid
stateid you MUST do an OPEN.

	-David

---

From: "Talpey, Thomas" <[email-masked]>
Date: Tue, 13 Mar 2001 14:36:05 -0500

At 06:23 PM 3/12/2001, David Robinson wrote:
>If we simply allowed a new OPEN 

This seems clearly the best way out of the situation. Especially for
stateid 0 which can be argued as unnecessary. But for stateid -1,
I'm not sure the goal is to get an advisory lock. It's more of a "don't
care". In this case, the server can manufacture a don't care stateid
of its own choosing and the client can proceed.

Tom Talpey
Network Appliance.