information on stable storage on the client. In this case,
DELEGPURGE should be issued immediately after doing delegation
recovery on all delegations know 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.
ERRORS
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE_CLIENTID
14.2.6. Operation 8: DELEGRETURN - Return Delegation
SYNOPSIS
stateid ->
ARGUMENT
struct DELEGRETURN4args {
stateid4 stateid;
};
RESULT
struct DELEGRETURN4res {
nfsstat4 status;
};
DESCRIPTION
Returns the delegation represented by the given stateid.
ERRORS
NFS4ERR_BAD_STATEID
NFS4ERR_OLD_STATEID
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
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 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 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_ACCES
NFS4ERR_BADHANDLE
NFS4ERR_DELAY
NFS4ERR_FHEXPIRED
NFS4ERR_INVAL
NFS4ERR_IO
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
NFS4ERR_WRONGSEC
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
NFS4ERR_WRONGSEC
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 file system on the server. On success, the current
filehandle will continue to be the target directory.
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 comments under RENAME regarding object and target residing on
the same file system apply here as well. The comments regarding
the target name applies as well.
Note that symbolic links are created with the CREATE operation.
ERRORS
NFS4ERR_ACCES NFS4ERR_BADHANDLE NFS4ERR_DELAY NFS4ERR_DQUOT
NFS4ERR_EXIST NFS4ERR_FHEXPIRED NFS4ERR_INVAL NFS4ERR_IO
NFS4ERR_ISDIR NFS4ERR_MLINK NFS4ERR_MOVED NFS4ERR_NAMETOOLONG
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) type, seqid, reclaim, stateid, offset, length -> stateid,
access
ARGUMENT
enum nfs4_lock_type {
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;
seqid4 seqid;
bool reclaim;
stateid4 stateid;
offset4 offset;
length4 length; };
RESULT
struct LOCK4denied {
nfs_lockowner4 owner;
offset4 offset;
length4 length; };
union LOCK4res switch (nfsstat4 status) {
case NFS4_OK:
stateid4 stateid;
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 nfs4_lock_types. 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). To
lock the entire file, use an offset of 0 (zero) and a length with
all bits set to 1. A length of 0 is reserved and should not be
used.
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.
ERRORS
NFS4ERR_ACCES NFS4ERR_BADHANDLE NFS4ERR_BAD_SEQID
NFS4ERR_BAD_STATEID NFS4ERR_DELAY NFS4ERR_DENIED 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_CLIENTID
NFS4ERR_STALE_STATEID NFS4ERR_WRONGSEC
14.2.11. Operation 13: LOCKT - Test For Lock
SYNOPSIS
(cfh) type, owner, offset, length -> {void, NFS4ERR_DENIED ->
owner}
ARGUMENT
struct LOCKT4args {
/* CURRENT_FH: file */
nfs_lock_type4 locktype;
nfs_lockowner4 owner;
offset4 offset;
length4 length; };
RESULT
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, and length of the
conflicting lock are returned; if no lock is held, nothing other
than NFS4_OK is 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 further discussion of
the file locking mechanisms.
LOCKT uses nfs_lockowner4 instead of a stateid4, as LOCK does, to
identify the owner so that the client does not have to open the
file to test for the existence of a lock.
ERRORS
NFS4ERR_ACCES
NFS4ERR_BADHANDLE
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
NFS4ERR_WRONGSEC
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.
On success, the current filehandle retains its value.
IMPLEMENTATION
The File Locking section contains a full description of this and
the other file locking procedures.
ERRORS
NFS4ERR_ACCES
NFS4ERR_BADHANDLE
NFS4ERR_BAD_SEQID
NFS4ERR_BAD_STATEID
NFS4ERR_EXPIRED
NFS4ERR_FHEXPIRED
NFS4ERR_GRACE
NFS4ERR_INVAL
NFS4ERR_LOCK_RANGE
NFS4ERR_LEASE_MOVED
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_OLD_STATEID
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
NFS4ERR_STALE_CLIENTID
NFS4ERR_STALE_STATEID
14.2.13. Operation 15: LOOKUP - Lookup Filename
SYNOPSIS
(cfh), filenames -> (cfh)
ARGUMENT
struct LOOKUP4args {
/* CURRENT_FH: directory */
pathname4 path;
};
RESULT
struct LOOKUP4res {
/* CURRENT_FH: object */
nfsstat4 status;
};
DESCRIPTION
This operation LOOKUPs or finds a file system object starting from
the directory specified by the current filehandle. LOOKUP
evaluates the pathname contained in the array of names and obtains
a new current filehandle from the final name. All but the final
name in the list must be the names of directories.
If the pathname cannot be evaluated either because a component
does not exist or because the client does not have permission to
evaluate a component of the path, then an error will be returned
and the current filehandle will be unchanged.
If the path 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.
IMPLEMENTATION
If the client prefers a partial evaluation of the path then a
sequence of LOOKUP operations can be substituted e.g.
PUTFH (directory filehandle)
LOOKUP "pub" "foo" "bar"
GETFH
or, if the client wishes to obtain the intermediate filehandles
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 procedure 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 file handle 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_ACCES
NFS4ERR_BADHANDLE
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_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_WRONGSEC
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 "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_WRONGSEC
14.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_WRONGSEC
14.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_WRONGSEC
14.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_STATEID
14.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_WRONGSEC
14.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_WRONGSEC
14.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_WRONGSEC
14.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.