Subject: LINK and RENAME issues

From: Mike Eisler <[email-masked]>
Date: Thu, 4 Nov 1999 19:53:35 -0800 (PST)

The arguments to the LINK and RENAME operations both contain a pair of
fields like:

	   nfs_fh4         dir;
           component4      newname;

The field 'dir' is the file handle of the target directory. The file
handle of the source directory, or if the case of LINK, the source
file, is passed to LINK and RENAME via a previous PUT*, RESTOREFH,
LOOKUP, LOOKUPP, or OPEN (and any other operation I've overlooked at
places a file handle into the compound operation stream).

This makes target directories second class citizens.

Consider that a client can do:

	COMPOUND { putrootfh  ; lookup "a" "b" "c" ; link dir "d" },

but in order to get 'dir', the client must incur a previous round trip of:

	COMPOUND { putrootfh ; lookup "a1" "b2" "c3" ; getfh }

Considering the WG's charter, to improve performance over the internet,
this shouldn't stand.

Three approaches occur to me:

	1. add variants of PUTFH, PUTROOTFH, PUTPUBFH that inject
		the fh into 'dir' argument of the next
		LINK/RENAME operation in the compound stream.

	2. add a variant of RESTOREFH, called say RESTOREFH_TARG, that
		injects any saved fh into the 'dir' argument of
		the next LINK/RENAME in the compound stream. The 'dir'
		argument of LINK/RENAME would be deleted. RESTOREFH_TARG
		extracts the fh from the same place RESTOREFH does. I'm
		assuming that one can RESTOREFH or RESTOREFH_TARG from
		SAVEFH "register" repeatably.

			Operation XX: RESTOREFH_TARG

			SYNOPSIS
				(sfh) -> (target_cfh)

			ARGUMENT
				 /* SAVED_FH: */
				void;

			Operation 26: RENAME 

	SYNOPSIS

			(cfh), oldname, (target_cfh), newname ->
				source_change_info, target_change_info

			ARGUMENT

			struct RENAME4args {
			     /* CURRENT_FH: source directory */
			     component4       oldname;
			     /* CURRENT_TARG_FH: target directory */
			     component4       newname;
			};

		LINK's changes are an exercise for the editor. :-)
		E.g.

		COMPOUND {
			putrootfh ;  lookup "a1" "b2" "c3" ; savefh ;
		
			putrootfh  ; lookup "a" "b" "c" ; restorefh_targ ;

			rename "d" "d4" ;

			getattr fh mtime ;# gets fh and attributes of src dir.
			restorefh ;	 # injects fh of target directory again 
			getattr fh mtime ;# gets fh and attributes of targ dir.
		}

	3. make the 'dir' field of LINK/RENAME arguments a discriminated
		union:

		union switch (int fhtype) {
		case 0:	/* root */
			void;
		case 1: /* public */
			void;
		case 2: 
			nfs4_fh dir;
		}

		and then change newname from a component4 to pathname4.

Approach number 2 seems like the least impact on the protocol, and
arguably simplifies it.

---

From: Brent <[email-masked]>
Date: Thu, 04 Nov 1999 20:44:47 -0800

> This makes target directories second class citizens.

I agree, that does seem like a wart.

I'd like to propose a simpler option.  Instead of adding
a new operation, why not just define the second LINK/RENAME
filehandle as the saved filehandle ?

So you get:

	SYNOPSIS
		(cfh), oldname, (savefh), newname -> source_change_info

or

     struct RENAME4args {
             /* CURRENT_FH: source directory */
             component4       oldname;
             /* SAVED_FH: target directory */
             component4       newname;
     };

It all works the same as "restorefh_targ" but without a new op.

	Brent

---

From: Mike Eisler <[email-masked]>
Date: Thu, 4 Nov 1999 21:24:44 -0800 (PST)

> filehandle as the saved filehandle ?

OK.

	-mre