16. NFSv4.1 Procedures
Both procedures, NULL and COMPOUND, MUST be implemented.
16.1. Procedure 0: NULL - No Operation
16.1.1. ARGUMENTS
void;16.1.2. RESULTS
void;16.1.3. DESCRIPTION
This is the standard NULL procedure with the standard void argument and 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.16.1.4. ERRORS
None.16.2. Procedure 1: COMPOUND - Compound Operations
16.2.1. ARGUMENTS
enum nfs_opnum4 { OP_ACCESS = 3, OP_CLOSE = 4, OP_COMMIT = 5, OP_CREATE = 6, OP_DELEGPURGE = 7, OP_DELEGRETURN = 8, OP_GETATTR = 9, OP_GETFH = 10, OP_LINK = 11, OP_LOCK = 12, OP_LOCKT = 13, OP_LOCKU = 14, OP_LOOKUP = 15, OP_LOOKUPP = 16, OP_NVERIFY = 17, OP_OPEN = 18, OP_OPENATTR = 19, OP_OPEN_CONFIRM = 20, /* Mandatory not-to-implement */ OP_OPEN_DOWNGRADE = 21, OP_PUTFH = 22,
OP_PUTPUBFH = 23, OP_PUTROOTFH = 24, OP_READ = 25, OP_READDIR = 26, OP_READLINK = 27, OP_REMOVE = 28, OP_RENAME = 29, OP_RENEW = 30, /* Mandatory not-to-implement */ OP_RESTOREFH = 31, OP_SAVEFH = 32, OP_SECINFO = 33, OP_SETATTR = 34, OP_SETCLIENTID = 35, /* Mandatory not-to-implement */ OP_SETCLIENTID_CONFIRM = 36, /* Mandatory not-to-implement */ OP_VERIFY = 37, OP_WRITE = 38, OP_RELEASE_LOCKOWNER = 39, /* Mandatory not-to-implement */ /* new operations for NFSv4.1 */ OP_BACKCHANNEL_CTL = 40, OP_BIND_CONN_TO_SESSION = 41, OP_EXCHANGE_ID = 42, OP_CREATE_SESSION = 43, OP_DESTROY_SESSION = 44, OP_FREE_STATEID = 45, OP_GET_DIR_DELEGATION = 46, OP_GETDEVICEINFO = 47, OP_GETDEVICELIST = 48, OP_LAYOUTCOMMIT = 49, OP_LAYOUTGET = 50, OP_LAYOUTRETURN = 51, OP_SECINFO_NO_NAME = 52, OP_SEQUENCE = 53, OP_SET_SSV = 54, OP_TEST_STATEID = 55, OP_WANT_DELEGATION = 56, OP_DESTROY_CLIENTID = 57, OP_RECLAIM_COMPLETE = 58, OP_ILLEGAL = 10044 };
union nfs_argop4 switch (nfs_opnum4 argop) { case OP_ACCESS: ACCESS4args opaccess; case OP_CLOSE: CLOSE4args opclose; case OP_COMMIT: COMMIT4args opcommit; case OP_CREATE: CREATE4args opcreate; case OP_DELEGPURGE: DELEGPURGE4args opdelegpurge; case OP_DELEGRETURN: DELEGRETURN4args opdelegreturn; case OP_GETATTR: GETATTR4args opgetattr; case OP_GETFH: void; case OP_LINK: LINK4args oplink; case OP_LOCK: LOCK4args oplock; case OP_LOCKT: LOCKT4args oplockt; case OP_LOCKU: LOCKU4args oplocku; case OP_LOOKUP: LOOKUP4args oplookup; case OP_LOOKUPP: void; case OP_NVERIFY: NVERIFY4args opnverify; case OP_OPEN: OPEN4args opopen; case OP_OPENATTR: OPENATTR4args opopenattr; /* Not for NFSv4.1 */ case OP_OPEN_CONFIRM: OPEN_CONFIRM4args opopen_confirm; case OP_OPEN_DOWNGRADE: OPEN_DOWNGRADE4args opopen_downgrade; case OP_PUTFH: PUTFH4args opputfh; case OP_PUTPUBFH: void; case OP_PUTROOTFH: void; case OP_READ: READ4args opread; case OP_READDIR: READDIR4args opreaddir; case OP_READLINK: void; case OP_REMOVE: REMOVE4args opremove; case OP_RENAME: RENAME4args oprename; /* Not for NFSv4.1 */ case OP_RENEW: RENEW4args oprenew; case OP_RESTOREFH: void; case OP_SAVEFH: void; case OP_SECINFO: SECINFO4args opsecinfo; case OP_SETATTR: SETATTR4args opsetattr; /* Not for NFSv4.1 */ case OP_SETCLIENTID: SETCLIENTID4args opsetclientid;
/* Not for NFSv4.1 */ case OP_SETCLIENTID_CONFIRM: SETCLIENTID_CONFIRM4args opsetclientid_confirm; case OP_VERIFY: VERIFY4args opverify; case OP_WRITE: WRITE4args opwrite; /* Not for NFSv4.1 */ case OP_RELEASE_LOCKOWNER: RELEASE_LOCKOWNER4args oprelease_lockowner; /* Operations new to NFSv4.1 */ case OP_BACKCHANNEL_CTL: BACKCHANNEL_CTL4args opbackchannel_ctl; case OP_BIND_CONN_TO_SESSION: BIND_CONN_TO_SESSION4args opbind_conn_to_session; case OP_EXCHANGE_ID: EXCHANGE_ID4args opexchange_id; case OP_CREATE_SESSION: CREATE_SESSION4args opcreate_session; case OP_DESTROY_SESSION: DESTROY_SESSION4args opdestroy_session; case OP_FREE_STATEID: FREE_STATEID4args opfree_stateid; case OP_GET_DIR_DELEGATION: GET_DIR_DELEGATION4args opget_dir_delegation; case OP_GETDEVICEINFO: GETDEVICEINFO4args opgetdeviceinfo; case OP_GETDEVICELIST: GETDEVICELIST4args opgetdevicelist; case OP_LAYOUTCOMMIT: LAYOUTCOMMIT4args oplayoutcommit; case OP_LAYOUTGET: LAYOUTGET4args oplayoutget; case OP_LAYOUTRETURN: LAYOUTRETURN4args oplayoutreturn; case OP_SECINFO_NO_NAME: SECINFO_NO_NAME4args opsecinfo_no_name; case OP_SEQUENCE: SEQUENCE4args opsequence; case OP_SET_SSV: SET_SSV4args opset_ssv; case OP_TEST_STATEID: TEST_STATEID4args optest_stateid; case OP_WANT_DELEGATION: WANT_DELEGATION4args opwant_delegation;
case OP_DESTROY_CLIENTID: DESTROY_CLIENTID4args opdestroy_clientid; case OP_RECLAIM_COMPLETE: RECLAIM_COMPLETE4args opreclaim_complete; /* Operations not new to NFSv4.1 */ case OP_ILLEGAL: void; }; struct COMPOUND4args { utf8str_cs tag; uint32_t minorversion; nfs_argop4 argarray<>; };16.2.2. RESULTS
union nfs_resop4 switch (nfs_opnum4 resop) { case OP_ACCESS: ACCESS4res opaccess; case OP_CLOSE: CLOSE4res opclose; case OP_COMMIT: COMMIT4res opcommit; case OP_CREATE: CREATE4res opcreate; case OP_DELEGPURGE: DELEGPURGE4res opdelegpurge; case OP_DELEGRETURN: DELEGRETURN4res opdelegreturn; case OP_GETATTR: GETATTR4res opgetattr; case OP_GETFH: GETFH4res opgetfh; case OP_LINK: LINK4res oplink; case OP_LOCK: LOCK4res oplock; case OP_LOCKT: LOCKT4res oplockt; case OP_LOCKU: LOCKU4res oplocku; case OP_LOOKUP: LOOKUP4res oplookup; case OP_LOOKUPP: LOOKUPP4res oplookupp; case OP_NVERIFY: NVERIFY4res opnverify; case OP_OPEN: OPEN4res opopen; case OP_OPENATTR: OPENATTR4res opopenattr; /* Not for NFSv4.1 */ case OP_OPEN_CONFIRM: OPEN_CONFIRM4res opopen_confirm; case OP_OPEN_DOWNGRADE: OPEN_DOWNGRADE4res opopen_downgrade; case OP_PUTFH: PUTFH4res opputfh; case OP_PUTPUBFH: PUTPUBFH4res opputpubfh;
case OP_PUTROOTFH: PUTROOTFH4res opputrootfh; case OP_READ: READ4res opread; case OP_READDIR: READDIR4res opreaddir; case OP_READLINK: READLINK4res opreadlink; case OP_REMOVE: REMOVE4res opremove; case OP_RENAME: RENAME4res oprename; /* Not for NFSv4.1 */ case OP_RENEW: RENEW4res oprenew; case OP_RESTOREFH: RESTOREFH4res oprestorefh; case OP_SAVEFH: SAVEFH4res opsavefh; case OP_SECINFO: SECINFO4res opsecinfo; case OP_SETATTR: SETATTR4res opsetattr; /* Not for NFSv4.1 */ case OP_SETCLIENTID: SETCLIENTID4res opsetclientid; /* Not for NFSv4.1 */ case OP_SETCLIENTID_CONFIRM: SETCLIENTID_CONFIRM4res opsetclientid_confirm; case OP_VERIFY: VERIFY4res opverify; case OP_WRITE: WRITE4res opwrite; /* Not for NFSv4.1 */ case OP_RELEASE_LOCKOWNER: RELEASE_LOCKOWNER4res oprelease_lockowner; /* Operations new to NFSv4.1 */ case OP_BACKCHANNEL_CTL: BACKCHANNEL_CTL4res opbackchannel_ctl; case OP_BIND_CONN_TO_SESSION: BIND_CONN_TO_SESSION4res opbind_conn_to_session; case OP_EXCHANGE_ID: EXCHANGE_ID4res opexchange_id; case OP_CREATE_SESSION: CREATE_SESSION4res opcreate_session; case OP_DESTROY_SESSION: DESTROY_SESSION4res opdestroy_session;
case OP_FREE_STATEID: FREE_STATEID4res opfree_stateid; case OP_GET_DIR_DELEGATION: GET_DIR_DELEGATION4res opget_dir_delegation; case OP_GETDEVICEINFO: GETDEVICEINFO4res opgetdeviceinfo; case OP_GETDEVICELIST: GETDEVICELIST4res opgetdevicelist; case OP_LAYOUTCOMMIT: LAYOUTCOMMIT4res oplayoutcommit; case OP_LAYOUTGET: LAYOUTGET4res oplayoutget; case OP_LAYOUTRETURN: LAYOUTRETURN4res oplayoutreturn; case OP_SECINFO_NO_NAME: SECINFO_NO_NAME4res opsecinfo_no_name; case OP_SEQUENCE: SEQUENCE4res opsequence; case OP_SET_SSV: SET_SSV4res opset_ssv; case OP_TEST_STATEID: TEST_STATEID4res optest_stateid; case OP_WANT_DELEGATION: WANT_DELEGATION4res opwant_delegation; case OP_DESTROY_CLIENTID: DESTROY_CLIENTID4res opdestroy_clientid; case OP_RECLAIM_COMPLETE: RECLAIM_COMPLETE4res opreclaim_complete; /* Operations not new to NFSv4.1 */ case OP_ILLEGAL: ILLEGAL4res opillegal; }; struct COMPOUND4res { nfsstat4 status; utf8str_cs tag; nfs_resop4 resarray<>; };
16.2.3. DESCRIPTION
The COMPOUND procedure is used to combine one or more NFSv4 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 until 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. See Section 2.10.6.4 for a more detailed discussion. The server will generally choose between two methods of decoding the client's request. The first would be the traditional one-pass XDR decode. If there is an XDR decoding error in this case, the 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 the individual operations; the most interesting is the decode of attributes. In this case, the server may encounter an XDR decode error during the second pass. If it does, the server would return the error NFS4ERR_BADXDR to signify the decode error. The COMPOUND arguments contain a "minorversion" field. For NFSv4.1, the value for this field is 1. 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 zero and one are not defined for the COMPOUND procedure. Operation 2 is not defined and is reserved for future definition and use with minor versioning. If the server receives an operation array that contains operation 2 and the minorversion field has a value of 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 be 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.16.2.3.1. Current Filehandle and Stateid
The COMPOUND procedure offers a simple environment for the execution of the operations specified by the client. The first two relate to the filehandle while the second two relate to the current stateid.16.2.3.1.1. Current Filehandle
The current and saved filehandles are used throughout the protocol. Most operations implicitly use the current filehandle as an argument, and many set the current filehandle as part of the results. The combination of client-specified sequences of operations and current and saved filehandle arguments and results allows for greater protocol flexibility. The best or easiest example of current filehandle usage is a sequence like the following: PUTFH fh1 {fh1} LOOKUP "compA" {fh2} GETATTR {fh2} LOOKUP "compB" {fh3} GETATTR {fh3} LOOKUP "compC" {fh4} GETATTR {fh4} GETFH Figure 2
In this example, the PUTFH (Section 18.19) operation explicitly sets the current filehandle value while the result of each LOOKUP operation sets the current filehandle value to the resultant file system object. Also, the client is able to insert GETATTR operations using the current filehandle as an argument. The PUTROOTFH (Section 18.21) and PUTPUBFH (Section 18.20) operations also set the current filehandle. The above example would replace "PUTFH fh1" with PUTROOTFH or PUTPUBFH with no filehandle argument in order to achieve the same effect (on the assumption that "compA" is directly below the root of the namespace). Along with the current filehandle, there is a saved filehandle. While the current filehandle is set as the result of operations like LOOKUP, the saved filehandle must be set directly with the use of the SAVEFH operation. The SAVEFH operation copies the current filehandle value to the saved value. The saved filehandle value is used in combination with the current filehandle value for the LINK and RENAME operations. The RESTOREFH operation will copy the saved filehandle value to the current filehandle value; as a result, the saved filehandle value may be used a sort of "scratch" area for the client's series of operations.16.2.3.1.2. Current Stateid
With NFSv4.1, additions of a current stateid and a saved stateid have been made to the COMPOUND processing environment; this allows for the passing of stateids between operations. There are no changes to the syntax of the protocol, only changes to the semantics of a few operations. A "current stateid" is the stateid that is associated with the current filehandle. The current stateid may only be changed by an operation that modifies the current filehandle or returns a stateid. If an operation returns a stateid, it MUST set the current stateid to the returned value. If an operation sets the current filehandle but does not return a stateid, the current stateid MUST be set to the all-zeros special stateid, i.e., (seqid, other) = (0, 0). If an operation uses a stateid as an argument but does not return a stateid, the current stateid MUST NOT be changed. For example, PUTFH, PUTROOTFH, and PUTPUBFH will change the current server state from {ocfh, (osid)} to {cfh, (0, 0)}, while LOCK will change the current state from {cfh, (osid} to {cfh, (nsid)}. Operations like LOOKUP that transform a current filehandle and component name into a new current filehandle will also change the current state to {0, 0}. The SAVEFH and RESTOREFH operations will save and restore both the current filehandle and the current stateid as a set.
The following example is the common case of a simple READ operation with a normal stateid showing that the PUTFH initializes the current stateid to (0, 0). The subsequent READ with stateid (sid1) leaves the current stateid unchanged. PUTFH fh1 - -> {fh1, (0, 0)} READ (sid1), 0, 1024 {fh1, (0, 0)} -> {fh1, (0, 0)} Figure 3 This next example performs an OPEN with the root filehandle and, as a result, generates stateid (sid1). The next operation specifies the READ with the argument stateid set such that (seqid, other) are equal to (1, 0), but the current stateid set by the previous operation is actually used when the operation is evaluated. This allows correct interaction with any existing, potentially conflicting, locks. PUTROOTFH - -> {fh1, (0, 0)} OPEN "compA" {fh1, (0, 0)} -> {fh2, (sid1)} READ (1, 0), 0, 1024 {fh2, (sid1)} -> {fh2, (sid1)} CLOSE (1, 0) {fh2, (sid1)} -> {fh2, (sid2)} Figure 4 This next example is similar to the second in how it passes the stateid sid2 generated by the LOCK operation to the next READ operation. This allows the client to explicitly surround a single I/O operation with a lock and its appropriate stateid to guarantee correctness with other client locks. The example also shows how SAVEFH and RESTOREFH can save and later reuse a filehandle and stateid, passing them as the current filehandle and stateid to a READ operation. PUTFH fh1 - -> {fh1, (0, 0)} LOCK 0, 1024, (sid1) {fh1, (sid1)} -> {fh1, (sid2)} READ (1, 0), 0, 1024 {fh1, (sid2)} -> {fh1, (sid2)} LOCKU 0, 1024, (1, 0) {fh1, (sid2)} -> {fh1, (sid3)} SAVEFH {fh1, (sid3)} -> {fh1, (sid3)} PUTFH fh2 {fh1, (sid3)} -> {fh2, (0, 0)} WRITE (1, 0), 0, 1024 {fh2, (0, 0)} -> {fh2, (0, 0)} RESTOREFH {fh2, (0, 0)} -> {fh1, (sid3)} READ (1, 0), 1024, 1024 {fh1, (sid3)} -> {fh1, (sid3)} Figure 5
The final example shows a disallowed use of the current stateid. The client is attempting to implicitly pass an anonymous special stateid, (0,0), to the READ operation. The server MUST return NFS4ERR_BAD_STATEID in the reply to the READ operation. PUTFH fh1 - -> {fh1, (0, 0)} READ (1, 0), 0, 1024 {fh1, (0, 0)} -> NFS4ERR_BAD_STATEID Figure 616.2.4. ERRORS
COMPOUND will of course return every error that each operation on the fore channel can return (see Table 6). However, if COMPOUND returns zero operations, obviously the error returned by COMPOUND has nothing to do with an error returned by an operation. The list of errors COMPOUND will return if it processes zero operations include: COMPOUND Error Returns +------------------------------+------------------------------------+ | Error | Notes | +------------------------------+------------------------------------+ | NFS4ERR_BADCHAR | The tag argument has a character | | | the replier does not support. | | NFS4ERR_BADXDR | | | NFS4ERR_DELAY | | | NFS4ERR_INVAL | The tag argument is not in UTF-8 | | | encoding. | | NFS4ERR_MINOR_VERS_MISMATCH | | | NFS4ERR_SERVERFAULT | | | NFS4ERR_TOO_MANY_OPS | | | NFS4ERR_REP_TOO_BIG | | | NFS4ERR_REP_TOO_BIG_TO_CACHE | | | NFS4ERR_REQ_TOO_BIG | | +------------------------------+------------------------------------+ Table 917. Operations: REQUIRED, RECOMMENDED, or OPTIONAL
The following tables summarize the operations of the NFSv4.1 protocol and the corresponding designation of REQUIRED, RECOMMENDED, and OPTIONAL to implement or MUST NOT implement. The designation of MUST NOT implement is reserved for those operations that were defined in NFSv4.0 and MUST NOT be implemented in NFSv4.1.
For the most part, the REQUIRED, RECOMMENDED, or OPTIONAL designation for operations sent by the client is for the server implementation. The client is generally required to implement the operations needed for the operating environment for which it serves. For example, a read-only NFSv4.1 client would have no need to implement the WRITE operation and is not required to do so. The REQUIRED or OPTIONAL designation for callback operations sent by the server is for both the client and server. Generally, the client has the option of creating the backchannel and sending the operations on the fore channel that will be a catalyst for the server sending callback operations. A partial exception is CB_RECALL_SLOT; the only way the client can avoid supporting this operation is by not creating a backchannel. Since this is a summary of the operations and their designation, there are subtleties that are not presented here. Therefore, if there is a question of the requirements of implementation, the operation descriptions themselves must be consulted along with other relevant explanatory text within this specification. The abbreviations used in the second and third columns of the table are defined as follows. REQ REQUIRED to implement REC RECOMMEND to implement OPT OPTIONAL to implement MNI MUST NOT implement For the NFSv4.1 features that are OPTIONAL, the operations that support those features are OPTIONAL, and the server would return NFS4ERR_NOTSUPP in response to the client's use of those operations. If an OPTIONAL feature is supported, it is possible that a set of operations related to the feature become REQUIRED to implement. The third column of the table designates the feature(s) and if the operation is REQUIRED or OPTIONAL in the presence of support for the feature. The OPTIONAL features identified and their abbreviations are as follows: pNFS Parallel NFS FDELG File Delegations
DDELG Directory Delegations Operations +----------------------+------------+--------------+----------------+ | Operation | REQ, REC, | Feature | Definition | | | OPT, or | (REQ, REC, | | | | MNI | or OPT) | | +----------------------+------------+--------------+----------------+ | ACCESS | REQ | | Section 18.1 | | BACKCHANNEL_CTL | REQ | | Section 18.33 | | BIND_CONN_TO_SESSION | REQ | | Section 18.34 | | CLOSE | REQ | | Section 18.2 | | COMMIT | REQ | | Section 18.3 | | CREATE | REQ | | Section 18.4 | | CREATE_SESSION | REQ | | Section 18.36 | | DELEGPURGE | OPT | FDELG (REQ) | Section 18.5 | | DELEGRETURN | OPT | FDELG, | Section 18.6 | | | | DDELG, pNFS | | | | | (REQ) | | | DESTROY_CLIENTID | REQ | | Section 18.50 | | DESTROY_SESSION | REQ | | Section 18.37 | | EXCHANGE_ID | REQ | | Section 18.35 | | FREE_STATEID | REQ | | Section 18.38 | | GETATTR | REQ | | Section 18.7 | | GETDEVICEINFO | OPT | pNFS (REQ) | Section 18.40 | | GETDEVICELIST | OPT | pNFS (OPT) | Section 18.41 | | GETFH | REQ | | Section 18.8 | | GET_DIR_DELEGATION | OPT | DDELG (REQ) | Section 18.39 | | LAYOUTCOMMIT | OPT | pNFS (REQ) | Section 18.42 | | LAYOUTGET | OPT | pNFS (REQ) | Section 18.43 | | LAYOUTRETURN | OPT | pNFS (REQ) | Section 18.44 | | LINK | OPT | | Section 18.9 | | LOCK | REQ | | Section 18.10 | | LOCKT | REQ | | Section 18.11 | | LOCKU | REQ | | Section 18.12 | | LOOKUP | REQ | | Section 18.13 | | LOOKUPP | REQ | | Section 18.14 | | NVERIFY | REQ | | Section 18.15 | | OPEN | REQ | | Section 18.16 | | OPENATTR | OPT | | Section 18.17 | | OPEN_CONFIRM | MNI | | N/A | | OPEN_DOWNGRADE | REQ | | Section 18.18 | | PUTFH | REQ | | Section 18.19 | | PUTPUBFH | REQ | | Section 18.20 | | PUTROOTFH | REQ | | Section 18.21 | | READ | REQ | | Section 18.22 | | READDIR | REQ | | Section 18.23 |
| READLINK | OPT | | Section 18.24 | | RECLAIM_COMPLETE | REQ | | Section 18.51 | | RELEASE_LOCKOWNER | MNI | | N/A | | REMOVE | REQ | | Section 18.25 | | RENAME | REQ | | Section 18.26 | | RENEW | MNI | | N/A | | RESTOREFH | REQ | | Section 18.27 | | SAVEFH | REQ | | Section 18.28 | | SECINFO | REQ | | Section 18.29 | | SECINFO_NO_NAME | REC | pNFS file | Section 18.45, | | | | layout (REQ) | Section 13.12 | | SEQUENCE | REQ | | Section 18.46 | | SETATTR | REQ | | Section 18.30 | | SETCLIENTID | MNI | | N/A | | SETCLIENTID_CONFIRM | MNI | | N/A | | SET_SSV | REQ | | Section 18.47 | | TEST_STATEID | REQ | | Section 18.48 | | VERIFY | REQ | | Section 18.31 | | WANT_DELEGATION | OPT | FDELG (OPT) | Section 18.49 | | WRITE | REQ | | Section 18.32 | +----------------------+------------+--------------+----------------+
Callback Operations +-------------------------+-----------+-------------+---------------+ | Operation | REQ, REC, | Feature | Definition | | | OPT, or | (REQ, REC, | | | | MNI | or OPT) | | +-------------------------+-----------+-------------+---------------+ | CB_GETATTR | OPT | FDELG (REQ) | Section 20.1 | | CB_LAYOUTRECALL | OPT | pNFS (REQ) | Section 20.3 | | CB_NOTIFY | OPT | DDELG (REQ) | Section 20.4 | | CB_NOTIFY_DEVICEID | OPT | pNFS (OPT) | Section 20.12 | | CB_NOTIFY_LOCK | OPT | | Section 20.11 | | CB_PUSH_DELEG | OPT | FDELG (OPT) | Section 20.5 | | CB_RECALL | OPT | FDELG, | Section 20.2 | | | | DDELG, pNFS | | | | | (REQ) | | | CB_RECALL_ANY | OPT | FDELG, | Section 20.6 | | | | DDELG, pNFS | | | | | (REQ) | | | CB_RECALL_SLOT | REQ | | Section 20.8 | | CB_RECALLABLE_OBJ_AVAIL | OPT | DDELG, pNFS | Section 20.7 | | | | (REQ) | | | CB_SEQUENCE | OPT | FDELG, | Section 20.9 | | | | DDELG, pNFS | | | | | (REQ) | | | CB_WANTS_CANCELLED | OPT | FDELG, | Section 20.10 | | | | DDELG, pNFS | | | | | (REQ) | | +-------------------------+-----------+-------------+---------------+18. NFSv4.1 Operations
18.1. Operation 3: ACCESS - Check Access Rights
18.1.1. ARGUMENTS
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; };
18.1.2. RESULTS
struct ACCESS4resok { uint32_t supported; uint32_t access; }; union ACCESS4res switch (nfsstat4 status) { case NFS4_OK: ACCESS4resok resok4; default: void; };18.1.3. 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 reply's supported and access fields MUST NOT contain more values than originally set in the request's access field. For example, if the client sends an ACCESS operation with just the ACCESS4_READ value set and the server supports this value, the server MUST NOT set more than ACCESS4_READ in the supported field even if it could have reliably checked other values. The reply's access field MUST NOT contain more values than the supported field. 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 do 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 a regular file (no meaning for a directory). On success, the current filehandle retains its value. ACCESS4_EXECUTE is a challenging semantic to implement because NFS provides remote file access, not remote execution. This leads to the following: o Whether or not a regular file is executable ought to be the responsibility of the NFS client and not the server. And yet the ACCESS operation is specified to seemingly require a server to own that responsibility. o When a client executes a regular file, it has to read the file from the server. Strictly speaking, the server should not allow the client to read a file being executed unless the user has read permissions on the file. Requiring explicit read permissions on executable files in order to access them over NFS is not going to be acceptable to some users and storage administrators. Historically, NFS servers have allowed a user to READ a file if the user has execute access to the file. As a practical example, the UNIX specification [52] states that an implementation claiming conformance to UNIX may indicate in the access() programming interface's result that a privileged user has execute rights, even if no execute permission bits are set on the regular file's attributes. It is possible to claim conformance to the UNIX specification and instead not indicate execute rights in that situation, which is true for some operating environments. Suppose the operating environments of the client and server are implementing the access() semantics for privileged users differently, and the ACCESS operation implementations of the client and server follow their respective access() semantics. This can cause undesired behavior: o Suppose the client's access() interface returns X_OK if the user is privileged and no execute permission bits are set on the regular file's attribute, and the server's access() interface does
not return X_OK in that situation. Then the client will be unable to execute files stored on the NFS server that could be executed if stored on a non-NFS file system. o Suppose the client's access() interface does not return X_OK if the user is privileged, and no execute permission bits are set on the regular file's attribute, and the server's access() interface does return X_OK in that situation. Then: * The client will be able to execute files stored on the NFS server that could be executed if stored on a non-NFS file system, unless the client's execution subsystem also checks for execute permission bits. * Even if the execution subsystem is checking for execute permission bits, there are more potential issues. For example, suppose the client is invoking access() to build a "path search table" of all executable files in the user's "search path", where the path is a list of directories each containing executable files. Suppose there are two files each in separate directories of the search path, such that files have the same component name. In the first directory the file has no execute permission bits set, and in the second directory the file has execute bits set. The path search table will indicate that the first directory has the executable file, but the execute subsystem will fail to execute it. The command shell might fail to try the second file in the second directory. And even if it did, this is a potential performance issue. Clearly, the desired outcome for the client is for the path search table to not contain the first file. To deal with the problems described above, the "smart client, stupid server" principle is used. The client owns overall responsibility for determining execute access and relies on the server to parse the execution permissions within the file's mode, acl, and dacl attributes. The rules for the client and server follow: o If the client is sending ACCESS in order to determine if the user can read the file, the client SHOULD set ACCESS4_READ in the request's access field. o If the client's operating environment only grants execution to the user if the user has execute access according to the execute permissions in the mode, acl, and dacl attributes, then if the client wants to determine execute access, the client SHOULD send an ACCESS request with ACCESS4_EXECUTE bit set in the request's access field.
o If the client's operating environment grants execution to the user even if the user does not have execute access according to the execute permissions in the mode, acl, and dacl attributes, then if the client wants to determine execute access, it SHOULD send an ACCESS request with both the ACCESS4_EXECUTE and ACCESS4_READ bits set in the request's access field. This way, if any read or execute permission grants the user read or execute access (or if the server interprets the user as privileged), as indicated by the presence of ACCESS4_EXECUTE and/or ACCESS4_READ in the reply's access field, the client will be able to grant the user execute access to the file. o If the server supports execute permission bits, or some other method for denoting executability (e.g., the suffix of the name of the file might indicate execute), it MUST check only execute permissions, not read permissions, when determining whether or not the reply will have ACCESS4_EXECUTE set in the access field. The server MUST NOT also examine read permission bits when determining whether or not the reply will have ACCESS4_EXECUTE set in the access field. Even if the server's operating environment would grant execute access to the user (e.g., the user is privileged), the server MUST NOT reply with ACCESS4_EXECUTE set in reply's access field unless there is at least one execute permission bit set in the mode, acl, or dacl attributes. In the case of acl and dacl, the "one execute permission bit" MUST be an ACE4_EXECUTE bit set in an ALLOW ACE. o If the server does not support execute permission bits or some other method for denoting executability, it MUST NOT set ACCESS4_EXECUTE in the reply's supported and access fields. If the client set ACCESS4_EXECUTE in the ACCESS request's access field, and ACCESS4_EXECUTE is not set in the reply's supported field, then the client will have to send an ACCESS request with the ACCESS4_READ bit set in the request's access field. o If the server supports read permission bits, it MUST only check for read permissions in the mode, acl, and dacl attributes when it receives an ACCESS request with ACCESS4_READ set in the access field. The server MUST NOT also examine execute permission bits when determining whether the reply will have ACCESS4_READ set in the access field or not. Note that if the ACCESS reply has ACCESS4_READ or ACCESS_EXECUTE set, then the user also has permissions to OPEN (Section 18.16) or READ (Section 18.22) the file. In other words, if the client sends an ACCESS request with the ACCESS4_READ and ACCESS_EXECUTE set in the access field (or two separate requests, one with ACCESS4_READ set and the other with ACCESS4_EXECUTE set), and the reply has just
ACCESS4_EXECUTE set in the access field (or just one reply has ACCESS4_EXECUTE set), then the user has authorization to OPEN or READ the file.18.1.4. 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 cannot reliably perform an access check with only current file attributes. In the NFSv2 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 NFSv4.1 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 that will result in an access failure. The OPEN operation provides a point where the server can verify access to the file object and a method to return that information to the client. The ACCESS operation is still useful for directory operations or for use in the case that the UNIX interface 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.
18.2. Operation 4: CLOSE - Close File
18.2.1. ARGUMENTS
struct CLOSE4args { /* CURRENT_FH: object */ seqid4 seqid; stateid4 open_stateid; };18.2.2. RESULTS
union CLOSE4res switch (nfsstat4 status) { case NFS4_OK: stateid4 open_stateid; default: void; };18.2.3. 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 are only those associated with the supplied stateid. State associated with other OPENs is not affected. If byte-range locks are held, the client SHOULD release all locks before sending 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 byte-range locks held. The server MUST return failure if any locks would exist after the CLOSE. The argument seqid MAY have any value, and the server MUST ignore seqid. On success, the current filehandle retains its value. The server MAY require that the combination of principal, security flavor, and, if applicable, GSS mechanism that sent the OPEN request also be the one to CLOSE the file. This might not be possible if credentials for the principal are no longer available. The server MAY allow the machine credential or SSV credential (see Section 18.35) to send CLOSE.
18.2.4. 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. To help find any uses of this stateid by clients, the server SHOULD return the invalid special stateid (the "other" value is zero and the "seqid" field is NFS4_UINT32_MAX, see Section 8.2.3). A CLOSE operation may make delegations grantable where they were not previously. Servers may choose to respond immediately if there are pending delegation want requests or may respond to the situation at a later time.18.3. Operation 5: COMMIT - Commit Cached Data
18.3.1. ARGUMENTS
struct COMMIT4args { /* CURRENT_FH: file */ offset4 offset; count4 count; };18.3.2. RESULTS
struct COMMIT4resok { verifier4 writeverf; }; union COMMIT4res switch (nfsstat4 status) { case NFS4_OK: COMMIT4resok resok4; default: void; };
18.3.3. DESCRIPTION
The COMMIT operation forces or flushes uncommitted, modified data to stable storage for the file specified by the current filehandle. The flushed data is that which was previously written with one or more WRITE operations that had the "committed" field of their results field set to UNSTABLE4. The offset specifies the position within the file where the flush is to begin. An offset value of zero means to flush data starting at the beginning of the file. The count specifies the number of bytes of data to flush. If the count is zero, a flush from the 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 between the initial WRITE operations and the COMMIT. The client does this by comparing the write verifier returned from the initial WRITE operations 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 restarted; however, other events at the server may result in uncommitted data loss as well. On success, the current filehandle retains its value.18.3.4. IMPLEMENTATION
The COMMIT operation is similar in operation and semantics to the POSIX fsync() [25] system interface 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(), 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() 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 the 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 zero and count zero, it should do the equivalent of applying
fsync() to the entire file. Otherwise, it should arrange to have the modified 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 modified data based on the offset and count, and flushes any modified metadata associated with the file. It then returns the status of the flush and the write verifier. The second 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 zero and count of zero, 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 (via the WRITE operation) by the client with the "committed" field in the result of WRITE 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 the "committed" field in the result 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 differs from that previously returned by the server, the client will need to retransmit all of the buffers containing uncommitted 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 be sent in a WRITE request with the FILE_SYNC4 stable parameter. If there is more than one buffer, it might be worthwhile retransmitting all of the buffers in WRITE operations 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. However, if the server repeatably returns from COMMIT a verifier that differs from that returned by WRITE, the only way to ensure progress is to retransmit all of the buffers with WRITE requests with the FILE_SYNC4 stable parameter.
The above description applies to page-cache-based systems as well as buffer-cache-based systems. In the former systems, the virtual memory system will need to be modified instead of the buffer cache.18.4. Operation 6: CREATE - Create a Non-Regular File Object
18.4.1. ARGUMENTS
union createtype4 switch (nfs_ftype4 type) { case NF4LNK: linktext4 linkdata; case NF4BLK: case NF4CHR: specdata4 devdata; case NF4SOCK: case NF4FIFO: case NF4DIR: void; default: void; /* server should return NFS4ERR_BADTYPE */ }; struct CREATE4args { /* CURRENT_FH: directory for creation */ createtype4 objtype; component4 objname; fattr4 createattrs; };18.4.2. RESULTS
struct CREATE4resok { change_info4 cinfo; bitmap4 attrset; /* attributes set */ }; union CREATE4res switch (nfsstat4 status) { case NFS4_OK: /* new CURRENTFH: created object */ CREATE4resok resok4; default: void; };
18.4.3. DESCRIPTION
The CREATE operation creates a file object other than an ordinary file in a directory with a given name. The OPEN operation MUST be used to create a regular file or a named attribute. The current filehandle must be a directory: an object of type NF4DIR. If the current filehandle is an attribute directory (type NF4ATTRDIR), the error NFS4ERR_WRONG_TYPE is returned. If the current file handle designates any other type of object, the error NFS4ERR_NOTDIR results. The objname specifies the name for the new object. The objtype determines the type of object to be created: directory, symlink, etc. If the object type specified is that of an ordinary file, a named attribute, or a named attribute directory, the error NFS4ERR_BADTYPE results. 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 data type, 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 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 file system 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 file system semantics may dictate other methods of derivation. Similarly, if createattrs includes neither the group attribute nor a group ACE, and if the server's file system 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 (e.g., POSIX systems have a user database [26] that has a group identifier for every user identifier), inherited from the directory in which the object is created, or whatever else the server's operating environment or file system semantics dictate. This applies to the OPEN operation too. Conversely, it is possible that the client will specify in createattrs an owner attribute, 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. If the current filehandle designates a directory for which another client holds a directory delegation, then, unless the delegation is such that the situation can be resolved by sending a notification, the delegation MUST be recalled, and the CREATE operation MUST NOT proceed until the delegation is returned or revoked. Except where this happens very quickly, one or more NFS4ERR_DELAY errors will be returned to requests made while delegation remains outstanding. When the current filehandle designates a directory for which one or more directory delegations exist, then, when those delegations request such notifications, NOTIFY4_ADD_ENTRY will be generated as a result of this operation. If the capability FSCHARSET_CAP4_ALLOWS_ONLY_UTF8 is set (Section 14.4), and a symbolic link is being created, then the content of the symbolic link MUST be in UTF-8 encoding.18.4.4. 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.18.5. Operation 7: DELEGPURGE - Purge Delegations Awaiting Recovery
18.5.1. ARGUMENTS
struct DELEGPURGE4args { clientid4 clientid; };
18.5.2. RESULTS
struct DELEGPURGE4res { nfsstat4 status; };18.5.3. DESCRIPTION
This operation purges all of the delegations awaiting recovery for a given client. This is useful for clients that 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. The client is NOT specified by the clientid field of the request. The client SHOULD set the client field to zero, and the server MUST ignore the clientid field. Instead, the server MUST derive the client ID from the value of the session ID in the arguments of the SEQUENCE operation that precedes DELEGPURGE in the COMPOUND request. The DELEGPURGE operation should be used by clients that record delegation information on stable storage on the client. In this case, after the client recovers all delegations it knows of, it should immediately send a DELEGPURGE operation. 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 which make requests that conflict with the unrecovered delegations. The set of delegations known to the server and the client might be different. The reason for this is that after sending a request that resulted in a delegation, the client might experience a failure before it both received the delegation and committed the delegation to the client's stable storage. The server MAY support DELEGPURGE, but if it does not, it MUST NOT support CLAIM_DELEGATE_PREV and MUST NOT support CLAIM_DELEG_PREV_FH.18.6. Operation 8: DELEGRETURN - Return Delegation
18.6.1. ARGUMENTS
struct DELEGRETURN4args { /* CURRENT_FH: delegated object */ stateid4 deleg_stateid; };
18.6.2. RESULTS
struct DELEGRETURN4res { nfsstat4 status; };18.6.3. DESCRIPTION
The DELEGRETURN operation returns the delegation represented by the current filehandle and stateid. Delegations may be returned voluntarily (i.e., before the server has recalled them) or when recalled. In either case, the client must properly propagate state changed under the context of the delegation to the server before returning the delegation. The server MAY require that the principal, security flavor, and if applicable, the GSS mechanism, combination that acquired the delegation also be the one to send DELEGRETURN on the file. This might not be possible if credentials for the principal are no longer available. The server MAY allow the machine credential or SSV credential (see Section 18.35) to send DELEGRETURN.18.7. Operation 9: GETATTR - Get Attributes
18.7.1. ARGUMENTS
struct GETATTR4args { /* CURRENT_FH: object */ bitmap4 attr_request; };18.7.2. RESULTS
struct GETATTR4resok { fattr4 obj_attributes; }; union GETATTR4res switch (nfsstat4 status) { case NFS4_OK: GETATTR4resok resok4; default: void; };
18.7.3. DESCRIPTION
The GETATTR operation will obtain attributes for the file system 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 that it was able to return, which will include all attributes requested by the client that are attributes supported by the server for the target file system. This bitmap is 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 for the target file system. If the server does not support a particular attribute on the target file system, 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 on the target but cannot obtain its value. In that case, no attribute values will be returned. File systems that are absent should be treated as having support for a very small set of attributes as described in Section 11.3.1, even if previously, when the file system was present, more attributes were supported. All servers MUST support the REQUIRED attributes as specified in Section 5.6, for all file systems, with the exception of absent file systems. On success, the current filehandle retains its value.18.7.4. IMPLEMENTATION
Suppose there is an OPEN_DELEGATE_WRITE delegation held by another client for the file in question and size and/or change are among the set of attributes being interrogated. The server has two choices. First, the server can obtain the actual current value of these attributes from the client holding the delegation by using the CB_GETATTR callback. Second, the server, particularly when the delegated client is unresponsive, can recall the delegation in question. The GETATTR MUST NOT proceed until one of the following occurs: o The requested attribute values are returned in the response to CB_GETATTR. o The OPEN_DELEGATE_WRITE delegation is returned.
o The OPEN_DELEGATE_WRITE delegation is revoked. Unless one of the above happens very quickly, one or more NFS4ERR_DELAY errors will be returned while a delegation is outstanding.18.8. Operation 10: GETFH - Get Current Filehandle
18.8.1. ARGUMENTS
/* CURRENT_FH: */ void;18.8.2. RESULTS
struct GETFH4resok { nfs_fh4 object; }; union GETFH4res switch (nfsstat4 status) { case NFS4_OK: GETFH4resok resok4; default: void; };18.8.3. DESCRIPTION
This operation returns the current filehandle value. On success, the current filehandle retains its value. As described in Section 2.10.6.4, GETFH is REQUIRED or RECOMMENDED to immediately follow certain operations, and servers are free to reject such operations if the client fails to insert GETFH in the request as REQUIRED or RECOMMENDED. Section 18.16.4.1 provides additional justification for why GETFH MUST follow OPEN.18.8.4. 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 look up a directory entry and obtain its filehandle, then the following request is needed. PUTFH (directory filehandle) LOOKUP (entry name) GETFH