Subject: Error for invalid op numbers in compound?

From: "Noveck, Dave" <[email-masked]>
Date: Thu, 2 Sep 1999 08:55:26 -0700

What is the right thing to return if you find an
invalid op number (0, 1, or too high) while executing
the ops for a compound?  To make things concrete,
suppose you a have a request that consists of the 
following 32-bit words:

	0,			/* We don't need no stinking tag */
	2,			/* op count */
	OP_PUTROOTFH,	/* First op */
	1000,			/* the op which ain't */

What does the response look like?

      NFS_OK,		/* Is this right?  Is this word
				   for global errors that happen
				   before any ops are processed 
				   or should it be an error in
				   this case. */
      0,			/* Still no tag. */
      2,			/* Count of result entries.  Maybe
				   this should be one? */
	OP_PUTROOTFH,	/* Discriminant for big union */
	NFS_OK,		/* This one worked. */
	1000,			/* This isn't valid for the discriminated
				   union but it seems like it should be
				   there if anything is. */
      ???			/* What error goes here?  INVAL?  The
				   spec says this is an invalid argument
				   for an operation and we don't even have
				   an operation.  My guess is we need a 
				   separate error code for this. */

---

From: Mike Eisler <[email-masked]>
Date: Thu, 2 Sep 1999 09:19:49 -0700 (PDT)

> 				   or should it be an error in

It should be an error. It is always equal to the status value of the
last operation the server executed.

>       2,			/* Count of result entries.  Maybe

no, 2 is correct.

> 				   separate error code for this. */

I was having similar thoughts last night while hacking on GETATTR (my
client supports GETATTR, and my server doesn't, and I wanted to
see what would happen when the client attempted the GETATTR).

In the next draft spec, the compound results will be:

struct COMPOUND4res {
        nfsstat4 status;
        utf8string      tag;
        resultdata      data<>;
} res;

where data is an array of:

union resultdata switch (unsigned resop){
 case OP_ACCESS:        ACCESS4res op;
 ...
 case OP_WRITE:         WRITE4res opwrite;
};

Given the above structure, there's no way for the server to put an error
in data[3], because that's operation 1000, and the server has no idea
what it looks like.

I propose that a new pseudo op, called ILLEGAL, be created, such that it has
void arguments, an opcode value of 33 (or where ever Spencer decides to place
it) and has this result:

	struct ILLEGAL4res {
		nfsstat4 status; /* always set to NFS4ERR_INVAL */
	};

So the results of your example request would be:

      NFS4ERR_INVAL
      0,			/* Still no tag. */
      2,			/* Count of result entries. */
      OP_PUTROOTFH,	/* Discriminant for big union */
      NFS4_OK,		/* This one worked. */
      OP_ILLEGAL,
      NFS4ERR_INVAL

A client MAY send an ILLEGAL. A server MUST support ILLEGAL by always
returning NFS4ERR_INVAL in response to an ILLEGAL or any operation not in the
the opcode enum.

Another thought I had was what to do about zero-length COMPOUND requests. I've
coded by server to support them by returning a zero length resultdata array,
with a status fo NFS4_OK.

	-mre