tech-invite   World Map     

IETF     RFCs     Groups     SIP     ABNFs    |    3GPP     Specs     Glossaries     Architecture     IMS     UICC    |    search     info

RFC 5661

 
 
 

Network File System (NFS) Version 4 Minor Version 1 Protocol

Part 15 of 20, p. 424 to 460
Prev RFC Part       Next RFC Part

 


prevText      Top      Up      ToC       Page 424 
18.9.  Operation 11: LINK - Create Link to a File

18.9.1.  ARGUMENTS

   struct LINK4args {
           /* SAVED_FH: source object */
           /* CURRENT_FH: target directory */
           component4      newname;
   };

18.9.2.  RESULTS

   struct LINK4resok {
           change_info4    cinfo;
   };

   union LINK4res switch (nfsstat4 status) {
    case NFS4_OK:
            LINK4resok resok4;
    default:
            void;
   };

18.9.3.  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 file system
   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 data type, 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 zero, or if newname does not obey the
   UTF-8 definition, the error NFS4ERR_INVAL will be returned.

18.9.4.  IMPLEMENTATION

   The server MAY impose restrictions on the LINK operation such that
   LINK may not be done when the file is open or when that open is done
   by particular protocols, or with particular options or access modes.
   When LINK is rejected because of such restrictions, the error
   NFS4ERR_FILE_OPEN is returned.

Top      Up      ToC       Page 425 
   If a server does implement such restrictions and those restrictions
   include cases of NFSv4 opens preventing successful execution of a
   link, the server needs to recall any delegations that could hide the
   existence of opens relevant to that decision.  The reason is that
   when a client holds a delegation, the server might not have an
   accurate account of the opens for that client, since the client may
   execute OPENs and CLOSEs locally.  The LINK operation must be delayed
   only until a definitive result can be obtained.  For example, suppose
   there are multiple delegations and one of them establishes an open
   whose presence would prevent the link.  Given the server's semantics,
   NFS4ERR_FILE_OPEN may be returned to the caller as soon as that
   delegation is returned without waiting for other delegations to be
   returned.  Similarly, if such opens are not associated with
   delegations, NFS4ERR_FILE_OPEN can be returned immediately with no
   delegation recall being done.

   If the current filehandle designates a directory for which another
   client holds a directory delegation, then, unless the delegation is
   such that the situation can be resolved by sending a notification,
   the delegation MUST be recalled, and the operation cannot be
   performed successfully until the delegation is returned or revoked.
   Except where this happens very quickly, one or more NFS4ERR_DELAY
   errors will be returned to requests made while delegation remains
   outstanding.

   When the current filehandle designates a directory for which one or
   more directory delegations exist, then, when those delegations
   request such notifications, instead of a recall, NOTIFY4_ADD_ENTRY
   will be generated as a result of the LINK operation.

   If the current file system supports the numlinks attribute, and other
   clients have delegations to the file being linked, then those
   delegations MUST be recalled and the LINK operation MUST NOT proceed
   until all delegations are returned or revoked.  Except where this
   happens very quickly, one or more NFS4ERR_DELAY errors will be
   returned to requests made while delegation remains outstanding.

   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 file system on the server" means that the fsid fields in the
   attributes for the objects are the same.  If they reside on different
   file systems, the error NFS4ERR_XDEV is returned.  This error may be
   returned by some servers when there is an internal partitioning of a
   file system that the LINK operation would violate.

Top      Up      ToC       Page 426 
   On some servers, "." and ".." are illegal values for newname and the
   error NFS4ERR_BADNAME will be returned if they are specified.

   When the current filehandle designates a named attribute directory
   and the object to be linked (the saved filehandle) is not a named
   attribute for the same object, the error NFS4ERR_XDEV MUST be
   returned.  When the saved filehandle designates a named attribute and
   the current filehandle is not the appropriate named attribute
   directory, the error NFS4ERR_XDEV MUST also be returned.

   When the current filehandle designates a named attribute directory
   and the object to be linked (the saved filehandle) is a named
   attribute within that directory, the server may return the error
   NFS4ERR_NOTSUPP.

   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.

18.10.  Operation 12: LOCK - Create Lock

18.10.1.  ARGUMENTS

   /*
    * For LOCK, transition from open_stateid and lock_owner
    * to a lock stateid.
    */
   struct open_to_lock_owner4 {
           seqid4          open_seqid;
           stateid4        open_stateid;
           seqid4          lock_seqid;
           lock_owner4     lock_owner;
   };

   /*
    * For LOCK, existing lock stateid continues to request new
    * file lock for the same lock_owner and open_stateid.
    */
   struct exist_lock_owner4 {
           stateid4        lock_stateid;
           seqid4          lock_seqid;
   };

Top      Up      ToC       Page 427 
   union locker4 switch (bool new_lock_owner) {
    case TRUE:
           open_to_lock_owner4     open_owner;
    case FALSE:
           exist_lock_owner4       lock_owner;
   };

   /*
    * LOCK/LOCKT/LOCKU: Record lock management
    */
   struct LOCK4args {
           /* CURRENT_FH: file */
           nfs_lock_type4  locktype;
           bool            reclaim;
           offset4         offset;
           length4         length;
           locker4         locker;
   };

18.10.2.  RESULTS

   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;
   };

18.10.3.  DESCRIPTION

   The LOCK operation requests a byte-range lock for the byte-range
   specified by the offset and length parameters, and lock type
   specified in the locktype parameter.  If this is a reclaim request,
   the reclaim parameter will be TRUE.

Top      Up      ToC       Page 428 
   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 equal to NFS4_UINT64_MAX.  The server MUST return
   NFS4ERR_INVAL under the following combinations of length and offset:

   o  Length is equal to zero.

   o  Length is not equal to NFS4_UINT64_MAX, and the sum of length and
      offset exceeds NFS4_UINT64_MAX.

   32-bit servers are servers that support locking for byte offsets that
   fit within 32 bits (i.e., less than or equal to NFS4_UINT32_MAX).  If
   the client specifies a range that overlaps one or more bytes beyond
   offset NFS4_UINT32_MAX but does not end at offset NFS4_UINT64_MAX,
   then such a 32-bit server MUST return the error NFS4ERR_BAD_RANGE.

   If the server returns NFS4ERR_DENIED, the owner, offset, and length
   of a conflicting lock are returned.

   The locker argument specifies the lock-owner that is associated with
   the LOCK operation.  The locker4 structure is a switched union that
   indicates whether the client has already created byte-range locking
   state associated with the current open file and lock-owner.  In the
   case in which it has, the argument is just a stateid representing the
   set of locks associated with that open file and lock-owner, together
   with a lock_seqid value that MAY be any value and MUST be ignored by
   the server.  In the case where no byte-range locking state has been
   established, or the client does not have the stateid available, the
   argument contains the stateid of the open file with which this lock
   is to be associated, together with the lock-owner with which the lock
   is to be associated.  The open_to_lock_owner case covers the very
   first lock done by a lock-owner for a given open file and offers a
   method to use the established state of the open_stateid to transition
   to the use of a lock stateid.

   The following fields of the locker parameter MAY be set to any value
   by the client and MUST be ignored by the server:

   o  The clientid field of the lock_owner field of the open_owner field
      (locker.open_owner.lock_owner.clientid).  The reason the server
      MUST ignore the clientid field is that the server MUST derive the
      client ID from the session ID from the SEQUENCE operation of the
      COMPOUND request.

   o  The open_seqid and lock_seqid fields of the open_owner field
      (locker.open_owner.open_seqid and locker.open_owner.lock_seqid).

