Tech-invite3GPPspaceIETFspace
959493929190898887868584838281807978777675747372717069686766656463626160595857565554535251504948474645444342414039383736353433323130292827262524232221201918171615141312111009080706050403020100
in Index   Prev   Next

RFC 3530

Network File System (NFS) version 4 Protocol

Pages: 275
Obsoletes:  3010
Obsoleted by:  7530
Part 6 of 8 – Pages 134 to 179
First   Prev   Next

ToP   noToC   RFC3530 - Page 134   prevText

13. NFS version 4 Requests

For the NFS version 4 RPC program, there are two traditional RPC procedures: NULL and COMPOUND. All other functionality is defined as a set of operations and these operations are defined in normal XDR/RPC syntax and semantics. However, these operations are encapsulated within the COMPOUND procedure. This requires that the client combine one or more of the NFS version 4 operations into a single request. The NFS4_CALLBACK program is used to provide server to client signaling and is constructed in a similar fashion as the NFS version 4 program. The procedures CB_NULL and CB_COMPOUND are defined in the same way as NULL and COMPOUND are within the NFS program. The CB_COMPOUND request also encapsulates the remaining operations of the NFS4_CALLBACK program. There is no predefined RPC program number for the NFS4_CALLBACK program. It is up to the client to specify a program number in the "transient" program range. The program and port number of the NFS4_CALLBACK program are provided by the client as part of the SETCLIENTID/SETCLIENTID_CONFIRM sequence. The program and port can be changed by another SETCLIENTID/SETCLIENTID_CONFIRM sequence, and it is possible to use the sequence to change them within a client incarnation without removing relevant leased client state.

13.1. Compound Procedure

The COMPOUND procedure provides the opportunity for better performance within high latency networks. The client can avoid cumulative latency of multiple RPCs by combining multiple dependent operations into a single COMPOUND procedure. A compound operation may provide for protocol simplification by allowing the client to combine basic procedures into a single request that is customized for the client's environment. The CB_COMPOUND procedure precisely parallels the features of COMPOUND as described above. The basic structure of the COMPOUND procedure is: +-----+--------------+--------+-----------+-----------+-----------+-- | tag | minorversion | numops | op + args | op + args | op + args | +-----+--------------+--------+-----------+-----------+-----------+--
ToP   noToC   RFC3530 - Page 135
   and the reply's structure is:

      +------------+-----+--------+-----------------------+--
      |last status | tag | numres | status + op + results |
      +------------+-----+--------+-----------------------+--

   The numops and numres fields, used in the depiction above, represent
   the count for the counted array encoding use to signify the number of
   arguments or results encoded in the request and response.  As per the
   XDR encoding, these counts must match exactly the number of operation
   arguments or results encoded.

13.2. Evaluation of a Compound Request

The server will process the COMPOUND procedure by evaluating each of the operations within the COMPOUND procedure in order. Each component operation consists of a 32 bit operation code, followed by the argument of length determined by the type of operation. The results of each operation are encoded in sequence into a reply buffer. The results of each operation are preceded by the opcode and a status code (normally zero). If an operation results in a non-zero status code, the status will be encoded and evaluation of the compound sequence will halt and the reply will be returned. Note that evaluation stops even in the event of "non error" conditions such as NFS4ERR_SAME. There are no atomicity requirements for the operations contained within the COMPOUND procedure. The operations being evaluated as part of a COMPOUND request may be evaluated simultaneously with other COMPOUND requests that the server receives. It is the client's responsibility for recovering from any partially completed COMPOUND procedure. Partially completed COMPOUND procedures may occur at any point due to errors such as NFS4ERR_RESOURCE and NFS4ERR_DELAY. This may occur even given an otherwise valid operation string. Further, a server reboot which occurs in the middle of processing a COMPOUND procedure may leave the client with the difficult task of determining how far COMPOUND processing has proceeded. Therefore, the client should avoid overly complex COMPOUND procedures in the event of the failure of an operation within the procedure. Each operation assumes a "current" and "saved" filehandle that is available as part of the execution context of the compound request. Operations may set, change, or return the current filehandle. The "saved" filehandle is used for temporary storage of a filehandle value and as operands for the RENAME and LINK operations.
ToP   noToC   RFC3530 - Page 136

13.3. Synchronous Modifying Operations

NFS version 4 operations that modify the filesystem are synchronous. When an operation is successfully completed at the server, the client can depend that any data associated with the request is now on stable storage (the one exception is in the case of the file data in a WRITE operation with the UNSTABLE option specified). This implies that any previous operations within the same compound request are also reflected in stable storage. This behavior enables the client's ability to recover from a partially executed compound request which may resulted from the failure of the server. For example, if a compound request contains operations A and B and the server is unable to send a response to the client, depending on the progress the server made in servicing the request the result of both operations may be reflected in stable storage or just operation A may be reflected. The server must not have just the results of operation B in stable storage.

13.4. Operation Values

The operations encoded in the COMPOUND procedure are identified by operation values. To avoid overlap with the RPC procedure numbers, operations 0 (zero) and 1 are not defined. Operation 2 is not defined but reserved for future use with minor versioning.

14. NFS version 4 Procedures

14.1. Procedure 0: NULL - No Operation

SYNOPSIS <null> ARGUMENT void; RESULT void;
ToP   noToC   RFC3530 - Page 137
   DESCRIPTION

      Standard NULL procedure.  Void argument, void response.  This
      procedure has no functionality associated with it.  Because of
      this it is sometimes used to measure the overhead of processing a
      service request.  Therefore, the server should ensure that no
      unnecessary work is done in servicing this procedure.

   ERRORS

      None.

14.2. Procedure 1: COMPOUND - Compound Operations

SYNOPSIS compoundargs -> compoundres ARGUMENT union nfs_argop4 switch (nfs_opnum4 argop) { case <OPCODE>: <argument>; ... }; struct COMPOUND4args { utf8str_cs tag; uint32_t minorversion; nfs_argop4 argarray<>; }; RESULT union nfs_resop4 switch (nfs_opnum4 resop){ case <OPCODE>: <result>; ... }; struct COMPOUND4res { nfsstat4 status; utf8str_cs tag; nfs_resop4 resarray<>; };
ToP   noToC   RFC3530 - Page 138
   DESCRIPTION

   The COMPOUND procedure is used to combine one or more of the NFS
   operations into a single RPC request.  The main NFS RPC program has
   two main procedures: NULL and COMPOUND.  All other operations use the
   COMPOUND procedure as a wrapper.

   The COMPOUND procedure is used to combine individual operations into
   a single RPC request.  The server interprets each of the operations
   in turn.  If an operation is executed by the server and the status of
   that operation is NFS4_OK, then the next operation in the COMPOUND
   procedure is executed.  The server continues this process until there
   are no more operations to be executed or one of the operations has a
   status value other than NFS4_OK.

   In the processing of the COMPOUND procedure, the server may find that
   it does not have the available resources to execute any or all of the
   operations within the COMPOUND sequence.  In this case, the error
   NFS4ERR_RESOURCE will be returned for the particular operation within
   the COMPOUND procedure where the resource exhaustion occurred.  This
   assumes that all previous operations within the COMPOUND sequence
   have been evaluated successfully.  The results for all of the
   evaluated operations must be returned to the client.

   The server will generally choose between two methods of decoding the
   client's request.  The first would be the traditional one-pass XDR
   decode, in which decoding of the entire COMPOUND precedes execution
   of any operation within it.  If there is an XDR decoding error in
   this case, an RPC XDR decode error would be returned.  The second
   method would be to make an initial pass to decode the basic COMPOUND
   request and then to XDR decode each of the individual operations, as
   the server is ready to execute it.  In this case, the server may
   encounter an XDR decode error during such an operation decode, after
   previous operations within the COMPOUND have been executed.  In this
   case, the server would return the error NFS4ERR_BADXDR to signify the
   decode error.

   The COMPOUND arguments contain a "minorversion" field.  The initial
   and default value for this field is 0 (zero).  This field will be
   used by future minor versions such that the client can communicate to
   the server what minor version is being requested.  If the server
   receives a COMPOUND procedure with a minorversion field value that it
   does not support, the server MUST return an error of
   NFS4ERR_MINOR_VERS_MISMATCH and a zero length resultdata array.

   Contained within the COMPOUND results is a "status" field.  If the
   results array length is non-zero, this status must be equivalent to
   the status of the last operation that was executed within the
