16.12. Operation 14: LOCKU - Unlock File
16.12.1. SYNOPSIS
(cfh) type, seqid, stateid, offset, length -> stateid16.12.2. ARGUMENT
struct LOCKU4args { /* CURRENT_FH: file */ nfs_lock_type4 locktype; seqid4 seqid; stateid4 lock_stateid; offset4 offset; length4 length; };16.12.3. RESULT
union LOCKU4res switch (nfsstat4 status) { case NFS4_OK: stateid4 lock_stateid; default: void; };16.12.4. 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. On success, the current filehandle retains its value.
16.12.5. 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 cases where (1) the area is not locked, (2) the area is a sub-range of the area locked, (3) it overlaps the area locked without matching exactly, or (4) the area specified includes multiple locks held by the lock-owner. In all of these cases, allowed by POSIX locking [fcntl] 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. When a client holds an OPEN_DELEGATE_WRITE delegation, it may choose (see Section 16.10.5) to handle LOCK requests locally. In such a case, LOCKU requests will similarly be handled locally.
16.13. Operation 15: LOOKUP - Look Up Filename
16.13.1. SYNOPSIS
(cfh), component -> (cfh)16.13.2. ARGUMENT
struct LOOKUP4args { /* CURRENT_FH: directory */ component4 objname; };16.13.3. RESULT
struct LOOKUP4res { /* CURRENT_FH: object */ nfsstat4 status; };16.13.4. DESCRIPTION
This operation performs a LOOKUP 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 because either it does not exist or the client does not have permission to evaluate it, then an error will be returned, and the current filehandle will be unchanged. 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 12.7 for further discussion.
16.13.5. IMPLEMENTATION
If the client wants to achieve the effect of a multi-component lookup, it may construct a COMPOUND request such as the following (and obtain each filehandle): PUTFH (directory filehandle) LOOKUP "pub" GETFH LOOKUP "foo" GETFH LOOKUP "bar" GETFH NFSv4 servers depart from the semantics of previous NFS versions in allowing LOOKUP requests to cross mount points on the server. The client can detect a mount point 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 mount point. UNIX clients that detect a mount point 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 "shares" 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 assigns no special semantics to these names. The LOOKUPP operator must be used to look up 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, NFS4ERR_SYMLINK is returned as the error. For all other non-directory file types, the error NFS4ERR_NOTDIR is returned.
16.14. Operation 16: LOOKUPP - Look Up Parent Directory
16.14.1. SYNOPSIS
(cfh) -> (cfh)16.14.2. ARGUMENT
/* CURRENT_FH: object */ void;16.14.3. RESULT
struct LOOKUPP4res { /* CURRENT_FH: directory */ nfsstat4 status; };16.14.4. 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.16.14.5. IMPLEMENTATION
As for LOOKUP, LOOKUPP will also cross mount points. If the current filehandle is not a directory or named attribute directory, the error NFS4ERR_NOTDIR is returned. If the current filehandle is a named attribute directory that is associated with a file system object via OPENATTR (i.e., not a subdirectory of a named attribute directory), LOOKUPP SHOULD return the filehandle of the associated file system object.
16.15. Operation 17: NVERIFY - Verify Difference in Attributes
16.15.1. SYNOPSIS
(cfh), fattr -> -16.15.2. ARGUMENT
struct NVERIFY4args { /* CURRENT_FH: object */ fattr4 obj_attributes; };16.15.3. RESULT
struct NVERIFY4res { nfsstat4 status; };16.15.4. 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.
16.15.5. 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 file system 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.
16.16. Operation 18: OPEN - Open a Regular File
16.16.1. SYNOPSIS
(cfh), seqid, share_access, share_deny, owner, openhow, claim -> (cfh), stateid, cinfo, rflags, attrset, delegation16.16.2. ARGUMENT
/* * Various definitions for OPEN */ enum createmode4 { UNCHECKED4 = 0, GUARDED4 = 1, EXCLUSIVE4 = 2 }; union createhow4 switch (createmode4 mode) { case UNCHECKED4: case GUARDED4: fattr4 createattrs; case EXCLUSIVE4: verifier4 createverf; }; 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 }; 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; }; /* * 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; };
16.16.3. 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 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; }; /* * 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; 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: /* CURRENT_FH: opened file */ OPEN4resok resok4; default: void; };16.16.4. Warning to Client Implementers
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.16.16.5. 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: UNCHECKED4, GUARDED4, or EXCLUSIVE4.
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. 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 a size of zero is specified, 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, an error of NFS4ERR_EXIST is returned as the status. If the object does not exist, the request is performed as described for UNCHECKED4. For each of these cases (UNCHECKED4 and GUARDED4), 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 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 verifier provided by the client, 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 was used 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 an 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 Section 9.9. 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 four basic claim types that cover the various situations for an OPEN. They are as follows: CLAIM_NULL: For the client, this is a new OPEN request, and there is no previous state associated 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. This is generally used when a server is returning persistent filehandles; the client may not have the filename to reclaim the OPEN. CLAIM_DELEGATE_CUR: The client is claiming a delegation for OPEN as granted by the server. This is generally done as part of recalling a delegation. CLAIM_DELEGATE_PREV: The client is claiming a delegation granted to a previous client instance. This claim type is for use after a SETCLIENTID_CONFIRM and before the corresponding DELEGPURGE in two situations: after a client reboot and after a lease expiration that resulted in loss of all lock state. 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. The following errors apply to use of the CLAIM_DELEGATE_PREV claim type: o NFS4ERR_NOTSUPP is returned if the server does not support this claim type. o NFS4ERR_INVAL is returned if the reclaim is done at an inappropriate time, e.g., after DELEGPURGE has been done.
o NFS4ERR_BAD_RECLAIM is returned if the other error conditions do not apply and the server has no record of the delegation whose reclaim is being attempted. 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 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. OPEN4_RESULT_CONFIRM indicates that the client MUST execute an OPEN_CONFIRM operation before using the open file. OPEN4_RESULT_LOCKTYPE_POSIX indicates that the server's file locking behavior supports the complete set of POSIX locking techniques [fcntl]. From this, the client can choose to manage file locking state in such a way as to handle a mismatch 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 Section 12.7 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 owner. In this case, the stateid returned has an "other" field that matches that of the previous open, while the seqid field is incremented to reflect the changed status due to the new open (Section 9.1.4).
If the underlying file system at the server is only accessible in a read-only mode and the OPEN request has specified OPEN4_SHARE_ACCESS_WRITE or OPEN4_SHARE_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 is specified and includes owner or group (or corresponding ACEs) that the principal in the RPC's credentials does not have authorization to create files for, then the server may return NFS4ERR_PERM. In the case where an OPEN 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.16.16.6. IMPLEMENTATION
The OPEN operation contains support for EXCLUSIVE4 create. The mechanism is similar to the support in NFSv3 [RFC1813]. As in NFSv3, this mechanism provides reliable exclusive creation. Exclusive create is invoked when the how parameter is EXCLUSIVE4. In this case, 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 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 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 file system environment, the expected storage location for the verifier on creation is the metadata (timestamps) 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 cannot 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 metadata 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 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 a sequence such as create, write, create (retransmitted) from occurring. For share reservations (see Section 9.9), the client must specify a value for share_access that is one of OPEN4_SHARE_ACCESS_READ, OPEN4_SHARE_ACCESS_WRITE, or OPEN4_SHARE_ACCESS_BOTH. For share_deny, the client must specify one of OPEN4_SHARE_DENY_NONE, OPEN4_SHARE_DENY_READ, OPEN4_SHARE_DENY_WRITE, or OPEN4_SHARE_DENY_BOTH. If the client fails to do this, the server must return NFS4ERR_INVAL. 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 is not authorized to READ or WRITE (depending on the share_access value), the server must return NFS4ERR_ACCESS. Note that since the NFSv4 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 resolves to something other than a regular file (or a named attribute), an error will be returned to the client. If it is a directory, NFS4ERR_ISDIR is returned; otherwise, NFS4ERR_SYMLINK is returned. Note that NFS4ERR_SYMLINK is returned for both symlinks and for special files of other types; NFS4ERR_INVAL would be inappropriate, since the arguments provided by the client were correct, and the client cannot necessarily know at the time it sent the OPEN that the component would resolve to a non-regular file. If the current filehandle is not a directory, the error NFS4ERR_NOTDIR will be returned. If a COMPOUND contains an OPEN that establishes an OPEN_DELEGATE_WRITE delegation, then subsequent GETATTRs normally result in a CB_GETATTR being sent to the client holding the delegation. However, in the case in which the OPEN and GETATTR are part of the same COMPOUND, the server SHOULD understand that the operations are for the same client ID and avoid querying the client, which will not be able to respond. This sequence of OPEN and GETATTR SHOULD be understood to be the retrieval of the size and change attributes at the time of OPEN. Further, as explained in Section 15.2.5, the client should not construct a COMPOUND that mixes operations for different client IDs.
16.17. Operation 19: OPENATTR - Open Named Attribute Directory
16.17.1. SYNOPSIS
(cfh) createdir -> (cfh)16.17.2. ARGUMENT
struct OPENATTR4args { /* CURRENT_FH: object */ bool createdir; };16.17.3. RESULT
struct OPENATTR4res { /* CURRENT_FH: named attr directory */ nfsstat4 status; };16.17.4. 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 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.16.17.5. IMPLEMENTATION
If the server does not support named attributes for the current filehandle, an error of NFS4ERR_NOTSUPP will be returned to the client.
16.18. Operation 20: OPEN_CONFIRM - Confirm Open
16.18.1. SYNOPSIS
(cfh), seqid, stateid -> stateid16.18.2. ARGUMENT
struct OPEN_CONFIRM4args { /* CURRENT_FH: opened file */ stateid4 open_stateid; seqid4 seqid; };16.18.3. RESULT
struct OPEN_CONFIRM4resok { stateid4 open_stateid; }; union OPEN_CONFIRM4res switch (nfsstat4 status) { case NFS4_OK: OPEN_CONFIRM4resok resok4; default: void; };16.18.4. DESCRIPTION
This operation is used to confirm the sequence id usage for the first time that an open-owner is used by a client. The stateid returned from the OPEN operation is used as the argument for this operation along with the next sequence id for the open-owner. The sequence id passed to the OPEN_CONFIRM must be 1 (one) greater than the seqid passed to the OPEN operation (Section 9.1.4). If the server receives an unexpected sequence id with respect to the original OPEN, then the server assumes that the client will not confirm the original OPEN and all state associated with the original OPEN is released by the server. On success, the current filehandle retains its value.16.18.5. IMPLEMENTATION
A given client might generate many open_owner4 data structures for a given client ID. The client will periodically either dispose of its open_owner4s or stop using them for indefinite periods of time. The latter situation is why the NFSv4 protocol does not have an explicit
operation to exit an open_owner4: such an operation is of no use in that situation. Instead, to avoid unbounded memory use, the server needs to implement a strategy for disposing of open_owner4s that have no current open state for any files and have not been used recently. The time period used to determine when to dispose of open_owner4s is an implementation choice. The time period should certainly be no less than the lease time plus any grace period the server wishes to implement beyond a lease time. The OPEN_CONFIRM operation allows the server to safely dispose of unused open_owner4 data structures. In the case that a client issues an OPEN operation and the server no longer has a record of the open_owner4, the server needs to ensure that this is a new OPEN and not a replay or retransmission. Servers MUST NOT require confirmation on OPENs that grant delegations or are doing reclaim operations. See Section 9.1.11 for details. The server can easily avoid this by noting whether it has disposed of one open_owner4 for the given client ID. If the server does not support delegation, it might simply maintain a single bit that notes whether any open_owner4 (for any client) has been disposed of. The server must hold unconfirmed OPEN state until one of three events occurs. First, the client sends an OPEN_CONFIRM request with the appropriate sequence id and stateid within the lease period. In this case, the OPEN state on the server goes to confirmed, and the open_owner4 on the server is fully established. Second, the client sends another OPEN request with a sequence id that is incorrect for the open_owner4 (out of sequence). In this case, the server assumes the second OPEN request is valid and the first one is a replay. The server cancels the OPEN state of the first OPEN request, establishes an unconfirmed OPEN state for the second OPEN request, and responds to the second OPEN request with an indication that an OPEN_CONFIRM is needed. The process then repeats itself. While there is a potential for a denial-of-service attack on the client, it is mitigated if the client and server require the use of a security flavor based on Kerberos V5 or some other flavor that uses cryptography. What if the server is in the unconfirmed OPEN state for a given open_owner4, and it receives an operation on the open_owner4 that has a stateid but the operation is not OPEN, or it is OPEN_CONFIRM but with the wrong stateid? Then, even if the seqid is correct, the server returns NFS4ERR_BAD_STATEID, because the server assumes the operation is a replay: if the server has no established OPEN state, then there is no way, for example, a LOCK operation could be valid.
Third, neither of the two aforementioned events occurs for the open_owner4 within the lease period. In this case, the OPEN state is canceled and disposal of the open_owner4 can occur.
16.19. Operation 21: OPEN_DOWNGRADE - Reduce Open File Access
16.19.1. SYNOPSIS
(cfh), stateid, seqid, access, deny -> stateid16.19.2. ARGUMENT
struct OPEN_DOWNGRADE4args { /* CURRENT_FH: opened file */ stateid4 open_stateid; seqid4 seqid; uint32_t share_access; uint32_t share_deny; };16.19.3. RESULT
struct OPEN_DOWNGRADE4resok { stateid4 open_stateid; }; union OPEN_DOWNGRADE4res switch (nfsstat4 status) { case NFS4_OK: OPEN_DOWNGRADE4resok resok4; default: void; };
16.19.4. DESCRIPTION
This operation is used to adjust the share_access and share_deny bits for a given open. This is necessary when a given open-owner opens the same file multiple times with different share_access and share_deny flags. 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. The share_access and share_deny bits specified in this operation replace the current ones for the specified open file. The share_access and share_deny bits specified must be exactly equal to the union of the share_access and share_deny bits specified for some subset of the OPENs in effect for the current open-owner on the current file. If that constraint is not respected, the error NFS4ERR_INVAL should be returned. Since share_access and share_deny bits are subsets of those already granted, it is not possible for this request to be denied because of conflicting share reservations. As the OPEN_DOWNGRADE may change a file to be not-open-for-write and a write byte-range lock might be held, the server may have to reject the OPEN_DOWNGRADE with an NFS4ERR_LOCKS_HELD. On success, the current filehandle retains its value.
16.20. Operation 22: PUTFH - Set Current Filehandle
16.20.1. SYNOPSIS
filehandle -> (cfh)16.20.2. ARGUMENT
struct PUTFH4args { nfs_fh4 object; };16.20.3. RESULT
struct PUTFH4res { /* CURRENT_FH: */ nfsstat4 status; };16.20.4. DESCRIPTION
PUTFH replaces the current filehandle with the filehandle provided as an argument. If the security mechanism used by the requester does not meet the requirements of the filehandle provided to this operation, the server MUST return NFS4ERR_WRONGSEC. See Section 15.2.4.1 for more details on the current filehandle.16.20.5. IMPLEMENTATION
PUTFH is commonly used as the first operator in an NFS request to set the context for operations that follow it.
16.21. Operation 23: PUTPUBFH - Set Public Filehandle
16.21.1. SYNOPSIS
- -> (cfh)16.21.2. ARGUMENT
void;16.21.3. RESULT
struct PUTPUBFH4res { /* CURRENT_FH: public fh */ nfsstat4 status; };16.21.4. DESCRIPTION
PUTPUBFH replaces the current filehandle with the filehandle that represents the public filehandle of the server's namespace. This filehandle may be different from the root filehandle, which may be associated with some other directory on the server. The public filehandle concept was introduced in [RFC2054], [RFC2055], and [RFC2224]. The intent for NFSv4 is that the public filehandle (represented by the PUTPUBFH operation) be used as a method of providing compatibility with the WebNFS server of NFSv2 and NFSv3. The public filehandle and the root filehandle (represented by the PUTROOTFH operation) should be equivalent. If the public and root filehandles are not equivalent, then the public filehandle MUST be a descendant of the root filehandle.
16.21.5. IMPLEMENTATION
PUTPUBFH is used as the first operator in an NFS request to set the context for operations that follow it. With the NFSv2 and NFSv3 public filehandle, the client is able to specify whether the pathname provided in the LOOKUP should be evaluated as either an absolute path relative to the server's root or relative to the public filehandle. [RFC2224] contains further discussion of the functionality. With NFSv4, that type of specification is not directly available in the LOOKUP operation. The reason for this is because the component separators needed to specify absolute versus relative are not allowed in NFSv4. Therefore, the client is responsible for constructing its request such that either PUTROOTFH or PUTPUBFH is used to signify absolute or relative evaluation of an NFS URL, respectively. Note that there are warnings mentioned in [RFC2224] with respect to the use of absolute evaluation and the restrictions the server may place on that evaluation with respect to how much of its namespace has been made available. These same warnings apply to NFSv4. It is likely, therefore, that because of server implementation details an NFSv3 absolute public filehandle lookup may behave differently than an NFSv4 absolute resolution. There is a form of security negotiation as described in [RFC2755] that uses the public filehandle as a method of employing the Simple and Protected GSS-API Negotiation Mechanism (SNEGO) [RFC4178]. This method is not available with NFSv4, as filehandles are not overloaded with special meaning and therefore do not provide the same framework as NFSv2 and NFSv3. Clients should therefore use the security negotiation mechanisms described in this RFC.