Top      Up      ToC       Page 429 
   o  The lock_seqid field of the lock_owner field
      (locker.lock_owner.lock_seqid).

   Note that the client ID appearing in a LOCK4denied structure is the
   actual client associated with the conflicting lock, whether this is
   the client ID associated with the current session or a different one.
   Thus, if the server returns NFS4ERR_DENIED, it MUST set the clientid
   field of the owner field of the denied field.

   If the current filehandle is not an ordinary file, an error will be
   returned to the client.  In the case that the current filehandle
   represents an object of type NF4DIR, NFS4ERR_ISDIR is returned.  If
   the current filehandle designates a symbolic link, NFS4ERR_SYMLINK is
   returned.  In all other cases, NFS4ERR_WRONG_TYPE is returned.

   On success, the current filehandle retains its value.

18.10.4.  IMPLEMENTATION

   If the server is unable to determine the exact offset and length of
   the conflicting byte-range lock, the same offset and length that were
   provided in the arguments should be returned in the denied results.

   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 types of locks reflect
   the semantics of the server-exported file system, and are not
   specified by the protocol.  For example, Windows 2000 allows a write
   lock of a file open for read access, while a POSIX-compliant system
   does not.

   When the client sends a LOCK operation that corresponds to a range
   that the lock-owner has locked already (with the same or different
   lock type), or to a sub-range of such a range, or to a byte-range
   that includes multiple locks already granted to that lock-owner, 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 sends a LOCK operation that amounts to
   upgrading (changing from a READ_LT lock to a WRITE_LT lock) or
   downgrading (changing from WRITE_LT lock to a READ_LT lock) an
   existing byte-range lock, and the server does not support such a

Top      Up      ToC       Page 430 
   lock, the server will return NFS4ERR_LOCK_NOTSUPP.  Such operations
   may not perfectly reflect the required semantics in the face of
   conflicting LOCK operations from other clients.

   When a client holds an OPEN_DELEGATE_WRITE delegation, the client
   holding that delegation is assured that there are no opens by other
   clients.  Thus, there can be no conflicting LOCK operations from such
   clients.  Therefore, the client may be handling locking requests
   locally, without doing LOCK operations on the server.  If it does
   that, it must be prepared to update the lock status on the server, by
   sending appropriate LOCK and LOCKU operations before returning the
   delegation.

   When one or more clients hold OPEN_DELEGATE_READ delegations, any
   LOCK operation where the server is implementing mandatory locking
   semantics MUST result in the recall of all such delegations.  The
   LOCK operation may not be granted until all such delegations are
   returned or revoked.  Except where this happens very quickly, one or
   more NFS4ERR_DELAY errors will be returned to requests made while the
   delegation remains outstanding.

18.11.  Operation 13: LOCKT - Test for Lock

18.11.1.  ARGUMENTS

   struct LOCKT4args {
           /* CURRENT_FH: file */
           nfs_lock_type4  locktype;
           offset4         offset;
           length4         length;
           lock_owner4     owner;
   };

18.11.2.  RESULTS

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

Top      Up      ToC       Page 431 
18.11.3.  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.  The owner field in the results
   includes the client ID of the owner of the conflicting lock, whether
   this is the client ID associated with the current session or a
   different client ID.  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.

   The clientid field of the owner MAY be set to any value by the client
   and MUST be ignored by the server.  The reason the server MUST ignore
   the clientid field is that the server MUST derive the client ID from
   the session ID from the SEQUENCE operation of the COMPOUND request.

   If the current filehandle is not an ordinary file, an error will be
   returned to the client.  In the case that the current filehandle
   represents an object of type NF4DIR, NFS4ERR_ISDIR is returned.  If
   the current filehandle designates a symbolic link, NFS4ERR_SYMLINK is
   returned.  In all other cases, NFS4ERR_WRONG_TYPE is returned.

   On success, the current filehandle retains its value.

18.11.4.  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.

   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 might not
   be available.

   As noted in Section 18.10.4, some servers may return
   NFS4ERR_LOCK_RANGE to certain (otherwise non-conflicting) LOCK
   operations that overlap ranges already granted to the current lock-
   owner.

Top      Up      ToC       Page 432 
   The LOCKT operation's test for conflicting locks SHOULD exclude locks
   for the current lock-owner, and thus should return NFS4_OK in such
   cases.  Note that this means that a server might return NFS4_OK to a
   LOCKT request even though a LOCK operation for the same range and
   lock-owner would fail with NFS4ERR_LOCK_RANGE.

   When a client holds an OPEN_DELEGATE_WRITE delegation, it may choose
   (see Section 18.10.4) to handle LOCK requests locally.  In such a
   case, LOCKT requests will similarly be handled locally.

18.12.  Operation 14: LOCKU - Unlock File

18.12.1.  ARGUMENTS

   struct LOCKU4args {
           /* CURRENT_FH: file */
           nfs_lock_type4  locktype;
           seqid4          seqid;
           stateid4        lock_stateid;
           offset4         offset;
           length4         length;
   };

18.12.2.  RESULTS

   union LOCKU4res switch (nfsstat4 status) {
    case   NFS4_OK:
            stateid4       lock_stateid;
    default:
            void;
   };

18.12.3.  DESCRIPTION

   The LOCKU operation unlocks the byte-range 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.

   The seqid parameter MAY be any value and the server MUST ignore it.