ToP   noToC   RFC3530 - Page 139
   COMPOUND procedure.  Therefore, if an operation incurred an error
   then the "status" value will be the same error value as is being
   returned for the operation that failed.

   Note that operations, 0 (zero) and 1 (one) are not defined for the
   COMPOUND procedure.  Operation 2 is not defined but reserved for
   future definition and use with minor versioning.  If the server
   receives a operation array that contains operation 2 and the
   minorversion field has a value of 0 (zero), an error of
   NFS4ERR_OP_ILLEGAL, as described in the next paragraph, is returned
   to the client.  If an operation array contains an operation 2 and the
   minorversion field is non-zero and the server does not support the
   minor version, the server returns an error of
   NFS4ERR_MINOR_VERS_MISMATCH.  Therefore, the
   NFS4ERR_MINOR_VERS_MISMATCH error takes precedence over all other
   errors.

   It is possible that the server receives a request that contains an
   operation that is less than the first legal operation (OP_ACCESS) or
   greater than the last legal operation (OP_RELEASE_LOCKOWNER).

   In this case, the server's response will encode the opcode OP_ILLEGAL
   rather than the illegal opcode of the request. The status field in
   the ILLEGAL return results will set to NFS4ERR_OP_ILLEGAL.  The
   COMPOUND procedure's return results will also be NFS4ERR_OP_ILLEGAL.

   The definition of the "tag" in the request is left to the
   implementor.  It may be used to summarize the content of the compound
   request for the benefit of packet sniffers and engineers debugging
   implementations.  However, the value of "tag" in the response SHOULD
   be the same value as provided in the request.  This applies to the
   tag field of the CB_COMPOUND procedure as well.

   IMPLEMENTATION

   Since an error of any type may occur after only a portion of the
   operations have been evaluated, the client must be prepared to
   recover from any failure.  If the source of an NFS4ERR_RESOURCE error
   was a complex or lengthy set of operations, it is likely that if the
   number of operations were reduced the server would be able to
   evaluate them successfully.  Therefore, the client is responsible for
   dealing with this type of complexity in recovery.

   ERRORS

   All errors defined in the protocol
ToP   noToC   RFC3530 - Page 140

14.2.1. Operation 3: ACCESS - Check Access Rights

SYNOPSIS (cfh), accessreq -> supported, accessrights ARGUMENT const ACCESS4_READ = 0x00000001; const ACCESS4_LOOKUP = 0x00000002; const ACCESS4_MODIFY = 0x00000004; const ACCESS4_EXTEND = 0x00000008; const ACCESS4_DELETE = 0x00000010; const ACCESS4_EXECUTE = 0x00000020; struct ACCESS4args { /* CURRENT_FH: object */ uint32_t access; }; RESULT struct ACCESS4resok { uint32_t supported; uint32_t access; }; union ACCESS4res switch (nfsstat4 status) { case NFS4_OK: ACCESS4resok resok4; default: void; }; DESCRIPTION ACCESS determines the access rights that a user, as identified by the credentials in the RPC request, has with respect to the file system object specified by the current filehandle. The client encodes the set of access rights that are to be checked in the bit mask "access". The server checks the permissions encoded in the bit mask. If a status of NFS4_OK is returned, two bit masks are included in the response. The first, "supported", represents the access rights for which the server can verify reliably. The second, "access", represents the access rights available to the user for the filehandle provided. On success, the current filehandle retains its value.
ToP   noToC   RFC3530 - Page 141
   Note that the supported field will contain only as many values as
   were originally sent in the arguments.  For example, if the client
   sends an ACCESS operation with only the ACCESS4_READ value set and
   the server supports this value, the server will return only
   ACCESS4_READ even if it could have reliably checked other values.

   The results of this operation are necessarily advisory in nature.  A
   return status of NFS4_OK and the appropriate bit set in the bit mask
   does not imply that such access will be allowed to the file system
   object in the future. This is because access rights can be revoked by
   the server at any time.

   The following access permissions may be requested:

   ACCESS4_READ    Read data from file or read a directory.

   ACCESS4_LOOKUP  Look up a name in a directory (no meaning for non-
                   directory objects).

   ACCESS4_MODIFY  Rewrite existing file data or modify existing
                   directory entries.

   ACCESS4_EXTEND  Write new data or add directory entries.

   ACCESS4_DELETE  Delete an existing directory entry.

   ACCESS4_EXECUTE Execute file (no meaning for a directory).

   On success, the current filehandle retains its value.

   IMPLEMENTATION

   In general, it is not sufficient for the client to attempt to deduce
   access permissions by inspecting the uid, gid, and mode fields in the
   file attributes or by attempting to interpret the contents of the ACL
   attribute.  This is because the server may perform uid or gid mapping
   or enforce additional access control restrictions.  It is also
   possible that the server may not be in the same ID space as the
   client.  In these cases (and perhaps others), the client can not
   reliably perform an access check with only current file attributes.

   In the NFS version 2 protocol, the only reliable way to determine
   whether an operation was allowed was to try it and see if it
   succeeded or failed.  Using the ACCESS operation in the NFS version 4
   protocol, the client can ask the server to indicate whether or not
   one or more classes of operations are permitted.  The ACCESS
   operation is provided to allow clients to check before doing a series
   of operations which will result in an access failure.  The OPEN
ToP   noToC   RFC3530 - Page 142
   operation provides a point where the server can verify access to the
   file object and method to return that information to the client.  The
   ACCESS operation is still useful for directory operations or for use
   in the case the UNIX API "access" is used on the client.

   The information returned by the server in response to an ACCESS call
   is not permanent.  It was correct at the exact time that the server
   performed the checks, but not necessarily afterwards.  The server can
   revoke access permission at any time.

   The client should use the effective credentials of the user to build
   the authentication information in the ACCESS request used to
   determine access rights.  It is the effective user and group
   credentials that are used in subsequent read and write operations.

   Many implementations do not directly support the ACCESS4_DELETE
   permission.  Operating systems like UNIX will ignore the
   ACCESS4_DELETE bit if set on an access request on a non-directory
   object.  In these systems, delete permission on a file is determined
   by the access permissions on the directory in which the file resides,
   instead of being determined by the permissions of the file itself.
   Therefore, the mask returned enumerating which access rights can be
   determined will have the ACCESS4_DELETE value set to 0.  This
   indicates to the client that the server was unable to check that
   particular access right.  The ACCESS4_DELETE bit in the access mask
   returned will then be ignored by the client.

   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_BADHANDLE
      NFS4ERR_BADXDR
      NFS4ERR_DELAY
      NFS4ERR_FHEXPIRED
      NFS4ERR_INVAL
      NFS4ERR_IO
      NFS4ERR_MOVED
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_RESOURCE
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE

14.2.2. Operation 4: CLOSE - Close File

SYNOPSIS (cfh), seqid, open_stateid -> open_stateid
ToP   noToC   RFC3530 - Page 143
   ARGUMENT

     struct CLOSE4args {
             /* CURRENT_FH: object */
             seqid4          seqid
             stateid4        open_stateid;
     };

   RESULT

     union CLOSE4res switch (nfsstat4 status) {
      case NFS4_OK:
              stateid4       open_stateid;
      default:
              void;
     };

   DESCRIPTION

   The CLOSE operation releases share reservations for the regular or
   named attribute file as specified by the current filehandle.  The
   share reservations and other state information released at the server
   as a result of this CLOSE is only associated with the supplied
   stateid.  The sequence id provides for the correct ordering. State
   associated with other OPENs is not affected.

   If record locks are held, the client SHOULD release all locks before
   issuing a CLOSE.  The server MAY free all outstanding locks on CLOSE
   but some servers may not support the CLOSE of a file that still has
   record locks held.  The server MUST return failure if any locks would
   exist after the CLOSE.

   On success, the current filehandle retains its value.

   IMPLEMENTATION

   Even though CLOSE returns a stateid, this stateid is not useful to
   the client and should be treated as deprecated.  CLOSE "shuts down"
   the state associated with all OPENs for the file by a single
   open_owner.  As noted above, CLOSE will either release all file
   locking state or return an error.  Therefore, the stateid returned by
   CLOSE is not useful for operations that follow.

   ERRORS

      NFS4ERR_ADMIN_REVOKED
      NFS4ERR_BADHANDLE
      NFS4ERR_BAD_SEQID
ToP   noToC   RFC3530 - Page 144
      NFS4ERR_BAD_STATEID
      NFS4ERR_BADXDR
      NFS4ERR_DELAY
      NFS4ERR_EXPIRED
      NFS4ERR_FHEXPIRED
      NFS4ERR_INVAL
      NFS4ERR_ISDIR
      NFS4ERR_LEASE_MOVED
      NFS4ERR_LOCKS_HELD
      NFS4ERR_MOVED
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_OLD_STATEID
      NFS4ERR_RESOURCE
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE
      NFS4ERR_STALE_STATEID

14.2.3. Operation 5: COMMIT - Commit Cached Data

