Subject: Re: Re: [nfsv4] Locking Semantics

From: [email-masked]
Date: Wed, 16 Mar 2005 17:13:26 -0500 (EST)

I think I know what you meant, but to me, it didn't read that way. I've
added assumptions. If my assumptions aren't correct, please correct them.
As I read Sec. 8.1.4, I think the second last sentence on pg. 71 clarifies
mandatory record locks as:
	Mandatory record locks, however, prevent conflicting I/O operations.

> Any READ or WRITE operation will succeed if there is no
> record lock held by anyone.
Makes sense to me, since no lock --> no conflict

> A WRITE operation can only succeed if the stateid in that
> operation is the result of a lock_owner having acquired
> an exclusive record lock.
I suspect you meant "assuming a write lock exists for that byte range on
the file"? In that case, I can see any write that doesn't use the lock
stateid as "conflicting"?

This can get interesting when delegations are involved. For example:
Client A Opens "foo" for writing, gets an OpenStateid_foo1, but no
	delegation, since some other client has "foo" open.
Client A Write locks a byte range on "foo" using OpenStateid_foo1 in an
	open_to_lock_owner, gets LockStateid_foo
Client A Opens "foo" for writing using a different open_owner. This time
	the server issues a write open delegation to ClientA, since the
	the other client has closed its open of "foo".
	--> gets OpenStateid_foo2 and DelegStateid_foo

Now, ClientA has 4 Stateids for "foo" (2 opens, 1 lock and 1 write
	delegation). Which of these can be used by ClientA to write "foo"?
- I'd say the DelegStateid_foo could be used for any/all writing,
  since the write delegation allows the client to issue write locks locally?
- The LockStateid_foo could be used, but only for writes within the byte range
  of the lock?
- The OpenStateid_foo[12] could be used, but only for byte ranges not locked?

> A READ operation can only succeed if the stateid in that
> operation is the result of a lock_owner having acquired
> an exclusive or a shared record lock.
Isn't a read op allowed unless there is a conflicting Write lock?
In the 3rd para on pg. 72:
	If there is no appropriate lock, the server checks if there is a
	conflicting lock (which can be done by attempting to to acquire
	the conflicting lock on the behalf of the lockowner, and if
	successful, release the lock after the READ or WRITE is done),...

To me, this says that "if the client could get a read lock, then the
read would be allowed". Getting a read lock would only fail if there
was a conflicting write lock.

> It is a two phase process, the LOCK operations govern which
> locks you can acquire, shared or exclusive, and hand back
> a stateid. That stateid is used to communicate on the I/O
> request which locks have been acquired and the server allows
> or denies based on that state.

The only place that I can find where a read or write lock is required
for the I/O to be allowed is w.r.t. client side caching in Sec. 9.3.3.
(It might be prudent for the client to do the above, to avoid any
 risk of NFS4ERR_LOCKED being returned from the read or write ops, but
 I don't see anything in the RFC that requires the lock be held.)

I will also note that I suspect some of the clients currently out there
don't follow the guidelines in Sec. 9.3.3 w.r.t. caching and might break
when a server enforces mandatory locking.

rick
ps: On the Errata side of things, I just noticed that the description
    for Read on pg. 188 doesn't include a delegation stateid as an
    allowable stateid argument. Since a client with a valid write
    delegation for the file may no longer have any other stateid for
    the file and it allows Opens, Locks to be done locally on the client,
    it seems it should be allowed in the args for Read, Write and Setattr?

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

---

From: eric kustarz <[email-masked]>
Date: Wed, 16 Mar 2005 14:41:03 -0800

>- The OpenStateid_foo[12] could be used, but only for byte ranges not locked?

Just as a point of reference, the Solaris client prioritizies the 
stateids in the above mentioned way:
delegation > lock > open > special

(use a delegation stateid first if you have it, then the lock stateid 
second if you have it, then the open stateid third if you have it, 
lastly just use special stateid)

eric

---

From: Spencer Shepler <[email-masked]>
Date: Wed, 16 Mar 2005 15:24:50 -0800

> - The LockStateid_foo could be used, but only for writes within the byte range

The client can use the lockstateid for any write on the file since it
represents its file locking state after the lock operation was completed.
The lockstateid isn't mean to represent a specific range but the state
of the file locks on the file.  

As an example of this, the client, having done two LOCK operations
for a file for disjoint ranges doesn't not have two valid lockstateids.
It has one valid lockstateid.

> - The OpenStateid_foo[12] could be used, but only for byte ranges not locked?

The openstateid can be used but the prefered stateid is the lockstateid;
as you point out however, if the client has a delegation for the file
a delegation stateid can also be used.

>     it seems it should be allowed in the args for Read, Write and Setattr?

Yes.  It should.  I will add this to the list.

Spencer

---

From: David Robinson <[email-masked]>
Date: Wed, 16 Mar 2005 18:54 -0600

...... Original Message .......
On Wed, 16 Mar 2005 17:13:26 -0500 (EST) <[email-masked]> 

>stateid as "conflicting"?

My wording was poor, earlier drafts talked about 'implicit' locks but that 
was causing confusion so we removed those words. The intended effect is to 
act as if before a READ a shared LOCK was acquired, if that lock wouls fail 
then the READ MUST fail. Likewise for a WRITE it would act as if an 
exclusive lock were acquired. 

When no lock for the range is held, or the caller is the one holding the 
lock, then there can be no conflict. The early confusion was if the LOCK 
should actually be acquired with the implication that an actual LOCK 
request would be impacted, it shouldn't. 

>This can get interesting when delegations are involved. For example:

Stateids are only used to communicate the current state, so as Eric 
described there is a hierarchy between the types, but for any one type 
there is just one valid stateid. Regardless of the number of byte range 
locks, there is only one valid stateid, that of the last lock request.

	-David