Top      Up      ToC       Page 433 
   If the current filehandle is not an ordinary file, an error will be
   returned to the client.  In the case that the current filehandle
   represents an object of type NF4DIR, NFS4ERR_ISDIR is returned.  If
   the current filehandle designates a symbolic link, NFS4ERR_SYMLINK is
   returned.  In all other cases, NFS4ERR_WRONG_TYPE is returned.

   On success, the current filehandle retains its value.

   The server MAY require that the principal, security flavor, and if
   applicable, the GSS mechanism, combination that sent a LOCK operation
   also be the one to send LOCKU on the file.  This might not be
   possible if credentials for the principal are no longer available.
   The server MAY allow the machine credential or SSV credential (see
   Section 18.35) to send LOCKU.

18.12.4.  IMPLEMENTATION

   If the area to be unlocked does not correspond exactly to a lock
   actually held by the lock-owner, 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 lock-owner.  In all of
   these cases, allowed by POSIX locking [24] 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
   operations for the sub-ranges not being unlocked.

   When a client holds an OPEN_DELEGATE_WRITE delegation, it may choose
   (see Section 18.10.4) to handle LOCK requests locally.  In such a
   case, LOCKU operations will similarly be handled locally.

18.13.  Operation 15: LOOKUP - Lookup Filename

18.13.1.  ARGUMENTS

   struct LOOKUP4args {
           /* CURRENT_FH: directory */
           component4      objname;
   };

18.13.2.  RESULTS

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

Top      Up      ToC       Page 434 
18.13.3.  DESCRIPTION

   The LOOKUP operation looks up or finds a file system 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.

18.13.4.  IMPLEMENTATION

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

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

   Unlike NFSv3, NFSv4.1 allows 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 file system.
   This needs to be done to maintain the file object identity checking
   mechanisms common to UNIX clients.

   Servers that limit NFS access to "shared" or "exported" file systems
   should provide a pseudo file system into which the exported file
   systems can be integrated, so that clients can browse the server's
   namespace.  The clients view of a pseudo file system will be limited
   to paths that lead to exported file systems.

   Note: previous versions of the protocol assigned special semantics to
   the names "." and "..".  NFSv4.1 assigns no special semantics to
   these names.  The LOOKUPP operator must be used to look up a parent
   directory.

Top      Up      ToC       Page 435 
   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 look up
   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.

18.14.  Operation 16: LOOKUPP - Lookup Parent Directory

18.14.1.  ARGUMENTS

   /* CURRENT_FH: object */
   void;

18.14.2.  RESULTS

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

18.14.3.  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.

   As is the case with LOOKUP, LOOKUPP will also cross mountpoints.

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

   If the requester's security flavor does not match that configured for
   the parent directory, then the server SHOULD return NFS4ERR_WRONGSEC
   (a future minor revision of NFSv4 may upgrade this to MUST) in the
   LOOKUPP response.  However, if the server does so, it MUST support
   the SECINFO_NO_NAME operation (Section 18.45), so that the client can
   gracefully determine the correct security flavor.

   If the current filehandle is a named attribute directory that is
   associated with a file system object via OPENATTR (i.e., not a sub-
   directory of a named attribute directory), LOOKUPP SHOULD return the
   filehandle of the associated file system object.

Top      Up      ToC       Page 436 
18.14.4.  IMPLEMENTATION

   An issue to note is upward navigation from named attribute
   directories.  The named attribute directories are essentially
   detached from the namespace, and this property should be safely
   represented in the client operating environment.  LOOKUPP on a named
   attribute directory may return the filehandle of the associated file,
   and conveying this to applications might be unsafe as many
   applications expect the parent of an object to always be a directory.
   Therefore, the client may want to hide the parent of named attribute
   directories (represented as ".." in UNIX) or represent the named
   attribute directory as its own parent (as is typically done for the
   file system root directory in UNIX).

18.15.  Operation 17: NVERIFY - Verify Difference in Attributes

18.15.1.  ARGUMENTS

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

18.15.2.  RESULTS

   struct NVERIFY4res {
           nfsstat4        status;
   };

18.15.3.  DESCRIPTION

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

   On success, the current filehandle retains its value.

Top      Up      ToC       Page 437 
18.15.4.  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:

         SEQUENCE
         PUTFH fh
         NVERIFY attrbits attrs
         READ 0 32767

   Contrast this with NFSv3, which would first send a GETATTR in one
   request/reply round trip, and then if attributes indicated that the
   client's cache was stale, then send a READ in another request/reply
   round trip.

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

   When the attribute rdattr_error or any set-only attribute (e.g.,
   time_modify_set) is specified, the error NFS4ERR_INVAL is returned to
   the client.

18.16.  Operation 18: OPEN - Open a Regular File

18.16.1.  ARGUMENTS

   /*
    * Various definitions for OPEN
    */
   enum createmode4 {
           UNCHECKED4      = 0,
           GUARDED4        = 1,
           /* Deprecated in NFSv4.1. */
           EXCLUSIVE4      = 2,
           /*
            * New to NFSv4.1. If session is persistent,
            * GUARDED4 MUST be used.  Otherwise, use
            * EXCLUSIVE4_1 instead of EXCLUSIVE4.
            */
           EXCLUSIVE4_1    = 3
   };

Top      Up      ToC       Page 438 
   struct creatverfattr {
            verifier4      cva_verf;
            fattr4         cva_attrs;
   };

   union createhow4 switch (createmode4 mode) {
    case UNCHECKED4:
    case GUARDED4:
            fattr4         createattrs;
    case EXCLUSIVE4:
            verifier4      createverf;
    case EXCLUSIVE4_1:
            creatverfattr  ch_createboth;
   };

   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;
   } ;