SYNOPSIS (cfh), offset, count -> verifier ARGUMENT struct COMMIT4args { /* CURRENT_FH: file */ offset4 offset; count4 count; }; RESULT struct COMMIT4resok { verifier4 writeverf; }; union COMMIT4res switch (nfsstat4 status) { case NFS4_OK: COMMIT4resok resok4; default: void; };
ToP   noToC   RFC3530 - Page 145
   DESCRIPTION

   The COMMIT operation forces or flushes data to stable storage for the
   file specified by the current filehandle.  The flushed data is that
   which was previously written with a WRITE operation which had the
   stable field set to UNSTABLE4.

   The offset specifies the position within the file where the flush is
   to begin.  An offset value of 0 (zero) means to flush data starting
   at the beginning of the file.  The count specifies the number of
   bytes of data to flush.  If count is 0 (zero), a flush from offset to
   the end of the file is done.

   The server returns a write verifier upon successful completion of the
   COMMIT.  The write verifier is used by the client to determine if the
   server has restarted or rebooted between the initial WRITE(s) and the
   COMMIT.  The client does this by comparing the write verifier
   returned from the initial writes and the verifier returned by the
   COMMIT operation.  The server must vary the value of the write
   verifier at each server event or instantiation that may lead to a
   loss of uncommitted data.  Most commonly this occurs when the server
   is rebooted; however, other events at the server may result in
   uncommitted data loss as well.

   On success, the current filehandle retains its value.

   IMPLEMENTATION

   The COMMIT operation is similar in operation and semantics to the
   POSIX fsync(2) system call that synchronizes a file's state with the
   disk (file data and metadata is flushed to disk or stable storage).
   COMMIT performs the same operation for a client, flushing any
   unsynchronized data and metadata on the server to the server's disk
   or stable storage for the specified file.  Like fsync(2), it may be
   that there is some modified data or no modified data to synchronize.
   The data may have been synchronized by the server's normal periodic
   buffer synchronization activity.  COMMIT should return NFS4_OK,
   unless there has been an unexpected error.

   COMMIT differs from fsync(2) in that it is possible for the client to
   flush a range of the file (most likely triggered by a buffer-
   reclamation scheme on the client before file has been completely
   written).

   The server implementation of COMMIT is reasonably simple.  If the
   server receives a full file COMMIT request, that is starting at
   offset 0 and count 0, it should do the equivalent of fsync()'ing the
   file.  Otherwise, it should arrange to have the cached data in the
ToP   noToC   RFC3530 - Page 146
   range specified by offset and count to be flushed to stable storage.
   In both cases, any metadata associated with the file must be flushed
   to stable storage before returning.  It is not an error for there to
   be nothing to flush on the server.  This means that the data and
   metadata that needed to be flushed have already been flushed or lost
   during the last server failure.

   The client implementation of COMMIT is a little more complex.  There
   are two reasons for wanting to commit a client buffer to stable
   storage.  The first is that the client wants to reuse a buffer.  In
   this case, the offset and count of the buffer are sent to the server
   in the COMMIT request.  The server then flushes any cached data based
   on the offset and count, and flushes any metadata associated with the
   file.  It then returns the status of the flush and the write
   verifier.  The other reason for the client to generate a COMMIT is
   for a full file flush, such as may be done at close.  In this case,
   the client would gather all of the buffers for this file that contain
   uncommitted data, do the COMMIT operation with an offset of 0 and
   count of 0, and then free all of those buffers.  Any other dirty
   buffers would be sent to the server in the normal fashion.

   After a buffer is written by the client with the stable parameter set
   to UNSTABLE4, the buffer must be considered as modified by the client
   until the buffer has either been flushed via a COMMIT operation or
   written via a WRITE operation with stable parameter set to FILE_SYNC4
   or DATA_SYNC4. This is done to prevent the buffer from being freed
   and reused before the data can be flushed to stable storage on the
   server.

   When a response is returned from either a WRITE or a COMMIT operation
   and it contains a write verifier that is different than previously
   returned by the server, the client will need to retransmit all of the
   buffers containing uncommitted cached data to the server.  How this
   is to be done is up to the implementor.  If there is only one buffer
   of interest, then it should probably be sent back over in a WRITE
   request with the appropriate stable parameter.  If there is more than
   one buffer, it might be worthwhile retransmitting all of the buffers
   in WRITE requests with the stable parameter set to UNSTABLE4 and then
   retransmitting the COMMIT operation to flush all of the data on the
   server to stable storage.  The timing of these retransmissions is
   left to the implementor.

   The above description applies to page-cache-based systems as well as
   buffer-cache-based systems.  In those systems, the virtual memory
   system will need to be modified instead of the buffer cache.
ToP   noToC   RFC3530 - Page 147
   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_BADHANDLE
      NFS4ERR_BADXDR
      NFS4ERR_FHEXPIRED
      NFS4ERR_INVAL
      NFS4ERR_IO
      NFS4ERR_ISDIR
      NFS4ERR_MOVED
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_RESOURCE
      NFS4ERR_ROFS
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE

14.2.4. Operation 6: CREATE - Create a Non-Regular File Object

SYNOPSIS (cfh), name, type, attrs -> (cfh), change_info, attrs_set ARGUMENT union createtype4 switch (nfs_ftype4 type) { case NF4LNK: linktext4 linkdata; case NF4BLK: case NF4CHR: specdata4 devdata; case NF4SOCK: case NF4FIFO: case NF4DIR: void; }; struct CREATE4args { /* CURRENT_FH: directory for creation */ createtype4 objtype; component4 objname; fattr4 createattrs; }; RESULT struct CREATE4resok { change_info4 cinfo; bitmap4 attrset; /* attributes set */
ToP   noToC   RFC3530 - Page 148
     };

     union CREATE4res switch (nfsstat4 status) {
      case NFS4_OK:
              CREATE4resok resok4;
      default:
              void;
     };

   DESCRIPTION

   The CREATE operation creates a non-regular file object in a directory
   with a given name.  The OPEN operation MUST be used to create a
   regular file.

   The objname specifies the name for the new object.  The objtype
   determines the type of object to be created: directory, symlink, etc.

   If an object of the same name already exists in the directory, the
   server will return the error NFS4ERR_EXIST.

   For the directory where the new file object was created, the server
   returns change_info4 information in cinfo.  With the atomic field of
   the change_info4 struct, the server will indicate if the before and
   after change attributes were obtained atomically with respect to the
   file object creation.

   If the objname has a length of 0 (zero), or if objname does not obey
   the UTF-8 definition, the error NFS4ERR_INVAL will be returned.

   The current filehandle is replaced by that of the new object.

   The createattrs specifies the initial set of attributes for the
   object.  The set of attributes may include any writable attribute
   valid for the object type. When the operation is successful, the
   server will return to the client an attribute mask signifying which
   attributes were successfully set for the object.

   If createattrs includes neither the owner attribute nor an ACL with
   an ACE for the owner, and if the server's filesystem both supports
   and requires an owner attribute (or an owner ACE) then the server
   MUST derive the owner (or the owner ACE). This would typically be
   from the principal indicated in the RPC credentials of the call, but
   the server's operating environment or filesystem semantics may
   dictate other methods of derivation. Similarly, if createattrs
   includes neither the group attribute nor a group ACE, and if the
   server's filesystem both supports and requires the notion of a group
   attribute (or group ACE), the server MUST derive the group attribute
ToP   noToC   RFC3530 - Page 149
   (or the corresponding owner ACE) for the file. This could be from the
   RPC call's credentials, such as the group principal if the
   credentials include it (such as with AUTH_SYS), from the group
   identifier associated with the principal in the credentials (for
   e.g., POSIX systems have a passwd database that has the group
   identifier for every user identifier), inherited from directory the
   object is created in, or whatever else the server's operating
   environment or filesystem semantics dictate. This applies to the OPEN
   operation too.

   Conversely, it is possible the client will specify in createattrs an
   owner attribute or group attribute or ACL that the principal
   indicated the RPC call's credentials does not have permissions to
   create files for. The error to be returned in this instance is
   NFS4ERR_PERM. This applies to the OPEN operation too.

   IMPLEMENTATION

   If the client desires to set attribute values after the create, a
   SETATTR operation can be added to the COMPOUND request so that the
   appropriate attributes will be set.

   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_ATTRNOTSUPP
      NFS4ERR_BADCHAR
      NFS4ERR_BADHANDLE
      NFS4ERR_BADNAME
      NFS4ERR_BADOWNER
      NFS4ERR_BADTYPE
      NFS4ERR_BADXDR
      NFS4ERR_DELAY
      NFS4ERR_DQUOT
      NFS4ERR_EXIST
      NFS4ERR_FHEXPIRED
      NFS4ERR_INVAL
      NFS4ERR_IO
      NFS4ERR_MOVED
      NFS4ERR_NAMETOOLONG
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_NOSPC
      NFS4ERR_NOTDIR
      NFS4ERR_PERM
      NFS4ERR_RESOURCE
      NFS4ERR_ROFS
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE
ToP   noToC   RFC3530 - Page 150

14.2.5. Operation 7: DELEGPURGE - Purge Delegations Awaiting Recovery

