The caching NFS client [GJB98] has been designed to address several performance issues relating to the implementation of NFS that is shipped with Linux 2.0 kernels. The most far reaching change is the implementation of a persistent cache for files retrieved from the server.
Blocks that are read from a NFS server are kept in a disk cache. As blocks of a file are read they are added to the cache for this file. Once the file is complete it is marked as being persistent and can survive client crashes. This is possible because once the whole file is cached kernel data structures are no longer necessary to gain information about which blocks of the file are present. If the cache becomes full a process runs through the cache and removes persistent objects with preference for least recently used objects. Partially cached files are not eligible for cleaning as the additional complexity of updating the kernel data structures associated with these files during cache cleaning is tedious at best. As this is mechanism favors files that are complete in the cache a background process runs to collect uncached blocks of partially cached files.
The client also supports an RPC lookup cache that holds recently requested information about file and directory attributes. These attribute requests actually contribute a large amount of the RPC traffic associated with NFS. This cache is however limited in its usefulness as the cache must expire after a time in the order of 100ms to maintain NFS semantics. If the cache is held for longer then the client may no longer hold an accurate view of the attributes held on the server and there are no conflict resolution procedures in the NFS protocol to handle such a situation.
Finally the client supports asynchronous writing of files. Buffering of writes of a file to a server avoids traffic in the situation where a file is modified many times in succession. This is of limited importance in the HTTP server application but becomes much more poignant when serving files to a group of workstations.
The lookup cache, asynchronous write buffer and persistent disk cache are all designed to reduce the number of RPC calls that a client makes and hence reduce latency and increase performance. The client runs under 2.0 series kernels and was designed to fill the gap between the poor performance of the current NFS implementation included with 2.0 kernels and the new implementation that is currently only available with 2.1 series development kernels. However at this time there is no maintainer for the project and hence deploying this in production is not strictly appropriate.