The revalidation technique parallels that discussed in the case of
name caching. When the client is not changing the directory in
question, checking the change attribute of the directory with GETATTR
is adequate. The lifetime of the cache entry can be extended at
these checkpoints. When a client is modifying the directory, the
client needs to use the change_info4 data to determine whether there
are other clients modifying the directory. If it is determined that
no other client modifications are occurring, the client may update
its directory cache to reflect its own changes.
As demonstrated previously, directory caching requires that the
client revalidate directory cache data by inspecting the change
attribute of a directory at the point when the directory was cached.
This requires that the server update the change attribute for
directories when the contents of the corresponding directory is
modified. For a client to use the change_info4 information
appropriately and correctly, the server must report the pre and post
operation change attribute values atomically. When the server is
unable to report the before and after values atomically with respect
to the directory operation, the server must indicate that fact in the
change_info4 return value. When the information is not atomically
reported, the client should not assume that other clients have not
changed the directory.
10. Minor Versioning
To address the requirement of an NFS protocol that can evolve as the
need arises, the NFS version 4 protocol contains the rules and
framework to allow for future minor changes or versioning.
The base assumption with respect to minor versioning is that any
future accepted minor version must follow the IETF process and be
documented in a standards track RFC. Therefore, each minor version
number will correspond to an RFC. Minor version zero of the NFS
version 4 protocol is represented by this RFC. The COMPOUND
procedure will support the encoding of the minor version being
requested by the client.
The following items represent the basic rules for the development of
minor versions. Note that a future minor version may decide to
modify or add to the following rules as part of the minor version
definition.
1 Procedures are not added or deleted
To maintain the general RPC model, NFS version 4 minor versions
will not add or delete procedures from the NFS program.
2 Minor versions may add operations to the COMPOUND and
CB_COMPOUND procedures.
The addition of operations to the COMPOUND and CB_COMPOUND
procedures does not affect the RPC model.
2.1 Minor versions may append attributes to GETATTR4args, bitmap4,
and GETATTR4res.
This allows for the expansion of the attribute model to allow
for future growth or adaptation.
2.2 Minor version X must append any new attributes after the last
documented attribute.
Since attribute results are specified as an opaque array of
per-attribute XDR encoded results, the complexity of adding new
attributes in the midst of the current definitions will be too
burdensome.
3 Minor versions must not modify the structure of an existing
operation's arguments or results.
Again the complexity of handling multiple structure definitions
for a single operation is too burdensome. New operations should
be added instead of modifying existing structures for a minor
version.
This rule does not preclude the following adaptations in a minor
version.
o adding bits to flag fields such as new attributes to
GETATTR's bitmap4 data type
o adding bits to existing attributes like ACLs that have flag
words
o extending enumerated types (including NFS4ERR_*) with new
values
4 Minor versions may not modify the structure of existing
attributes.
5 Minor versions may not delete operations.
This prevents the potential reuse of a particular operation
"slot" in a future minor version.
6 Minor versions may not delete attributes.
7 Minor versions may not delete flag bits or enumeration values.
8 Minor versions may declare an operation as mandatory to NOT
implement.
Specifying an operation as "mandatory to not implement" is
equivalent to obsoleting an operation. For the client, it means
that the operation should not be sent to the server. For the
server, an NFS error can be returned as opposed to "dropping"
the request as an XDR decode error. This approach allows for
the obsolescence of an operation while maintaining its structure
so that a future minor version can reintroduce the operation.
8.1 Minor versions may declare attributes mandatory to NOT
implement.
8.2 Minor versions may declare flag bits or enumeration values as
mandatory to NOT implement.
9 Minor versions may downgrade features from mandatory to
recommended, or recommended to optional.
10 Minor versions may upgrade features from optional to recommended
or recommended to mandatory.
11 A client and server that support minor version X must support
minor versions 0 (zero) through X-1 as well.
12 No new features may be introduced as mandatory in a minor
version.
This rule allows for the introduction of new functionality and
forces the use of implementation experience before designating a
feature as mandatory.
13 A client MUST NOT attempt to use a stateid, file handle, or
similar returned object from the COMPOUND procedure with minor
version X for another COMPOUND procedure with minor version Y,
where X != Y.
11. Internationalization
The primary issue in which NFS needs to deal with
internationalization, or I18n, is with respect to file names and
other strings as used within the protocol. The choice of string
representation must allow reasonable name/string access to clients
which use various languages. The UTF-8 encoding of the UCS as
defined by [ISO10646] allows for this type of access and follows the
policy described in "IETF Policy on Character Sets and Languages",
[RFC2277]. This choice is explained further in the following.
11.1. Universal Versus Local Character Sets
[RFC1345] describes a table of 16 bit characters for many different
languages (the bit encodings match Unicode, though of course RFC1345
is somewhat out of date with respect to current Unicode assignments).
Each character from each language has a unique 16 bit value in the 16
bit character set. Thus this table can be thought of as a universal
character set. [RFC1345] then talks about groupings of subsets of
the entire 16 bit character set into "Charset Tables". For example
one might take all the Greek characters from the 16 bit table (which
are consecutively allocated), and normalize their offsets to a table
that fits in 7 bits. Thus it is determined that "lower case alpha"
is in the same position as "upper case a" in the US-ASCII table, and
"upper case alpha" is in the same position as "lower case a" in the
US-ASCII table.
These normalized subset character sets can be thought of as "local
character sets", suitable for an operating system locale.
Local character sets are not suitable for the NFS protocol. Consider
someone who creates a file with a name in a Swedish character set.
If someone else later goes to access the file with their locale set
to the Swedish language, then there are no problems. But if someone
in say the US-ASCII locale goes to access the file, the file name
will look very different, because the Swedish characters in the 7 bit
table will now be represented in US-ASCII characters on the display.
It would be preferable to give the US-ASCII user a way to display the
file name using Swedish glyphs. In order to do that, the NFS protocol
would have to include the locale with the file name on each operation
to create a file.
But then what of the situation when there is a path name on the
server like:
/component-1/component-2/component-3
Each component could have been created with a different locale. If
one issues CREATE with multi-component path name, and if some of the
leading components already exist, what is to be done with the
existing components? Is the current locale attribute replaced with
the user's current one? These types of situations quickly become too
complex when there is an alternate solution.
If the NFS version 4 protocol used a universal 16 bit or 32 bit
character set (or an encoding of a 16 bit or 32 bit character set
into octets), then the server and client need not care if the locale
of the user accessing the file is different than the locale of the
user who created the file. The unique 16 bit or 32 bit encoding of
the character allows for determination of what language the character
is from and also how to display that character on the client. The
server need not know what locales are used.
11.2. Overview of Universal Character Set Standards
The previous section makes a case for using a universal character
set. This section makes the case for using UTF-8 as the specific
universal character set for the NFS version 4 protocol.
[RFC2279] discusses UTF-* (UTF-8 and other UTF-XXX encodings),
Unicode, and UCS-*. There are two standards bodies managing
universal code sets:
o ISO/IEC which has the standard 10646-1
o Unicode which has the Unicode standard
Both standards bodies have pledged to track each other's assignments
of character codes.
The following is a brief analysis of the various standards.
UCS Universal Character Set. This is ISO/IEC 10646-1: "a
multi-octet character set called the Universal Character
Set (UCS), which encompasses most of the world's writing
systems."
UCS-2 a two octet per character encoding that addresses the first
2^16 characters of UCS. Currently there are no UCS
characters beyond that range.
UCS-4 a four octet per character encoding that permits the
encoding of up to 2^31 characters.
UTF UTF is an abbreviation of the term "UCS transformation
format" and is used in the naming of various standards for
encoding of UCS characters as described below.
UTF-1 Only historical interest; it has been removed from 10646-1
UTF-7 Encodes the entire "repertoire" of UCS "characters using
only octets with the higher order bit clear". [RFC2152]
describes UTF-7. UTF-7 accomplishes this by reserving one
of the 7bit US-ASCII characters as a "shift" character to
indicate non-US-ASCII characters.
UTF-8 Unlike UTF-7, uses all 8 bits of the octets. US-ASCII
characters are encoded as before unchanged. Any octet with
the high bit cleared can only mean a US-ASCII character.
The high bit set means that a UCS character is being
encoded.
UTF-16 Encodes UCS-4 characters into UCS-2 characters using a
reserved range in UCS-2.
Unicode Unicode and UCS-2 are the same; [RFC2279] states:
Up to the present time, changes in Unicode and amendments
to ISO/IEC 10646 have tracked each other, so that the
character repertoires and code point assignments have
remained in sync. The relevant standardization committees
have committed to maintain this very useful synchronism.
11.3. Difficulties with UCS-4, UCS-2, Unicode
Adapting existing applications, and file systems to multi-octet
schemes like UCS and Unicode can be difficult. A significant amount
of code has been written to process streams of bytes. Also there are
many existing stored objects described with 7 bit or 8 bit
characters. Doubling or quadrupling the bandwidth and storage
requirements seems like an expensive way to accomplish I18N.
UCS-2 and Unicode are "only" 16 bits long. That might seem to be
enough but, according to [Unicode1], 49,194 Unicode characters are
already assigned. According to [Unicode2] there are still more
languages that need to be added.
11.4. UTF-8 and its solutions
UTF-8 solves problems for NFS that exist with the use of UCS and
Unicode. UTF-8 will encode 16 bit and 32 bit characters in a way
that will be compact for most users. The encoding table from UCS-4 to
UTF-8, as copied from [RFC2279]:
UCS-4 range (hex.) UTF-8 octet sequence (binary)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0400 0000-7FFF FFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
10xxxxxx
See [RFC2279] for precise encoding and decoding rules. Note because
of UTF-16, the algorithm from Unicode/UCS-2 to UTF-8 needs to account
for the reserved range between D800 and DFFF.
Note that the 16 bit UCS or Unicode characters require no more than 3
octets to encode into UTF-8
Interestingly, UTF-8 has room to handle characters larger than 31
bits, because the leading octet of form:
1111111x
is not defined. If needed, ISO could either use that octet to
indicate a sequence of an encoded 8 octet character, or perhaps use
11111110 to permit the next octet to indicate an even more expandable
character set.
So using UTF-8 to represent character encodings means never having to
run out of room.
11.5. Normalization
The client and server operating environments may differ in their
policies and operational methods with respect to character
normalization (See [Unicode1] for a discussion of normalization
forms). This difference may also exist between applications on the
same client. This adds to the difficulty of providing a single
normalization policy for the protocol that allows for maximal
interoperability. This issue is similar to the character case issues
where the server may or may not support case insensitive file name
matching and may or may not preserve the character case when storing
file names. The protocol does not mandate a particular behavior but
allows for the various permutations.
The NFS version 4 protocol does not mandate the use of a particular
normalization form at this time. A later revision of this
specification may specify a particular normalization form.
Therefore, the server and client can expect that they may receive
unnormalized characters within protocol requests and responses. If
the operating environment requires normalization, then the
implementation must normalize the various UTF-8 encoded strings
within the protocol before presenting the information to an
application (at the client) or local file system (at the server).
12. Error Definitions
NFS error numbers are assigned to failed operations within a compound
request. A compound request contains a number of NFS operations that
have their results encoded in sequence in a compound reply. The
results of successful operations will consist of an NFS4_OK status
followed by the encoded results of the operation. If an NFS
operation fails, an error status will be entered in the reply and the
compound request will be terminated.
A description of each defined error follows:
NFS4_OK Indicates the operation completed successfully.
NFS4ERR_ACCES Permission denied. The caller does not have the
correct permission to perform the requested
operation. Contrast this with NFS4ERR_PERM,
which restricts itself to owner or privileged
user permission failures.
NFS4ERR_BADHANDLE Illegal NFS file handle. The file handle failed
internal consistency checks.
NFS4ERR_BADTYPE An attempt was made to create an object of a
type not supported by the server.
NFS4ERR_BAD_COOKIE READDIR cookie is stale.
NFS4ERR_BAD_SEQID The sequence number in a locking request is
neither the next expected number or the last
number processed.
NFS4ERR_BAD_STATEID A stateid generated by the current server
instance, but which does not designate any
locking state (either current or superseded)
for a current lockowner-file pair, was used.
NFS4ERR_CLID_INUSE The SETCLIENTID procedure has found that a
client id is already in use by another client.
NFS4ERR_DELAY The server initiated the request, but was not
able to complete it in a timely fashion. The
client should wait and then try the request
with a new RPC transaction ID. For example,
this error should be returned from a server
that supports hierarchical storage and receives
a request to process a file that has been
migrated. In this case, the server should start
the immigration process and respond to client
with this error. This error may also occur
when a necessary delegation recall makes
processing a request in a timely fashion
impossible.
NFS4ERR_DENIED An attempt to lock a file is denied. Since
this may be a temporary condition, the client
is encouraged to retry the lock request until
the lock is accepted.
NFS4ERR_DQUOT Resource (quota) hard limit exceeded. The
user's resource limit on the server has been
exceeded.
NFS4ERR_EXIST File exists. The file specified already exists.
NFS4ERR_EXPIRED A lease has expired that is being used in the
current procedure.
NFS4ERR_FBIG File too large. The operation would have caused
a file to grow beyond the server's limit.
NFS4ERR_FHEXPIRED The file handle provided is volatile and has
expired at the server.
NFS4ERR_GRACE The server is in its recovery or grace period
which should match the lease period of the
server.
NFS4ERR_INVAL Invalid argument or unsupported argument for an
operation. Two examples are attempting a
READLINK on an object other than a symbolic
link or attempting to SETATTR a time field on a
server that does not support this operation.
NFS4ERR_IO I/O error. A hard error (for example, a disk
error) occurred while processing the requested
operation.
NFS4ERR_ISDIR Is a directory. The caller specified a
directory in a non-directory operation.
NFS4ERR_LEASE_MOVED A lease being renewed is associated with a file
system that has been migrated to a new server.
NFS4ERR_LOCKED A read or write operation was attempted on a
locked file.
NFS4ERR_LOCK_RANGE A lock request is operating on a sub-range of a
current lock for the lock owner and the server
does not support this type of request.
NFS4ERR_MINOR_VERS_MISMATCH
The server has received a request that
specifies an unsupported minor version. The
server must return a COMPOUND4res with a zero
length operations result array.
NFS4ERR_MLINK Too many hard links.
NFS4ERR_MOVED The filesystem which contains the current
filehandle object has been relocated or
migrated to another server. The client may
obtain the new filesystem location by obtaining
the "fs_locations" attribute for the current
filehandle. For further discussion, refer to
the section "Filesystem Migration or
Relocation".
NFS4ERR_NAMETOOLONG The filename in an operation was too long.
NFS4ERR_NODEV No such device.
NFS4ERR_NOENT No such file or directory. The file or
directory name specified does not exist.
NFS4ERR_NOFILEHANDLE The logical current file handle value has not
been set properly. This may be a result of a
malformed COMPOUND operation (i.e. no PUTFH or
PUTROOTFH before an operation that requires the
current file handle be set).
NFS4ERR_NOSPC No space left on device. The operation would
have caused the server's file system to exceed
its limit.
NFS4ERR_NOTDIR Not a directory. The caller specified a non-
directory in a directory operation.
NFS4ERR_NOTEMPTY An attempt was made to remove a directory that
was not empty.
NFS4ERR_NOTSUPP Operation is not supported.
NFS4ERR_NOT_SAME This error is returned by the VERIFY operation
to signify that the attributes compared were
not the same as provided in the client's
request.
NFS4ERR_NXIO I/O error. No such device or address.
NFS4ERR_OLD_STATEID A stateid which designates the locking state
for a lockowner-file at an earlier time was
used.
NFS4ERR_PERM Not owner. The operation was not allowed
because the caller is either not a privileged
user (root) or not the owner of the target of
the operation.
NFS4ERR_READDIR_NOSPC The encoded response to a READDIR request
exceeds the size limit set by the initial
request.
NFS4ERR_RESOURCE For the processing of the COMPOUND procedure,
the server may exhaust available resources and
can not continue processing procedures within
the COMPOUND operation. This error will be
returned from the server in those instances of
resource exhaustion related to the processing
of the COMPOUND procedure.
NFS4ERR_ROFS Read-only file system. A modifying operation
was attempted on a read-only file system.
NFS4ERR_SAME This error is returned by the NVERIFY operation
to signify that the attributes compared were
the same as provided in the client's request.
NFS4ERR_SERVERFAULT An error occurred on the server which does not
map to any of the legal NFS version 4 protocol
error values. The client should translate this
into an appropriate error. UNIX clients may
choose to translate this to EIO.
NFS4ERR_SHARE_DENIED An attempt to OPEN a file with a share
reservation has failed because of a share
conflict.
NFS4ERR_STALE Invalid file handle. The file handle given in
the arguments was invalid. The file referred to
by that file handle no longer exists or access
to it has been revoked.
NFS4ERR_STALE_CLIENTID A clientid not recognized by the server was
used in a locking or SETCLIENTID_CONFIRM
request.
NFS4ERR_STALE_STATEID A stateid generated by an earlier server
instance was used.
NFS4ERR_SYMLINK The current file handle provided for a LOOKUP
is not a directory but a symbolic link. Also
used if the final component of the OPEN path is
a symbolic link.
NFS4ERR_TOOSMALL Buffer or request is too
small.
NFS4ERR_WRONGSEC The security mechanism being used by the client
for the procedure does not match the server's
security policy. The client should change the
security mechanism being used and retry the
operation.
NFS4ERR_XDEV Attempt to do a cross-device hard link.
13. NFS Version 4 Requests
For the NFS version 4 RPC program, there are two traditional RPC
procedures: NULL and COMPOUND. All other functionality is defined as
a set of operations and these operations are defined in normal
XDR/RPC syntax and semantics. However, these operations are
encapsulated within the COMPOUND procedure. This requires that the
client combine one or more of the NFS version 4 operations into a
single request.
The NFS4_CALLBACK program is used to provide server to client
signaling and is constructed in a similar fashion as the NFS version
4 program. The procedures CB_NULL and CB_COMPOUND are defined in the
same way as NULL and COMPOUND are within the NFS program. The
CB_COMPOUND request also encapsulates the remaining operations of the
NFS4_CALLBACK program. There is no predefined RPC program number for
the NFS4_CALLBACK program. It is up to the client to specify a
program number in the "transient" program range. The program and
port number of the NFS4_CALLBACK program are provided by the client
as part of the SETCLIENTID operation and therefore is fixed for the
life of the client instantiation.
13.1. Compound Procedure
The COMPOUND procedure provides the opportunity for better
performance within high latency networks. The client can avoid
cumulative latency of multiple RPCs by combining multiple dependent
operations into a single COMPOUND procedure. A compound operation
may provide for protocol simplification by allowing the client to
combine basic procedures into a single request that is customized for
the client's environment.
The CB_COMPOUND procedure precisely parallels the features of
COMPOUND as described above.
The basics of the COMPOUND procedures construction is:
+-----------+-----------+-----------+--
| op + args | op + args | op + args |
+-----------+-----------+-----------+--
and the reply looks like this:
+------------+-----------------------+-----------------------+--
|last status | status + op + results | status + op + results |
+------------+-----------------------+-----------------------+--
13.2. Evaluation of a Compound Request
The server will process the COMPOUND procedure by evaluating each of
the operations within the COMPOUND procedure in order. Each
component operation consists of a 32 bit operation code, followed by
the argument of length determined by the type of operation. The
results of each operation are encoded in sequence into a reply
buffer. The results of each operation are preceded by the opcode and
a status code (normally zero). If an operation results in a non-zero
status code, the status will be encoded and evaluation of the
compound sequence will halt and the reply will be returned. Note
that evaluation stops even in the event of "non error" conditions
such as NFS4ERR_SAME.
There are no atomicity requirements for the operations contained
within the COMPOUND procedure. The operations being evaluated as
part of a COMPOUND request may be evaluated simultaneously with other
COMPOUND requests that the server receives.
It is the client's responsibility for recovering from any partially
completed COMPOUND procedure. Partially completed COMPOUND
procedures may occur at any point due to errors such as
NFS4ERR_RESOURCE and NFS4ERR_LONG_DELAY. This may occur even given
an otherwise valid operation string. Further, a server reboot which
occurs in the middle of processing a COMPOUND procedure may leave the
client with the difficult task of determining how far COMPOUND
processing has proceeded. Therefore, the client should avoid overly
complex COMPOUND procedures in the event of the failure of an
operation within the procedure.
Each operation assumes a "current" and "saved" filehandle that is
available as part of the execution context of the compound request.
Operations may set, change, or return the current filehandle. The
"saved" filehandle is used for temporary storage of a filehandle
value and as operands for the RENAME and LINK operations.
13.3. Synchronous Modifying Operations
NFS version 4 operations that modify the file system are synchronous.
When an operation is successfully completed at the server, the client
can depend that any data associated with the request is now on stable
storage (the one exception is in the case of the file data in a WRITE
operation with the UNSTABLE option specified).
This implies that any previous operations within the same compound
request are also reflected in stable storage. This behavior enables
the client's ability to recover from a partially executed compound
request which may resulted from the failure of the server. For
example, if a compound request contains operations A and B and the
server is unable to send a response to the client, depending on the
progress the server made in servicing the request the result of both
operations may be reflected in stable storage or just operation A may
be reflected. The server must not have just the results of operation
B in stable storage.
13.4. Operation Values
The operations encoded in the COMPOUND procedure are identified by
operation values. To avoid overlap with the RPC procedure numbers,
operations 0 (zero) and 1 are not defined. Operation 2 is not
defined but reserved for future use with minor versioning.
14. NFS Version 4 Procedures
14.1. Procedure 0: NULL - No Operation
SYNOPSIS
<null>
ARGUMENT
void;
RESULT
void;
DESCRIPTION
Standard NULL procedure. Void argument, void response. This
procedure has no functionality associated with it. Because of
this it is sometimes used to measure the overhead of processing a
service request. Therefore, the server should ensure that no
unnecessary work is done in servicing this procedure.
ERRORS
None.
14.2. Procedure 1: COMPOUND - Compound Operations
SYNOPSIS
compoundargs -> compoundres
ARGUMENT
union nfs_argop4 switch (nfs_opnum4 argop) {
case <OPCODE>: <argument>;
...
};
struct COMPOUND4args {
utf8string tag;
uint32_t minorversion;
nfs_argop4 argarray<>;
};
RESULT
union nfs_resop4 switch (nfs_opnum4 resop){
case <OPCODE>: <result>;
...
};
struct COMPOUND4res {
nfsstat4 status;
utf8string tag;
nfs_resop4 resarray<>;
};
DESCRIPTION
The COMPOUND procedure is used to combine one or more of the NFS
operations into a single RPC request. The main NFS RPC program
has two main procedures: NULL and COMPOUND. All other operations
use the COMPOUND procedure as a wrapper.
The COMPOUND procedure is used to combine individual operations
into a single RPC request. The server interprets each of the
operations in turn. If an operation is executed by the server and
the status of that operation is NFS4_OK, then the next operation
in the COMPOUND procedure is executed. The server continues this
process until there are no more operations to be executed or one
of the operations has a status value other than NFS4_OK.
In the processing of the COMPOUND procedure, the server may find
that it does not have the available resources to execute any or
all of the operations within the COMPOUND sequence. In this case,
the error NFS4ERR_RESOURCE will be returned for the particular
operation within the COMPOUND procedure where the resource
exhaustion occurred. This assumes that all previous operations
within the COMPOUND sequence have been evaluated successfully.
The results for all of the evaluated operations must be returned
to the client.
The COMPOUND arguments contain a "minorversion" field. The
initial and default value for this field is 0 (zero). This field
will be used by future minor versions such that the client can
communicate to the server what minor version is being requested.
If the server receives a COMPOUND procedure with a minorversion
field value that it does not support, the server MUST return an
error of NFS4ERR_MINOR_VERS_MISMATCH and a zero length resultdata
array.
Contained within the COMPOUND results is a "status" field. If the
results array length is non-zero, this status must be equivalent
to the status of the last operation that was executed within the
COMPOUND procedure. Therefore, if an operation incurred an error
then the "status" value will be the same error value as is being
returned for the operation that failed.
Note that operations, 0 (zero) and 1 (one) are not defined for the
COMPOUND procedure. If the server receives an operation array
with either of these included, an error of NFS4ERR_NOTSUPP must be
returned. Operation 2 is not defined but reserved for future
definition and use with minor versioning. If the server receives
a operation array that contains operation 2 and the minorversion
field has a value of 0 (zero), an error of NFS4ERR_NOTSUPP is
returned. 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.
IMPLEMENTATION
Note that the definition of the "tag" in both the request and
response are 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.
Since an error of any type may occur after only a portion of the
operations have been evaluated, the client must be prepared to
recover from any failure. If the source of an NFS4ERR_RESOURCE
error was a complex or lengthy set of operations, it is likely
that if the number of operations were reduced the server would be
able to evaluate them successfully. Therefore, the client is
responsible for dealing with this type of complexity in recovery.
ERRORS
All errors defined in the protocol
14.2.1. Operation 3: ACCESS - Check Access Rights
SYNOPSIS
(cfh), accessreq -> supported, accessrights
ARGUMENT
const ACCESS4_READ = 0x00000001;
const ACCESS4_LOOKUP = 0x00000002;
const ACCESS4_MODIFY = 0x00000004;
const ACCESS4_EXTEND = 0x00000008;
const ACCESS4_DELETE = 0x00000010;
const ACCESS4_EXECUTE = 0x00000020;
struct ACCESS4args {
/* CURRENT_FH: object */
uint32_t access;
};
RESULT
struct ACCESS4resok {
uint32_t supported;
uint32_t access;
};
union ACCESS4res switch (nfsstat4 status) {
case NFS4_OK:
ACCESS4resok resok4;
default:
void;
};
DESCRIPTION
ACCESS determines the access rights that a user, as identified by
the credentials in the RPC request, has with respect to the file
system object specified by the current filehandle. The client
encodes the set of access rights that are to be checked in the bit
mask "access". The server checks the permissions encoded in the
bit mask. If a status of NFS4_OK is returned, two bit masks are
included in the response. The first, "supported", represents the
access rights for which the server can verify reliably. The
second, "access", represents the access rights available to the
user for the filehandle provided. On success, the current
filehandle retains its value.
Note that the supported field will contain only as many values as
was originally sent in the arguments. For example, if the client
sends an ACCESS operation with only the ACCESS4_READ value set and
the server supports this value, the server will return only
ACCESS4_READ even if it could have reliably checked other values.
The results of this operation are necessarily advisory in nature.
A return status of NFS4_OK and the appropriate bit set in the bit
mask does not imply that such access will be allowed to the file
system object in the future. This is because access rights can be
revoked by the server at any time.
The following access permissions may be requested:
ACCESS4_READ Read data from file or read a directory.
ACCESS4_LOOKUP Look up a name in a directory (no meaning for non-
directory objects).
ACCESS4_MODIFY Rewrite existing file data or modify existing
directory entries.
ACCESS4_EXTEND Write new data or add directory entries.
ACCESS4_DELETE Delete an existing directory entry (no meaning for
non-directory objects).
ACCESS4_EXECUTE Execute file (no meaning for a directory).
On success, the current filehandle retains its value.
IMPLEMENTATION
For the NFS version 4 protocol, the use of the ACCESS procedure
when opening a regular file is deprecated in favor of using OPEN.
In general, it is not sufficient for the client to attempt to
deduce access permissions by inspecting the uid, gid, and mode
fields in the file attributes or by attempting to interpret the
contents of the ACL attribute. This is because the server may
perform uid or gid mapping or enforce additional access control
restrictions. It is also possible that the server may not be in
the same ID space as the client. In these cases (and perhaps
others), the client can not reliably perform an access check with
only current file attributes.
In the NFS version 2 protocol, the only reliable way to determine
whether an operation was allowed was to try it and see if it
succeeded or failed. Using the ACCESS procedure in the NFS
version 4 protocol, the client can ask the server to indicate
whether or not one or more classes of operations are permitted.
The ACCESS operation is provided to allow clients to check before
doing a series of operations which will result in an access
failure. The OPEN operation provides a point where the server can
verify access to the file object and method to return that
information to the client. The ACCESS operation is still useful
for directory operations or for use in the case the UNIX API
"access" is used on the client.
The information returned by the server in response to an ACCESS
call is not permanent. It was correct at the exact time that the
server performed the checks, but not necessarily afterwards. The
server can revoke access permission at any time.
The client should use the effective credentials of the user to
build the authentication information in the ACCESS request used to
determine access rights. It is the effective user and group
credentials that are used in subsequent read and write operations.
Many implementations do not directly support the ACCESS4_DELETE
permission. Operating systems like UNIX will ignore the
ACCESS4_DELETE bit if set on an access request on a non-directory
object. In these systems, delete permission on a file is
determined by the access permissions on the directory in which the
file resides, instead of being determined by the permissions of
the file itself. Therefore, the mask returned enumerating which
access rights can be determined will have the ACCESS4_DELETE value
set to 0. This indicates to the client that the server was unable
to check that particular access right. The ACCESS4_DELETE bit in
the access mask returned will then be ignored by the client.
ERRORS
NFS4ERR_ACCES
NFS4ERR_BADHANDLE
NFS4ERR_DELAY
NFS4ERR_FHEXPIRED
NFS4ERR_IO
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
NFS4ERR_WRONGSEC
14.2.2. Operation 4: CLOSE - Close File
SYNOPSIS
(cfh), seqid, stateid -> stateid
ARGUMENT
struct CLOSE4args {
/* CURRENT_FH: object */
seqid4 seqid
stateid4 stateid;
};
RESULT
union CLOSE4res switch (nfsstat4 status) {
case NFS4_OK:
stateid4 stateid;
default:
void;
};
DESCRIPTION
The CLOSE operation releases share reservations for the file as
specified by the current filehandle. The share reservations and
other state information released at the server as a result of this
CLOSE is only associated with the supplied stateid. The sequence
id provides for the correct ordering. State associated with other
OPENs is not affected.
If record locks are held, the client SHOULD release all locks
before issuing a CLOSE. The server MAY free all outstanding locks
on CLOSE but some servers may not support the CLOSE of a file that
still has record locks held. The server MUST return failure if
any locks would exist after the CLOSE.
On success, the current filehandle retains its value.
IMPLEMENTATION
ERRORS
NFS4ERR_BADHANDLE
NFS4ERR_BAD_SEQID
NFS4ERR_BAD_STATEID
NFS4ERR_DELAY
NFS4ERR_EXPIRED
NFS4ERR_FHEXPIRED
NFS4ERR_GRACE
NFS4ERR_INVAL
NFS4ERR_ISDIR
NFS4ERR_LEASE_MOVED
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_OLD_STATEID
NFS4ERR_RESOURCE
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
NFS4ERR_STALE_STATEID
14.2.3. Operation 5: COMMIT - Commit Cached Data
SYNOPSIS
(cfh), offset, count -> verifier
ARGUMENT
struct COMMIT4args {
/* CURRENT_FH: file */
offset4 offset;
count4 count;
};
RESULT
struct COMMIT4resok {
verifier4 writeverf;
};
union COMMIT4res switch (nfsstat4 status) {
case NFS4_OK:
COMMIT4resok resok4;
default:
void;
};
DESCRIPTION
The COMMIT operation forces or flushes data to stable storage for
the file specified by the current file handle. The flushed data
is that which was previously written with a WRITE operation which
had the stable field set to UNSTABLE4.
The offset specifies the position within the file where the flush
is to begin. An offset value of 0 (zero) means to flush data
starting at the beginning of the file. The count specifies the
number of bytes of data to flush. If count is 0 (zero), a flush
from offset to the end of the file is done.
The server returns a write verifier upon successful completion of
the COMMIT. The write verifier is used by the client to determine
if the server has restarted or rebooted between the initial
WRITE(s) and the COMMIT. The client does this by comparing the
write verifier returned from the initial writes and the verifier
returned by the COMMIT procedure. The server must vary the value
of the write verifier at each server event or instantiation that
may lead to a loss of uncommitted data. Most commonly this occurs
when the server is rebooted; however, other events at the server
may result in uncommitted data loss as well.
On success, the current filehandle retains its value.
IMPLEMENTATION
The COMMIT procedure is similar in operation and semantics to the
POSIX fsync(2) system call that synchronizes a file's state with
the disk (file data and metadata is flushed to disk or stable
storage). COMMIT performs the same operation for a client,
flushing any unsynchronized data and metadata on the server to the
server's disk or stable storage for the specified file. Like
fsync(2), it may be that there is some modified data or no
modified data to synchronize. The data may have been synchronized
by the server's normal periodic buffer synchronization activity.
COMMIT should return NFS4_OK, unless there has been an unexpected
error.
COMMIT differs from fsync(2) in that it is possible for the client
to flush a range of the file (most likely triggered by a buffer-
reclamation scheme on the client before file has been completely
written).
The server implementation of COMMIT is reasonably simple. If the
server receives a full file COMMIT request, that is starting at
offset 0 and count 0, it should do the equivalent of fsync()'ing
the file. Otherwise, it should arrange to have the cached data in
the range specified by offset and count to be flushed to stable
storage. In both cases, any metadata associated with the file
must be flushed to stable storage before returning. It is not an
error for there to be nothing to flush on the server. This means
that the data and metadata that needed to be flushed have already
been flushed or lost during the last server failure.
The client implementation of COMMIT is a little more complex.
There are two reasons for wanting to commit a client buffer to
stable storage. The first is that the client wants to reuse a
buffer. In this case, the offset and count of the buffer are sent
to the server in the COMMIT request. The server then flushes any
cached data based on the offset and count, and flushes any
metadata associated with the file. It then returns the status of
the flush and the write verifier. The other reason for the client
to generate a COMMIT is for a full file flush, such as may be done
at close. In this case, the client would gather all of the
buffers for this file that contain uncommitted data, do the COMMIT
operation with an offset of 0 and count of 0, and then free all of
those buffers. Any other dirty buffers would be sent to the
server in the normal fashion.
After a buffer is written by the client with the stable parameter
set to UNSTABLE4, the buffer must be considered as modified by the
client until the buffer has either been flushed via a COMMIT
operation or written via a WRITE operation with stable parameter
set to FILE_SYNC4 or DATA_SYNC4. This is done to prevent the
buffer from being freed and reused before the data can be flushed
to stable storage on the server.
When a response is returned from either a WRITE or a COMMIT
operation and it contains a write verifier that is different than
previously returned by the server, the client will need to
retransmit all of the buffers containing uncommitted cached data
to the server. How this is to be done is up to the implementor.
If there is only one buffer of interest, then it should probably
be sent back over in a WRITE request with the appropriate stable
parameter. If there is more than one buffer, it might be
worthwhile retransmitting all of the buffers in WRITE requests
with the stable parameter set to UNSTABLE4 and then retransmitting
the COMMIT operation to flush all of the data on the server to
stable storage. The timing of these retransmissions is left to
the implementor.
The above description applies to page-cache-based systems as well
as buffer-cache-based systems. In those systems, the virtual
memory system will need to be modified instead of the buffer
cache.
ERRORS
NFS4ERR_ACCES
NFS4ERR_BADHANDLE
NFS4ERR_FHEXPIRED
NFS4ERR_IO
NFS4ERR_ISDIR
NFS4ERR_LOCKED
NFS4ERR_MOVED
NFS4ERR_NOFILEHANDLE
NFS4ERR_RESOURCE
NFS4ERR_ROFS
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
NFS4ERR_WRONGSEC
14.2.4. Operation 6: CREATE - Create a Non-Regular File Object
SYNOPSIS
(cfh), name, type -> (cfh), change_info
ARGUMENT
union createtype4 switch (nfs_ftype4 type) {
case NF4LNK:
linktext4 linkdata;
case NF4BLK:
case NF4CHR:
specdata4 devdata;
case NF4SOCK:
case NF4FIFO:
case NF4DIR:
void;
};
struct CREATE4args {
/* CURRENT_FH: directory for creation */
component4 objname;
createtype4 objtype;
};
RESULT
struct CREATE4resok {
change_info4 cinfo;
};
union CREATE4res switch (nfsstat4 status) {
case NFS4_OK:
CREATE4resok resok4;
default:
void;
};
DESCRIPTION
The CREATE operation creates a non-regular file object in a
directory with a given name. The OPEN procedure MUST be used to
create a regular file.
The objname specifies the name for the new object. If the objname
has a length of 0 (zero), the error NFS4ERR_INVAL will be
returned. The objtype determines the type of object to be
created: directory, symlink, etc.
If an object of the same name already exists in the directory, the
server will return the error NFS4ERR_EXIST.
For the directory where the new file object was created, the
server returns change_info4 information in cinfo. With the atomic
field of the change_info4 struct, the server will indicate if the
before and after change attributes were obtained atomically with
respect to the file object creation.
If the objname has a length of 0 (zero), or if objname does not
obey the UTF-8 definition, the error NFS4ERR_INVAL will be
returned.
The current filehandle is replaced by that of the new object.
IMPLEMENTATION
If the client desires to set attribute values after the create, a
SETATTR operation can be added to the COMPOUND request so that the
appropriate attributes will be set.
ERRORS
NFS4ERR_ACCES
NFS4ERR_BADHANDLE
NFS4ERR_BADTYPE
NFS4ERR_DQUOT
NFS4ERR_EXIST
NFS4ERR_FHEXPIRED
NFS4ERR_INVAL
NFS4ERR_IO
NFS4ERR_MOVED
NFS4ERR_NAMETOOLONG
NFS4ERR_NOFILEHANDLE
NFS4ERR_NOSPC
NFS4ERR_NOTDIR
NFS4ERR_NOTSUPP
NFS4ERR_RESOURCE
NFS4ERR_ROFS
NFS4ERR_SERVERFAULT
NFS4ERR_STALE
NFS4ERR_WRONGSEC
14.2.5. Operation 7: DELEGPURGE - Purge Delegations Awaiting Recovery
SYNOPSIS
clientid ->
ARGUMENT
struct DELEGPURGE4args {
clientid4 clientid;
};
RESULT
struct DELEGPURGE4res {
nfsstat4 status;
};
DESCRIPTION
Purges all of the delegations awaiting recovery for a given
client. This is useful for clients which do not commit delegation
information to stable storage to indicate that conflicting
requests need not be delayed by the server awaiting recovery of
delegation information.
This operation should be used by clients that record delegation