SYNOPSIS clientid -> ARGUMENT struct DELEGPURGE4args { clientid4 clientid; }; RESULT struct DELEGPURGE4res { nfsstat4 status; }; DESCRIPTION Purges all of the delegations awaiting recovery for a given client. This is useful for clients which do not commit delegation information to stable storage to indicate that conflicting requests need not be delayed by the server awaiting recovery of delegation information. This operation should be used by clients that record delegation information on stable storage on the client. In this case, DELEGPURGE should be issued immediately after doing delegation recovery on all delegations known to the client. Doing so will notify the server that no additional delegations for the client will be recovered allowing it to free resources, and avoid delaying other clients who make requests that conflict with the unrecovered delegations. The set of delegations known to the server and the client may be different. The reason for this is that a client may fail after making a request which resulted in delegation but before it received the results and committed them to the client's stable storage. The server MAY support DELEGPURGE, but if it does not, it MUST NOT support CLAIM_DELEGATE_PREV. ERRORS NFS4ERR_BADXDR NFS4ERR_NOTSUPP NFS4ERR_LEASE_MOVED NFS4ERR_MOVED NFS4ERR_RESOURCE
ToP   noToC   RFC3530 - Page 151
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE_CLIENTID

14.2.6. Operation 8: DELEGRETURN - Return Delegation

SYNOPSIS (cfh), stateid -> ARGUMENT struct DELEGRETURN4args { /* CURRENT_FH: delegated file */ stateid4 stateid; }; RESULT struct DELEGRETURN4res { nfsstat4 status; }; DESCRIPTION Returns the delegation represented by the current filehandle and stateid. Delegations may be returned when recalled or voluntarily (i.e., before the server has recalled them). In either case the client must properly propagate state changed under the context of the delegation to the server before returning the delegation. ERRORS NFS4ERR_ADMIN_REVOKED NFS4ERR_BAD_STATEID NFS4ERR_BADXDR NFS4ERR_EXPIRED NFS4ERR_INVAL NFS4ERR_LEASE_MOVED NFS4ERR_MOVED NFS4ERR_NOFILEHANDLE NFS4ERR_NOTSUPP NFS4ERR_OLD_STATEID NFS4ERR_RESOURCE NFS4ERR_SERVERFAULT NFS4ERR_STALE NFS4ERR_STALE_STATEID
ToP   noToC   RFC3530 - Page 152

14.2.7. Operation 9: GETATTR - Get Attributes

SYNOPSIS (cfh), attrbits -> attrbits, attrvals ARGUMENT struct GETATTR4args { /* CURRENT_FH: directory or file */ bitmap4 attr_request; }; RESULT struct GETATTR4resok { fattr4 obj_attributes; }; union GETATTR4res switch (nfsstat4 status) { case NFS4_OK: GETATTR4resok resok4; default: void; }; DESCRIPTION The GETATTR operation will obtain attributes for the filesystem object specified by the current filehandle. The client sets a bit in the bitmap argument for each attribute value that it would like the server to return. The server returns an attribute bitmap that indicates the attribute values for which it was able to return, followed by the attribute values ordered lowest attribute number first. The server must return a value for each attribute that the client requests if the attribute is supported by the server. If the server does not support an attribute or cannot approximate a useful value then it must not return the attribute value and must not set the attribute bit in the result bitmap. The server must return an error if it supports an attribute but cannot obtain its value. In that case no attribute values will be returned. All servers must support the mandatory attributes as specified in the section "File Attributes". On success, the current filehandle retains its value.
ToP   noToC   RFC3530 - Page 153
   IMPLEMENTATION

   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_BADHANDLE
      NFS4ERR_BADXDR
      NFS4ERR_DELAY
      NFS4ERR_FHEXPIRED
      NFS4ERR_INVAL
      NFS4ERR_IO
      NFS4ERR_MOVED
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_RESOURCE
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE

14.2.8. Operation 10: GETFH - Get Current Filehandle

SYNOPSIS (cfh) -> filehandle ARGUMENT /* CURRENT_FH: */ void; RESULT struct GETFH4resok { nfs_fh4 object; }; union GETFH4res switch (nfsstat4 status) { case NFS4_OK: GETFH4resok resok4; default: void; }; DESCRIPTION This operation returns the current filehandle value. On success, the current filehandle retains its value.
ToP   noToC   RFC3530 - Page 154
   IMPLEMENTATION

   Operations that change the current filehandle like LOOKUP or CREATE
   do not automatically return the new filehandle as a result.  For
   instance, if a client needs to lookup a directory entry and obtain
   its filehandle then the following request is needed.

      PUTFH  (directory filehandle)
      LOOKUP (entry name)
      GETFH

   ERRORS

      NFS4ERR_BADHANDLE
      NFS4ERR_FHEXPIRED
      NFS4ERR_MOVED
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_RESOURCE
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE

14.2.9. Operation 11: LINK - Create Link to a File

SYNOPSIS (sfh), (cfh), newname -> (cfh), change_info ARGUMENT struct LINK4args { /* SAVED_FH: source object */ /* CURRENT_FH: target directory */ component4 newname; }; RESULT struct LINK4resok { change_info4 cinfo; }; union LINK4res switch (nfsstat4 status) { case NFS4_OK: LINK4resok resok4; default: void; };
ToP   noToC   RFC3530 - Page 155
   DESCRIPTION

   The LINK operation creates an additional newname for the file
   represented by the saved filehandle, as set by the SAVEFH operation,
   in the directory represented by the current filehandle.  The existing
   file and the target directory must reside within the same filesystem
   on the server.  On success, the current filehandle will continue to
   be the target directory.  If an object exists in the target directory
   with the same name as newname, the server must return NFS4ERR_EXIST.

   For the target directory, the server returns change_info4 information
   in cinfo.  With the atomic field of the change_info4 struct, the
   server will indicate if the before and after change attributes were
   obtained atomically with respect to the link creation.

   If the newname has a length of 0 (zero), or if newname does not obey
   the UTF-8 definition, the error NFS4ERR_INVAL will be returned.

   IMPLEMENTATION

   Changes to any property of the "hard" linked files are reflected in
   all of the linked files.  When a link is made to a file, the
   attributes for the file should have a value for numlinks that is one
   greater than the value before the LINK operation.

   The statement "file and the target directory must reside within the
   same filesystem on the server" means that the fsid fields in the
   attributes for the objects are the same. If they reside on different
   filesystems, the error, NFS4ERR_XDEV, is returned.  On some servers,
   the filenames, "." and "..", are illegal as newname.

   In the case that newname is already linked to the file represented by
   the saved filehandle, the server will return NFS4ERR_EXIST.

   Note that symbolic links are created with the CREATE operation.

   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_BADCHAR
      NFS4ERR_BADHANDLE
      NFS4ERR_BADNAME
      NFS4ERR_BADXDR
      NFS4ERR_DELAY
      NFS4ERR_DQUOT
      NFS4ERR_EXIST
      NFS4ERR_FHEXPIRED
      NFS4ERR_FILE_OPEN
ToP   noToC   RFC3530 - Page 156
      NFS4ERR_INVAL
      NFS4ERR_IO
      NFS4ERR_ISDIR
      NFS4ERR_MLINK
      NFS4ERR_MOVED
      NFS4ERR_NAMETOOLONG
      NFS4ERR_NOENT
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_NOSPC
      NFS4ERR_NOTDIR
      NFS4ERR_NOTSUPP
      NFS4ERR_RESOURCE
      NFS4ERR_ROFS
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE
      NFS4ERR_WRONGSEC
      NFS4ERR_XDEV

14.2.10. Operation 12: LOCK - Create Lock

SYNOPSIS (cfh) locktype, reclaim, offset, length, locker -> stateid ARGUMENT struct open_to_lock_owner4 { seqid4 open_seqid; stateid4 open_stateid; seqid4 lock_seqid; lock_owner4 lock_owner; }; struct exist_lock_owner4 { stateid4 lock_stateid; seqid4 lock_seqid; }; union locker4 switch (bool new_lock_owner) { case TRUE: open_to_lock_owner4 open_owner; case FALSE: exist_lock_owner4 lock_owner; }; enum nfs_lock_type4 { READ_LT = 1, WRITE_LT = 2,
ToP   noToC   RFC3530 - Page 157
             READW_LT        = 3,    /* blocking read */
             WRITEW_LT       = 4     /* blocking write */
     };

     struct LOCK4args {
             /* CURRENT_FH: file */
             nfs_lock_type4  locktype;
             bool            reclaim;
             offset4         offset;
             length4         length;
             locker4         locker;
     };

   RESULT

     struct LOCK4denied {
             offset4         offset;
             length4         length;
             nfs_lock_type4  locktype;
             lock_owner4     owner;
     };

     struct LOCK4resok {
             stateid4        lock_stateid;
     };

     union LOCK4res switch (nfsstat4 status) {
      case NFS4_OK:
              LOCK4resok     resok4;
      case NFS4ERR_DENIED:
              LOCK4denied    denied;
      default:
              void;
     };

   DESCRIPTION

   The LOCK operation requests a record lock for the byte range
   specified by the offset and length parameters.  The lock type is also
   specified to be one of the nfs_lock_type4s.  If this is a reclaim
   request, the reclaim parameter will be TRUE;

   Bytes in a file may be locked even if those bytes are not currently
   allocated to the file.  To lock the file from a specific offset
   through the end-of-file (no matter how long the file actually is) use
   a length field with all bits set to 1 (one).  If the length is zero,