Top      Up      ToC       Page 439 
   /*
    * Share Access and Deny constants for open argument
    */
   const OPEN4_SHARE_ACCESS_READ   = 0x00000001;
   const OPEN4_SHARE_ACCESS_WRITE  = 0x00000002;
   const OPEN4_SHARE_ACCESS_BOTH   = 0x00000003;

   const OPEN4_SHARE_DENY_NONE     = 0x00000000;
   const OPEN4_SHARE_DENY_READ     = 0x00000001;
   const OPEN4_SHARE_DENY_WRITE    = 0x00000002;
   const OPEN4_SHARE_DENY_BOTH     = 0x00000003;


   /* new flags for share_access field of OPEN4args */
   const OPEN4_SHARE_ACCESS_WANT_DELEG_MASK        = 0xFF00;
   const OPEN4_SHARE_ACCESS_WANT_NO_PREFERENCE     = 0x0000;
   const OPEN4_SHARE_ACCESS_WANT_READ_DELEG        = 0x0100;
   const OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG       = 0x0200;
   const OPEN4_SHARE_ACCESS_WANT_ANY_DELEG         = 0x0300;
   const OPEN4_SHARE_ACCESS_WANT_NO_DELEG          = 0x0400;
   const OPEN4_SHARE_ACCESS_WANT_CANCEL            = 0x0500;

   const
    OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL
    = 0x10000;

   const
    OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED
    = 0x20000;

   enum open_delegation_type4 {
           OPEN_DELEGATE_NONE      = 0,
           OPEN_DELEGATE_READ      = 1,
           OPEN_DELEGATE_WRITE     = 2,
           OPEN_DELEGATE_NONE_EXT  = 3 /* new to v4.1 */
   };

   enum open_claim_type4 {
           /*
            * Not a reclaim.
            */
           CLAIM_NULL              = 0,

           CLAIM_PREVIOUS          = 1,
           CLAIM_DELEGATE_CUR      = 2,
           CLAIM_DELEGATE_PREV     = 3,

Top      Up      ToC       Page 440 
           /*
            * Not a reclaim.
            *
            * Like CLAIM_NULL, but object identified
            * by the current filehandle.
            */
           CLAIM_FH                = 4, /* new to v4.1 */

           /*
            * Like CLAIM_DELEGATE_CUR, but object identified
            * by current filehandle.
            */
           CLAIM_DELEG_CUR_FH      = 5, /* new to v4.1 */

           /*
            * Like CLAIM_DELEGATE_PREV, but object identified
            * by current filehandle.
            */
           CLAIM_DELEG_PREV_FH     = 6 /* new to v4.1 */
   };

   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;

Top      Up      ToC       Page 441 
    /*
     * 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;

    /*
     * Like CLAIM_NULL.  No special rights
     * to file.  Ordinary OPEN of the
     * specified file by current filehandle.
     */
    case CLAIM_FH: /* new to v4.1 */
           /* CURRENT_FH: regular file to open */
           void;

    /*
     * Like CLAIM_DELEGATE_PREV.  Right to file based on a
     * delegation granted to a previous boot
     * instance of the client.  File is identified by
     * by filehandle.
     */
    case CLAIM_DELEG_PREV_FH: /* new to v4.1 */
           /* CURRENT_FH: file being opened */
           void;

    /*
     * Like CLAIM_DELEGATE_CUR.  Right to file based on
     * a delegation granted by the server.
     * File is identified by filehandle.
     */
    case CLAIM_DELEG_CUR_FH: /* new to v4.1 */
            /* CURRENT_FH: file being opened */
            stateid4       oc_delegate_stateid;

   };

Top      Up      ToC       Page 442 
   /*
    * OPEN: Open a file, potentially receiving an OPEN delegation
    */
   struct OPEN4args {
           seqid4          seqid;
           uint32_t        share_access;
           uint32_t        share_deny;
           open_owner4     owner;
           openflag4       openhow;
           open_claim4     claim;
   };

18.16.2.  RESULTS

   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
                            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. */
   };

Top      Up      ToC       Page 443 
   enum why_no_delegation4 { /* new to v4.1 */
           WND4_NOT_WANTED         = 0,
           WND4_CONTENTION         = 1,
           WND4_RESOURCE           = 2,
           WND4_NOT_SUPP_FTYPE     = 3,
           WND4_WRITE_DELEG_NOT_SUPP_FTYPE = 4,
           WND4_NOT_SUPP_UPGRADE   = 5,
           WND4_NOT_SUPP_DOWNGRADE = 6,
           WND4_CANCELLED          = 7,
           WND4_IS_DIR             = 8
   };

   union open_none_delegation4 /* new to v4.1 */
   switch (why_no_delegation4 ond_why) {
           case WND4_CONTENTION:
                   bool ond_server_will_push_deleg;
           case WND4_RESOURCE:
                   bool ond_server_will_signal_avail;
           default:
                   void;
   };

   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;
           case OPEN_DELEGATE_NONE_EXT: /* new to v4.1 */
                   open_none_delegation4 od_whynone;
   };

   /*
    * Result flags
    */

   /* Client must confirm open */
   const OPEN4_RESULT_CONFIRM      = 0x00000002;
   /* Type of file locking behavior at the server */
   const OPEN4_RESULT_LOCKTYPE_POSIX = 0x00000004;
   /* Server will preserve file if removed while open */
   const OPEN4_RESULT_PRESERVE_UNLINKED = 0x00000008;

Top      Up      ToC       Page 444 
   /*
    * Server may use CB_NOTIFY_LOCK on locks
    * derived from this open
    */
   const OPEN4_RESULT_MAY_NOTIFY_LOCK = 0x00000020;

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

   union OPEN4res switch (nfsstat4 status) {
    case NFS4_OK:
           /* New CURRENT_FH: opened file */
           OPEN4resok      resok4;
    default:
           void;
   };

18.16.3.  DESCRIPTION

   The OPEN operation opens a regular file in a directory with the
   provided name or filehandle.  OPEN can also create a file if a name
   is provided, and the client specifies it wants to create a file.
   Specification of whether or not a file is to be created, and the
   method of creation is via the openhow parameter.  The openhow
   parameter consists of a switched union (data type opengflag4), which
   switches on the value of opentype (OPEN4_NOCREATE or OPEN4_CREATE).
   If OPEN4_CREATE is specified, this leads to another switched union
   (data type createhow4) that supports four cases of creation methods:
   UNCHECKED4, GUARDED4, EXCLUSIVE4, or EXCLUSIVE4_1.  If opentype is
   OPEN4_CREATE, then the claim field of the claim field MUST be one of
   CLAIM_NULL, CLAIM_DELEGATE_CUR, or CLAIM_DELEGATE_PREV, because these
   claim methods include a component of a file name.

   Upon success (which might entail creation of a new file), the current
   filehandle is replaced by that of the created or existing object.

   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 or EXCLUSIVE4_1 and the current filehandle is a named
   attribute directory, the server will return EINVAL.

