17.4 NFS

Written by Bill Swingle.

Among the many different file systems that FreeBSD supports is the Network File System or NFS. NFS allows you to share directories and files on one machine with others via the network they are attached to. Using NFS, users and programs can access files on remote systems as if they were local files.

NFS has several benefits:

17.4.1 How It Works

NFS is composed of two sides - a client side and a server side. Think of it as a want/have relationship. The client wants the data that the server side has. The server shares its data with the client. In order for this system to function properly a few processes have to be configured and running.

The server has to be running the following daemons:

Daemon Description
nfsd The NFS Daemon which services requests from NFS clients.
mountd The NFS Mount Daemon which actually carries out requests that nfsd(8) passes on to it.
portmap The portmapper daemon which allows NFS clients to find out which port the NFS server is using.

The client side only needs to run a single daemon:

nfsiod The NFS async I/O Daemon which services requests from its NFS server.

17.4.2 Configuring NFS

Luckily for us, on a FreeBSD system this setup is a snap. The processes that need to be running can all be run at boot time with a few modifications to your /etc/rc.conf file.

On the NFS server make sure you have:

    portmap_enable="YES"
    nfs_server_enable="YES"
    nfs_server_flags="-u -t -n 4"
    mountd_flags="-r"

mountd is automatically run whenever the NFS server is enabled. The -u and -t flags to nfsd tell it to serve UDP and TCP clients. The -n 4 flag tells nfsd to start 4 copies of itself.

On the client, make sure you have:

    nfs_client_enable="YES"
    nfs_client_flags="-n 4"

Like nfsd, the -n 4 tells nfsiod to start 4 copies of itself.

The last configuration step requires that you create a file called /etc/exports. The exports file specifies which file systems on your server will be shared (a.k.a., ``exported'') and with what clients they will be shared. Each line in the file specifies a file system to be shared. There are a handful of options that can be used in this file but only a few will be mentioned here. You can find out about the rest in the exports(5) manual page.

Here are a few example /etc/exports entries:

The following line exports /cdrom to three silly machines that have the same domain name as the server (hence the lack of a domain name for each) or have entries in your /etc/hosts file. The -ro flag makes the shared file system read-only. With this flag, the remote system will not be able to make any changes to the shared file system.

    /cdrom -ro moe larry curly

The following line exports /home to three hosts by IP address. This is a useful setup if you have a private network but do not have DNS running. The -alldirs flag allows all the directories below the specified file system to be exported as well.

    /home  -alldirs  10.0.0.2 10.0.0.3 10.0.0.4

The following line exports /a to two machines that have different domain names than the server. The -maproot=0 flag allows the root user on the remote system to write to the shared file system as root. Without the -maproot=0 flag even if someone has root access on the remote system they will not be able to modify files on the shared file system.

    /a  -maproot=0  host.domain.com box.example.com

In order for a client to access- an exported file system it must have permission to do so. Make sure your client is listed in your /etc/exports file.

It is important to remember that you must restart mountd whenever you modify /etc/exports so that your changes take effect. This can be accomplished by sending the hangup signal to the mountd process :

    # kill -HUP `cat /var/run/mountd.pid`

Now that you have made all these changes you can just reboot and let FreeBSD start everything for you at boot time or you can run the following commands as root:

On the NFS server:

    # portmap
    # nfsd -u -t -n 4
    # mountd -r

On the NFS client:

    # nfsiod -n 4

Now you should be ready to actually mount a remote file system. This can be done one of two ways. In these examples the server's name will be server and the client's name will be client. If you just want to temporarily mount a remote file system or just want to test out your configuration you can run a command like this as root on the client:

    # mount server:/home /mnt

This will mount the /home directory on the server at /mnt on the client. If everything is setup correctly you should be able to go into /mnt on the client and see all the files that are on the server.

If you want to permanently (each time you reboot) mount a remote file system you need to add it to your /etc/fstab file. Here is an example line:

    server:/home   /mnt    nfs rw  0   0

Read the fstab(5) manual page for more options.

17.4.3 Practical Uses

There are many very cool uses for NFS. Some of the more common ones are listed below.

17.4.4 amd

Contributed by Wylie Stilwell. Rewritten by Chern Lee.

amd(8), which is also known as the automatic mounter daemon, is a useful utility used for automatically mounting a remote filesystem whenever a file or directory within that filesystem is accessed. Filesystems that are inactive for a period of time will also be automatically unmounted by amd. Using amd provides a simplistic alternative to static mounts.

amd operates by attaching itself as an NFS server to the /host and /net directories. When a file is accessed within one of these directories, amd looks up the corresponding remote mount and automatically mounts it. /net is used to mount an exported filesystem from an IP address, while /host is used to mount an export from a remote hostname.