ToP   noToC   RFC3530 - Page 158
   or if a length which is not all bits set to one is specified, and
   length when added to the offset exceeds the maximum 64-bit unsigned
   integer value, the error NFS4ERR_INVAL will result.

   Some servers may only support locking for byte offsets that fit
   within 32 bits.  If the client specifies a range that includes a byte
   beyond the last byte offset of the 32-bit range, but does not include
   the last byte offset of the 32-bit and all of the byte offsets beyond
   it, up to the end of the valid 64-bit range, such a 32-bit server
   MUST return the error NFS4ERR_BAD_RANGE.

   In the case that the lock is denied, the owner, offset, and length of
   a conflicting lock are returned.

   On success, the current filehandle retains its value.

   IMPLEMENTATION

   If the server is unable to determine the exact offset and length of
   the conflicting lock, the same offset and length that were provided
   in the arguments should be returned in the denied results.  The File
   Locking section contains a full description of this and the other
   file locking operations.

   LOCK operations are subject to permission checks and to checks
   against the access type of the associated file.  However, the
   specific right and modes required for various type of locks, reflect
   the semantics of the server-exported filesystem, and are not
   specified by the protocol.  For example, Windows 2000 allows a write
   lock of a file open for READ, while a POSIX-compliant system does
   not.

   When the client makes a lock request that corresponds to a range that
   the lockowner has locked already (with the same or different lock
   type), or to a sub-region of such a range, or to a region which
   includes multiple locks already granted to that lockowner, in whole
   or in part, and the server does not support such locking operations
   (i.e., does not support POSIX locking semantics), the server will
   return the error NFS4ERR_LOCK_RANGE.  In that case, the client may
   return an error, or it may emulate the required operations, using
   only LOCK for ranges that do not include any bytes already locked by
   that lock_owner and LOCKU of locks held by that lock_owner
   (specifying an exactly-matching range and type).  Similarly, when the
   client makes a lock request that amounts to upgrading (changing from
   a read lock to a write lock) or downgrading (changing from write lock
   to a read lock) an existing record lock, and the server does not
ToP   noToC   RFC3530 - Page 159
   support such a lock, the server will return NFS4ERR_LOCK_NOTSUPP.
   Such operations may not perfectly reflect the required semantics in
   the face of conflicting lock requests from other clients.

   The locker argument specifies the lock_owner that is associated with
   the LOCK request.  The locker4 structure is a switched union that
   indicates whether the lock_owner is known to the server or if the
   lock_owner is new to the server.  In the case that the lock_owner is
   known to the server and has an established lock_seqid, the argument
   is just the lock_owner and lock_seqid.  In the case that the
   lock_owner is not known to the server, the argument contains not only
   the lock_owner and lock_seqid but also the open_stateid and
   open_seqid.  The new lock_owner case covers the very first lock done
   by the lock_owner and offers a method to use the established state of
   the open_stateid to transition to the use of the lock_owner.

   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_ADMIN_REVOKED
      NFS4ERR_BADHANDLE
      NFS4ERR_BAD_RANGE
      NFS4ERR_BAD_SEQID
      NFS4ERR_BAD_STATEID
      NFS4ERR_BADXDR
      NFS4ERR_DEADLOCK
      NFS4ERR_DELAY
      NFS4ERR_DENIED
      NFS4ERR_EXPIRED
      NFS4ERR_FHEXPIRED
      NFS4ERR_GRACE
      NFS4ERR_INVAL
      NFS4ERR_ISDIR
      NFS4ERR_LEASE_MOVED
      NFS4ERR_LOCK_NOTSUPP
      NFS4ERR_LOCK_RANGE
      NFS4ERR_MOVED
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_NO_GRACE
      NFS4ERR_OLD_STATEID
      NFS4ERR_OPENMODE
      NFS4ERR_RECLAIM_BAD
      NFS4ERR_RECLAIM_CONFLICT
      NFS4ERR_RESOURCE
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE
      NFS4ERR_STALE_CLIENTID
      NFS4ERR_STALE_STATEID
ToP   noToC   RFC3530 - Page 160

14.2.11. Operation 13: LOCKT - Test For Lock

SYNOPSIS (cfh) locktype, offset, length owner -> {void, NFS4ERR_DENIED -> owner} ARGUMENT struct LOCKT4args { /* CURRENT_FH: file */ nfs_lock_type4 locktype; offset4 offset; length4 length; lock_owner4 owner; }; RESULT struct LOCK4denied { offset4 offset; length4 length; nfs_lock_type4 locktype; lock_owner4 owner; }; union LOCKT4res switch (nfsstat4 status) { case NFS4ERR_DENIED: LOCK4denied denied; case NFS4_OK: void; default: void; }; DESCRIPTION The LOCKT operation tests the lock as specified in the arguments. If a conflicting lock exists, the owner, offset, length, and type of the conflicting lock are returned; if no lock is held, nothing other than NFS4_OK is returned. Lock types READ_LT and READW_LT are processed in the same way in that a conflicting lock test is done without regard to blocking or non-blocking. The same is true for WRITE_LT and WRITEW_LT. The ranges are specified as for LOCK. The NFS4ERR_INVAL and NFS4ERR_BAD_RANGE errors are returned under the same circumstances as for LOCK.
ToP   noToC   RFC3530 - Page 161
   On success, the current filehandle retains its value.

   IMPLEMENTATION

   If the server is unable to determine the exact offset and length of
   the conflicting lock, the same offset and length that were provided
   in the arguments should be returned in the denied results.  The File
   Locking section contains further discussion of the file locking
   mechanisms.

   LOCKT uses a lock_owner4 rather a stateid4, as is used in LOCK to
   identify the owner.  This is because the client does not have to open
   the file to test for the existence of a lock, so a stateid may not be
   available.

   The test for conflicting locks should exclude locks for the current
   lockowner.  Note that since such locks are not examined the possible
   existence of overlapping ranges may not affect the results of LOCKT.
   If the server does examine locks that match the lockowner for the
   purpose of range checking, NFS4ERR_LOCK_RANGE may be returned..  In
   the event that it returns NFS4_OK, clients may do a LOCK and receive
   NFS4ERR_LOCK_RANGE on the LOCK request because of the flexibility
   provided to the server.

   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_BADHANDLE
      NFS4ERR_BAD_RANGE
      NFS4ERR_BADXDR
      NFS4ERR_DELAY
      NFS4ERR_DENIED
      NFS4ERR_FHEXPIRED
      NFS4ERR_GRACE
      NFS4ERR_INVAL
      NFS4ERR_ISDIR
      NFS4ERR_LEASE_MOVED
      NFS4ERR_LOCK_RANGE
      NFS4ERR_MOVED
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_RESOURCE
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE
      NFS4ERR_STALE_CLIENTID
ToP   noToC   RFC3530 - Page 162

14.2.12. Operation 14: LOCKU - Unlock File

SYNOPSIS (cfh) type, seqid, stateid, offset, length -> stateid ARGUMENT struct LOCKU4args { /* CURRENT_FH: file */ nfs_lock_type4 locktype; seqid4 seqid; stateid4 stateid; offset4 offset; length4 length; }; RESULT union LOCKU4res switch (nfsstat4 status) { case NFS4_OK: stateid4 stateid; default: void; }; DESCRIPTION The LOCKU operation unlocks the record lock specified by the parameters. The client may set the locktype field to any value that is legal for the nfs_lock_type4 enumerated type, and the server MUST accept any legal value for locktype. Any legal value for locktype has no effect on the success or failure of the LOCKU operation. The ranges are specified as for LOCK. The NFS4ERR_INVAL and NFS4ERR_BAD_RANGE errors are returned under the same circumstances as for LOCK. On success, the current filehandle retains its value. IMPLEMENTATION If the area to be unlocked does not correspond exactly to a lock actually held by the lockowner the server may return the error NFS4ERR_LOCK_RANGE. This includes the case in which the area is not locked, where the area is a sub-range of the area locked, where it overlaps the area locked without matching exactly or the area specified includes multiple locks held by the lockowner. In all of
ToP   noToC   RFC3530 - Page 163
   these cases, allowed by POSIX locking semantics, a client receiving
   this error, should if it desires support for such operations,
   simulate the operation using LOCKU on ranges corresponding to locks
   it actually holds, possibly followed by LOCK requests for the sub-
   ranges not being unlocked.

   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_ADMIN_REVOKED
      NFS4ERR_BADHANDLE
      NFS4ERR_BAD_RANGE
      NFS4ERR_BAD_SEQID
      NFS4ERR_BAD_STATEID
      NFS4ERR_BADXDR
      NFS4ERR_EXPIRED
      NFS4ERR_FHEXPIRED
      NFS4ERR_GRACE
      NFS4ERR_INVAL
      NFS4ERR_ISDIR
      NFS4ERR_LEASE_MOVED
      NFS4ERR_LOCK_RANGE
      NFS4ERR_MOVED
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_OLD_STATEID
      NFS4ERR_RESOURCE
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE
      NFS4ERR_STALE_STATEID

