svn commit: r290196 - head/sys/kern

Edward Tomasz Napierala trasz at FreeBSD.org
Fri Oct 30 15:35:05 UTC 2015


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);


More information about the svn-src-all mailing list