Subject: issue11 - CB_GETATTR/change attribute

From: Mike Eisler <[email-masked]>
Date: Thu, 29 Aug 2002 13:00:24 -0700

Issue11: 
The original post for this issue starts here 

    At least two places in the specification say a write
    delegation can modify its cached copy of the "change"
    attribute:
    
       The server will use a CB_GETATTR callback, if the GETATTR attribute
       bits include any of the attributes that a write open delegate may
       modify (size, time_modify, change).
    
    AND:
    
    	    The client returns attrbits and the associated attribute values
    	    only for attributes that it may change (change, time_modify, size).

    How is this possible? The client has no idea how the server is
    constructing the change attribute.

confirm that text added for latest draft is sufficient

--------------------------

I've read the entire specification, and there is still one
issue, in 9.4.3.  Handling of CB_GETATTR:

   For the server, the following steps will be taken when providing a
   write delegation:

   o    On providing a write delegation, the server will cache a copy of
        the change attribute.  Let this value be represented by sc.

   o    The server obtains the change attribute from the client.  Let
        this value be cc.

   o    If the value cc is equal to sc, the file is not modified and the
        server returns the current values for change and time_modify
        (for example) to the client requesting GETATTR.

   o    If the value cc is NOT equal to sc, the file is currently
        modified at the client and most likely will be modified at the
        server at a future time.  The server then uses the current time
        to construct attributes values for change and time_modify and
        returns those values to the requestor.

The last bullet item above has a serious problem because
the fragment: "uses the current time to construct
attributes values for change and time_modify" apparently
assumes that the change attribute will be derived from
time_modify. Not at all. The ideal server implementation
uses a unsigned integer that is incremented on each data
change and metadata change (except those metadata changes
that alter time_access an no other metadata). Also, the
server cannot construct change from a high resolution time_modify
even if it wanted to; it has to used time_metadata if it is going
to use any time-based atrribute.

Suggested text follows:

CHANGE:

   While the change attribute is opaque to client in the sense that it
   has no idea what units of time, if any, the server is counting change
   with, it is not opaque in that the client has to treat it as an
   integer, and the server has to be able to see the results of the
   client's changes to that integer. Therefore, the server MUST encode
   the change attribute in network order when sending it to the client,
   the client MUST decode it from network order to its native order when
   receiving it, and the client MUST encode it network order when
   sending it to the server. For this reason, change is defined as an
   integer, rather than an opaque array of octets.

   For the server, the following steps will be taken when providing a
   write delegation:

   o    On providing a write delegation, the server will cache a copy of
        the change attribute.  Let this value be represented by sc.

   o    The server obtains the change attribute from the client.  Let
        this value be cc.

   o    If the value cc is equal to sc, the file is not modified and the
        server returns the current values for change, time_modify,
        and time_metadata (for example) to the client requesting GETATTR.

   o    If the value cc is NOT equal to sc, the file is currently
        modified at the client and most likely will be modified at the
        server at a future time.  The server then uses the current time
        to construct attributes values for change and time_modify and
        returns those values to the requestor.

TO:

   While the change attribute is opaque to client in the sense that it
   has no idea what units of time, if any, the server is counting change
   with, it is not opaque in that the client has to treat it as an
   integer, and the server has to be able to see the results of the
   client's changes to that integer. Therefore, the server MUST encode
   the change attribute in network order when sending it to the client,
   the client MUST decode it from network order to its native order when
   receiving it, and the client MUST encode it network order when
   sending it to the server. For this reason, change is defined as an
   unsigned integer, rather than an opaque array of octets.

   For the server, the following steps will be taken when providing a
   write delegation:

   o    On providing a write delegation, the server will cache a copy of
        the change attribute.  Let this value be represented by sc.

   o    The server obtains the change attribute from the client.  Let
        this value be cc.

   o    If the value cc is equal to sc, the file is not modified and the
        server returns the current values for change and time_modify
        (for example) to the client requesting GETATTR.

   o    If the value cc is NOT equal to sc, the file is currently
        modified at the client and most likely will be modified at the
        server at a future time.  The server then uses the current time
        to construct attribute values for time_metadata and time_modify.
	It uses cc and sc to construct a provisional value
	for change, which we will represent as pc, such
	that pc is greater than sc, and if cc > sc, pc ==
	sc (not withstanding the following paragraph). The
	server then returns the constructed time_metadata,
	time_modify, and pc values to the requestor.

	Furthermore, in the event of another GETATTR
	of the delegated file, and the client returns
	a cc value that was different than that of
	previous CB_GETATTR, the server must take care
	to ensure that new pc it constructs and returns
	is greater than the previous pc it returned.
	This is not necessarily trivially done if the
	server constructs change from a high resolution
	time_metadata attribute, because the client does
	not know how the server constructs change. It is
	conceivable that the cc value is greater than the
	server's current time.

---

From: Spencer Shepler <[email-masked]>
Date: Thu, 29 Aug 2002 17:46:34 -0500

> 	conceivable that the cc value is greater than the

The only requirement for the management of the change attribute with
CB_GETATTR to work properly is that the client return a value cc that
is sc+1.  At each CB_GETATTR, the client does not have to keep
returning a value for cc that different from the last value returned.
The server only needs to know if unwritten/modified data exists at the
client and from this the server can then represent the appropriate
attributes as suggested above.

Therefore, if we were to restrict what the client returns for a value
of change (e.g. cc in the above notation) to either sc or sc+1, then
that helps the server a little.  The server still needs to manage the
value of pc carefully such that it represents to the third party that
the file is "changing".

Is there an alternate interpretation of how the client should
represent the value cc?  The reason it had been suggested that it be
one value or the other (sc or sc+1) is that this eases the client's
implementation of checking for modified data in its cache.

-- 
Spencer

---

From: Mike Eisler <[email-masked]>
Date: Thu, 29 Aug 2002 15:04:52 -0700

> returning a value for cc that different from the last value returned.

What if the client changes the file on its end a second time? Why wouldn't that be interesting
to other clients? Put differently, if we feel that's not interesting, then why is
the first change in the clients modified cache interesting?

	-mre

---

From: Spencer Shepler <[email-masked]>
Date: Thu, 29 Aug 2002 18:32:29 -0500

> the first change in the clients modified cache interesting?

We were trying to avoid the issue of what "modified" meant and how
strictly the client would need to bookkeep to meet the requirement of
telling the server if the file data had been modified since the last
time CB_GETATTR was used.

The most aggravating case is that of a memory mapped file.  An
application that continually overwrites a page(s) such that the
traditional NFS client is unable to determine if the application has
modified the file pages since the last time it checked.  Because of
this and other scenarios, we provided the suggested mechanism to avoid
imposing extreme overhead on the client.  Otherwise, the client may
have to scan page lists on each CB_GETATTR to determine if modified
pages were different than the list time around.

This is all based on the premise that if a second client is asking for
attributes and is going to act on a modified file that the action is
going to be to OPEN the file which will recall the delegation.

Also, the proposed mechanism is no worse than if the client did not
hold a delegation and was holding modified file data in its cache.  In
this case, the server has no method of determining if modified data
exists and will respond with the information that exists at the
server.

In summary, it seems most important to allow the client to signify to
the server that the file has been modified such that a second client
can tell if a modification has occurred and and can decide to take
action based on that modification.  It is less important or maybe not
important at all to tell the server that additional modifications have
been made since the last CB_GETATTR.  The proposed approach takes the
conservative view in representing the file as having been modified at
each CB_GETATTR.

-- 
Spencer