Top      Up      ToC       Page 445 
   UNCHECKED4 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
   UNCHECKED4 create encounters an existing file, the attributes
   specified by createattrs are not used, except that when createattrs
   specifies the size attribute with a size of zero, the existing file
   is truncated.

   If GUARDED4 is specified, the server checks for the presence of a
   duplicate object by name before performing the create.  If a
   duplicate exists, NFS4ERR_EXIST is returned.  If the object does not
   exist, the request is performed as described for UNCHECKED4.

   For the UNCHECKED4 and GUARDED4 cases, where the operation is
   successful, the server will return to the client an attribute mask
   signifying which attributes were successfully set for the object.

   EXCLUSIVE4_1 and EXCLUSIVE4 specify 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.

   If using EXCLUSIVE4, and if the server uses attributes to store the
   exclusive create verifier, the server will signify which attributes
   it used by setting the appropriate bits in the attribute mask that is
   returned in the results.  Unlike UNCHECKED4, GUARDED4, and
   EXCLUSIVE4_1, EXCLUSIVE4 does not support the setting of attributes
   at file creation, and after a successful OPEN via EXCLUSIVE4, the
   client MUST send a SETATTR to set attributes to a known state.

   In NFSv4.1, EXCLUSIVE4 has been deprecated in favor of EXCLUSIVE4_1.
   Unlike EXCLUSIVE4, attributes may be provided in the EXCLUSIVE4_1
   case, but because the server may use attributes of the target object
   to store the verifier, the set of allowable attributes may be fewer
   than the set of attributes SETATTR allows.  The allowable attributes
   for EXCLUSIVE4_1 are indicated in the suppattr_exclcreat
   (Section 5.8.1.14) attribute.  If the client attempts to set in
   cva_attrs an attribute that is not in suppattr_exclcreat, the server
   MUST return NFS4ERR_INVAL.  The response field, attrset, indicates
   both which attributes the server set from cva_attrs and which
   attributes the server used to store the verifier.  As described in

Top      Up      ToC       Page 446 
   Section 18.16.4, the client can compare cva_attrs.attrmask with
   attrset to determine which attributes were used to store the
   verifier.

   With the addition of persistent sessions and pNFS, under some
   conditions EXCLUSIVE4 MUST NOT be used by the client or supported by
   the server.  The following table summarizes the appropriate and
   mandated exclusive create methods for implementations of NFSv4.1:

                   Required methods for exclusive create

   +----------------+-----------+---------------+----------------------+
   | Persistent     | Server    | Server        | Client Allowed       |
   | Reply Cache    | Supports  | REQUIRED      |                      |
   | Enabled        | pNFS      |               |                      |
   +----------------+-----------+---------------+----------------------+
   | no             | no        | EXCLUSIVE4_1  | EXCLUSIVE4_1         |
   |                |           | and           | (SHOULD) or          |
   |                |           | EXCLUSIVE4    | EXCLUSIVE4 (SHOULD   |
   |                |           |               | NOT)                 |
   | no             | yes       | EXCLUSIVE4_1  | EXCLUSIVE4_1         |
   | yes            | no        | GUARDED4      | GUARDED4             |
   | yes            | yes       | GUARDED4      | GUARDED4             |
   +----------------+-----------+---------------+----------------------+

                                 Table 10

   If CREATE_SESSION4_FLAG_PERSIST is set in the results of
   CREATE_SESSION, the reply cache is persistent (see Section 18.36).
   If the EXCHGID4_FLAG_USE_PNFS_MDS flag is set in the results from
   EXCHANGE_ID, the server is a pNFS server (see Section 18.35).  If the
   client attempts to use EXCLUSIVE4 on a persistent session, or a
   session derived from an EXCHGID4_FLAG_USE_PNFS_MDS client ID, the
   server MUST return NFS4ERR_INVAL.

   With persistent sessions, exclusive create semantics are fully
   achievable via GUARDED4, and so EXCLUSIVE4 or EXCLUSIVE4_1 MUST NOT
   be used.  When pNFS is being used, the layout_hint attribute might
   not be supported after the file is created.  Only the EXCLUSIVE4_1
   and GUARDED methods of exclusive file creation allow the atomic
   setting of attributes.

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

Top      Up      ToC       Page 447 
   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
   OPEN4_SHARE_DENY_NONE.  In the case that there is an existing SHARE
   reservation that conflicts with the OPEN request, the server returns
   the error NFS4ERR_SHARE_DENIED.  For additional discussion of SHARE
   semantics, see Section 9.7.

   For each OPEN, the client provides a value for the owner field of the
   OPEN argument.  The owner field is of data type open_owner4, and
   contains a field called clientid and a field called owner.  The
   client can set the clientid field to any value and the server MUST
   ignore it.  Instead, the server MUST derive the client ID from the
   session ID of the SEQUENCE operation of the COMPOUND request.

   The "seqid" field of the request is not used in NFSv4.1, but it MAY
   be any value and the server MUST ignore it.

   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 that the client claims to
   possess.  There are seven claim types as follows:

Top      Up      ToC       Page 448 
   +----------------------+--------------------------------------------+
   | open type            | description                                |
   +----------------------+--------------------------------------------+
   | CLAIM_NULL, CLAIM_FH | For the client, this is a new OPEN request |
   |                      | and there is no previous state associated  |
   |                      | with the file for the client.  With        |
   |                      | CLAIM_NULL, the file is identified by the  |
   |                      | current filehandle and the specified       |
   |                      | component name.  With CLAIM_FH (new to     |
   |                      | NFSv4.1), the file is identified by just   |
   |                      | the current filehandle.                    |
   | CLAIM_PREVIOUS       | The client is claiming basic OPEN state    |
   |                      | for a file that was held previous to a     |
   |                      | server restart.  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    |
   | CLAIM_DELEG_CUR_FH   | OPEN as granted by the server.  Generally, |
   |                      | this is done as part of recalling a        |
   |                      | delegation.  With CLAIM_DELEGATE_CUR, the  |
   |                      | file is identified by the current          |
   |                      | filehandle and the specified component     |
   |                      | name.  With CLAIM_DELEG_CUR_FH (new to     |
   |                      | NFSv4.1), the file is identified by just   |
   |                      | the current filehandle.                    |
   | CLAIM_DELEGATE_PREV, | The client is claiming a delegation        |
   | CLAIM_DELEG_PREV_FH  | granted to a previous client instance;     |
   |                      | used after the client restarts.  The       |
   |                      | server MAY support CLAIM_DELEGATE_PREV     |
   |                      | and/or CLAIM_DELEG_PREV_FH (new to         |
   |                      | NFSv4.1).  If it does support either claim |
   |                      | type, CREATE_SESSION MUST NOT remove the   |
   |                      | client's delegation state, and the server  |
   |                      | MUST support the DELEGPURGE operation.     |
   +----------------------+--------------------------------------------+

   For OPEN requests that reach the server during the grace period, the
   server returns an error of NFS4ERR_GRACE.  The following claim types
   are exceptions:

   o  OPEN requests specifying the claim type CLAIM_PREVIOUS are devoted
      to reclaiming opens after a server restart and are typically only
      valid during the grace period.

   o  OPEN requests specifying the claim types CLAIM_DELEGATE_CUR and
      CLAIM_DELEG_CUR_FH are valid both during and after the grace
      period.  Since the granting of the delegation that they are

