kernel - Force NFSv3 for diskless nfs mount
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 19 Oct 2010 19:31:29 +0000 (12:31 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 19 Oct 2010 19:31:29 +0000 (12:31 -0700)
* Ignore any file handles passed from bootp.  These are NFSv2 handles
  and NFSv2 just doesn't have the directory support needed if the
  server is running a filesystem with 64-bit directory cookies (as HAMMER
  does).

  This will force the kernel's diskless nfs mount to re-authorize and
  acquire a NFSv3 handle for the root mount.

* Undo a bit of a previous commit where I tried to enable readdirplus for
  NFSv2 to workaround NFSv2 directory cookie issues.  It just doesn't work.
  readdirplus is again force-disabled for NFSv2 mounts.

sys/vfs/nfs/nfs_vfsops.c
sys/vfs/nfs/nfs_vnops.c

index c7bb09b..cdc8de7 100644 (file)
@@ -252,9 +252,16 @@ nfs_convert_diskless(void)
                sizeof(struct ifaliasreq));
        bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
                sizeof(struct sockaddr_in));
-       nfs_convert_oargs(&nfsv3_diskless.swap_args,&nfs_diskless.swap_args);
+       nfs_convert_oargs(&nfsv3_diskless.swap_args, &nfs_diskless.swap_args);
 
-       bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH);
+       /*
+        * Copy the NFS handle passed from the diskless code.
+        *
+        * XXX CURRENTLY DISABLED - bootp passes us a NFSv2 handle which
+        * will fail utterly with HAMMER due to limitations with NFSv2
+        * directory cookies.
+        */
+       bcopy(nfs_diskless.swap_fh, nfsv3_diskless.swap_fh, NFSX_V2FH);
        nfsv3_diskless.swap_fhsize = NFSX_V2FH;
        for (i = NFSX_V2FH - 1; i >= 0; --i) {
                if (nfs_diskless.swap_fh[i])
@@ -262,6 +269,7 @@ nfs_convert_diskless(void)
        }
        if (i < 0)
                nfsv3_diskless.swap_fhsize = 0;
+       nfsv3_diskless.swap_fhsize = 0;         /* FORCE DISABLE */
 
        bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr,
                sizeof(struct sockaddr_in));
@@ -269,9 +277,16 @@ nfs_convert_diskless(void)
        nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks;
        bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred,
                sizeof(struct ucred));
-       nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
+       nfs_convert_oargs(&nfsv3_diskless.root_args, &nfs_diskless.root_args);
 
-       bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH);
+       /*
+        * Copy the NFS handle passed from the diskless code.
+        *
+        * XXX CURRENTLY DISABLED - bootp passes us a NFSv2 handle which
+        * will fail utterly with HAMMER due to limitations with NFSv2
+        * directory cookies.
+        */
+       bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
        nfsv3_diskless.root_fhsize = NFSX_V2FH;
        for (i = NFSX_V2FH - 1; i >= 0; --i) {
                if (nfs_diskless.root_fh[i])
@@ -279,6 +294,7 @@ nfs_convert_diskless(void)
        }
        if (i < 0)
                nfsv3_diskless.root_fhsize = 0;
+       nfsv3_diskless.root_fhsize = 0;         /* FORCE DISABLE */
 
        bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
                sizeof(struct sockaddr_in));
@@ -567,9 +583,16 @@ nfs_mountroot(struct mount *mp)
        /*
         * The boot code may have passed us a diskless structure.
         */
+       kprintf("DISKLESS %d\n", nfs_diskless_valid);
        if (nfs_diskless_valid == 1)
                nfs_convert_diskless();
 
+       /*
+        * NFSv3 is required.
+        */
+       nd->root_args.flags |= NFSMNT_NFSV3 | NFSMNT_RDIRPLUS;
+       nd->swap_args.flags |= NFSMNT_NFSV3;
+
 #define SINP(sockaddr) ((struct sockaddr_in *)(sockaddr))
        kprintf("nfs_mountroot: interface %s ip %s",
                nd->myif.ifra_name,
@@ -635,8 +658,9 @@ nfs_mountroot(struct mount *mp)
                (l >> 24) & 0xff, (l >> 16) & 0xff,
                (l >>  8) & 0xff, (l >>  0) & 0xff,nd->root_hostnam);
        kprintf("NFS_ROOT: %s\n",buf);
-       if ((error = nfs_mountdiskless(buf, "/", MNT_RDONLY,
-           &nd->root_saddr, &nd->root_args, td, &vp, &mp)) != 0) {
+       error = nfs_mountdiskless(buf, "/", MNT_RDONLY, &nd->root_saddr,
+                                 &nd->root_args, td, &vp, &mp);
+       if (error) {
                mp->mnt_vfc->vfc_refcount--;
                crit_exit();
                return (error);
@@ -659,8 +683,9 @@ nfs_mountroot(struct mount *mp)
                        (l >> 24) & 0xff, (l >> 16) & 0xff,
                        (l >>  8) & 0xff, (l >>  0) & 0xff,nd->swap_hostnam);
                kprintf("NFS SWAP: %s\n",buf);
-               if ((error = nfs_mountdiskless(buf, "/swap", 0,
-                   &nd->swap_saddr, &nd->swap_args, td, &vp, &swap_mp)) != 0) {
+               error = nfs_mountdiskless(buf, "/swap", 0, &nd->swap_saddr,
+                                         &nd->swap_args, td, &vp, &swap_mp);
+               if (error) {
                        crit_exit();
                        return (error);
                }
@@ -727,7 +752,8 @@ nfs_mountdiskless(char *path, char *which, int mountflag,
        if (args->fhsize == 0) {
                char *xpath = path;
 
-               kprintf("NFS_ROOT: No FH passed from loader, attempting mount rpc...");
+               kprintf("NFS_ROOT: No FH passed from loader, attempting "
+                       "mount rpc...");
                while (*xpath && *xpath != ':')
                        ++xpath;
                if (*xpath)
@@ -775,21 +801,12 @@ nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp)
        }
 
        /*
-        * Ok, this is a problem.  bootp is NFSv2 and we will wind up
-        * mounting a diskless root NFSv2 until we fix it.  However,
-        * NFSv2 just doesn't work with HAMMER directories (the cookies
-        * are only 32 bits).  The only way around this is to allow
-        * the 'readdirplus' for NFSv2.
-        *
-        * If this is a problem the client needs to specify the 'nordirplus'
-        * option for any NFSv2 NFS mount.
+        * readdirplus is NFSv3 only.
         */
-#if 0
        if ((argp->flags & NFSMNT_NFSV3) == 0) {
                nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
                argp->flags &= ~NFSMNT_RDIRPLUS;
        }
-#endif
 
        /*
         * Re-bind if rsrvd port flag has changed
index c54c1bc..8f210f6 100644 (file)
@@ -2679,7 +2679,7 @@ nfs_readdirplusrpc_uio(struct vnode *vp, struct uio *uiop)
        while (more_dirs && bigenough) {
                nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
                nfsm_reqhead(&info, vp, NFSPROC_READDIRPLUS,
-                            NFSX_FH(1) + 6 * NFSX_UNSIGNED);
+                            NFSX_FH(info.v3) + 6 * NFSX_UNSIGNED);
                ERROROUT(nfsm_fhtom(&info, vp));
                tl = nfsm_build(&info, 6 * NFSX_UNSIGNED);
                *tl++ = cookie.nfsuquad[0];