Symbolic links
Symbolic links are both useful and confusing when used with NFS-mounted filesystems. They can be used to "shape" a filesystem arbitrarily, giving the system administrator freedom to organize filesystems and pathnames in convenient ways. When used badly, symbolic links have unexpected and unwanted side effects, including poor performance and "missing" files or directories. In this section, we'll discuss the many effects that symbolic links can have on NFS. Symbolic links differ from hard links in several ways, but the salient distinction is that hard links duplicate directory entries, while symbolic links are new directory entries of a special type. Using a hard link to a file is no different from using the original file, but referencing a symbolic link requires reading the link to find out where it points and then referencing that file or directory. It is possible to create a loop of symbolic links, but the kernel routines that read the links and build up pathnames eventually return an error when too many links have been traversed in a single pathname.Resolving symbolic links in NFS
When an NFS client does a stat( ) of a directory entry and finds it is a symbolic link, it issues an RPC call to read the link (on the server) and determine where the link points. This is the equivalent of doing a local readlink( ) system call to examine the contents of a symbolic link. The server returns a pathname that is interpreted on the client, not on the server. The pathname may point to a directory that the client has mounted, or it may not make sense on the client. If you uncover a link that was made on the server that points to a filesystem not exported from the server, you will have either trouble or confusion if you resolve the link. If the link accidentally points to a valid file or directory on the client, the results are often unpredictable and sometimes unwanted. If the link points to something nonexistent on the client, an attempt to use it produces an error. An example here helps explain how links can point in unwanted directions. Let's say that you install a new publishing package, marker, in the tools filesystem on an NFS server. Once it's loaded, you realize that you need to free some space on the /tools filesystem, so you move the font directory used by marker to the /usr filesystem, and make a symbolic link to redirect the fonts subdirectory to its new location:#mkdir /usr/marker
#cd /tools/marker
#tar cf - fonts | ( cd /usr/marker; tar xbBfp 20 - )
#rm -rf fonts
#ln -s /usr/marker/fonts fonts
The tar command copies the entire directory tree from the current directory to /usr/marker (see the manpage for tar(1) for a more detailed explanation). On the server, the redirection imposed by the symbolic link is invisible to users. However, an NFS client that mounts /tools/marker and tries to use it will be in for a surprise when the client tries to find the fonts subdirectory. The client looks at /tools/marker/fonts, realizes that it's a symbolic link, and asks the NFS server to read the link. The NFS server returns the link's target -- /usr/marker/fonts -- and the client tries to open this directory instead. On the client, however, this directory does not exist. It was created for convenience on the server, but breaks the NFS clients that use it. To fix this problem, you must create the same symbolic link on all of the clients, and ensure that the clients can locate the target of the link. Think of symbolic links as you would files on an NFS server. The server does not interpret the contents of files, nor does it do anything with the contents of a link except pass it back to the user process that issued the readlink RPC. Symbolic links are treated as if they existed on the local host, and they are interpreted relative to the client's filesystem hierarchy.
Absolute and relative pathnames
Symbolic links can point to an absolute pathname (one beginning with / ) or a pathname relative to the link's path. Relative symbolic link targets are resolved relative to the place at which the link appears in the client's filesystem, not the server's, so it is possible for a relative link to point at a nonexistent file or directory on the client. Consider this server for /usr/local:%cd /usr/local/bin
%ls -l
total 1 lrwxrwxrwx 1 root bin 16 Jun 8 1990 a2ps -> ../bin.mips/a2ps lrwxrwxrwx 1 root bin 12 Jun 8 1990 mp -> ../bin.mips/mp
If you mount just /usr/local/bin from this server, you will not be able to use any of the executables in it unless you have them in the directory /usr/local/bin.mips. Using symbolic links to reduce the number of directories in a pathname is beneficial only if users are not tempted to cd from one link to another:
#ln -s /minnow/fred /u/fred
#ln -s /alewife/lucy /u/lucy
The unsuspecting user tries to use the path-compressed names, but finds that relative pathnames aren't relative to the link directory:
%cd /u/fred
%cd ../lucy
../lucy: No such file or directory
A user may be bewildered by this behavior. According to the /u directory, fred and lucy are subdirectories of a common parent. In reality, they aren't. The symbolic links hide the real locations of the fred and lucy directories, which do not have a common parent. Using symbolic links to shorten pathnames in this fashion is not always the most efficient solution to the problem; NFS mounts can often be used to produce the same filesystem naming conventions.
Mount points, exports, and links
Symbolic links have strange effects on mounting and exporting filesystems. A good general rule to remember is that filesystem operations apply to the target of a link, not to the link itself. The symbolic link is just a pointer to the real operand. If you mount a filesystem on a symbolic link, the actual mount occurs on the directory pointed to by the link. The following sequence of operations produces the same net result:#mkdir -p /users/hal
#ln -s /users/hal /usr/hal
#mount bitatron:/export/home/hal /usr/hal
as this sequence does:
#mkdir -p /users/hal
#mount bitatron:/export/home/hal /users/hal
#ln -s /users/hal /usr/hal
The filesystem is mounted on the directory /users/hal and the symbolic link /usr/hal has the mount point as its target. You should make sure that the directory pointed to by the link is on a filesystem that is mounted read/write and that performing the mount will not obscure any required filesystem underneath the symbolic link target. Exporting a symbolic link from a server follows similar rules. The filesystem or subtree of a filesystem that is really exported is the one pointed to by the symbolic link. If the parent of the link's target has already been exported, or a subtree of it is exported, the attempt to export the link fails. More interesting than exporting a symbolic link is mounting one from the server. Mounting a link from a server is not the same thing as mounting a filesystem containing a symbolic link. The latter means that there is a symbolic link somewhere in the filesystem mounted using NFS. The former case implies that the server pathname used to locate the remote filesystem is a link and directs the mount somewhere else. The client mounts the directory pointed to by the link. As shown in Figure 6-1, if /usr/man is a symbolic link to /usr/share/man, then this mount command:
#mount bitatron:/usr/share/man /mnt
does the same thing as this mount command:
#mount bitatron:/usr/man /mnt
