[OpenAFS-devel] Potential write-consistency race

David Howells dhowells@redhat.com
Fri, 04 Oct 2002 17:11:21 +0100


Hi,

In discussing the relative merits of Coda and AFS, I have come across a race
in AFS between writes (you may or may not be aware of it).

The problem is due to the fact that StoreData() takes an unconditional
argument that specifies the "new" file size. For example, the race occurs in
the following situation:

	CLIENT-A		CLIENT-B
	==>FetchStatus
	<== { EOF=x }
				==>FetchStatus
				<== { EOF=x }
	==>StoreStatus(EOF=y)
				==>StoreStatus(EOF=z)
				[receive callback]
	<== { EOF=? }
	[receive callback]
				<== { EOF=? }

So client A may have its data arbitrarily truncated by client B.

Furthermore, a similar problem occurs if the client tries to "append" to a
file. The point at which it appends may no longer be the end of the file.


What I propose, though it may not be possible to implement for standardisation
reasons, is two additional afsint.xg operations:

	InsertData(
	  IN  AFSFid *Fid, 
	  AFSStoreStatus *InStatus, 
	  afs_int32 Pos, 
	  afs_int32 Length, 
	  OUT AFSFetchStatus *OutStatus, 
	  AFSVolSync *Sync
	) split = ?;

Which would insert data at the given position in the file without any explicit
reference to the new EOF position. The file would be extended automatically if
the new data overlapped the old EOF position.

And also:

	AppendData(
	  IN  AFSFid *Fid, 
	  AFSStoreStatus *InStatus, 
	  afs_int32 Length, 
	  OUT AFSFetchStatus *OutStatus, 
	  AFSVolSync *Sync
	) split = ?;

Which would append the data to the current EOF as held on the server, without
any explicit reference to the old or new EOF positions. The position at which
the append occurs can be calculated by subtracting the length appended from
the new EOF position as returned in OutStatus.

I think these should be very easy to add to the fileservers (they just have to
overload the StoreData() operatiosn), and a little harder to add to the
client.

If the client tries the operations and they fail to work, they can just fall
back to invoking StoreData() is they do currently.

What do you think?

David