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_ENOENT error must be returned. Therefore, NFS4ERR_ENOENT 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_ACCES NFS4ERR_BADHANDLE NFS4ERR_FHEXPIRED NFS4ERR_INVAL NFS4ERR_IO NFS4ERR_MOVED NFS4ERR_NOENT NFS4ERR_NOFILEHANDLE NFS4ERR_NOTDIR NFS4ERR_RESOURCE NFS4ERR_SERVERFAULT
NFS4ERR_STALE NFS4ERR_WRONGSEC14.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 "pub" "foo" "bar" NVERIFY attrbits attrs READ 0 32767 In the case that a recommended attribute is specified in the NVERIFY operation and the server does not support that attribute for the file system object, the error NFS4ERR_NOTSUPP is returned to the client.
ERRORS NFS4ERR_ACCES NFS4ERR_BADHANDLE NFS4ERR_DELAY NFS4ERR_FHEXPIRED NFS4ERR_INVAL NFS4ERR_IO NFS4ERR_MOVED NFS4ERR_NOFILEHANDLE NFS4ERR_NOTSUPP NFS4ERR_RESOURCE NFS4ERR_SAME NFS4ERR_SERVERFAULT NFS4ERR_STALE NFS4ERR_WRONGSEC14.2.16. Operation 18: OPEN - Open a Regular File
SYNOPSIS (cfh), claim, openhow, owner, seqid, access, deny -> (cfh), stateid, cinfo, rflags, open_confirm, delegation ARGUMENT struct OPEN4args { open_claim4 claim; openflag4 openhow; nfs_lockowner4 owner; seqid4 seqid; uint32_t share_access; uint32_t share_deny; }; 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 { pathname4 file;
stateid4 delegate_stateid; }; 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 */ pathname4 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 */ uint32_t 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 */ pathname4 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_MLOCK = 0x00000001; const OPEN4_RESULT_CONFIRM= 0x00000002; struct OPEN4resok { stateid4 stateid; /* Stateid for open */ change_info4 cinfo; /* Directory Change Info */ uint32_t rflags; /* Result flags */ verifier4 open_confirm; /* OPEN_CONFIRM verifier */ 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. 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 includes any writable attribute valid for regular files. When an UNCHECKED create encounters an existing file, the attributes specified by createattrs is not used, except that when an object_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. 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. 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 procedure provides for DOS SHARE capability with the use of the access and deny fields of the OPEN arguments. The client specifies at OPEN the required access and 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_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 reclaim 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 file handles; 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. 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_MLOCK indicates to the caller that mandatory locking is in effect for this file and the client should act appropriately with regard to data cached on the client. OPEN4_RESULT_CONFIRM indicates that the client MUST execute an OPEN_CONFIRM operation before using the open file. If the file is a zero length array, if any component does not obey the UTF-8 definition, or if any component in the path is of zero length, the error NFS4ERR_INVAL will be returned. 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 OPEN's were completed.
IMPLEMENTATION The OPEN procedure 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 file systems that do not provide a mechanism for the storage of arbitrary file attributes, the server may use one or more elements of the object 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 file system 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 procedure can fail with NFS4ERR_EXIST, even though the create was performed successfully. For SHARE reservations, the client must specify a value for access that is one of READ, WRITE, or BOTH. For 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. If the final component provided to OPEN is a symbolic link, the error NFS4ERR_SYMLINK will be returned to the client. If an intermediate component of the pathname provided to OPEN is a symbolic link, the error NFS4ERR_NOTDIR will be returned to the client. ERRORS NFS4ERR_ACCES NFS4ERR_BAD_SEQID NFS4ERR_DELAY NFS4ERR_DQUOT NFS4ERR_EXIST NFS4ERR_FHEXPIRED NFS4ERR_GRACE NFS4ERR_IO NFS4ERR_ISDIR NFS4ERR_LEASE_MOVED NFS4ERR_MOVED NFS4ERR_NAMETOOLONG NFS4ERR_NOFILEHANDLE NFS4ERR_NOSPC NFS4ERR_NOTDIR NFS4ERR_NOTSUPP NFS4ERR_RESOURCE NFS4ERR_ROFS NFS4ERR_SERVERFAULT NFS4ERR_SHARE_DENIED NFS4ERR_STALE_CLIENTID NFS4ERR_SYMLINK
14.2.17. Operation 19: OPENATTR - Open Named Attribute Directory
SYNOPSIS (cfh) -> (cfh) ARGUMENT /* CURRENT_FH: file or directory */ void; RESULT struct OPENATTR4res { /* CURRENT_FH: name 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 procedures can be used to obtain filehandles for the various named attributes associated with the original file system object. Filehandles returned within the named attribute directory will have a type of NF4NAMEDATTR. 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_ACCES NFS4ERR_BADHANDLE NFS4ERR_DELAY NFS4ERR_FHEXPIRED NFS4ERR_INVAL NFS4ERR_IO NFS4ERR_MOVED NFS4ERR_NOENT NFS4ERR_NOFILEHANDLE NFS4ERR_NOTSUPP NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT NFS4ERR_STALE NFS4ERR_WRONGSEC14.2.18. Operation 20: OPEN_CONFIRM - Confirm Open
SYNOPSIS (cfh), seqid, open_confirm-> stateid ARGUMENT struct OPEN_CONFIRM4args { /* CURRENT_FH: opened file */ seqid4 seqid; verifier4 open_confirm; /* OPEN_CONFIRM verifier */ }; RESULT struct OPEN_CONFIRM4resok { stateid4 stateid; }; union OPEN_CONFIRM4res switch (nfsstat4 status) { case NFS4_OK: OPEN_CONFIRM4resok resok4; default: void; }; DESCRIPTION This operation is used to confirm the sequence id usage for the first time that a nfs_lockowner is used by a client. The OPEN operation returns a opaque confirmation verifier that is then passed to this operation along with the next sequence id for the nfs_lockowner. The sequence id passed to the OPEN_CONFIRM must be 1 (one) greater than the seqid passed to the OPEN operation from which the open_confirm value was obtained. If the server receives an unexpected sequence id with respect to the original open, then the server assumes that the client will not confirm the original OPEN and all state associated with the original OPEN is released by the server. On success, the current filehandle retains its value.
IMPLEMENTATION A given client might generate many nfs_lockowner data structures for a given clientid. The client will periodically either dispose of its nfs_lockowners or stop using them for indefinite periods of time. The latter situation is why the NFS version 4 protocol does not have a an explicit operation to exit an nfs_lockowner: such an operation is of no use in that situation. Instead, to avoid unbounded memory use, the server needs to implement a strategy for disposing of nfs_lockowners that have no current lock, open, or delegation state for any files and have not been used recently. The time period used to determine when to dispose of nfs_lockowners is an implementation choice. The time period should certainly be no less than the lease time plus any grace period the server wishes to implement beyond a lease time. The OPEN_CONFIRM operation allows the server to safely dispose of unused nfs_lockowner data structures. In the case that a client issues an OPEN operation and the server no longer has a record of the nfs_lockowner, the server needs ensure that this is a new OPEN and not a replay or retransmission. A lazy server implementation might require confirmation for every nfs_lockowner for which it has no record. However, this is not necessary until the server records the fact that it has disposed of one nfs_lockowner for the given clientid. The server must hold unconfirmed OPEN state until one of three events occur. First, the client sends an OPEN_CONFIRM request with the appropriate sequence id and confirmation verifier within the lease period. In this case, the OPEN state on the server goes to confirmed, and the nfs_lockowner on the server is fully established. Second, the client sends another OPEN request with a sequence id that is incorrect for the nfs_lockowner (out of sequence). In this case, the server assumes the second OPEN request is valid and the first one is a replay. The server cancels the OPEN state of the first OPEN request, establishes an unconfirmed OPEN state for the second OPEN request, and responds to the second OPEN request with an indication that an OPEN_CONFIRM is needed. The process then repeats itself. While there is a potential for a denial of service attack on the client, it is mitigated if the client and server require the use of a security flavor based on Kerberos V5, LIPKEY, or some other flavor that uses cryptography.
What if the server is in the unconfirmed OPEN state for a given nfs_lockowner, and it receives an operation on the nfs_lockowner that has a stateid but the operation is not OPEN, or it is OPEN_CONFIRM but with the wrong confirmation verifier? Then, even if the seqid is correct, the server returns NFS4ERR_BAD_STATEID, because the server assumes the operation is a replay: if the server has no established OPEN state, then there is no way, for example, a LOCK operation could be valid. Third, neither of the two aforementioned events occur for the nfs_lockowner within the lease period. In this case, the OPEN state is cancelled and disposal of the nfs_lockowner can occur. ERRORS NFS4ERR_BADHANDLE NFS4ERR_BAD_SEQID NFS4ERR_EXPIRED NFS4ERR_FHEXPIRED NFS4ERR_GRACE NFS4ERR_INVAL NFS4ERR_MOVED NFS4ERR_NOENT NFS4ERR_NOFILEHANDLE NFS4ERR_NOTSUPP NFS4ERR_RESOURCE NFS4ERR_SERVERFAULT NFS4ERR_STALE NFS4ERR_WRONGSEC14.2.19. Operation 21: OPEN_DOWNGRADE - Reduce Open File Access
SYNOPSIS (cfh), stateid, seqid, access, deny -> stateid ARGUMENT struct OPEN_DOWNGRADE4args { /* CURRENT_FH: opened file */ stateid4 stateid; seqid4 seqid; uint32_t share_access; uint32_t share_deny; }; RESULT
struct OPEN_DOWNGRADE4resok { stateid4 stateid; }; union OPEN_DOWNGRADE4res switch(nfsstat4 status) { case NFS4_OK: OPEN_DOWNGRADE4resok resok4; default: void; }; This operation is used to adjust the access and deny bits for a given open. This is necessary when a given lockowner opens the same file multiple times with different access and deny flags. In this situation, a close of one of the open's may change the appropriate access and deny flags to remove bits associated with open's no longer in effect. The access and deny bits specified in this operation replace the current ones for the specified open file. If either the access or the deny mode specified includes bits not in effect for the open, the error NFS4ERR_INVAL should be returned. Since access and deny bits are subsets of those already granted, it is not possible for this request to be denied because of conflicting share reservations. On success, the current filehandle retains its value. ERRORS NFS4ERR_BADHANDLE NFS4ERR_BAD_SEQID NFS4ERR_BAD_STATEID NFS4ERR_EXPIRED NFS4ERR_FHEXPIRED NFS4ERR_INVAL NFS4ERR_MOVED NFS4ERR_NOFILEHANDLE NFS4ERR_OLD_STATEID NFS4ERR_RESOURCE NFS4ERR_SERVERFAULT NFS4ERR_STALE NFS4ERR_STALE_STATEID14.2.20. Operation 22: PUTFH - Set Current Filehandle
SYNOPSIS filehandle -> (cfh) ARGUMENT struct PUTFH4args { nfs4_fh object; }; RESULT struct PUTFH4res {
/* CURRENT_FH: */ nfsstat4 status; }; DESCRIPTION Replaces the current filehandle with the filehandle provided as an argument. IMPLEMENTATION Commonly used as the first operator in an NFS request to set the context for following operations. ERRORS NFS4ERR_BADHANDLE NFS4ERR_FHEXPIRED NFS4ERR_MOVED NFS4ERR_RESOURCE NFS4ERR_SERVERFAULT NFS4ERR_STALE NFS4ERR_WRONGSEC14.2.21. Operation 23: PUTPUBFH - Set Public Filehandle
SYNOPSIS - -> (cfh) ARGUMENT void; RESULT struct PUTPUBFH4res { /* CURRENT_FH: public fh */ nfsstat4 status; }; DESCRIPTION Replaces the current filehandle with the filehandle that represents the public filehandle of the server's name space. This filehandle may be different from the "root" filehandle which may be associated with some other directory on the server.
IMPLEMENTATION Used as the first operator in an NFS request to set the context for following operations. ERRORS NFS4ERR_RESOURCE NFS4ERR_SERVERFAULT NFS4ERR_WRONGSEC14.2.22. Operation 24: PUTROOTFH - Set Root Filehandle
SYNOPSIS - -> (cfh) ARGUMENT void; RESULT struct PUTROOTFH4res { /* CURRENT_FH: root fh */ nfsstat4 status; }; DESCRIPTION Replaces the current filehandle with the filehandle that represents the root of the server's name space. From this filehandle a LOOKUP operation can locate any other filehandle on the server. This filehandle may be different from the "public" filehandle which may be associated with some other directory on the server. IMPLEMENTATION Commonly used as the first operator in an NFS request to set the context for following operations. ERRORS NFS4ERR_RESOURCE NFS4ERR_SERVERFAULT NFS4ERR_WRONGSEC
14.2.23. Operation 25: READ - Read from File
SYNOPSIS (cfh), offset, count, stateid -> eof, data ARGUMENT struct READ4args { /* CURRENT_FH: file */ stateid4 stateid; offset4 offset; count4 count; }; RESULT struct READ4resok { bool eof; opaque data<>; }; union READ4res switch (nfsstat4 status) { case NFS4_OK: READ4resok resok4; default: void; }; DESCRIPTION The READ operation reads data from the regular file identified by the current filehandle. The client provides an offset of where the READ is to start and a count of how many bytes are to be read. An offset of 0 (zero) means to read data starting at the beginning of the file. If offset is greater than or equal to the size of the file, the status, NFS4_OK, is returned with a data length set to 0 (zero) and eof is set to TRUE. The READ is subject to access permissions checking. If the client specifies a count value of 0 (zero), the READ succeeds and returns 0 (zero) bytes of data again subject to access permissions checking. The server may choose to return fewer bytes than specified by the client. The client needs to check for this condition and handle the condition appropriately.
The stateid value for a READ request represents a value returned from a previous record lock or share reservation request. Used by the server to verify that the associated lock is still valid and to update lease timeouts for the client. If the read ended at the end-of-file (formally, in a correctly formed READ request, if offset + count is equal to the size of the file), or the read request extends beyond the size of the file (if offset + count is greater than the size of the file), eof is returned as TRUE; otherwise it is FALSE. A successful READ of an empty file will always return eof as TRUE. On success, the current filehandle retains its value. IMPLEMENTATION It is possible for the server to return fewer than count bytes of data. If the server returns less than the count requested and eof set to FALSE, the client should issue another READ to get the remaining data. A server may return less data than requested under several circumstances. The file may have been truncated by another client or perhaps on the server itself, changing the file size from what the requesting client believes to be the case. This would reduce the actual amount of data available to the client. It is possible that the server may back off the transfer size and reduce the read request return. Server resource exhaustion may also occur necessitating a smaller read return. If the file is locked the server will return an NFS4ERR_LOCKED error. Since the lock may be of short duration, the client may choose to retransmit the READ request (with exponential backoff) until the operation succeeds. ERRORS NFS4ERR_ACCES NFS4ERR_BADHANDLE NFS4ERR_BAD_STATEID NFS4ERR_DELAY NFS4ERR_DENIED NFS4ERR_EXPIRED NFS4ERR_FHEXPIRED NFS4ERR_GRACE NFS4ERR_INVAL NFS4ERR_IO NFS4ERR_LOCKED NFS4ERR_LEASE_MOVED NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE NFS4ERR_NXIO NFS4ERR_OLD_STATEID NFS4ERR_RESOURCE NFS4ERR_SERVERFAULT NFS4ERR_STALE NFS4ERR_STALE_STATEID NFS4ERR_WRONGSEC14.2.24. Operation 26: READDIR - Read Directory
SYNOPSIS (cfh), cookie, cookieverf, dircount, maxcount, attrbits -> cookieverf { cookie, filename, attrbits, attributes } ARGUMENT struct READDIR4args { /* CURRENT_FH: directory */ nfs_cookie4 cookie; verifier4 cookieverf; count4 dircount; count4 maxcount; bitmap4 attr_request; }; RESULT struct entry4 { nfs_cookie4 cookie; component4 name; fattr4 attrs; entry4 *nextentry; }; struct dirlist4 { entry4 *entries; bool eof; }; struct READDIR4resok { verifier4 cookieverf; dirlist4 reply; }; union READDIR4res switch (nfsstat4 status) {
case NFS4_OK: READDIR4resok resok4; default: void; }; DESCRIPTION The READDIR operation retrieves a variable number of entries from a file system directory and returns client requested attributes for each entry along with information to allow the client to request additional directory entries in a subsequent READDIR. The arguments contain a cookie value that represents where the READDIR should start within the directory. A value of 0 (zero) for the cookie is used to start reading at the beginning of the directory. For subsequent READDIR requests, the client specifies a cookie value that is provided by the server on a previous READDIR request. The cookieverf value should be set to 0 (zero) when the cookie value is 0 (zero) (first directory read). On subsequent requests, it should be a cookieverf as returned by the server. The cookieverf must match that returned by the READDIR in which the cookie was acquired. The dircount portion of the argument is a hint of the maximum number of bytes of directory information that should be returned. This value represents the length of the names of the directory entries and the cookie value for these entries. This length represents the XDR encoding of the data (names and cookies) and not the length in the native format of the server. The server may return less data. The maxcount value of the argument is the maximum number of bytes for the result. This maximum size represents all of the data being returned and includes the XDR overhead. The server may return less data. If the server is unable to return a single directory entry within the maxcount limit, the error NFS4ERR_READDIR_NOSPC will be returned to the client. Finally, attrbits represents the list of attributes to be returned for each directory entry supplied by the server. On successful return, the server's response will provide a list of directory entries. Each of these entries contains the name of the directory entry, a cookie value for that entry, and the associated attributes as requested.
The cookie value is only meaningful to the server and is used as a "bookmark" for the directory entry. As mentioned, this cookie is used by the client for subsequent READDIR operations so that it may continue reading a directory. The cookie is similar in concept to a READ offset but should not be interpreted as such by the client. Ideally, the cookie value should not change if the directory is modified since the client may be caching these values. In some cases, the server may encounter an error while obtaining the attributes for a directory entry. Instead of returning an error for the entire READDIR operation, the server can instead return the attribute 'fattr4_rdattr_error'. With this, the server is able to communicate the failure to the client and not fail the entire operation in the instance of what might be a transient failure. Obviously, the client must request the fattr4_rdattr_error attribute for this method to work properly. If the client does not request the attribute, the server has no choice but to return failure for the entire READDIR operation. For some file system environments, the directory entries "." and ".." have special meaning and in other environments, they may not. If the server supports these special entries within a directory, they should not be returned to the client as part of the READDIR response. To enable some client environments, the cookie values of 0, 1, and 2 are to be considered reserved. Note that the Unix client will use these values when combining the server's response and local representations to enable a fully formed Unix directory presentation to the application. For READDIR arguments, cookie values of 1 and 2 should not be used and for READDIR results cookie values of 0, 1, and 2 should not returned. On success, the current filehandle retains its value. IMPLEMENTATION The server's file system directory representations can differ greatly. A client's programming interfaces may also be bound to the local operating environment in a way that does not translate well into the NFS protocol. Therefore the use of the dircount and maxcount fields are provided to allow the client the ability to provide guidelines to the server. If the client is aggressive about attribute collection during a READDIR, the server has an idea of how to limit the encoded response. The dircount field provides a hint on the number of entries based solely on the names of the directory entries. Since it is a hint, it may be possible
that a dircount value is zero. In this case, the server is free to ignore the dircount value and return directory information based on the specified maxcount value. The cookieverf may be used by the server to help manage cookie values that may become stale. It should be a rare occurrence that a server is unable to continue properly reading a directory with the provided cookie/cookieverf pair. The server should make every effort to avoid this condition since the application at the client may not be able to properly handle this type of failure. The use of the cookieverf will also protect the client from using READDIR cookie values that may be stale. For example, if the file system has been migrated, the server may or may not be able to use the same cookie values to service READDIR as the previous server used. With the client providing the cookieverf, the server is able to provide the appropriate response to the client. This prevents the case where the server may accept a cookie value but the underlying directory has changed and the response is invalid from the client's context of its previous READDIR. Since some servers will not be returning "." and ".." entries as has been done with previous versions of the NFS protocol, the client that requires these entries be present in READDIR responses must fabricate them. ERRORS NFS4ERR_ACCES NFS4ERR_BADHANDLE NFS4ERR_BAD_COOKIE NFS4ERR_DELAY NFS4ERR_FHEXPIRED NFS4ERR_INVAL NFS4ERR_IO NFS4ERR_MOVED NFS4ERR_NOFILEHANDLE NFS4ERR_NOTDIR NFS4ERR_NOTSUPP NFS4ERR_READDIR_NOSPC NFS4ERR_RESOURCE NFS4ERR_SERVERFAULT NFS4ERR_STALE NFS4ERR_TOOSMALL NFS4ERR_WRONGSEC