Author: trasz
Date: Fri Oct 30 15:35:04 2015
New Revision: 290196
URL: https://svnweb.freebsd.org/changeset/base/290196

Log:
  Make root mount wait mechanism smarter, by making it wait only if the root
  device doesn't yet exist.
  
  Reviewed by:  kib@, marcel@
  MFC after:    1 month
  Sponsored by: The FreeBSD Foundation
  Differential Revision:        https://reviews.freebsd.org/D3709

Modified:
  head/sys/kern/vfs_mountroot.c

Modified: head/sys/kern/vfs_mountroot.c
==============================================================================
--- head/sys/kern/vfs_mountroot.c       Fri Oct 30 14:50:29 2015        
(r290195)
+++ head/sys/kern/vfs_mountroot.c       Fri Oct 30 15:35:04 2015        
(r290196)
@@ -88,6 +88,7 @@ __FBSDID("$FreeBSD$");
 
 static int parse_mount(char **);
 static struct mntarg *parse_mountroot_options(struct mntarg *, const char *);
+static int vfs_mountroot_wait_if_neccessary(const char *fs, const char *dev);
 
 /*
  * The vnode of the system's root (/ in the filesystem, without chroot
@@ -673,7 +674,7 @@ parse_mount(char **conf)
        char *errmsg;
        struct mntarg *ma;
        char *dev, *fs, *opts, *tok;
-       int delay, error, timeout;
+       int error;
 
        error = parse_token(conf, &tok);
        if (error)
@@ -710,20 +711,9 @@ parse_mount(char **conf)
                goto out;
        }
 
-       if (strcmp(fs, "zfs") != 0 && strstr(fs, "nfs") == NULL && 
-           dev[0] != '\0' && !parse_mount_dev_present(dev)) {
-               printf("mountroot: waiting for device %s ...\n", dev);
-               delay = hz / 10;
-               timeout = root_mount_timeout * hz;
-               do {
-                       pause("rmdev", delay);
-                       timeout -= delay;
-               } while (timeout > 0 && !parse_mount_dev_present(dev));
-               if (timeout <= 0) {
-                       error = ENODEV;
-                       goto out;
-               }
-       }
+       error = vfs_mountroot_wait_if_neccessary(fs, dev);
+       if (error != 0)
+               goto out;
 
        ma = NULL;
        ma = mount_arg(ma, "fstype", fs, -1);
@@ -931,6 +921,51 @@ vfs_mountroot_wait(void)
        }
 }
 
+static int
+vfs_mountroot_wait_if_neccessary(const char *fs, const char *dev)
+{
+       int delay, timeout;
+
+       /*
+        * In case of ZFS and NFS we don't have a way to wait for
+        * specific device.
+        */
+       if (strcmp(fs, "zfs") == 0 || strstr(fs, "nfs") != NULL ||
+           dev[0] == '\0') {
+               vfs_mountroot_wait();
+               return (0);
+       }
+
+       /*
+        * Otherwise, no point in waiting if the device is already there.
+        * Note that we must wait for GEOM to finish reconfiguring itself,
+        * eg for geom_part(4) to finish tasting.
+        */
+       DROP_GIANT();
+       g_waitidle();
+       PICKUP_GIANT();
+       if (parse_mount_dev_present(dev))
+               return (0);
+
+       /*
+        * No luck.  Let's wait.  This code looks weird, but it's that way
+        * to behave exactly as it used to work before.
+        */
+       vfs_mountroot_wait();
+       printf("mountroot: waiting for device %s...\n", dev);
+       delay = hz / 10;
+       timeout = root_mount_timeout * hz;
+       do {
+               pause("rmdev", delay);
+               timeout -= delay;
+       } while (timeout > 0 && !parse_mount_dev_present(dev));
+
+       if (timeout <= 0)
+               return (ENODEV);
+
+       return (0);
+}
+
 void
 vfs_mountroot(void)
 {
@@ -942,8 +977,6 @@ vfs_mountroot(void)
 
        td = curthread;
 
-       vfs_mountroot_wait();
-
        sb = sbuf_new_auto();
        vfs_mountroot_conf0(sb);
        sbuf_finish(sb);
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to