Top      Up      ToC       Page 449 
      subordinate to assures that there is no conflict with locks to be
      reclaimed by other clients, the server need not return
      NFS4ERR_GRACE when these are received during the grace period.

   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 Section 10.4.  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.

   o  OPEN4_RESULT_CONFIRM is deprecated and MUST NOT be returned by an
      NFSv4.1 server.

   o  OPEN4_RESULT_LOCKTYPE_POSIX indicates that the server's byte-range
      locking behavior supports the complete set of POSIX locking
      techniques [24].  From this, the client can choose to manage byte-
      range locking state in a way to handle a mismatch of byte-range
      locking management.

   o  OPEN4_RESULT_PRESERVE_UNLINKED indicates that the server will
      preserve the open file if the client (or any other client) removes
      the file as long as it is open.  Furthermore, the server promises
      to preserve the file through the grace period after server
      restart, thereby giving the client the opportunity to reclaim its
      open.

   o  OPEN4_RESULT_MAY_NOTIFY_LOCK indicates that the server may attempt
      CB_NOTIFY_LOCK callbacks for locks on this file.  This flag is a
      hint only, and may be safely ignored by the client.

   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 Section 14.5 for further discussion.

   When an OPEN is done and the specified open-owner 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 open-owner.  In this case, the

Top      Up      ToC       Page 450 
   stateid returned as an "other" field that matches that of the
   previous open while the "seqid" field is incremented to reflect the
   change status due to the new open.

   If the underlying file system 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 file system.

   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 file system.  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 (UNCHECKED4 or GUARDED4) or cva_attrs (EXCLUSIVE4_1) is
   specified, and includes an owner, owner_group, or ACE 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 an OPEN that specifies a size of zero (e.g.,
   truncation) and the file has named attributes, the named attributes
   are left as is and are not removed.

   NFSv4.1 gives more precise control to clients over acquisition of
   delegations via the following new flags for the share_access field of
   OPEN4args:

   OPEN4_SHARE_ACCESS_WANT_READ_DELEG

   OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG

   OPEN4_SHARE_ACCESS_WANT_ANY_DELEG

   OPEN4_SHARE_ACCESS_WANT_NO_DELEG

   OPEN4_SHARE_ACCESS_WANT_CANCEL

   OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL

   OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED

   If (share_access & OPEN4_SHARE_ACCESS_WANT_DELEG_MASK) is not zero,
   then the client will have specified one and only one of:

   OPEN4_SHARE_ACCESS_WANT_READ_DELEG

   OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG

Top      Up      ToC       Page 451 
   OPEN4_SHARE_ACCESS_WANT_ANY_DELEG

   OPEN4_SHARE_ACCESS_WANT_NO_DELEG

   OPEN4_SHARE_ACCESS_WANT_CANCEL

   Otherwise, the client is neither indicating a desire nor a non-desire
   for a delegation, and the server MAY or MAY not return a delegation
   in the OPEN response.

   If the server supports the new _WANT_ flags and the client sends one
   or more of the new flags, then in the event the server does not
   return a delegation, it MUST return a delegation type of
   OPEN_DELEGATE_NONE_EXT.  The field ond_why in the reply indicates why
   no delegation was returned and will be one of:

   WND4_NOT_WANTED  The client specified
      OPEN4_SHARE_ACCESS_WANT_NO_DELEG.

   WND4_CONTENTION  There is a conflicting delegation or open on the
      file.

   WND4_RESOURCE  Resource limitations prevent the server from granting
      a delegation.

   WND4_NOT_SUPP_FTYPE  The server does not support delegations on this
      file type.

   WND4_WRITE_DELEG_NOT_SUPP_FTYPE  The server does not support
      OPEN_DELEGATE_WRITE delegations on this file type.

   WND4_NOT_SUPP_UPGRADE  The server does not support atomic upgrade of
      an OPEN_DELEGATE_READ delegation to an OPEN_DELEGATE_WRITE
      delegation.

   WND4_NOT_SUPP_DOWNGRADE  The server does not support atomic downgrade
      of an OPEN_DELEGATE_WRITE delegation to an OPEN_DELEGATE_READ
      delegation.

   WND4_CANCELED  The client specified OPEN4_SHARE_ACCESS_WANT_CANCEL
      and now any "want" for this file object is cancelled.

   WND4_IS_DIR  The specified file object is a directory, and the
      operation is OPEN or WANT_DELEGATION, which do not support
      delegations on directories.

Top      Up      ToC       Page 452 
   OPEN4_SHARE_ACCESS_WANT_READ_DELEG,
   OPEN_SHARE_ACCESS_WANT_WRITE_DELEG, or
   OPEN_SHARE_ACCESS_WANT_ANY_DELEG mean, respectively, the client wants
   an OPEN_DELEGATE_READ, OPEN_DELEGATE_WRITE, or any delegation
   regardless which of OPEN4_SHARE_ACCESS_READ,
   OPEN4_SHARE_ACCESS_WRITE, or OPEN4_SHARE_ACCESS_BOTH is set.  If the
   client has an OPEN_DELEGATE_READ delegation on a file and requests an
   OPEN_DELEGATE_WRITE delegation, then the client is requesting atomic
   upgrade of its OPEN_DELEGATE_READ delegation to an
   OPEN_DELEGATE_WRITE delegation.  If the client has an
   OPEN_DELEGATE_WRITE delegation on a file and requests an
   OPEN_DELEGATE_READ delegation, then the client is requesting atomic
   downgrade to an OPEN_DELEGATE_READ delegation.  A server MAY support
   atomic upgrade or downgrade.  If it does, then the returned
   delegation_type of OPEN_DELEGATE_READ or OPEN_DELEGATE_WRITE that is
   different from the delegation type the client currently has,
   indicates successful upgrade or downgrade.  If the server does not
   support atomic delegation upgrade or downgrade, then ond_why will be
   set to WND4_NOT_SUPP_UPGRADE or WND4_NOT_SUPP_DOWNGRADE.

   OPEN4_SHARE_ACCESS_WANT_NO_DELEG means that the client wants no
   delegation.

   OPEN4_SHARE_ACCESS_WANT_CANCEL means that the client wants no
   delegation and wants to cancel any previously registered "want" for a
   delegation.

   The client may set one or both of
   OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL and
   OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED.  However, they
   will have no effect unless one of following is set:

   o  OPEN4_SHARE_ACCESS_WANT_READ_DELEG

   o  OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG

   o  OPEN4_SHARE_ACCESS_WANT_ANY_DELEG

   If the client specifies
   OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL, then it wishes
   to register a "want" for a delegation, in the event the OPEN results
   do not include a delegation.  If so and the server denies the
   delegation due to insufficient resources, the server MAY later inform
   the client, via the CB_RECALLABLE_OBJ_AVAIL operation, that the
   resource limitation condition has eased.  The server will tell the
   client that it intends to send a future CB_RECALLABLE_OBJ_AVAIL
   operation by setting delegation_type in the results to
   OPEN_DELEGATE_NONE_EXT, ond_why to WND4_RESOURCE, and

