13. NFS version 4 Requests
For the NFS version 4 RPC program, there are two traditional RPC procedures: NULL and COMPOUND. All other functionality is defined as a set of operations and these operations are defined in normal XDR/RPC syntax and semantics. However, these operations are encapsulated within the COMPOUND procedure. This requires that the client combine one or more of the NFS version 4 operations into a single request. The NFS4_CALLBACK program is used to provide server to client signaling and is constructed in a similar fashion as the NFS version 4 program. The procedures CB_NULL and CB_COMPOUND are defined in the same way as NULL and COMPOUND are within the NFS program. The CB_COMPOUND request also encapsulates the remaining operations of the NFS4_CALLBACK program. There is no predefined RPC program number for the NFS4_CALLBACK program. It is up to the client to specify a program number in the "transient" program range. The program and port number of the NFS4_CALLBACK program are provided by the client as part of the SETCLIENTID/SETCLIENTID_CONFIRM sequence. The program and port can be changed by another SETCLIENTID/SETCLIENTID_CONFIRM sequence, and it is possible to use the sequence to change them within a client incarnation without removing relevant leased client state.13.1. Compound Procedure
The COMPOUND procedure provides the opportunity for better performance within high latency networks. The client can avoid cumulative latency of multiple RPCs by combining multiple dependent operations into a single COMPOUND procedure. A compound operation may provide for protocol simplification by allowing the client to combine basic procedures into a single request that is customized for the client's environment. The CB_COMPOUND procedure precisely parallels the features of COMPOUND as described above. The basic structure of the COMPOUND procedure is: +-----+--------------+--------+-----------+-----------+-----------+-- | tag | minorversion | numops | op + args | op + args | op + args | +-----+--------------+--------+-----------+-----------+-----------+--
and the reply's structure is:
+------------+-----+--------+-----------------------+--
|last status | tag | numres | status + op + results |
+------------+-----+--------+-----------------------+--
The numops and numres fields, used in the depiction above, represent
the count for the counted array encoding use to signify the number of
arguments or results encoded in the request and response. As per the
XDR encoding, these counts must match exactly the number of operation
arguments or results encoded.
13.2. Evaluation of a Compound Request
The server will process the COMPOUND procedure by evaluating each of
the operations within the COMPOUND procedure in order. Each
component operation consists of a 32 bit operation code, followed by
the argument of length determined by the type of operation. The
results of each operation are encoded in sequence into a reply
buffer. The results of each operation are preceded by the opcode and
a status code (normally zero). If an operation results in a non-zero
status code, the status will be encoded and evaluation of the
compound sequence will halt and the reply will be returned. Note
that evaluation stops even in the event of "non error" conditions
such as NFS4ERR_SAME.
There are no atomicity requirements for the operations contained
within the COMPOUND procedure. The operations being evaluated as
part of a COMPOUND request may be evaluated simultaneously with other
COMPOUND requests that the server receives.
It is the client's responsibility for recovering from any partially
completed COMPOUND procedure. Partially completed COMPOUND
procedures may occur at any point due to errors such as
NFS4ERR_RESOURCE and NFS4ERR_DELAY. This may occur even given an
otherwise valid operation string. Further, a server reboot which
occurs in the middle of processing a COMPOUND procedure may leave the
client with the difficult task of determining how far COMPOUND
processing has proceeded. Therefore, the client should avoid overly
complex COMPOUND procedures in the event of the failure of an
operation within the procedure.
Each operation assumes a "current" and "saved" filehandle that is
available as part of the execution context of the compound request.
Operations may set, change, or return the current filehandle. The
"saved" filehandle is used for temporary storage of a filehandle
value and as operands for the RENAME and LINK operations.
13.3. Synchronous Modifying Operations
NFS version 4 operations that modify the filesystem are synchronous. When an operation is successfully completed at the server, the client can depend that any data associated with the request is now on stable storage (the one exception is in the case of the file data in a WRITE operation with the UNSTABLE option specified). This implies that any previous operations within the same compound request are also reflected in stable storage. This behavior enables the client's ability to recover from a partially executed compound request which may resulted from the failure of the server. For example, if a compound request contains operations A and B and the server is unable to send a response to the client, depending on the progress the server made in servicing the request the result of both operations may be reflected in stable storage or just operation A may be reflected. The server must not have just the results of operation B in stable storage.13.4. Operation Values
The operations encoded in the COMPOUND procedure are identified by operation values. To avoid overlap with the RPC procedure numbers, operations 0 (zero) and 1 are not defined. Operation 2 is not defined but reserved for future use with minor versioning.14. NFS version 4 Procedures
14.1. Procedure 0: NULL - No Operation
SYNOPSIS <null> ARGUMENT void; RESULT void;
DESCRIPTION
Standard NULL procedure. Void argument, void response. This
procedure has no functionality associated with it. Because of
this it is sometimes used to measure the overhead of processing a
service request. Therefore, the server should ensure that no
unnecessary work is done in servicing this procedure.
ERRORS
None.
14.2. Procedure 1: COMPOUND - Compound Operations
SYNOPSIS
compoundargs -> compoundres
ARGUMENT
union nfs_argop4 switch (nfs_opnum4 argop) {
case <OPCODE>: <argument>;
...
};
struct COMPOUND4args {
utf8str_cs tag;
uint32_t minorversion;
nfs_argop4 argarray<>;
};
RESULT
union nfs_resop4 switch (nfs_opnum4 resop){
case <OPCODE>: <result>;
...
};
struct COMPOUND4res {
nfsstat4 status;
utf8str_cs tag;
nfs_resop4 resarray<>;
};
DESCRIPTION The COMPOUND procedure is used to combine one or more of the NFS operations into a single RPC request. The main NFS RPC program has two main procedures: NULL and COMPOUND. All other operations use the COMPOUND procedure as a wrapper. The COMPOUND procedure is used to combine individual operations into a single RPC request. The server interprets each of the operations in turn. If an operation is executed by the server and the status of that operation is NFS4_OK, then the next operation in the COMPOUND procedure is executed. The server continues this process until there are no more operations to be executed or one of the operations has a status value other than NFS4_OK. In the processing of the COMPOUND procedure, the server may find that it does not have the available resources to execute any or all of the operations within the COMPOUND sequence. In this case, the error NFS4ERR_RESOURCE will be returned for the particular operation within the COMPOUND procedure where the resource exhaustion occurred. This assumes that all previous operations within the COMPOUND sequence have been evaluated successfully. The results for all of the evaluated operations must be returned to the client. The server will generally choose between two methods of decoding the client's request. The first would be the traditional one-pass XDR decode, in which decoding of the entire COMPOUND precedes execution of any operation within it. If there is an XDR decoding error in this case, an RPC XDR decode error would be returned. The second method would be to make an initial pass to decode the basic COMPOUND request and then to XDR decode each of the individual operations, as the server is ready to execute it. In this case, the server may encounter an XDR decode error during such an operation decode, after previous operations within the COMPOUND have been executed. In this case, the server would return the error NFS4ERR_BADXDR to signify the decode error. The COMPOUND arguments contain a "minorversion" field. The initial and default value for this field is 0 (zero). This field will be used by future minor versions such that the client can communicate to the server what minor version is being requested. If the server receives a COMPOUND procedure with a minorversion field value that it does not support, the server MUST return an error of NFS4ERR_MINOR_VERS_MISMATCH and a zero length resultdata array. Contained within the COMPOUND results is a "status" field. If the results array length is non-zero, this status must be equivalent to the status of the last operation that was executed within the
COMPOUND procedure. Therefore, if an operation incurred an error then the "status" value will be the same error value as is being returned for the operation that failed. Note that operations, 0 (zero) and 1 (one) are not defined for the COMPOUND procedure. Operation 2 is not defined but reserved for future definition and use with minor versioning. If the server receives a operation array that contains operation 2 and the minorversion field has a value of 0 (zero), an error of NFS4ERR_OP_ILLEGAL, as described in the next paragraph, is returned to the client. If an operation array contains an operation 2 and the minorversion field is non-zero and the server does not support the minor version, the server returns an error of NFS4ERR_MINOR_VERS_MISMATCH. Therefore, the NFS4ERR_MINOR_VERS_MISMATCH error takes precedence over all other errors. It is possible that the server receives a request that contains an operation that is less than the first legal operation (OP_ACCESS) or greater than the last legal operation (OP_RELEASE_LOCKOWNER). In this case, the server's response will encode the opcode OP_ILLEGAL rather than the illegal opcode of the request. The status field in the ILLEGAL return results will set to NFS4ERR_OP_ILLEGAL. The COMPOUND procedure's return results will also be NFS4ERR_OP_ILLEGAL. The definition of the "tag" in the request is left to the implementor. It may be used to summarize the content of the compound request for the benefit of packet sniffers and engineers debugging implementations. However, the value of "tag" in the response SHOULD be the same value as provided in the request. This applies to the tag field of the CB_COMPOUND procedure as well. IMPLEMENTATION Since an error of any type may occur after only a portion of the operations have been evaluated, the client must be prepared to recover from any failure. If the source of an NFS4ERR_RESOURCE error was a complex or lengthy set of operations, it is likely that if the number of operations were reduced the server would be able to evaluate them successfully. Therefore, the client is responsible for dealing with this type of complexity in recovery. ERRORS All errors defined in the protocol
14.2.1. Operation 3: ACCESS - Check Access Rights
SYNOPSIS (cfh), accessreq -> supported, accessrights ARGUMENT const ACCESS4_READ = 0x00000001; const ACCESS4_LOOKUP = 0x00000002; const ACCESS4_MODIFY = 0x00000004; const ACCESS4_EXTEND = 0x00000008; const ACCESS4_DELETE = 0x00000010; const ACCESS4_EXECUTE = 0x00000020; struct ACCESS4args { /* CURRENT_FH: object */ uint32_t access; }; RESULT struct ACCESS4resok { uint32_t supported; uint32_t access; }; union ACCESS4res switch (nfsstat4 status) { case NFS4_OK: ACCESS4resok resok4; default: void; }; DESCRIPTION ACCESS determines the access rights that a user, as identified by the credentials in the RPC request, has with respect to the file system object specified by the current filehandle. The client encodes the set of access rights that are to be checked in the bit mask "access". The server checks the permissions encoded in the bit mask. If a status of NFS4_OK is returned, two bit masks are included in the response. The first, "supported", represents the access rights for which the server can verify reliably. The second, "access", represents the access rights available to the user for the filehandle provided. On success, the current filehandle retains its value.
Note that the supported field will contain only as many values as
were originally sent in the arguments. For example, if the client
sends an ACCESS operation with only the ACCESS4_READ value set and
the server supports this value, the server will return only
ACCESS4_READ even if it could have reliably checked other values.
The results of this operation are necessarily advisory in nature. A
return status of NFS4_OK and the appropriate bit set in the bit mask
does not imply that such access will be allowed to the file system
object in the future. This is because access rights can be revoked by
the server at any time.
The following access permissions may be requested:
ACCESS4_READ Read data from file or read a directory.
ACCESS4_LOOKUP Look up a name in a directory (no meaning for non-
directory objects).
ACCESS4_MODIFY Rewrite existing file data or modify existing
directory entries.
ACCESS4_EXTEND Write new data or add directory entries.
ACCESS4_DELETE Delete an existing directory entry.
ACCESS4_EXECUTE Execute file (no meaning for a directory).
On success, the current filehandle retains its value.
IMPLEMENTATION
In general, it is not sufficient for the client to attempt to deduce
access permissions by inspecting the uid, gid, and mode fields in the
file attributes or by attempting to interpret the contents of the ACL
attribute. This is because the server may perform uid or gid mapping
or enforce additional access control restrictions. It is also
possible that the server may not be in the same ID space as the
client. In these cases (and perhaps others), the client can not
reliably perform an access check with only current file attributes.
In the NFS version 2 protocol, the only reliable way to determine
whether an operation was allowed was to try it and see if it
succeeded or failed. Using the ACCESS operation in the NFS version 4
protocol, the client can ask the server to indicate whether or not
one or more classes of operations are permitted. The ACCESS
operation is provided to allow clients to check before doing a series
of operations which will result in an access failure. The OPEN
operation provides a point where the server can verify access to the
file object and method to return that information to the client. The
ACCESS operation is still useful for directory operations or for use
in the case the UNIX API "access" is used on the client.
The information returned by the server in response to an ACCESS call
is not permanent. It was correct at the exact time that the server
performed the checks, but not necessarily afterwards. The server can
revoke access permission at any time.
The client should use the effective credentials of the user to build
the authentication information in the ACCESS request used to
determine access rights. It is the effective user and group
credentials that are used in subsequent read and write operations.
Many implementations do not directly support the ACCESS4_DELETE
permission. Operating systems like UNIX will ignore the
ACCESS4_DELETE bit if set on an access request on a non-directory
object. In these systems, delete permission on a file is determined
by the access permissions on the directory in which the file resides,
instead of being determined by the permissions of the file itself.
Therefore, the mask returned enumerating which access rights can be
determined will have the ACCESS4_DELETE value set to 0. This
indicates to the client that the server was unable to check that
particular access right. The ACCESS4_DELETE bit in the access mask
returned will then be ignored by the client.
ERRORS
NFS4ERR_ACCESS
NFS4ERR_BADHANDLE
NFS4ERR_BADXDR
NFS4ERR_DELAY
NFS4ERR_FHEXPIRED
NFS4ERR_INVAL
NFS4ERR_IO
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
14.2.2. Operation 4: CLOSE - Close File
SYNOPSIS
(cfh), seqid, open_stateid -> open_stateid
ARGUMENT
struct CLOSE4args {
/* CURRENT_FH: object */
seqid4 seqid
stateid4 open_stateid;
};
RESULT
union CLOSE4res switch (nfsstat4 status) {
case NFS4_OK:
stateid4 open_stateid;
default:
void;
};
DESCRIPTION
The CLOSE operation releases share reservations for the regular or
named attribute file as specified by the current filehandle. The
share reservations and other state information released at the server
as a result of this CLOSE is only associated with the supplied
stateid. The sequence id provides for the correct ordering. State
associated with other OPENs is not affected.
If record locks are held, the client SHOULD release all locks before
issuing a CLOSE. The server MAY free all outstanding locks on CLOSE
but some servers may not support the CLOSE of a file that still has
record locks held. The server MUST return failure if any locks would
exist after the CLOSE.
On success, the current filehandle retains its value.
IMPLEMENTATION
Even though CLOSE returns a stateid, this stateid is not useful to
the client and should be treated as deprecated. CLOSE "shuts down"
the state associated with all OPENs for the file by a single
open_owner. As noted above, CLOSE will either release all file
locking state or return an error. Therefore, the stateid returned by
CLOSE is not useful for operations that follow.
ERRORS
NFS4ERR_ADMIN_REVOKED
NFS4ERR_BADHANDLE
NFS4ERR_BAD_SEQID
NFS4ERR_BAD_STATEID
NFS4ERR_BADXDR
NFS4ERR_DELAY
NFS4ERR_EXPIRED
NFS4ERR_FHEXPIRED
NFS4ERR_INVAL
NFS4ERR_ISDIR
NFS4ERR_LEASE_MOVED
NFS4ERR_LOCKS_HELD
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_OLD_STATEID
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
NFS4ERR_STALE_STATEID
14.2.3. Operation 5: COMMIT - Commit Cached Data
SYNOPSIS
(cfh), offset, count -> verifier
ARGUMENT
struct COMMIT4args {
/* CURRENT_FH: file */
offset4 offset;
count4 count;
};
RESULT
struct COMMIT4resok {
verifier4 writeverf;
};
union COMMIT4res switch (nfsstat4 status) {
case NFS4_OK:
COMMIT4resok resok4;
default:
void;
};
DESCRIPTION The COMMIT operation forces or flushes data to stable storage for the file specified by the current filehandle. The flushed data is that which was previously written with a WRITE operation which had the stable field set to UNSTABLE4. The offset specifies the position within the file where the flush is to begin. An offset value of 0 (zero) means to flush data starting at the beginning of the file. The count specifies the number of bytes of data to flush. If count is 0 (zero), a flush from offset to the end of the file is done. The server returns a write verifier upon successful completion of the COMMIT. The write verifier is used by the client to determine if the server has restarted or rebooted between the initial WRITE(s) and the COMMIT. The client does this by comparing the write verifier returned from the initial writes and the verifier returned by the COMMIT operation. The server must vary the value of the write verifier at each server event or instantiation that may lead to a loss of uncommitted data. Most commonly this occurs when the server is rebooted; however, other events at the server may result in uncommitted data loss as well. On success, the current filehandle retains its value. IMPLEMENTATION The COMMIT operation is similar in operation and semantics to the POSIX fsync(2) system call that synchronizes a file's state with the disk (file data and metadata is flushed to disk or stable storage). COMMIT performs the same operation for a client, flushing any unsynchronized data and metadata on the server to the server's disk or stable storage for the specified file. Like fsync(2), it may be that there is some modified data or no modified data to synchronize. The data may have been synchronized by the server's normal periodic buffer synchronization activity. COMMIT should return NFS4_OK, unless there has been an unexpected error. COMMIT differs from fsync(2) in that it is possible for the client to flush a range of the file (most likely triggered by a buffer- reclamation scheme on the client before file has been completely written). The server implementation of COMMIT is reasonably simple. If the server receives a full file COMMIT request, that is starting at offset 0 and count 0, it should do the equivalent of fsync()'ing the file. Otherwise, it should arrange to have the cached data in the
range specified by offset and count to be flushed to stable storage. In both cases, any metadata associated with the file must be flushed to stable storage before returning. It is not an error for there to be nothing to flush on the server. This means that the data and metadata that needed to be flushed have already been flushed or lost during the last server failure. The client implementation of COMMIT is a little more complex. There are two reasons for wanting to commit a client buffer to stable storage. The first is that the client wants to reuse a buffer. In this case, the offset and count of the buffer are sent to the server in the COMMIT request. The server then flushes any cached data based on the offset and count, and flushes any metadata associated with the file. It then returns the status of the flush and the write verifier. The other reason for the client to generate a COMMIT is for a full file flush, such as may be done at close. In this case, the client would gather all of the buffers for this file that contain uncommitted data, do the COMMIT operation with an offset of 0 and count of 0, and then free all of those buffers. Any other dirty buffers would be sent to the server in the normal fashion. After a buffer is written by the client with the stable parameter set to UNSTABLE4, the buffer must be considered as modified by the client until the buffer has either been flushed via a COMMIT operation or written via a WRITE operation with stable parameter set to FILE_SYNC4 or DATA_SYNC4. This is done to prevent the buffer from being freed and reused before the data can be flushed to stable storage on the server. When a response is returned from either a WRITE or a COMMIT operation and it contains a write verifier that is different than previously returned by the server, the client will need to retransmit all of the buffers containing uncommitted cached data to the server. How this is to be done is up to the implementor. If there is only one buffer of interest, then it should probably be sent back over in a WRITE request with the appropriate stable parameter. If there is more than one buffer, it might be worthwhile retransmitting all of the buffers in WRITE requests with the stable parameter set to UNSTABLE4 and then retransmitting the COMMIT operation to flush all of the data on the server to stable storage. The timing of these retransmissions is left to the implementor. The above description applies to page-cache-based systems as well as buffer-cache-based systems. In those systems, the virtual memory system will need to be modified instead of the buffer cache.
ERRORS
NFS4ERR_ACCESS
NFS4ERR_BADHANDLE
NFS4ERR_BADXDR
NFS4ERR_FHEXPIRED
NFS4ERR_INVAL
NFS4ERR_IO
NFS4ERR_ISDIR
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_RESOURCE
NFS4ERR_ROFS
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
14.2.4. Operation 6: CREATE - Create a Non-Regular File Object
SYNOPSIS
(cfh), name, type, attrs -> (cfh), change_info, attrs_set
ARGUMENT
union createtype4 switch (nfs_ftype4 type) {
case NF4LNK:
linktext4 linkdata;
case NF4BLK:
case NF4CHR:
specdata4 devdata;
case NF4SOCK:
case NF4FIFO:
case NF4DIR:
void;
};
struct CREATE4args {
/* CURRENT_FH: directory for creation */
createtype4 objtype;
component4 objname;
fattr4 createattrs;
};
RESULT
struct CREATE4resok {
change_info4 cinfo;
bitmap4 attrset; /* attributes set */
};
union CREATE4res switch (nfsstat4 status) {
case NFS4_OK:
CREATE4resok resok4;
default:
void;
};
DESCRIPTION
The CREATE operation creates a non-regular file object in a directory
with a given name. The OPEN operation MUST be used to create a
regular file.
The objname specifies the name for the new object. The objtype
determines the type of object to be created: directory, symlink, etc.
If an object of the same name already exists in the directory, the
server will return the error NFS4ERR_EXIST.
For the directory where the new file object was created, the server
returns change_info4 information in cinfo. With the atomic field of
the change_info4 struct, the server will indicate if the before and
after change attributes were obtained atomically with respect to the
file object creation.
If the objname has a length of 0 (zero), or if objname does not obey
the UTF-8 definition, the error NFS4ERR_INVAL will be returned.
The current filehandle is replaced by that of the new object.
The createattrs specifies the initial set of attributes for the
object. The set of attributes may include any writable attribute
valid for the object type. When the operation is successful, the
server will return to the client an attribute mask signifying which
attributes were successfully set for the object.
If createattrs includes neither the owner attribute nor an ACL with
an ACE for the owner, and if the server's filesystem both supports
and requires an owner attribute (or an owner ACE) then the server
MUST derive the owner (or the owner ACE). This would typically be
from the principal indicated in the RPC credentials of the call, but
the server's operating environment or filesystem semantics may
dictate other methods of derivation. Similarly, if createattrs
includes neither the group attribute nor a group ACE, and if the
server's filesystem both supports and requires the notion of a group
attribute (or group ACE), the server MUST derive the group attribute
(or the corresponding owner ACE) for the file. This could be from the
RPC call's credentials, such as the group principal if the
credentials include it (such as with AUTH_SYS), from the group
identifier associated with the principal in the credentials (for
e.g., POSIX systems have a passwd database that has the group
identifier for every user identifier), inherited from directory the
object is created in, or whatever else the server's operating
environment or filesystem semantics dictate. This applies to the OPEN
operation too.
Conversely, it is possible the client will specify in createattrs an
owner attribute or group attribute or ACL that the principal
indicated the RPC call's credentials does not have permissions to
create files for. The error to be returned in this instance is
NFS4ERR_PERM. This applies to the OPEN operation too.
IMPLEMENTATION
If the client desires to set attribute values after the create, a
SETATTR operation can be added to the COMPOUND request so that the
appropriate attributes will be set.
ERRORS
NFS4ERR_ACCESS
NFS4ERR_ATTRNOTSUPP
NFS4ERR_BADCHAR
NFS4ERR_BADHANDLE
NFS4ERR_BADNAME
NFS4ERR_BADOWNER
NFS4ERR_BADTYPE
NFS4ERR_BADXDR
NFS4ERR_DELAY
NFS4ERR_DQUOT
NFS4ERR_EXIST
NFS4ERR_FHEXPIRED
NFS4ERR_INVAL
NFS4ERR_IO
NFS4ERR_MOVED
NFS4ERR_NAMETOOLONG
NFS4ERR_NOFILEHANDLE
NFS4ERR_NOSPC
NFS4ERR_NOTDIR
NFS4ERR_PERM
NFS4ERR_RESOURCE
NFS4ERR_ROFS
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
14.2.5. Operation 7: DELEGPURGE - Purge Delegations Awaiting Recovery
SYNOPSIS clientid -> ARGUMENT struct DELEGPURGE4args { clientid4 clientid; }; RESULT struct DELEGPURGE4res { nfsstat4 status; }; DESCRIPTION Purges all of the delegations awaiting recovery for a given client. This is useful for clients which do not commit delegation information to stable storage to indicate that conflicting requests need not be delayed by the server awaiting recovery of delegation information. This operation should be used by clients that record delegation information on stable storage on the client. In this case, DELEGPURGE should be issued immediately after doing delegation recovery on all delegations known to the client. Doing so will notify the server that no additional delegations for the client will be recovered allowing it to free resources, and avoid delaying other clients who make requests that conflict with the unrecovered delegations. The set of delegations known to the server and the client may be different. The reason for this is that a client may fail after making a request which resulted in delegation but before it received the results and committed them to the client's stable storage. The server MAY support DELEGPURGE, but if it does not, it MUST NOT support CLAIM_DELEGATE_PREV. ERRORS NFS4ERR_BADXDR NFS4ERR_NOTSUPP NFS4ERR_LEASE_MOVED NFS4ERR_MOVED NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE_CLIENTID
14.2.6. Operation 8: DELEGRETURN - Return Delegation
SYNOPSIS
(cfh), stateid ->
ARGUMENT
struct DELEGRETURN4args {
/* CURRENT_FH: delegated file */
stateid4 stateid;
};
RESULT
struct DELEGRETURN4res {
nfsstat4 status;
};
DESCRIPTION
Returns the delegation represented by the current filehandle and
stateid.
Delegations may be returned when recalled or voluntarily (i.e.,
before the server has recalled them). In either case the client must
properly propagate state changed under the context of the delegation
to the server before returning the delegation.
ERRORS
NFS4ERR_ADMIN_REVOKED
NFS4ERR_BAD_STATEID
NFS4ERR_BADXDR
NFS4ERR_EXPIRED
NFS4ERR_INVAL
NFS4ERR_LEASE_MOVED
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_NOTSUPP
NFS4ERR_OLD_STATEID
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
NFS4ERR_STALE_STATEID
14.2.7. Operation 9: GETATTR - Get Attributes
SYNOPSIS (cfh), attrbits -> attrbits, attrvals ARGUMENT struct GETATTR4args { /* CURRENT_FH: directory or file */ bitmap4 attr_request; }; RESULT struct GETATTR4resok { fattr4 obj_attributes; }; union GETATTR4res switch (nfsstat4 status) { case NFS4_OK: GETATTR4resok resok4; default: void; }; DESCRIPTION The GETATTR operation will obtain attributes for the filesystem object specified by the current filehandle. The client sets a bit in the bitmap argument for each attribute value that it would like the server to return. The server returns an attribute bitmap that indicates the attribute values for which it was able to return, followed by the attribute values ordered lowest attribute number first. The server must return a value for each attribute that the client requests if the attribute is supported by the server. If the server does not support an attribute or cannot approximate a useful value then it must not return the attribute value and must not set the attribute bit in the result bitmap. The server must return an error if it supports an attribute but cannot obtain its value. In that case no attribute values will be returned. All servers must support the mandatory attributes as specified in the section "File Attributes". On success, the current filehandle retains its value.
IMPLEMENTATION
ERRORS
NFS4ERR_ACCESS
NFS4ERR_BADHANDLE
NFS4ERR_BADXDR
NFS4ERR_DELAY
NFS4ERR_FHEXPIRED
NFS4ERR_INVAL
NFS4ERR_IO
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
14.2.8. Operation 10: GETFH - Get Current Filehandle
SYNOPSIS
(cfh) -> filehandle
ARGUMENT
/* CURRENT_FH: */
void;
RESULT
struct GETFH4resok {
nfs_fh4 object;
};
union GETFH4res switch (nfsstat4 status) {
case NFS4_OK:
GETFH4resok resok4;
default:
void;
};
DESCRIPTION
This operation returns the current filehandle value.
On success, the current filehandle retains its value.
IMPLEMENTATION
Operations that change the current filehandle like LOOKUP or CREATE
do not automatically return the new filehandle as a result. For
instance, if a client needs to lookup a directory entry and obtain
its filehandle then the following request is needed.
PUTFH (directory filehandle)
LOOKUP (entry name)
GETFH
ERRORS
NFS4ERR_BADHANDLE
NFS4ERR_FHEXPIRED
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
14.2.9. Operation 11: LINK - Create Link to a File
SYNOPSIS
(sfh), (cfh), newname -> (cfh), change_info
ARGUMENT
struct LINK4args {
/* SAVED_FH: source object */
/* CURRENT_FH: target directory */
component4 newname;
};
RESULT
struct LINK4resok {
change_info4 cinfo;
};
union LINK4res switch (nfsstat4 status) {
case NFS4_OK:
LINK4resok resok4;
default:
void;
};
DESCRIPTION
The LINK operation creates an additional newname for the file
represented by the saved filehandle, as set by the SAVEFH operation,
in the directory represented by the current filehandle. The existing
file and the target directory must reside within the same filesystem
on the server. On success, the current filehandle will continue to
be the target directory. If an object exists in the target directory
with the same name as newname, the server must return NFS4ERR_EXIST.
For the target directory, the server returns change_info4 information
in cinfo. With the atomic field of the change_info4 struct, the
server will indicate if the before and after change attributes were
obtained atomically with respect to the link creation.
If the newname has a length of 0 (zero), or if newname does not obey
the UTF-8 definition, the error NFS4ERR_INVAL will be returned.
IMPLEMENTATION
Changes to any property of the "hard" linked files are reflected in
all of the linked files. When a link is made to a file, the
attributes for the file should have a value for numlinks that is one
greater than the value before the LINK operation.
The statement "file and the target directory must reside within the
same filesystem on the server" means that the fsid fields in the
attributes for the objects are the same. If they reside on different
filesystems, the error, NFS4ERR_XDEV, is returned. On some servers,
the filenames, "." and "..", are illegal as newname.
In the case that newname is already linked to the file represented by
the saved filehandle, the server will return NFS4ERR_EXIST.
Note that symbolic links are created with the CREATE operation.
ERRORS
NFS4ERR_ACCESS
NFS4ERR_BADCHAR
NFS4ERR_BADHANDLE
NFS4ERR_BADNAME
NFS4ERR_BADXDR
NFS4ERR_DELAY
NFS4ERR_DQUOT
NFS4ERR_EXIST
NFS4ERR_FHEXPIRED
NFS4ERR_FILE_OPEN
NFS4ERR_INVAL
NFS4ERR_IO
NFS4ERR_ISDIR
NFS4ERR_MLINK
NFS4ERR_MOVED
NFS4ERR_NAMETOOLONG
NFS4ERR_NOENT
NFS4ERR_NOFILEHANDLE
NFS4ERR_NOSPC
NFS4ERR_NOTDIR
NFS4ERR_NOTSUPP
NFS4ERR_RESOURCE
NFS4ERR_ROFS
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
NFS4ERR_WRONGSEC
NFS4ERR_XDEV
14.2.10. Operation 12: LOCK - Create Lock
SYNOPSIS
(cfh) locktype, reclaim, offset, length, locker -> stateid
ARGUMENT
struct open_to_lock_owner4 {
seqid4 open_seqid;
stateid4 open_stateid;
seqid4 lock_seqid;
lock_owner4 lock_owner;
};
struct exist_lock_owner4 {
stateid4 lock_stateid;
seqid4 lock_seqid;
};
union locker4 switch (bool new_lock_owner) {
case TRUE:
open_to_lock_owner4 open_owner;
case FALSE:
exist_lock_owner4 lock_owner;
};
enum nfs_lock_type4 {
READ_LT = 1,
WRITE_LT = 2,
READW_LT = 3, /* blocking read */
WRITEW_LT = 4 /* blocking write */
};
struct LOCK4args {
/* CURRENT_FH: file */
nfs_lock_type4 locktype;
bool reclaim;
offset4 offset;
length4 length;
locker4 locker;
};
RESULT
struct LOCK4denied {
offset4 offset;
length4 length;
nfs_lock_type4 locktype;
lock_owner4 owner;
};
struct LOCK4resok {
stateid4 lock_stateid;
};
union LOCK4res switch (nfsstat4 status) {
case NFS4_OK:
LOCK4resok resok4;
case NFS4ERR_DENIED:
LOCK4denied denied;
default:
void;
};
DESCRIPTION
The LOCK operation requests a record lock for the byte range
specified by the offset and length parameters. The lock type is also
specified to be one of the nfs_lock_type4s. If this is a reclaim
request, the reclaim parameter will be TRUE;
Bytes in a file may be locked even if those bytes are not currently
allocated to the file. To lock the file from a specific offset
through the end-of-file (no matter how long the file actually is) use
a length field with all bits set to 1 (one). If the length is zero,
or if a length which is not all bits set to one is specified, and length when added to the offset exceeds the maximum 64-bit unsigned integer value, the error NFS4ERR_INVAL will result. Some servers may only support locking for byte offsets that fit within 32 bits. If the client specifies a range that includes a byte beyond the last byte offset of the 32-bit range, but does not include the last byte offset of the 32-bit and all of the byte offsets beyond it, up to the end of the valid 64-bit range, such a 32-bit server MUST return the error NFS4ERR_BAD_RANGE. In the case that the lock is denied, the owner, offset, and length of a conflicting lock are returned. On success, the current filehandle retains its value. IMPLEMENTATION If the server is unable to determine the exact offset and length of the conflicting lock, the same offset and length that were provided in the arguments should be returned in the denied results. The File Locking section contains a full description of this and the other file locking operations. LOCK operations are subject to permission checks and to checks against the access type of the associated file. However, the specific right and modes required for various type of locks, reflect the semantics of the server-exported filesystem, and are not specified by the protocol. For example, Windows 2000 allows a write lock of a file open for READ, while a POSIX-compliant system does not. When the client makes a lock request that corresponds to a range that the lockowner has locked already (with the same or different lock type), or to a sub-region of such a range, or to a region which includes multiple locks already granted to that lockowner, in whole or in part, and the server does not support such locking operations (i.e., does not support POSIX locking semantics), the server will return the error NFS4ERR_LOCK_RANGE. In that case, the client may return an error, or it may emulate the required operations, using only LOCK for ranges that do not include any bytes already locked by that lock_owner and LOCKU of locks held by that lock_owner (specifying an exactly-matching range and type). Similarly, when the client makes a lock request that amounts to upgrading (changing from a read lock to a write lock) or downgrading (changing from write lock to a read lock) an existing record lock, and the server does not
support such a lock, the server will return NFS4ERR_LOCK_NOTSUPP.
Such operations may not perfectly reflect the required semantics in
the face of conflicting lock requests from other clients.
The locker argument specifies the lock_owner that is associated with
the LOCK request. The locker4 structure is a switched union that
indicates whether the lock_owner is known to the server or if the
lock_owner is new to the server. In the case that the lock_owner is
known to the server and has an established lock_seqid, the argument
is just the lock_owner and lock_seqid. In the case that the
lock_owner is not known to the server, the argument contains not only
the lock_owner and lock_seqid but also the open_stateid and
open_seqid. The new lock_owner case covers the very first lock done
by the lock_owner and offers a method to use the established state of
the open_stateid to transition to the use of the lock_owner.
ERRORS
NFS4ERR_ACCESS
NFS4ERR_ADMIN_REVOKED
NFS4ERR_BADHANDLE
NFS4ERR_BAD_RANGE
NFS4ERR_BAD_SEQID
NFS4ERR_BAD_STATEID
NFS4ERR_BADXDR
NFS4ERR_DEADLOCK
NFS4ERR_DELAY
NFS4ERR_DENIED
NFS4ERR_EXPIRED
NFS4ERR_FHEXPIRED
NFS4ERR_GRACE
NFS4ERR_INVAL
NFS4ERR_ISDIR
NFS4ERR_LEASE_MOVED
NFS4ERR_LOCK_NOTSUPP
NFS4ERR_LOCK_RANGE
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_NO_GRACE
NFS4ERR_OLD_STATEID
NFS4ERR_OPENMODE
NFS4ERR_RECLAIM_BAD
NFS4ERR_RECLAIM_CONFLICT
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
NFS4ERR_STALE_CLIENTID
NFS4ERR_STALE_STATEID
14.2.11. Operation 13: LOCKT - Test For Lock
SYNOPSIS (cfh) locktype, offset, length owner -> {void, NFS4ERR_DENIED -> owner} ARGUMENT struct LOCKT4args { /* CURRENT_FH: file */ nfs_lock_type4 locktype; offset4 offset; length4 length; lock_owner4 owner; }; RESULT struct LOCK4denied { offset4 offset; length4 length; nfs_lock_type4 locktype; lock_owner4 owner; }; union LOCKT4res switch (nfsstat4 status) { case NFS4ERR_DENIED: LOCK4denied denied; case NFS4_OK: void; default: void; }; DESCRIPTION The LOCKT operation tests the lock as specified in the arguments. If a conflicting lock exists, the owner, offset, length, and type of the conflicting lock are returned; if no lock is held, nothing other than NFS4_OK is returned. Lock types READ_LT and READW_LT are processed in the same way in that a conflicting lock test is done without regard to blocking or non-blocking. The same is true for WRITE_LT and WRITEW_LT. The ranges are specified as for LOCK. The NFS4ERR_INVAL and NFS4ERR_BAD_RANGE errors are returned under the same circumstances as for LOCK.
On success, the current filehandle retains its value. IMPLEMENTATION If the server is unable to determine the exact offset and length of the conflicting lock, the same offset and length that were provided in the arguments should be returned in the denied results. The File Locking section contains further discussion of the file locking mechanisms. LOCKT uses a lock_owner4 rather a stateid4, as is used in LOCK to identify the owner. This is because the client does not have to open the file to test for the existence of a lock, so a stateid may not be available. The test for conflicting locks should exclude locks for the current lockowner. Note that since such locks are not examined the possible existence of overlapping ranges may not affect the results of LOCKT. If the server does examine locks that match the lockowner for the purpose of range checking, NFS4ERR_LOCK_RANGE may be returned.. In the event that it returns NFS4_OK, clients may do a LOCK and receive NFS4ERR_LOCK_RANGE on the LOCK request because of the flexibility provided to the server. ERRORS NFS4ERR_ACCESS NFS4ERR_BADHANDLE NFS4ERR_BAD_RANGE NFS4ERR_BADXDR NFS4ERR_DELAY NFS4ERR_DENIED NFS4ERR_FHEXPIRED NFS4ERR_GRACE NFS4ERR_INVAL NFS4ERR_ISDIR NFS4ERR_LEASE_MOVED NFS4ERR_LOCK_RANGE NFS4ERR_MOVED NFS4ERR_NOFILEHANDLE NFS4ERR_RESOURCE NFS4ERR_SERVERFAULT NFS4ERR_STALE NFS4ERR_STALE_CLIENTID
14.2.12. Operation 14: LOCKU - Unlock File
SYNOPSIS (cfh) type, seqid, stateid, offset, length -> stateid ARGUMENT struct LOCKU4args { /* CURRENT_FH: file */ nfs_lock_type4 locktype; seqid4 seqid; stateid4 stateid; offset4 offset; length4 length; }; RESULT union LOCKU4res switch (nfsstat4 status) { case NFS4_OK: stateid4 stateid; default: void; }; DESCRIPTION The LOCKU operation unlocks the record lock specified by the parameters. The client may set the locktype field to any value that is legal for the nfs_lock_type4 enumerated type, and the server MUST accept any legal value for locktype. Any legal value for locktype has no effect on the success or failure of the LOCKU operation. The ranges are specified as for LOCK. The NFS4ERR_INVAL and NFS4ERR_BAD_RANGE errors are returned under the same circumstances as for LOCK. On success, the current filehandle retains its value. IMPLEMENTATION If the area to be unlocked does not correspond exactly to a lock actually held by the lockowner the server may return the error NFS4ERR_LOCK_RANGE. This includes the case in which the area is not locked, where the area is a sub-range of the area locked, where it overlaps the area locked without matching exactly or the area specified includes multiple locks held by the lockowner. In all of
these cases, allowed by POSIX locking semantics, a client receiving
this error, should if it desires support for such operations,
simulate the operation using LOCKU on ranges corresponding to locks
it actually holds, possibly followed by LOCK requests for the sub-
ranges not being unlocked.
ERRORS
NFS4ERR_ACCESS
NFS4ERR_ADMIN_REVOKED
NFS4ERR_BADHANDLE
NFS4ERR_BAD_RANGE
NFS4ERR_BAD_SEQID
NFS4ERR_BAD_STATEID
NFS4ERR_BADXDR
NFS4ERR_EXPIRED
NFS4ERR_FHEXPIRED
NFS4ERR_GRACE
NFS4ERR_INVAL
NFS4ERR_ISDIR
NFS4ERR_LEASE_MOVED
NFS4ERR_LOCK_RANGE
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_OLD_STATEID
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
NFS4ERR_STALE_STATEID
14.2.13. Operation 15: LOOKUP - Lookup Filename
SYNOPSIS
(cfh), component -> (cfh)
ARGUMENT
struct LOOKUP4args {
/* CURRENT_FH: directory */
component4 objname;
};
RESULT
struct LOOKUP4res {
/* CURRENT_FH: object */
nfsstat4 status;
};
DESCRIPTION
This operation LOOKUPs or finds a filesystem object using the
directory specified by the current filehandle. LOOKUP evaluates the
component and if the object exists the current filehandle is replaced
with the component's filehandle.
If the component cannot be evaluated either because it does not exist
or because the client does not have permission to evaluate the
component, then an error will be returned and the current filehandle
will be unchanged.
If the component is a zero length string or if any component does not
obey the UTF-8 definition, the error NFS4ERR_INVAL will be returned.
IMPLEMENTATION
If the client wants to achieve the effect of a multi-component
lookup, it may construct a COMPOUND request such as (and obtain each
filehandle):
PUTFH (directory filehandle)
LOOKUP "pub"
GETFH
LOOKUP "foo"
GETFH
LOOKUP "bar"
GETFH
NFS version 4 servers depart from the semantics of previous NFS
versions in allowing LOOKUP requests to cross mountpoints on the
server. The client can detect a mountpoint crossing by comparing the
fsid attribute of the directory with the fsid attribute of the
directory looked up. If the fsids are different then the new
directory is a server mountpoint. UNIX clients that detect a
mountpoint crossing will need to mount the server's filesystem. This
needs to be done to maintain the file object identity checking
mechanisms common to UNIX clients.
Servers that limit NFS access to "shares" or "exported" filesystems
should provide a pseudo-filesystem into which the exported
filesystems can be integrated, so that clients can browse the
server's name space. The clients' view of a pseudo filesystem will
be limited to paths that lead to exported filesystems.
Note: previous versions of the protocol assigned special semantics to
the names "." and "..". NFS version 4 assigns no special semantics
to these names. The LOOKUPP operator must be used to lookup a parent
directory.
Note that this operation does not follow symbolic links. The client
is responsible for all parsing of filenames including filenames that
are modified by symbolic links encountered during the lookup process.
If the current filehandle supplied is not a directory but a symbolic
link, the error NFS4ERR_SYMLINK is returned as the error. For all
other non-directory file types, the error NFS4ERR_NOTDIR is returned.
ERRORS
NFS4ERR_ACCESS
NFS4ERR_BADCHAR
NFS4ERR_BADHANDLE
NFS4ERR_BADNAME
NFS4ERR_BADXDR
NFS4ERR_FHEXPIRED
NFS4ERR_INVAL
NFS4ERR_IO
NFS4ERR_MOVED
NFS4ERR_NAMETOOLONG
NFS4ERR_NOENT
NFS4ERR_NOFILEHANDLE
NFS4ERR_NOTDIR
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
NFS4ERR_SYMLINK
NFS4ERR_WRONGSEC
14.2.14. Operation 16: LOOKUPP - Lookup Parent Directory
SYNOPSIS
(cfh) -> (cfh)
ARGUMENT
/* CURRENT_FH: object */
void;
RESULT
struct LOOKUPP4res {
/* CURRENT_FH: directory */
nfsstat4 status;
};
DESCRIPTION
The current filehandle is assumed to refer to a regular directory
or a named attribute directory. LOOKUPP assigns the filehandle for
its parent directory to be the current filehandle. If there is no
parent directory an NFS4ERR_NOENT error must be returned.
Therefore, NFS4ERR_NOENT will be returned by the server when the
current filehandle is at the root or top of the server's file tree.
IMPLEMENTATION
As for LOOKUP, LOOKUPP will also cross mountpoints.
If the current filehandle is not a directory or named attribute
directory, the error NFS4ERR_NOTDIR is returned.
ERRORS
NFS4ERR_ACCESS
NFS4ERR_BADHANDLE
NFS4ERR_FHEXPIRED
NFS4ERR_IO
NFS4ERR_MOVED
NFS4ERR_NOENT
NFS4ERR_NOFILEHANDLE
NFS4ERR_NOTDIR
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
14.2.15. Operation 17: NVERIFY - Verify Difference in Attributes
SYNOPSIS
(cfh), fattr -> -
ARGUMENT
struct NVERIFY4args {
/* CURRENT_FH: object */
fattr4 obj_attributes;
};
RESULT
struct NVERIFY4res {
nfsstat4 status;
};
DESCRIPTION
This operation is used to prefix a sequence of operations to be
performed if one or more attributes have changed on some filesystem
object. If all the attributes match then the error NFS4ERR_SAME must
be returned.
On success, the current filehandle retains its value.
IMPLEMENTATION
This operation is useful as a cache validation operator. If the
object to which the attributes belong has changed then the following
operations may obtain new data associated with that object. For
instance, to check if a file has been changed and obtain new data if
it has:
PUTFH (public)
LOOKUP "foobar"
NVERIFY attrbits attrs
READ 0 32767
In the case that a recommended attribute is specified in the NVERIFY
operation and the server does not support that attribute for the
filesystem object, the error NFS4ERR_ATTRNOTSUPP is returned to the
client.
When the attribute rdattr_error or any write-only attribute (e.g.,
time_modify_set) is specified, the error NFS4ERR_INVAL is returned to
the client.
ERRORS
NFS4ERR_ACCESS
NFS4ERR_ATTRNOTSUPP
NFS4ERR_BADCHAR
NFS4ERR_BADHANDLE
NFS4ERR_BADXDR
NFS4ERR_DELAY
NFS4ERR_FHEXPIRED
NFS4ERR_INVAL
NFS4ERR_IO
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_RESOURCE
NFS4ERR_SAME
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
14.2.16. Operation 18: OPEN - Open a Regular File
SYNOPSIS
(cfh), seqid, share_access, share_deny, owner, openhow, claim ->
(cfh), stateid, cinfo, rflags, open_confirm, attrset delegation
ARGUMENT
struct OPEN4args {
seqid4 seqid;
uint32_t share_access;
uint32_t share_deny;
open_owner4 owner;
openflag4 openhow;
open_claim4 claim;
};
enum createmode4 {
UNCHECKED4 = 0,
GUARDED4 = 1,
EXCLUSIVE4 = 2
};
union createhow4 switch (createmode4 mode) {
case UNCHECKED4:
case GUARDED4:
fattr4 createattrs;
case EXCLUSIVE4:
verifier4 createverf;
};
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;
};
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;
};
const OPEN4_RESULT_CONFIRM = 0x00000002;
const OPEN4_RESULT_LOCKTYPE_POSIX = 0x00000004;
struct OPEN4resok {
stateid4 stateid; /* Stateid for open */
change_info4 cinfo; /* Directory Change Info */
uint32_t rflags; /* Result flags */
bitmap4 attrset; /* attributes on create */
open_delegation4 delegation; /* Info on any open
delegation */
};
union OPEN4res switch (nfsstat4 status) {
case NFS4_OK:
/* CURRENT_FH: opened file */
OPEN4resok resok4;
default:
void;
};
WARNING TO CLIENT IMPLEMENTORS
OPEN resembles LOOKUP in that it generates a filehandle for the
client to use. Unlike LOOKUP though, OPEN creates server state on
the filehandle. In normal circumstances, the client can only release
this state with a CLOSE operation. CLOSE uses the current filehandle
to determine which file to close. Therefore the client MUST follow
every OPEN operation with a GETFH operation in the same COMPOUND
procedure. This will supply the client with the filehandle such that
CLOSE can be used appropriately.
Simply waiting for the lease on the file to expire is insufficient
because the server may maintain the state indefinitely as long as
another client does not attempt to make a conflicting access to the
same file.
DESCRIPTION
The OPEN operation creates and/or opens a regular file in a directory
with the provided name. If the file does not exist at the server and
creation is desired, specification of the method of creation is
provided by the openhow parameter. The client has the choice of
three creation methods: UNCHECKED, GUARDED, or EXCLUSIVE.
If the current filehandle is a named attribute directory, OPEN will
then create or open a named attribute file. Note that exclusive
create of a named attribute is not supported. If the createmode is
EXCLUSIVE4 and the current filehandle is a named attribute directory,
the server will return EINVAL.
UNCHECKED means that the file should be created if a file of that
name does not exist and encountering an existing regular file of that
name is not an error. For this type of create, createattrs specifies
the initial set of attributes for the file. The set of attributes
may include any writable attribute valid for regular files. When an
UNCHECKED create encounters an existing file, the attributes
specified by createattrs are not used, except that when an size of
zero is specified, the existing file is truncated. If GUARDED is
specified, the server checks for the presence of a duplicate object
by name before performing the create. If a duplicate exists, an
error of NFS4ERR_EXIST is returned as the status. If the object does
not exist, the request is performed as described for UNCHECKED. For
each of these cases (UNCHECKED and GUARDED) where the operation is successful, the server will return to the client an attribute mask signifying which attributes were successfully set for the object. EXCLUSIVE specifies that the server is to follow exclusive creation semantics, using the verifier to ensure exclusive creation of the target. The server should check for the presence of a duplicate object by name. If the object does not exist, the server creates the object and stores the verifier with the object. If the object does exist and the stored verifier matches the client provided verifier, the server uses the existing object as the newly created object. If the stored verifier does not match, then an error of NFS4ERR_EXIST is returned. No attributes may be provided in this case, since the server may use an attribute of the target object to store the verifier. If the server uses an attribute to store the exclusive create verifier, it will signify which attribute by setting the appropriate bit in the attribute mask that is returned in the results. For the target directory, the server returns change_info4 information in cinfo. With the atomic field of the change_info4 struct, the server will indicate if the before and after change attributes were obtained atomically with respect to the link creation. Upon successful creation, the current filehandle is replaced by that of the new object. The OPEN operation provides for Windows share reservation capability with the use of the share_access and share_deny fields of the OPEN arguments. The client specifies at OPEN the required share_access and share_deny modes. For clients that do not directly support SHAREs (i.e., UNIX), the expected deny value is DENY_NONE. In the case that there is a existing SHARE reservation that conflicts with the OPEN request, the server returns the error NFS4ERR_SHARE_DENIED. For a complete SHARE request, the client must provide values for the owner and seqid fields for the OPEN argument. For additional discussion of SHARE semantics see the section on 'Share Reservations'. In the case that the client is recovering state from a server failure, the claim field of the OPEN argument is used to signify that the request is meant to reclaim state previously held. The "claim" field of the OPEN argument is used to specify the file to be opened and the state information which the client claims to possess. There are four basic claim types which cover the various situations for an OPEN. They are as follows:
CLAIM_NULL
For the client, this is a new OPEN
request and there is no previous state
associate with the file for the client.
CLAIM_PREVIOUS
The client is claiming basic OPEN state
for a file that was held previous to a
server reboot. Generally used when a
server is returning persistent
filehandles; the client may not have the
file name to reclaim the OPEN.
CLAIM_DELEGATE_CUR
The client is claiming a delegation for
OPEN as granted by the server.
Generally this is done as part of
recalling a delegation.
CLAIM_DELEGATE_PREV
The client is claiming a delegation
granted to a previous client instance;
used after the client reboots. The
server MAY support CLAIM_DELEGATE_PREV.
If it does support CLAIM_DELEGATE_PREV,
SETCLIENTID_CONFIRM MUST NOT remove the
client's delegation state, and the
server MUST support the DELEGPURGE
operation.
For OPEN requests whose claim type is other than CLAIM_PREVIOUS
(i.e., requests other than those devoted to reclaiming opens after a
server reboot) that reach the server during its grace or lease
expiration period, the server returns an error of NFS4ERR_GRACE.
For any OPEN request, the server may return an open delegation, which
allows further opens and closes to be handled locally on the client
as described in the section Open Delegation. Note that delegation is
up to the server to decide. The client should never assume that
delegation will or will not be granted in a particular instance. It
should always be prepared for either case. A partial exception is
the reclaim (CLAIM_PREVIOUS) case, in which a delegation type is
claimed. In this case, delegation will always be granted, although
the server may specify an immediate recall in the delegation
structure.
The rflags returned by a successful OPEN allow the server to return
information governing how the open file is to be handled.
OPEN4_RESULT_CONFIRM indicates that the client MUST execute an OPEN_CONFIRM operation before using the open file. OPEN4_RESULT_LOCKTYPE_POSIX indicates the server's file locking behavior supports the complete set of Posix locking techniques. From this the client can choose to manage file locking state in a way to handle a mis-match of file locking management. If the component is of zero length, NFS4ERR_INVAL will be returned. The component is also subject to the normal UTF-8, character support, and name checks. See the section "UTF-8 Related Errors" for further discussion. When an OPEN is done and the specified lockowner already has the resulting filehandle open, the result is to "OR" together the new share and deny status together with the existing status. In this case, only a single CLOSE need be done, even though multiple OPENs were completed. When such an OPEN is done, checking of share reservations for the new OPEN proceeds normally, with no exception for the existing OPEN held by the same lockowner. If the underlying filesystem at the server is only accessible in a read-only mode and the OPEN request has specified ACCESS_WRITE or ACCESS_BOTH, the server will return NFS4ERR_ROFS to indicate a read- only filesystem. As with the CREATE operation, the server MUST derive the owner, owner ACE, group, or group ACE if any of the four attributes are required and supported by the server's filesystem. For an OPEN with the EXCLUSIVE4 createmode, the server has no choice, since such OPEN calls do not include the createattrs field. Conversely, if createattrs is specified, and includes owner or group (or corresponding ACEs) that the principal in the RPC call's credentials does not have authorization to create files for, then the server may return NFS4ERR_PERM. In the case of a OPEN which specifies a size of zero (e.g., truncation) and the file has named attributes, the named attributes are left as is. They are not removed. IMPLEMENTATION The OPEN operation contains support for EXCLUSIVE create. The mechanism is similar to the support in NFS version 3 [RFC1813]. As in NFS version 3, this mechanism provides reliable exclusive creation. Exclusive create is invoked when the how parameter is EXCLUSIVE. In this case, the client provides a verifier that can reasonably be expected to be unique. A combination of a client
identifier, perhaps the client network address, and a unique number generated by the client, perhaps the RPC transaction identifier, may be appropriate. If the object does not exist, the server creates the object and stores the verifier in stable storage. For filesystems that do not provide a mechanism for the storage of arbitrary file attributes, the server may use one or more elements of the object meta-data to store the verifier. The verifier must be stored in stable storage to prevent erroneous failure on retransmission of the request. It is assumed that an exclusive create is being performed because exclusive semantics are critical to the application. Because of the expected usage, exclusive CREATE does not rely solely on the normally volatile duplicate request cache for storage of the verifier. The duplicate request cache in volatile storage does not survive a crash and may actually flush on a long network partition, opening failure windows. In the UNIX local filesystem environment, the expected storage location for the verifier on creation is the meta-data (time stamps) of the object. For this reason, an exclusive object create may not include initial attributes because the server would have nowhere to store the verifier. If the server can not support these exclusive create semantics, possibly because of the requirement to commit the verifier to stable storage, it should fail the OPEN request with the error, NFS4ERR_NOTSUPP. During an exclusive CREATE request, if the object already exists, the server reconstructs the object's verifier and compares it with the verifier in the request. If they match, the server treats the request as a success. The request is presumed to be a duplicate of an earlier, successful request for which the reply was lost and that the server duplicate request cache mechanism did not detect. If the verifiers do not match, the request is rejected with the status, NFS4ERR_EXIST. Once the client has performed a successful exclusive create, it must issue a SETATTR to set the correct object attributes. Until it does so, it should not rely upon any of the object attributes, since the server implementation may need to overload object meta-data to store the verifier. The subsequent SETATTR must not occur in the same COMPOUND request as the OPEN. This separation will guarantee that the exclusive create mechanism will continue to function properly in the face of retransmission of the request. Use of the GUARDED attribute does not provide exactly-once semantics. In particular, if a reply is lost and the server does not detect the retransmission of the request, the operation can fail with
NFS4ERR_EXIST, even though the create was performed successfully.
The client would use this behavior in the case that the application
has not requested an exclusive create but has asked to have the file
truncated when the file is opened. In the case of the client timing
out and retransmitting the create request, the client can use GUARDED
to prevent against a sequence like: create, write, create
(retransmitted) from occurring.
For SHARE reservations, the client must specify a value for
share_access that is one of READ, WRITE, or BOTH. For share_deny,
the client must specify one of NONE, READ, WRITE, or BOTH. If the
client fails to do this, the server must return NFS4ERR_INVAL.
Based on the share_access value (READ, WRITE, or BOTH) the client
should check that the requester has the proper access rights to
perform the specified operation. This would generally be the results
of applying the ACL access rules to the file for the current
requester. However, just as with the ACCESS operation, the client
should not attempt to second-guess the server's decisions, as access
rights may change and may be subject to server administrative
controls outside the ACL framework. If the requester is not
authorized to READ or WRITE (depending on the share_access value),
the server must return NFS4ERR_ACCESS. Note that since the NFS
version 4 protocol does not impose any requirement that READs and
WRITEs issued for an open file have the same credentials as the OPEN
itself, the server still must do appropriate access checking on the
READs and WRITEs themselves.
If the component provided to OPEN is a symbolic link, the error
NFS4ERR_SYMLINK will be returned to the client. If the current
filehandle is not a directory, the error NFS4ERR_NOTDIR will be
returned.
ERRORS
NFS4ERR_ACCESS
NFS4ERR_ADMIN_REVOKED
NFS4ERR_ATTRNOTSUPP
NFS4ERR_BADCHAR
NFS4ERR_BADHANDLE
NFS4ERR_BADNAME
NFS4ERR_BADOWNER
NFS4ERR_BAD_SEQID
NFS4ERR_BADXDR
NFS4ERR_DELAY
NFS4ERR_DQUOT
NFS4ERR_EXIST
NFS4ERR_EXPIRED
NFS4ERR_FHEXPIRED
NFS4ERR_GRACE
NFS4ERR_IO
NFS4ERR_INVAL
NFS4ERR_ISDIR
NFS4ERR_LEASE_MOVED
NFS4ERR_MOVED
NFS4ERR_NAMETOOLONG
NFS4ERR_NOENT
NFS4ERR_NOFILEHANDLE
NFS4ERR_NOSPC
NFS4ERR_NOTDIR
NFS4ERR_NOTSUPP
NFS4ERR_NO_GRACE
NFS4ERR_PERM
NFS4ERR_RECLAIM_BAD
NFS4ERR_RECLAIM_CONFLICT
NFS4ERR_RESOURCE
NFS4ERR_ROFS
NFS4ERR_SERVERFAULT
NFS4ERR_SHARE_DENIED
NFS4ERR_STALE
NFS4ERR_STALE_CLIENTID
NFS4ERR_SYMLINK
NFS4ERR_WRONGSEC
14.2.17. Operation 19: OPENATTR - Open Named Attribute Directory
SYNOPSIS
(cfh) createdir -> (cfh)
ARGUMENT
struct OPENATTR4args {
/* CURRENT_FH: object */
bool createdir;
};
RESULT
struct OPENATTR4res {
/* CURRENT_FH: named attr directory*/
nfsstat4 status;
};
DESCRIPTION
The OPENATTR operation is used to obtain the filehandle of the named
attribute directory associated with the current filehandle. The
result of the OPENATTR will be a filehandle to an object of type
NF4ATTRDIR. From this filehandle, READDIR and LOOKUP operations can
be used to obtain filehandles for the various named attributes
associated with the original filesystem object. Filehandles returned
within the named attribute directory will have a type of
NF4NAMEDATTR.
The createdir argument allows the client to signify if a named
attribute directory should be created as a result of the OPENATTR
operation. Some clients may use the OPENATTR operation with a value
of FALSE for createdir to determine if any named attributes exist for
the object. If none exist, then NFS4ERR_NOENT will be returned. If
createdir has a value of TRUE and no named attribute directory
exists, one is created. The creation of a named attribute directory
assumes that the server has implemented named attribute support in
this fashion and is not required to do so by this definition.
IMPLEMENTATION
If the server does not support named attributes for the current
filehandle, an error of NFS4ERR_NOTSUPP will be returned to the
client.
ERRORS
NFS4ERR_ACCESS
NFS4ERR_BADHANDLE
NFS4ERR_BADXDR
NFS4ERR_DELAY
NFS4ERR_DQUOT
NFS4ERR_FHEXPIRED
NFS4ERR_IO
NFS4ERR_MOVED
NFS4ERR_NOENT
NFS4ERR_NOFILEHANDLE
NFS4ERR_NOSPC
NFS4ERR_NOTSUPP
NFS4ERR_RESOURCE
NFS4ERR_ROFS
NFS4ERR_SERVERFAULT
NFS4ERR_STALE