NFS Root on Tru64 File Server

Purpose

The patches on this pages allows the root file system to be on a NFS share on a COMPAQ Tru64 file server.
The patches have been tested with Tru64 5.1. They should also work with other versions and with TruCluster. Please send feedback about other working configuration to me.

The information on this page comes from various sources. A good source of information is the Tru64-UNIX-Manager mailing list and the Tru64 FAQ. The mailing list has also a searchable archive.

Issues

RPC Authentication

The Tru64 NFS server does not support RPC_AUTH_NULL RPCs. On mounting a normal NFS share, the RPC authentication gets negotiated and, if the file server runs Tru64, RPC_AUTH_UNIX gets selected. For the root file system Linux insists on using RPC_AUTH_NULL.

The authentication method can be forced to be RPC_AUTH_UNIX with the following patch:

diff -u linux-2.4.0.orig/fs/nfs/mount_clnt.c linux-2.4.0/fs/nfs/mount_clnt.c
--- linux-2.4.0.orig/fs/nfs/mount_clnt.c        Thu Apr 13 10:54:19 2000
+++ linux-2.4.0/fs/nfs/mount_clnt.c     Wed Jan 24 19:16:06 2001
@@ -87,7 +87,7 @@
 
        clnt = rpc_create_client(xprt, hostname,
                                &mnt_program, version,
-                               RPC_AUTH_NULL);
+                               RPC_AUTH_UNIX);
        if (!clnt) {
                xprt_destroy(xprt);
        } else {

Device Special Files

The maximum size of minor numbers is different between Tru64 (12 bit major, 20 bit minor) and Linux (8 bit major, 8 bit minor). This small routine converts them:
/* This kludge converts 16bit DUNIX device numbers
 * into 8-bit Linux ones.
 */
static u32
do_that_magic(u32 rdev)
{
    if (((rdev & 0xffff0000) != 0) &&
        ((rdev & 0x0ff000ff) == rdev)) {
        u32 tmp ;
        tmp = ((rdev & 0x0ff00000) >> 12) | (rdev & 0xff) ;
        rdev = tmp ;
    }
    return rdev ;
}
The conversion is needed at two places in inode.c in fs/nfs:
diff -u linux-2.4.0.orig/fs/nfs/inode.c linux-2.4.0/fs/nfs/inode.c
--- linux-2.4.0.orig/fs/nfs/inode.c     Mon Dec 11 20:46:04 2000
+++ linux-2.4.0/fs/nfs/inode.c  Thu Jan 25 18:08:38 2001
@@ -547,6 +547,22 @@
        nfs_zap_caches(inode);
 }
 
+/* This kludge converts 16bit DUNIX device numbers
+ * into 8-bit Linux ones.
+ */
+static u32
+do_that_magic(u32 rdev)
+{
+    if (((rdev & 0xffff0000) != 0) &&
+        ((rdev & 0x0ff000ff) == rdev)) {
+        u32 tmp ;
+        tmp = ((rdev & 0x0ff00000) >> 12) | (rdev & 0xff) ;
+        //printk("doing that magic!! %08x -> %08x\n", rdev, tmp) ;
+        rdev = tmp ;
+    }
+    return rdev ;
+}
+
 /*
  * Fill in inode information from the fattr.
  */
@@ -574,7 +590,7 @@
                } else if (S_ISLNK(inode->i_mode))
                        inode->i_op = &nfs_symlink_inode_operations;
                else
-                       init_special_inode(inode, inode->i_mode, fattr->rdev);
+                       init_special_inode(inode, inode->i_mode, do_that_magic(fattr->rdev));
                /*
                 * Preset the size and mtime, as there's no need
                 * to invalidate the caches.
@@ -1009,7 +1025,7 @@
        }
        inode->i_rdev = 0;
        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-               inode->i_rdev = to_kdev_t(fattr->rdev);
+               inode->i_rdev = to_kdev_t(do_that_magic(fattr->rdev));
  
        /* Update attrtimeo value */
        if (!invalid && time_after(jiffies, NFS_ATTRTIMEO_UPDATE(inode)+NFS_ATTRTIMEO(inode))) {
and the other way round in fs/nfs/proc.c:
--- linux.orig/fs/nfs/proc.c    Fri Feb  9 14:29:44 2001
+++ linux.nfs/fs/nfs/proc.c     Mon Apr 30 16:54:48 2001
@@ -181,6 +181,10 @@
        return status;
 }
 
+/* convert Linux major/minor number into Tru64 major/minor */
+#define linux2tru64(rdev) \
+        (MAJOR((rdev))<<20 | MINOR((rdev)))
+
 /*
  * In NFSv2, mknod is grafted onto the create call.
  */
@@ -201,7 +205,7 @@
                sattr->ia_valid &= ~ATTR_SIZE;
        } else if (S_ISCHR(mode) || S_ISBLK(mode)) {
                sattr->ia_valid |= ATTR_SIZE;
-               sattr->ia_size   = rdev;        /* get out your barf bag */
+               sattr->ia_size   = linux2tru64(rdev);   /* get out your barf bag */
        }
 
        fattr->valid = 0;
Note: NFS3 handles the conversion ok, the patch is only needed for NFS2. The root filesystem get always mounted as NFS2 filesystem, so using NFS3 is no valid workaround unfortunately.

Patches

Kernel VersionPatch File
2.2.18patch-nfs-2.2.18.gz
2.4.2patch-nfs-2.4.2.gz

Comments, Corrections

Please send comments, corrections etc. to the address below.
frey@scs.ch