Top      Up      ToC       Page 453 
   ond_server_will_signal_avail set to TRUE.  If
   ond_server_will_signal_avail is set to TRUE, the server MUST later
   send a CB_RECALLABLE_OBJ_AVAIL operation.

   If the client specifies
   OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_UNCONTENDED, then it wishes
   to register a "want" for a delegation, in the event the OPEN results
   do not include a delegation.  If so and the server denies the
   delegation due to contention, the server MAY later inform the client,
   via the CB_PUSH_DELEG operation, that the contention condition has
   eased.  The server will tell the client that it intends to send a
   future CB_PUSH_DELEG operation by setting delegation_type in the
   results to OPEN_DELEGATE_NONE_EXT, ond_why to WND4_CONTENTION, and
   ond_server_will_push_deleg to TRUE.  If ond_server_will_push_deleg is
   TRUE, the server MUST later send a CB_PUSH_DELEG operation.

   If the client has previously registered a want for a delegation on a
   file, and then sends a request to register a want for a delegation on
   the same file, the server MUST return a new error:
   NFS4ERR_DELEG_ALREADY_WANTED.  If the client wishes to register a
   different type of delegation want for the same file, it MUST cancel
   the existing delegation WANT.

18.16.4.  IMPLEMENTATION

   In absence of a persistent session, the client invokes exclusive
   create by setting the how parameter to EXCLUSIVE4 or EXCLUSIVE4_1.
   In these cases, the client provides a verifier that can reasonably be
   expected to be unique.  A combination of a client 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 file systems that do not
   provide a mechanism for the storage of arbitrary file attributes, the
   server may use one or more elements of the object's metadata 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 server's reply
   cache for storage of the verifier.  A nonpersistent reply cache does
   not survive a crash and the session and reply cache may be deleted
   after a network partition that exceeds the lease time, thus opening
   failure windows.

Top      Up      ToC       Page 454 
   An NFSv4.1 server SHOULD NOT store the verifier in any of the file's
   RECOMMENDED or REQUIRED attributes.  If it does, the server SHOULD
   use time_modify_set or time_access_set to store the verifier.  The
   server SHOULD NOT store the verifier in the following attributes:

      acl (it is desirable for access control to be established at
      creation),

      dacl (ditto),

      mode (ditto),

      owner (ditto),

      owner_group (ditto),

      retentevt_set (it may be desired to establish retention at
      creation)

      retention_hold (ditto),

      retention_set (ditto),

      sacl (it is desirable for auditing control to be established at
      creation),

      size (on some servers, size may have a limited range of values),

      mode_set_masked (as with mode),

         and

      time_creation (a meaningful file creation should be set when the
      file is created).

   Another alternative for the server is to use a named attribute to
   store the verifier.

   Because the EXCLUSIVE4 create method does not specify initial
   attributes when processing an EXCLUSIVE4 create, the server

   o  SHOULD set the owner of the file to that corresponding to the
      credential of request's RPC header.

   o  SHOULD NOT leave the file's access control to anyone but the owner
      of the file.

Top      Up      ToC       Page 455 
   If the server cannot support 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.

   After the client has performed a successful exclusive create, the
   attrset response indicates which attributes were used to store the
   verifier.  If EXCLUSIVE4 was used, the attributes set in attrset were
   used for the verifier.  If EXCLUSIVE4_1 was used, the client
   determines the attributes used for the verifier by comparing attrset
   with cva_attrs.attrmask; any bits set in the former but not the
   latter identify the attributes used to store the verifier.  The
   client MUST immediately send a SETATTR to set attributes used to
   store the verifier.  Until it does so, the attributes used to store
   the verifier cannot be relied upon.  The subsequent SETATTR MUST NOT
   occur in the same COMPOUND request as the OPEN.

   Unless a persistent session is used, use of the GUARDED4 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 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 GUARDED4 to
   prevent against a sequence like create, write, create (retransmitted)
   from occurring.

   For SHARE reservations, the value of the expression (share_access &
   ~OPEN4_SHARE_ACCESS_WANT_DELEG_MASK) MUST be one of
   OPEN4_SHARE_ACCESS_READ, OPEN4_SHARE_ACCESS_WRITE, or
   OPEN4_SHARE_ACCESS_BOTH.  If not, the server MUST return
   NFS4ERR_INVAL.  The value of share_deny MUST be one of
   OPEN4_SHARE_DENY_NONE, OPEN4_SHARE_DENY_READ, OPEN4_SHARE_DENY_WRITE,
   or OPEN4_SHARE_DENY_BOTH.  If not, the server MUST return
   NFS4ERR_INVAL.

