1.6 Philosophy

1.6 Philosophy

This specification defines the NFS version 3 protocol, that is
the over-the-wire protocol by which a client accesses a server.
The protocol provides a well-defined interface to a server's
file resources. A client or server implements the protocol and
provides a mapping of the local file system semantics and
actions into those defined in the NFS version 3 protocol.
Implementations may differ to varying degrees, depending on the
extent to which a given environment can support all the
operations and semantics defined in the NFS version 3 protocol.
Although implementations exist and are used to illustrate
various aspects of the NFS version 3 protocol, the protocol
specification itself is the final description of how clients
access server resources.

Because the NFS version 3 protocol is designed to be
operating-system independent, it does not necessarily match the
semantics of any existing system. Server implementations are
expected to make a best effort at supporting the protocol. If a
server cannot support a particular protocol procedure, it may
return the error, NFS3ERR_NOTSUP, that indicates that the
operation is not supported. For example, many operating systems
do not support the notion of a hard link. A server that cannot
support hard links should return NFS3ERR_NOTSUP in response to a
LINK request. FSINFO describes the most commonly unsupported
procedures in the properties bit map. Alternatively, a server
may not natively support a given operation, but can emulate it
in the NFS version 3 protocol implementation to provide greater
functionality.

In some cases, a server can support most of the semantics
described by the protocol but not all. For example, the ctime
field in the fattr structure gives the time that a file's
attributes were last modified. Many systems do not keep this
information. In this case, rather than not support the GETATTR
operation, a server could simulate it by returning the last
modified time in place of ctime. Servers must be careful when
simulating attribute information because of possible side
effects on clients. For example, many clients use file
modification times as a basis for their cache consistency
scheme.

NFS servers are dumb and NFS clients are smart. It is the
clients that do the work required to convert the generalized
file access that servers provide into a file access method that
is useful to applications and users. In the LINK example given
above, a UNIX client that received an NFS3ERR_NOTSUP error from
a server would do the recovery necessary to either make it look
to the application like the link request had succeeded or return
a reasonable error. In general, it is the burden of the client
to recover.

The NFS version 3 protocol assumes a stateless server
implementation. Statelessness means that the server does not
need to maintain state about any of its clients in order to
function correctly. Stateless servers have a distinct advantage
over stateful servers in the event of a crash. With stateless
servers, a client need only retry a request until the server
responds; the client does not even need to know that the server
has crashed. See additional comments in Duplicate request cache
on page 99.

For a server to be useful, it holds nonvolatile state: data
stored in the file system. Design assumptions in the NFS version
3 protocol regarding flushing of modified data to stable storage
reduce the number of failure modes in which data loss can occur.
In this way, NFS version 3 protocol implementations can tolerate
transient failures, including transient failures of the network.
In general, server implementations of the NFS version 3 protocol
cannot tolerate a non-transient failure of the stable storage
itself. However, there exist fault tolerant implementations
which attempt to address such problems.

That is not to say that an NFS version 3 protocol server can't
maintain noncritical state. In many cases, servers will maintain
state (cache) about previous operations to increase performance.
For example, a client READ request might trigger a read-ahead of
the next block of the file into the server's data cache in the
anticipation that the client is doing a sequential read and the
next client READ request will be satisfied from the server's
data cache instead of from the disk. Read-ahead on the server
increases performance by overlapping server disk I/O with client
requests. The important point here is that the read-ahead block
is not necessary for correct server behavior. If the server
crashes and loses its memory cache of read buffers, recovery is
simple on reboot - clients will continue read operations
retrieving data from the server disk.

Most data-modifying operations in the NFS protocol are
synchronous. That is, when a data modifying procedure returns
to the client, the client can assume that the operation has
completed and any modified data associated with the request is
now on stable storage. For example, a synchronous client WRITE
request may cause the server to update data blocks, file system
information blocks, and file attribute information - the latter
information is usually referred to as metadata. When the WRITE
operation completes, the client can assume that the write data
is safe and discard it. This is a very important part of the
stateless nature of the server. If the server did not flush
dirty data to stable storage before returning to the client, the
client would have no way of knowing when it was safe to discard
modified data. The following data modifying procedures are
synchronous: WRITE (with stable flag set to FILE_SYNC), CREATE,
MKDIR, SYMLINK, MKNOD, REMOVE, RMDIR, RENAME, LINK, and COMMIT.

The NFS version 3 protocol introduces safe asynchronous writes
on the server, when the WRITE procedure is used in conjunction
with the COMMIT procedure. The COMMIT procedure provides a way
for the client to flush data from previous asynchronous WRITE
requests on the server to stable storage and to detect whether
it is necessary to retransmit the data. See the procedure
descriptions of WRITE on page 49 and COMMIT on page 92.

The LOOKUP procedure is used by the client to traverse
multicomponent file names (pathnames). Each call to LOOKUP is
used to resolve one segment of a pathname. There are two reasons
for restricting LOOKUP to a single segment: it is hard to
standardize a common format for hierarchical file names and the
client and server may have different mappings of pathnames to
file systems. This would imply that either the client must break
the path name at file system attachment points, or the server
must know about the client's file system attachment points. In
NFS version 3 protocol implementations, it is the client that
constructs the hierarchical file name space using mounts to
build a hierarchy. Support utilities, such as the Automounter,
provide a way to manage a shared, consistent image of the file
name space while still being driven by the client mount
process.

Clients can perform caching in varied manner. The general
practice with the NFS version 2 protocol was to implement a
time-based client-server cache consistency mechanism. It is
expected NFS version 3 protocol implementations will use a
similar mechanism. The NFS version 3 protocol has some explicit
support, in the form of additional attribute information to
eliminate explicit attribute checks. However, caching is not
required, nor is any caching policy defined by the protocol.
Neither the NFS version 2 protocol nor the NFS version 3
protocol provide a means of maintaining strict client-server
consistency (and, by implication, consistency across client
caches).