14.2.13. Operation 15: LOOKUP - Lookup Filename

SYNOPSIS (cfh), component -> (cfh) ARGUMENT struct LOOKUP4args { /* CURRENT_FH: directory */ component4 objname; };
ToP   noToC   RFC3530 - Page 164
   RESULT

     struct LOOKUP4res {
             /* CURRENT_FH: object */
             nfsstat4        status;
     };

   DESCRIPTION

   This operation LOOKUPs or finds a filesystem object using the
   directory specified by the current filehandle.  LOOKUP evaluates the
   component and if the object exists the current filehandle is replaced
   with the component's filehandle.

   If the component cannot be evaluated either because it does not exist
   or because the client does not have permission to evaluate the
   component, then an error will be returned and the current filehandle
   will be unchanged.

   If the component is a zero length string or if any component does not
   obey the UTF-8 definition, the error NFS4ERR_INVAL will be returned.

   IMPLEMENTATION

   If the client wants to achieve the effect of a multi-component
   lookup, it may construct a COMPOUND request such as (and obtain each
   filehandle):

      PUTFH  (directory filehandle)
      LOOKUP "pub"
      GETFH
      LOOKUP "foo"
      GETFH
      LOOKUP "bar"
      GETFH

   NFS version 4 servers depart from the semantics of previous NFS
   versions in allowing LOOKUP requests to cross mountpoints on the
   server.  The client can detect a mountpoint crossing by comparing the
   fsid attribute of the directory with the fsid attribute of the
   directory looked up.  If the fsids are different then the new
   directory is a server mountpoint.  UNIX clients that detect a
   mountpoint crossing will need to mount the server's filesystem.  This
   needs to be done to maintain the file object identity checking
   mechanisms common to UNIX clients.
ToP   noToC   RFC3530 - Page 165
   Servers that limit NFS access to "shares" or "exported" filesystems
   should provide a pseudo-filesystem into which the exported
   filesystems can be integrated, so that clients can browse the
   server's name space.  The clients' view of a pseudo filesystem will
   be limited to paths that lead to exported filesystems.

   Note: previous versions of the protocol assigned special semantics to
   the names "." and "..".  NFS version 4 assigns no special semantics
   to these names.  The LOOKUPP operator must be used to lookup a parent
   directory.

   Note that this operation does not follow symbolic links.  The client
   is responsible for all parsing of filenames including filenames that
   are modified by symbolic links encountered during the lookup process.

   If the current filehandle supplied is not a directory but a symbolic
   link, the error NFS4ERR_SYMLINK is returned as the error.  For all
   other non-directory file types, the error NFS4ERR_NOTDIR is returned.

   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_BADCHAR
      NFS4ERR_BADHANDLE
      NFS4ERR_BADNAME
      NFS4ERR_BADXDR
      NFS4ERR_FHEXPIRED
      NFS4ERR_INVAL
      NFS4ERR_IO
      NFS4ERR_MOVED
      NFS4ERR_NAMETOOLONG
      NFS4ERR_NOENT
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_NOTDIR
      NFS4ERR_RESOURCE
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE
      NFS4ERR_SYMLINK
      NFS4ERR_WRONGSEC

14.2.14. Operation 16: LOOKUPP - Lookup Parent Directory

SYNOPSIS (cfh) -> (cfh)
ToP   noToC   RFC3530 - Page 166
   ARGUMENT

     /* CURRENT_FH: object */
     void;

   RESULT

     struct LOOKUPP4res {
             /* CURRENT_FH: directory */
             nfsstat4        status;
     };

   DESCRIPTION

   The current filehandle is assumed to refer to a regular directory
   or a named attribute directory.  LOOKUPP assigns the filehandle for
   its parent directory to be the current filehandle.  If there is no
   parent directory an NFS4ERR_NOENT error must be returned.
   Therefore, NFS4ERR_NOENT will be returned by the server when the
   current filehandle is at the root or top of the server's file tree.

   IMPLEMENTATION

   As for LOOKUP, LOOKUPP will also cross mountpoints.

   If the current filehandle is not a directory or named attribute
   directory, the error NFS4ERR_NOTDIR is returned.

   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_BADHANDLE
      NFS4ERR_FHEXPIRED
      NFS4ERR_IO
      NFS4ERR_MOVED
      NFS4ERR_NOENT
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_NOTDIR
      NFS4ERR_RESOURCE
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE

14.2.15. Operation 17: NVERIFY - Verify Difference in Attributes

SYNOPSIS (cfh), fattr -> -
ToP   noToC   RFC3530 - Page 167
   ARGUMENT

     struct NVERIFY4args {
             /* CURRENT_FH: object */
             fattr4          obj_attributes;
     };

   RESULT

     struct NVERIFY4res {
             nfsstat4        status;
     };

   DESCRIPTION

   This operation is used to prefix a sequence of operations to be
   performed if one or more attributes have changed on some filesystem
   object.  If all the attributes match then the error NFS4ERR_SAME must
   be returned.

   On success, the current filehandle retains its value.

   IMPLEMENTATION

   This operation is useful as a cache validation operator.  If the
   object to which the attributes belong has changed then the following
   operations may obtain new data associated with that object.  For
   instance, to check if a file has been changed and obtain new data if
   it has:

      PUTFH  (public)
      LOOKUP "foobar"
      NVERIFY attrbits attrs
      READ 0 32767

   In the case that a recommended attribute is specified in the NVERIFY
   operation and the server does not support that attribute for the
   filesystem object, the error NFS4ERR_ATTRNOTSUPP is returned to the
   client.

   When the attribute rdattr_error or any write-only attribute (e.g.,
   time_modify_set) is specified, the error NFS4ERR_INVAL is returned to
   the client.
ToP   noToC   RFC3530 - Page 168
   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_ATTRNOTSUPP
      NFS4ERR_BADCHAR
      NFS4ERR_BADHANDLE
      NFS4ERR_BADXDR
      NFS4ERR_DELAY
      NFS4ERR_FHEXPIRED
      NFS4ERR_INVAL
      NFS4ERR_IO
      NFS4ERR_MOVED
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_RESOURCE
      NFS4ERR_SAME
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE

14.2.16. Operation 18: OPEN - Open a Regular File

SYNOPSIS (cfh), seqid, share_access, share_deny, owner, openhow, claim -> (cfh), stateid, cinfo, rflags, open_confirm, attrset delegation ARGUMENT struct OPEN4args { seqid4 seqid; uint32_t share_access; uint32_t share_deny; open_owner4 owner; openflag4 openhow; open_claim4 claim; }; enum createmode4 { UNCHECKED4 = 0, GUARDED4 = 1, EXCLUSIVE4 = 2 }; union createhow4 switch (createmode4 mode) { case UNCHECKED4: case GUARDED4: fattr4 createattrs; case EXCLUSIVE4: verifier4 createverf;
ToP   noToC   RFC3530 - Page 169
     };

     enum opentype4 {
             OPEN4_NOCREATE  = 0,
             OPEN4_CREATE    = 1
     };

     union openflag4 switch (opentype4 opentype) {
      case OPEN4_CREATE:
              createhow4     how;
      default:
              void;
     };

     /* Next definitions used for OPEN delegation */
     enum limit_by4 {
             NFS_LIMIT_SIZE          = 1,
             NFS_LIMIT_BLOCKS        = 2
             /* others as needed */
     };

     struct nfs_modified_limit4 {
             uint32_t        num_blocks;
             uint32_t        bytes_per_block;
     };

     union nfs_space_limit4 switch (limit_by4 limitby) {
      /* limit specified as file size */
      case NFS_LIMIT_SIZE:
              uint64_t               filesize;
      /* limit specified by number of blocks */
      case NFS_LIMIT_BLOCKS:
              nfs_modified_limit4    mod_blocks;
     } ;

     enum open_delegation_type4 {
             OPEN_DELEGATE_NONE      = 0,
             OPEN_DELEGATE_READ      = 1,
             OPEN_DELEGATE_WRITE     = 2
     };

     enum open_claim_type4 {
             CLAIM_NULL              = 0,
             CLAIM_PREVIOUS          = 1,
             CLAIM_DELEGATE_CUR      = 2,
             CLAIM_DELEGATE_PREV     = 3
     };