Top      Up      ToC       Page 456 
   Based on the share_access value (OPEN4_SHARE_ACCESS_READ,
   OPEN4_SHARE_ACCESS_WRITE, or OPEN4_SHARE_ACCESS_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's READ or WRITE
   operation is not authorized (depending on the share_access value),
   the server MUST return NFS4ERR_ACCESS.

   Note that if the client ID was not created with the
   EXCHGID4_FLAG_BIND_PRINC_STATEID capability set in the reply to
   EXCHANGE_ID, then the server MUST NOT impose any requirement that
   READs and WRITEs sent for an open file have the same credentials as
   the OPEN itself, and the server is REQUIRED to perform access
   checking on the READs and WRITEs themselves.  Otherwise, if the reply
   to EXCHANGE_ID did have EXCHGID4_FLAG_BIND_PRINC_STATEID set, then
   with one exception, the credentials used in the OPEN request MUST
   match those used in the READs and WRITEs, and the stateids in the
   READs and WRITEs MUST match, or be derived from the stateid from the
   reply to OPEN.  The exception is if SP4_SSV or SP4_MACH_CRED state
   protection is used, and the spo_must_allow result of EXCHANGE_ID
   includes the READ and/or WRITE operations.  In that case, the machine
   or SSV credential will be allowed to send READ and/or WRITE.  See
   Section 18.35.

   If the component provided to OPEN is a symbolic link, the error
   NFS4ERR_SYMLINK will be returned to the client, while if it is a
   directory the error NFS4ERR_ISDIR will be returned.  If the component
   is neither of those but not an ordinary file, the error
   NFS4ERR_WRONG_TYPE is returned.  If the current filehandle is not a
   directory, the error NFS4ERR_NOTDIR will be returned.

   The use of the OPEN4_RESULT_PRESERVE_UNLINKED result flag allows a
   client to avoid the common implementation practice of renaming an
   open file to ".nfs<unique value>" after it removes the file.  After
   the server returns OPEN4_RESULT_PRESERVE_UNLINKED, if a client sends
   a REMOVE operation that would reduce the file's link count to zero,
   the server SHOULD report a value of zero for the numlinks attribute
   on the file.

   If another client has a delegation of the file being opened that
   conflicts with open being done (sometimes depending on the
   share_access or share_deny value specified), the delegation(s) MUST
   be recalled, and the operation cannot proceed until each such
   delegation is returned or revoked.  Except where this happens very

Top      Up      ToC       Page 457 
   quickly, one or more NFS4ERR_DELAY errors will be returned to
   requests made while delegation remains outstanding.  In the case of
   an OPEN_DELEGATE_WRITE delegation, any open by a different client
   will conflict, while for an OPEN_DELEGATE_READ delegation, only opens
   with one of the following characteristics will be considered
   conflicting:

   o  The value of share_access includes the bit
      OPEN4_SHARE_ACCESS_WRITE.

   o  The value of share_deny specifies OPEN4_SHARE_DENY_READ or
      OPEN4_SHARE_DENY_BOTH.

   o  OPEN4_CREATE is specified together with UNCHECKED4, the size
      attribute is specified as zero (for truncation), and an existing
      file is truncated.

   If OPEN4_CREATE is specified and the file does not exist and the
   current filehandle designates a directory for which another client
   holds a directory delegation, then, unless the delegation is such
   that the situation can be resolved by sending a notification, the
   delegation MUST be recalled, and the operation cannot proceed until
   the delegation is returned or revoked.  Except where this happens
   very quickly, one or more NFS4ERR_DELAY errors will be returned to
   requests made while delegation remains outstanding.

   If OPEN4_CREATE is specified and the file does not exist and the
   current filehandle designates a directory for which one or more
   directory delegations exist, then, when those delegations request
   such notifications, NOTIFY4_ADD_ENTRY will be generated as a result
   of this operation.

18.16.4.1.  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.

Top      Up      ToC       Page 458 
   See also Section 2.10.6.4.

18.17.  Operation 19: OPENATTR - Open Named Attribute Directory

18.17.1.  ARGUMENTS

   struct OPENATTR4args {
           /* CURRENT_FH: object */
           bool    createdir;
   };


18.17.2.  RESULTS

   struct OPENATTR4res {
           /*
            * If status is NFS4_OK,
            *   new CURRENT_FH: named attribute
            *                   directory
            */
           nfsstat4        status;
   };

18.17.3.  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 file system object.  Filehandles
   returned within the named attribute directory will designate objects
   of 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 and its filehandle becomes the current
   filehandle.  On the other hand, if createdir has a value of TRUE and
   the named attribute directory already exists, no error results and
   the filehandle of the existing directory becomes the current
   filehandle.  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.

Top      Up      ToC       Page 459 
   If the current file handle designates an object of type NF4NAMEDATTR
   (a named attribute) or NF4ATTRDIR (a named attribute directory), an
   error of NFS4ERR_WRONG_TYPE is returned to the client.  Named
   attributes or a named attribute directory MUST NOT have their own
   named attributes.

18.17.4.  IMPLEMENTATION

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

18.18.  Operation 21: OPEN_DOWNGRADE - Reduce Open File Access

18.18.1.  ARGUMENTS

   struct OPEN_DOWNGRADE4args {
           /* CURRENT_FH: opened file */
           stateid4        open_stateid;
           seqid4          seqid;
           uint32_t        share_access;
           uint32_t        share_deny;
   };

18.18.2.  RESULTS

   struct OPEN_DOWNGRADE4resok {
           stateid4        open_stateid;
   };

   union OPEN_DOWNGRADE4res switch(nfsstat4 status) {
    case NFS4_OK:
           OPEN_DOWNGRADE4resok    resok4;
    default:
            void;
   };

18.18.3.  DESCRIPTION

   This operation is used to adjust the access and deny states for a
   given open.  This is necessary when a given open-owner opens the same
   file multiple times with different access and deny values.  In this
   situation, a close of one of the opens may change the appropriate
   share_access and share_deny flags to remove bits associated with
   opens no longer in effect.

Top      Up      ToC       Page 460 
   Valid values for the expression (share_access &
   ~OPEN4_SHARE_ACCESS_WANT_DELEG_MASK) are OPEN4_SHARE_ACCESS_READ,
   OPEN4_SHARE_ACCESS_WRITE, or OPEN4_SHARE_ACCESS_BOTH.  If the client
   specifies other values, the server MUST reply with NFS4ERR_INVAL.

   Valid values for the share_deny field are OPEN4_SHARE_DENY_NONE,
   OPEN4_SHARE_DENY_READ, OPEN4_SHARE_DENY_WRITE, or
   OPEN4_SHARE_DENY_BOTH.  If the client specifies other values, the
   server MUST reply with NFS4ERR_INVAL.

   After checking for valid values of share_access and share_deny, the
   server replaces the current access and deny modes on the file with
   share_access and share_deny subject to the following constraints:

   o  The bits in share_access SHOULD equal the union of the
      share_access bits (not including OPEN4_SHARE_WANT_* bits)
      specified for some subset of the OPENs in effect for the current
      open-owner on the current file.

   o  The bits in share_deny SHOULD equal the union of the share_deny
      bits specified for some subset of the OPENs in effect for the
      current open-owner on the current file.

   If the above constraints are not respected, the server SHOULD return
   the error NFS4ERR_INVAL.  Since share_access and share_deny bits
   should be subsets of those already granted, short of a defect in the
   client or server implementation, it is not possible for the
   OPEN_DOWNGRADE request to be denied because of conflicting share
   reservations.

   The seqid argument is not used in NFSv4.1, MAY be any value, and MUST
   be ignored by the server.

   On success, the current filehandle retains its value.

18.18.4.  IMPLEMENTATION

   An OPEN_DOWNGRADE operation may make OPEN_DELEGATE_READ delegations
   grantable where they were not previously.  Servers may choose to
   respond immediately if there are pending delegation want requests or
   may respond to the situation at a later time.


Next RFC Part