Subject: [nfsv4] is this a valid locking sequence?

From: Ronald E Bretschneider <[email-masked]>
Date: Thu, 28 Aug 2003 15:58:05 -0700

Hi,

Section 8.1.5 says "Note for requests that contain a sequence number, for
each lock_owner, there should be no more than one  outstanding request".
What does "one outstanding request" mean? Does the request mean the RPC
operation or does it mean the completion of the asynchronous lock grant? As
an example, does this mean that if a lockowner has issued a blocking lock
request which has been denied, must the client poll for the results before
issuing a subsequent locking request on behalf of this lockowner?

In other words, is the following locking sequence valid? Certainly each
lock request is in a different compound RPC.
/* blocking request, cfh=f1 */

Lock  locktype=writew_lt
      reclaim=false
      offset=0
      length=100
      locker.lock_stateid=x1
      locker.lock_seqid=y
/* server returns NFS4ERR_DENIED */

/* blocking request, different range than the previous request, cfh=f1 */
lock  locktype=writew_lt      blocking request for a different range
      reclaim=false
      offset=1000
      length=200
      locker.lock_stateid=x1
      locker.lock_seqid=y+1

Does the server allow this request, or must the client poll for the granted
lock before being allowed to issue the second lock request?

thanks,
Ron

_______________________________________________
nfsv4 mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/nfsv4

---

From: eric kustarz <[email-masked]>
Date: Fri, 29 Aug 2003 11:22:05 -0700

> issuing a subsequent locking request on behalf of this lockowner?

Read on to the next paragraph:
"
If a request (r) with a previous sequence number (r < L) is received,
   it is rejected with the return of error NFS4ERR_BAD_SEQID.  Given a
   properly-functioning client, the response to (r) must have been
   received before the last request (L) was sent.  If a duplicate of
   last request (r == L) is received, the stored response is returned.
   If a request beyond the next sequence (r == L + 2) is received, it is
   rejected with the return of error NFS4ERR_BAD_SEQID.
"

The "one outstanding request" means that the server MUST return an error
of BAD_SEQID if it gets your requests out of order.  So if you send two
requests to the server, you don't know the order in which they will be
received.  If the server gets the second request (with the higher seqid)
first, it will return BAD_SEQID.  NFSv4 doesn't have the server hold
onto all incoming packets waiting to "reassemble" them, unlike some
other protocols.  The server just does the simple check noted above.

Also, there are certain errors that the seqid doesn't get bumped:

8.1.5
...
"
The client MUST monotonically increment the sequence number for the
   CLOSE, LOCK, LOCKU, OPEN, OPEN_CONFIRM, and OPEN_DOWNGRADE
   operations.  This is true even in the event that the previous
   operation that used the sequence number received an error.  The only
   exception to this rule is if the previous operation received one of
   the following errors: NFS4ERR_STALE_CLIENTID, NFS4ERR_STALE_STATEID,
   NFS4ERR_BAD_STATEID, NFS4ERR_BAD_SEQID, NFS4ERR_BADXDR,
   NFS4ERR_RESOURCE, NFS4ERR_NOFILEHANDLE.
"

So if you don't poll your results, you don't know what seqid you should
be sending.

As a side issue, how could the server ever know if the client ever sent
another lock request before querying the results from a previous reply?

I do believe that there is one implementation that sends multiple lock
requests out at a time.  The onus is then on the client to figure out
which requests were ok and which got bad seqid (in the case the packets
got received out of order), and then replay the necessary requests.

eric

---

From: David Robinson <[email-masked]>
Date: Fri, 29 Aug 2003 12:09:30 -0500

> issuing a subsequent locking request on behalf of this lockowner?

The sequence numbers provide at-most-once semantics, in this context
and outstanding request is an RPC that the client has sent but has
not received an RPC reply. It is illegal to send a new RPC with a
new sequence number until the reply of the previous RPC has
been received.

The server should keep track of the last seqid that it has
seen (N) and responded to. If it see's N again it is an
indication that its reply has been lost and this is
a retransmit.  If it see's a value < N, then this is a
replayed request that got lost in the ether and should
be dropped. If it see's N+1 it is simply a new request
and updates the last seen to be N+1.  If it see's a value
greater than N+1 the client is broken as it MUST NOT send
N+2 until it has seen the reply to N+1 which the server has
not yet seen or sent.

Most of this is useful when working over unreliable transports
(e.g. UDP). Except in the case of connections being dropped,
it is mostly unneeded. If someone wants to mandate reliable
transports I would gladly rip the seqid out in a future version.

	-David