An access to a file within /host/foobar/usr would tell amd to attempt to mount the /usr export on the host foobar.

Example 17-1. Mounting an Export with amd

    % showmount -e foobar
    Exports list on foobar:
    /usr                               10.10.10.0
    /a                                 10.10.10.0
    % cd /host/foobar/usr

As seen in the example, the showmount shows /usr as an export. When changing directories to /host/foobar/usr, amd attempts to resolve the hostname foobar and automatically mount the desired export.

amd can be started through the rc.conf system by placing the following lines in /etc/rc.conf:

    amd_enable="YES"

Additionally, custom flags can be passed to amd from the amd_flags option. By default, amd_flags is set to:

    amd_flags="-a /.amd_mnt -l syslog /host /etc/amd.map /net /etc/amd.map"

The /etc/amd.map file defines the default options that exports are mounted with. The /etc/amd.conf file defines some of the more advanced features of amd.

Consult the amd(8) and amd.conf(5) man pages for more information.

17.4.5 Problems Integrating with Other Systems

Contributed by John Lind.

Certain Ethernet adapters for ISA PC systems have limitations which can lead to serious network problems, particularly with NFS. This difficulty is not specific to FreeBSD, but FreeBSD systems are affected by it.

The problem nearly always occurs when (FreeBSD) PC systems are networked with high-performance workstations, such as those made by Silicon Graphics, Inc., and Sun Microsystems, Inc. The NFS mount will work fine, and some operations may succeed, but suddenly the server will seem to become unresponsive to the client, even though requests to and from other systems continue to be processed. This happens to the client system, whether the client is the FreeBSD system or the workstation. On many systems, there is no way to shut down the client gracefully once this problem has manifested itself. The only solution is often to reset the client, because the NFS situation cannot be resolved.

Though the ``correct'' solution is to get a higher performance and capacity Ethernet adapter for the FreeBSD system, there is a simple workaround that will allow satisfactory operation. If the FreeBSD system is the server, include the option -w=1024 on the mount from the client. If the FreeBSD system is the client, then mount the NFS file system with the option -r=1024. These options may be specified using the fourth field of the fstab entry on the client for automatic mounts, or by using the -o parameter of the mount command for manual mounts.

It should be noted that there is a different problem, sometimes mistaken for this one, when the NFS servers and clients are on different networks. If that is the case, make certain that your routers are routing the necessary UDP information, or you will not get anywhere, no matter what else you are doing.

In the following examples, fastws is the host (interface) name of a high-performance workstation, and freebox is the host (interface) name of a FreeBSD system with a lower-performance Ethernet adapter. Also, /sharedfs will be the exported NFS filesystem (see exports(5)), and /project will be the mount point on the client for the exported file system. In all cases, note that additional options, such as hard or soft and bg may be desirable in your application.

Examples for the FreeBSD system (freebox) as the client: in /etc/fstab on freebox:

    fastws:/sharedfs /project nfs rw,-r=1024 0 0

As a manual mount command on freebox:

    # mount -t nfs -o -r=1024 fastws:/sharedfs /project

Examples for the FreeBSD system as the server: in /etc/fstab on fastws:

    freebox:/sharedfs /project nfs rw,-w=1024 0 0

As a manual mount command on fastws:

    # mount -t nfs -o -w=1024 freebox:/sharedfs /project

Nearly any 16-bit Ethernet adapter will allow operation without the above restrictions on the read or write size.

For anyone who cares, here is what happens when the failure occurs, which also explains why it is unrecoverable. NFS typically works with a ``block'' size of 8k (though it may do fragments of smaller sizes). Since the maximum Ethernet packet is around 1500 bytes, the NFS ``block'' gets split into multiple Ethernet packets, even though it is still a single unit to the upper-level code, and must be received, assembled, and acknowledged as a unit. The high-performance workstations can pump out the packets which comprise the NFS unit one right after the other, just as close together as the standard allows. On the smaller, lower capacity cards, the later packets overrun the earlier packets of the same unit before they can be transferred to the host and the unit as a whole cannot be reconstructed or acknowledged. As a result, the workstation will time out and try again, but it will try again with the entire 8K unit, and the process will be repeated, ad infinitum.

By keeping the unit size below the Ethernet packet size limitation, we ensure that any complete Ethernet packet received can be acknowledged individually, avoiding the deadlock situation.

Overruns may still occur when a high-performance workstations is slamming data out to a PC system, but with the better cards, such overruns are not guaranteed on NFS ``units''. When an overrun occurs, the units affected will be retransmitted, and there will be a fair chance that they will be received, assembled, and acknowledged.

This, and other documents, can be downloaded from ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

For questions about FreeBSD, read the documentation before contacting <questions@FreeBSD.org>.
For questions about this documentation, e-mail <doc@FreeBSD.org>.