ToP   noToC   RFC3530 - Page 170
     struct open_claim_delegate_cur4 {
             stateid4        delegate_stateid;
             component4      file;
     };

     union open_claim4 switch (open_claim_type4 claim) {
      /*
       * No special rights to file. Ordinary OPEN of the specified file.
       */
      case CLAIM_NULL:
              /* CURRENT_FH: directory */
              component4     file;

      /*
       * Right to the file established by an open previous to server
       * reboot.  File identified by filehandle obtained at that time
       * rather than by name.
       */
      case CLAIM_PREVIOUS:
              /* CURRENT_FH: file being reclaimed */
              open_delegation_type4   delegate_type;

      /*
       * Right to file based on a delegation granted by the server.
       * File is specified by name.
       */
      case CLAIM_DELEGATE_CUR:
              /* CURRENT_FH: directory */
              open_claim_delegate_cur4       delegate_cur_info;

      /* Right to file based on a delegation granted to a previous boot
       * instance of the client.  File is specified by name.
       */
      case CLAIM_DELEGATE_PREV:
              /* CURRENT_FH: directory */
              component4     file_delegate_prev;
     };

   RESULT

   struct open_read_delegation4 {
           stateid4        stateid;        /* Stateid for delegation*/
           bool            recall;         /* Pre-recalled flag for
                                              delegations obtained
                                              by reclaim
                                              (CLAIM_PREVIOUS) */
           nfsace4         permissions;    /* Defines users who don't
                                              need an ACCESS call to
ToP   noToC   RFC3530 - Page 171
                                              open for read */
   };

   struct open_write_delegation4 {
           stateid4        stateid;        /* Stateid for delegation*/
           bool            recall;         /* Pre-recalled flag for
                                              delegations obtained
                                              by reclaim
                                              (CLAIM_PREVIOUS) */
           nfs_space_limit4 space_limit;   /* Defines condition that
                                              the client must check to
                                              determine whether the
                                              file needs to be flushed
                                              to the server on close.
                                              */
           nfsace4         permissions;    /* Defines users who don't
                                              need an ACCESS call as
                                              part of a delegated
                                              open. */
   };

   union open_delegation4
   switch (open_delegation_type4 delegation_type) {
           case OPEN_DELEGATE_NONE:
                   void;
           case OPEN_DELEGATE_READ:
                   open_read_delegation4 read;
           case OPEN_DELEGATE_WRITE:
                   open_write_delegation4 write;
   };

   const OPEN4_RESULT_CONFIRM      = 0x00000002;
   const OPEN4_RESULT_LOCKTYPE_POSIX = 0x00000004;

   struct OPEN4resok {
           stateid4        stateid;        /* Stateid for open */
           change_info4    cinfo;          /* Directory Change Info */
           uint32_t        rflags;         /* Result flags */
           bitmap4         attrset;        /* attributes on create */
           open_delegation4 delegation;    /* Info on any open
                                              delegation */
   };

   union OPEN4res switch (nfsstat4 status) {
    case NFS4_OK:
           /* CURRENT_FH: opened file */
           OPEN4resok      resok4;
    default:
ToP   noToC   RFC3530 - Page 172
           void;
   };

   WARNING TO CLIENT IMPLEMENTORS

   OPEN resembles LOOKUP in that it generates a filehandle for the
   client to use.  Unlike LOOKUP though, OPEN creates server state on
   the filehandle.  In normal circumstances, the client can only release
   this state with a CLOSE operation.  CLOSE uses the current filehandle
   to determine which file to close.  Therefore the client MUST follow
   every OPEN operation with a GETFH operation in the same COMPOUND
   procedure.  This will supply the client with the filehandle such that
   CLOSE can be used appropriately.

   Simply waiting for the lease on the file to expire is insufficient
   because the server may maintain the state indefinitely as long as
   another client does not attempt to make a conflicting access to the
   same file.

   DESCRIPTION

   The OPEN operation creates and/or opens a regular file in a directory
   with the provided name.  If the file does not exist at the server and
   creation is desired, specification of the method of creation is
   provided by the openhow parameter.  The client has the choice of
   three creation methods: UNCHECKED, GUARDED, or EXCLUSIVE.

   If the current filehandle is a named attribute directory, OPEN will
   then create or open a named attribute file.  Note that exclusive
   create of a named attribute is not supported.  If the createmode is
   EXCLUSIVE4 and the current filehandle is a named attribute directory,
   the server will return EINVAL.

   UNCHECKED means that the file should be created if a file of that
   name does not exist and encountering an existing regular file of that
   name is not an error.  For this type of create, createattrs specifies
   the initial set of attributes for the file.  The set of attributes
   may include any writable attribute valid for regular files.  When an
   UNCHECKED create encounters an existing file, the attributes
   specified by createattrs are not used, except that when an size of
   zero is specified, the existing file is truncated.  If GUARDED is
   specified, the server checks for the presence of a duplicate object
   by name before performing the create.  If a duplicate exists, an
   error of NFS4ERR_EXIST is returned as the status.  If the object does
   not exist, the request is performed as described for UNCHECKED.  For
ToP   noToC   RFC3530 - Page 173
   each of these cases (UNCHECKED and GUARDED) where the operation is
   successful, the server will return to the client an attribute mask
   signifying which attributes were successfully set for the object.

   EXCLUSIVE specifies that the server is to follow exclusive creation
   semantics, using the verifier to ensure exclusive creation of the
   target.  The server should check for the presence of a duplicate
   object by name.  If the object does not exist, the server creates the
   object and stores the verifier with the object.  If the object does
   exist and the stored verifier matches the client provided verifier,
   the server uses the existing object as the newly created object.  If
   the stored verifier does not match, then an error of NFS4ERR_EXIST is
   returned.  No attributes may be provided in this case, since the
   server may use an attribute of the target object to store the
   verifier.  If the server uses an attribute to store the exclusive
   create verifier, it will signify which attribute by setting the
   appropriate bit in the attribute mask that is returned in the
   results.

   For the target directory, the server returns change_info4 information
   in cinfo.  With the atomic field of the change_info4 struct, the
   server will indicate if the before and after change attributes were
   obtained atomically with respect to the link creation.

   Upon successful creation, the current filehandle is replaced by that
   of the new object.

   The OPEN operation provides for Windows share reservation capability
   with the use of the share_access and share_deny fields of the OPEN
   arguments.  The client specifies at OPEN the required share_access
   and share_deny modes.  For clients that do not directly support
   SHAREs (i.e., UNIX), the expected deny value is DENY_NONE.  In the
   case that there is a existing SHARE reservation that conflicts with
   the OPEN request, the server returns the error NFS4ERR_SHARE_DENIED.
   For a complete SHARE request, the client must provide values for the
   owner and seqid fields for the OPEN argument.  For additional
   discussion of SHARE semantics see the section on 'Share
   Reservations'.

   In the case that the client is recovering state from a server
   failure, the claim field of the OPEN argument is used to signify that
   the request is meant to reclaim state previously held.

   The "claim" field of the OPEN argument is used to specify the file to
   be opened and the state information which the client claims to
   possess.  There are four basic claim types which cover the various
   situations for an OPEN.  They are as follows:
ToP   noToC   RFC3530 - Page 174
   CLAIM_NULL
                         For the client, this is a new OPEN
                         request and there is no previous state
                         associate with the file for the client.

   CLAIM_PREVIOUS
                         The client is claiming basic OPEN state
                         for a file that was held previous to a
                         server reboot.  Generally used when a
                         server is returning persistent
                         filehandles; the client may not have the
                         file name to reclaim the OPEN.

   CLAIM_DELEGATE_CUR
                         The client is claiming a delegation for
                         OPEN as granted by the server.
                         Generally this is done as part of
                         recalling a delegation.

   CLAIM_DELEGATE_PREV
                         The client is claiming a delegation
                         granted to a previous client instance;
                         used after the client reboots. The
                         server MAY support CLAIM_DELEGATE_PREV.
                         If it does support CLAIM_DELEGATE_PREV,
                         SETCLIENTID_CONFIRM MUST NOT remove the
                         client's delegation state, and the
                         server MUST support the DELEGPURGE
                         operation.

   For OPEN requests whose claim type is other than CLAIM_PREVIOUS
   (i.e., requests other than those devoted to reclaiming opens after a
   server reboot) that reach the server during its grace or lease
   expiration period, the server returns an error of NFS4ERR_GRACE.

   For any OPEN request, the server may return an open delegation, which
   allows further opens and closes to be handled locally on the client
   as described in the section Open Delegation.  Note that delegation is
   up to the server to decide.  The client should never assume that
   delegation will or will not be granted in a particular instance.  It
   should always be prepared for either case.  A partial exception is
   the reclaim (CLAIM_PREVIOUS) case, in which a delegation type is
   claimed.  In this case, delegation will always be granted, although
   the server may specify an immediate recall in the delegation
   structure.

   The rflags returned by a successful OPEN allow the server to return
   information governing how the open file is to be handled.
