hi all,

I'd like to request a code review for Juergen Keil's fixes for these bugs:

6317111 newboot x86 diskless client refuses to use nfs vers3 for root 
filesystem
6350002 newboot: failed VFS_MOUNTROOT() panics with a useless error message
6350006 BAD TRAP panic, when using unknown nfs protocol version in 
fstype property

Unified diffs are appended.

The current versions of the changed files, for reference:

http://cvs.opensolaris.org/source/xref/on/usr/src/uts/common/fs/vfs.c
http://cvs.opensolaris.org/source/xref/on/usr/src/uts/common/os/swapgeneric.c

thanks much for any comments.

(and thanks to Juergen for contributing the fixes)

cheers,
calum.


------- usr/src/uts/common/fs/vfs.c -------

--- -   Wed Dec 14 19:36:03 2005
+++ usr/src/uts/common/fs/vfs.c Wed Dec 14 17:59:39 2005
@@ -3892,19 +3892,44 @@
         int error;
         struct vfssw *vsw;
         extern void pm_init();
-       char *fstyp;
+       char *fstype;

-       fstyp = getrootfs();
+       /*
+        * Init the root filesystem type (rootfs.bo_fstype), and for
+        * diskless clients, the filesystem name (rootfs.bo_name).
+        *
+        * For diskless clients, rootfs.bo_name is set to the internal
+        * filesystem name (nfsdyn/nfs/nfs3/nfs4) mapped from the user
+        * specified external fstype name (nfs/nfs2/nfs3/nfs4).  For
+        * error messages we report a fstype of nfs in all cases,
+        * trying to hide our internal nfs filesystem names from the
+        * user.
+        *
+        * In all other cases, rootfs.bo_name and the local variable
+        * fstype have the same name.
+        */
+       fstype = getrootfs();

         if (error = clboot_rootconf())
                 return (error);

-       if (modload("fs", fstyp) == -1)
-               cmn_err(CE_PANIC, "Cannot _init %s module\n", fstyp);
+       /*
+        * Run _init on the root filesystem (we already loaded it
+        * but we've been waiting until now to _init it) which will
+        * have the side-effect of running vsw_init() on this vfs.
+        */
+       if (modload("fs", fstype) == -1) {
+               cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", 
fstype);
+               return (ENXIO);
+       }

         RLOCK_VFSSW();
-       vsw = vfs_getvfsswbyname(fstyp);
+       vsw = vfs_getvfsswbyname(rootfs.bo_fstype);
         RUNLOCK_VFSSW();
+       if (vsw == NULL) {
+               cmn_err(CE_CONT, "Cannot find %s filesystem\n", fstype);
+               return (ENXIO);
+       }
         VFS_INIT(rootvfs, &vsw->vsw_vfsops, 0);
         VFS_HOLD(rootvfs);

@@ -3921,7 +3946,12 @@
         rootdev = rootvfs->vfs_dev;

         if (error)
-               cmn_err(CE_PANIC, "cannot mount root path %s", 
svm_bootpath);
+               cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n",
+                   rootfs.bo_name, fstype);
+       else
+               cmn_err(CE_CONT, "?root on %s fstype %s\n", rootfs.bo_name,
+                   fstype);
+
         return (error);
  }

@@ -3940,9 +3970,23 @@
  }

  /*
- * If server_path exists, then we are booting a diskless
- * client. Otherwise, we default to ufs. Zfs should perhaps be
- * another property.
+ * Init the root filesystem type (rootfs.bo_fstype) from the "fstype"
+ * property.
+ *
+ * Filesystem types starting with the prefix "nfs" are diskless clients;
+ * init the root filename name (rootfs.bo_name), too.
+ *
+ * If we are booting via NFS we currently have these options:
+ *     nfs -   dynamically choose NFS V2, V3, or V4 (default)
+ *     nfs2 -  force NFS V2
+ *     nfs3 -  force NFS V3
+ *     nfs4 -  force NFS V4
+ * Because we need to maintain backward compatibility with the naming
+ * convention that the NFS V2 filesystem name is "nfs" (see vfs_conf.c)
+ * we need to map "nfs" => "nfsdyn" and "nfs2" => "nfs".  The dynamic
+ * nfs module will map the type back to either "nfs", "nfs3", or "nfs4".
+ * This is only for root filesystems, all other uses such as cachefs
+ * will expect that "nfs" == NFS V2.
   */
  static char *
  getrootfs(void)
@@ -3950,7 +3994,10 @@
         extern char *strplumb_get_netdev_path(void);
         char *propstr = NULL;

-       /* check fstype property; it should be nfsdyn for diskless */
+       /*
+        * Check fstype property; for diskless it should be one of "nfs",
+        * "nfs2", "nfs3" or "nfs4".
+        */
         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
             DDI_PROP_DONTPASS, "fstype", &propstr)
             == DDI_SUCCESS) {
@@ -3962,6 +4009,12 @@
                 return (rootfs.bo_fstype);

         ++netboot;
+
+       if (strcmp(rootfs.bo_fstype, "nfs2") == 0)
+               (void) strcpy(rootfs.bo_fstype, "nfs");
+       else if (strcmp(rootfs.bo_fstype, "nfs") == 0)
+               (void) strcpy(rootfs.bo_fstype, "nfsdyn");
+
         /* check if path to network interface is specified in bootpath */
         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
             DDI_PROP_DONTPASS, "bootpath", &propstr)

------- usr/src/uts/common/os/swapgeneric.c -------

--- -   Wed Dec 14 19:36:03 2005
+++ usr/src/uts/common/os/swapgeneric.c Wed Dec 14 17:43:45 2005
@@ -169,6 +169,11 @@
         RLOCK_VFSSW();
         vsw = vfs_getvfsswbyname(rootfs.bo_fstype);
         RUNLOCK_VFSSW();
+       if (vsw == NULL) {
+               cmn_err(CE_CONT, "Cannot find %s filesystem\n",
+                   rootfs.bo_fstype);
+               return (ENXIO);
+       }
         VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0);
         VFS_HOLD(rootvfs);

Reply via email to