Coda File System

Re: corruption question?

From: Jan Harkes <jaharkes_at_cs.cmu.edu>
Date: Tue, 8 Jul 2003 12:41:32 -0400
On Tue, Jul 08, 2003 at 05:11:43PM +0100, lou wrote:
> In some email I received from Jan Harkes <jaharkes_at_cs.cmu.edu> on Tue, 8 Jul 2003 11:39:45 -0400, wrote:
> > On Tue, Jul 08, 2003 at 03:27:41PM +0100, lou wrote:
> [...]
> > AFS3 concurrent O_RDWR scenario
> > 
> >     client2
> > 	foo = open('foo', O_RDWR);
> > 	write(foo, "a");
> > 
> >     client1
> > 	foo = open('foo', O_RDWR);
> > 	write(foo, "test");
> > 	close(foo);
> > 	/* foo now contains "test" */
> > 
> >     client2
> > 	close(foo);
> > 	/* surprise! foo now contains "t" */
> 
> You mean 'a' not 't' right?

No, I'm serious. The way AFS3 implemented partial file fetches, client 2
fetches 'test' into memory as soon as it receives the callback from the
server. It then writes out 'test', but with an i_size of 1 (i.e. the
size of whatever it had written itself earlier. So the file ends up with
't', which is surprisingly different from what either client has
actually written to the file.

It works fine when the client opens the file O_WRONLY, probably because
the partial file fetch logic isn't triggered.

> > I actually like it that Coda gives me a conflict in these situations, at
> > least I get to keep both pieces.
> 
> That's good enough, but wont it be more sensible instead of taking a
> whole volume into a disconnect write mode to happen something like:

Well, the solution would probably be the 'application specific
resolvers', or 'Coda-sidekick'. It hasn't been seriously used, but the
idea is that whenever the client hits a conflict it notifies a helper
process which is given a chance to resolve the conflict before we return
a failure to the user.

The sidekick could (should) be taught to do things like,

    case $file in
    # object files can be rebuilt
    *.o) removeinc $file
	 make $file
	 ;;

    # C files can be merged successfully most of the time
    *.c) cfs br $file
         merge $file/local $file/global /tmp/merged
	 cfs er $file
	 removeinc $file
	 cp /tmp/merged $file
	 ;;

    # important files, try to keep both pieces
    important/*)
         cfs br $file
         cp $file/local /tmp/local_copy
         cp $file/global /tmp/global_copy
	 cfs er $file
	 removeinc $file
	 cp /tmp/global_copy $file
	 cp /tmp/local_copy $file@`hostname`
         ;;

    # all other files simply get last_writer_wins semantics
    *)   cfs br $file
         cp $file/local /tmp/last_writer_wins
	 cfs er $file
	 removeinc $file
	 cp /tmp/last_writer_wins $file
         ;;
    esac

Jan
Received on 2003-07-08 12:43:25