ToP   noToC   RFC3530 - Page 175
   OPEN4_RESULT_CONFIRM indicates that the client MUST execute an
   OPEN_CONFIRM operation before using the open file.
   OPEN4_RESULT_LOCKTYPE_POSIX indicates the server's file locking
   behavior supports the complete set of Posix locking techniques.  From
   this the client can choose to manage file locking state in a way to
   handle a mis-match of file locking management.

   If the component is of zero length, NFS4ERR_INVAL will be returned.
   The component is also subject to the normal UTF-8, character support,
   and name checks.  See the section "UTF-8 Related Errors" for further
   discussion.

   When an OPEN is done and the specified lockowner already has the
   resulting filehandle open, the result is to "OR" together the new
   share and deny status together with the existing status.  In this
   case, only a single CLOSE need be done, even though multiple OPENs
   were completed.  When such an OPEN is done, checking of share
   reservations for the new OPEN proceeds normally, with no exception
   for the existing OPEN held by the same lockowner.

   If the underlying filesystem at the server is only accessible in a
   read-only mode and the OPEN request has specified ACCESS_WRITE or
   ACCESS_BOTH, the server will return NFS4ERR_ROFS to indicate a read-
   only filesystem.

   As with the CREATE operation, the server MUST derive the owner, owner
   ACE, group, or group ACE if any of the four attributes are required
   and supported by the server's filesystem.  For an OPEN with the
   EXCLUSIVE4 createmode, the server has no choice, since such OPEN
   calls do not include the createattrs field.  Conversely, if
   createattrs is specified, and includes owner or group (or
   corresponding ACEs) that the principal in the RPC call's credentials
   does not have authorization to create files for, then the server may
   return NFS4ERR_PERM.

   In the case of a OPEN which specifies a size of zero (e.g.,
   truncation) and the file has named attributes, the named attributes
   are left as is.  They are not removed.

   IMPLEMENTATION

   The OPEN operation contains support for EXCLUSIVE create.  The
   mechanism is similar to the support in NFS version 3 [RFC1813].  As
   in NFS version 3, this mechanism provides reliable exclusive
   creation.  Exclusive create is invoked when the how parameter is
   EXCLUSIVE.  In this case, the client provides a verifier that can
   reasonably be expected to be unique.  A combination of a client
ToP   noToC   RFC3530 - Page 176
   identifier, perhaps the client network address, and a unique number
   generated by the client, perhaps the RPC transaction identifier, may
   be appropriate.

   If the object does not exist, the server creates the object and
   stores the verifier in stable storage. For filesystems that do not
   provide a mechanism for the storage of arbitrary file attributes, the
   server may use one or more elements of the object meta-data to store
   the verifier. The verifier must be stored in stable storage to
   prevent erroneous failure on retransmission of the request. It is
   assumed that an exclusive create is being performed because exclusive
   semantics are critical to the application. Because of the expected
   usage, exclusive CREATE does not rely solely on the normally volatile
   duplicate request cache for storage of the verifier. The duplicate
   request cache in volatile storage does not survive a crash and may
   actually flush on a long network partition, opening failure windows.
   In the UNIX local filesystem environment, the expected storage
   location for the verifier on creation is the meta-data (time stamps)
   of the object. For this reason, an exclusive object create may not
   include initial attributes because the server would have nowhere to
   store the verifier.

   If the server can not support these exclusive create semantics,
   possibly because of the requirement to commit the verifier to stable
   storage, it should fail the OPEN request with the error,
   NFS4ERR_NOTSUPP.

   During an exclusive CREATE request, if the object already exists, the
   server reconstructs the object's verifier and compares it with the
   verifier in the request. If they match, the server treats the request
   as a success. The request is presumed to be a duplicate of an
   earlier, successful request for which the reply was lost and that the
   server duplicate request cache mechanism did not detect.  If the
   verifiers do not match, the request is rejected with the status,
   NFS4ERR_EXIST.

   Once the client has performed a successful exclusive create, it must
   issue a SETATTR to set the correct object attributes.  Until it does
   so, it should not rely upon any of the object attributes, since the
   server implementation may need to overload object meta-data to store
   the verifier.  The subsequent SETATTR must not occur in the same
   COMPOUND request as the OPEN.  This separation will guarantee that
   the exclusive create mechanism will continue to function properly in
   the face of retransmission of the request.

   Use of the GUARDED attribute does not provide exactly-once semantics.
   In particular, if a reply is lost and the server does not detect the
   retransmission of the request, the operation can fail with
ToP   noToC   RFC3530 - Page 177
   NFS4ERR_EXIST, even though the create was performed successfully.
   The client would use this behavior in the case that the application
   has not requested an exclusive create but has asked to have the file
   truncated when the file is opened.  In the case of the client timing
   out and retransmitting the create request, the client can use GUARDED
   to prevent against a sequence like: create, write, create
   (retransmitted) from occurring.

   For SHARE reservations, the client must specify a value for
   share_access that is one of READ, WRITE, or BOTH.  For share_deny,
   the client must specify one of NONE, READ, WRITE, or BOTH.  If the
   client fails to do this, the server must return NFS4ERR_INVAL.

   Based on the share_access value (READ, WRITE, or BOTH) the client
   should check that the requester has the proper access rights to
   perform the specified operation.  This would generally be the results
   of applying the ACL access rules to the file for the current
   requester.  However, just as with the ACCESS operation, the client
   should not attempt to second-guess the server's decisions, as access
   rights may change and may be subject to server administrative
   controls outside the ACL framework.  If the requester is not
   authorized to READ or WRITE (depending on the share_access value),
   the server must return NFS4ERR_ACCESS.  Note that since the NFS
   version 4 protocol does not impose any requirement that READs and
   WRITEs issued for an open file have the same credentials as the OPEN
   itself, the server still must do appropriate access checking on the
   READs and WRITEs themselves.

   If the component provided to OPEN is a symbolic link, the error
   NFS4ERR_SYMLINK will be returned to the client.  If the current
   filehandle is not a directory, the error NFS4ERR_NOTDIR will be
   returned.

   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_ADMIN_REVOKED
      NFS4ERR_ATTRNOTSUPP
      NFS4ERR_BADCHAR
      NFS4ERR_BADHANDLE
      NFS4ERR_BADNAME
      NFS4ERR_BADOWNER
      NFS4ERR_BAD_SEQID
      NFS4ERR_BADXDR
      NFS4ERR_DELAY
      NFS4ERR_DQUOT
      NFS4ERR_EXIST
      NFS4ERR_EXPIRED
ToP   noToC   RFC3530 - Page 178
      NFS4ERR_FHEXPIRED
      NFS4ERR_GRACE
      NFS4ERR_IO
      NFS4ERR_INVAL
      NFS4ERR_ISDIR
      NFS4ERR_LEASE_MOVED
      NFS4ERR_MOVED
      NFS4ERR_NAMETOOLONG
      NFS4ERR_NOENT
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_NOSPC
      NFS4ERR_NOTDIR
      NFS4ERR_NOTSUPP
      NFS4ERR_NO_GRACE
      NFS4ERR_PERM
      NFS4ERR_RECLAIM_BAD
      NFS4ERR_RECLAIM_CONFLICT
      NFS4ERR_RESOURCE
      NFS4ERR_ROFS
      NFS4ERR_SERVERFAULT
      NFS4ERR_SHARE_DENIED
      NFS4ERR_STALE
      NFS4ERR_STALE_CLIENTID
      NFS4ERR_SYMLINK
      NFS4ERR_WRONGSEC

14.2.17. Operation 19: OPENATTR - Open Named Attribute Directory

SYNOPSIS (cfh) createdir -> (cfh) ARGUMENT struct OPENATTR4args { /* CURRENT_FH: object */ bool createdir; }; RESULT struct OPENATTR4res { /* CURRENT_FH: named attr directory*/ nfsstat4 status; };
ToP   noToC   RFC3530 - Page 179
   DESCRIPTION

   The OPENATTR operation is used to obtain the filehandle of the named
   attribute directory associated with the current filehandle.  The
   result of the OPENATTR will be a filehandle to an object of type
   NF4ATTRDIR.  From this filehandle, READDIR and LOOKUP operations can
   be used to obtain filehandles for the various named attributes
   associated with the original filesystem object.  Filehandles returned
   within the named attribute directory will have a type of
   NF4NAMEDATTR.

   The createdir argument allows the client to signify if a named
   attribute directory should be created as a result of the OPENATTR
   operation.  Some clients may use the OPENATTR operation with a value
   of FALSE for createdir to determine if any named attributes exist for
   the object.  If none exist, then NFS4ERR_NOENT will be returned.  If
   createdir has a value of TRUE and no named attribute directory
   exists, one is created.  The creation of a named attribute directory
   assumes that the server has implemented named attribute support in
   this fashion and is not required to do so by this definition.

   IMPLEMENTATION

   If the server does not support named attributes for the current
   filehandle, an error of NFS4ERR_NOTSUPP will be returned to the
   client.

   ERRORS

      NFS4ERR_ACCESS
      NFS4ERR_BADHANDLE
      NFS4ERR_BADXDR
      NFS4ERR_DELAY
      NFS4ERR_DQUOT
      NFS4ERR_FHEXPIRED
      NFS4ERR_IO
      NFS4ERR_MOVED
      NFS4ERR_NOENT
      NFS4ERR_NOFILEHANDLE
      NFS4ERR_NOSPC
      NFS4ERR_NOTSUPP
      NFS4ERR_RESOURCE
      NFS4ERR_ROFS
      NFS4ERR_SERVERFAULT
      NFS4ERR_STALE