summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2015-10-30 15:35:04 +0000
committertrasz <trasz@FreeBSD.org>2015-10-30 15:35:04 +0000
commit3b970d7ccc00f84d53bef1b8094f2907ff67b750 (patch)
tree0d0b7ab821e634932bdc50f24d5539dc449ecb29 /sys
parent232f7e59dfdfb0b4695e73ef77162336c2931fe7 (diff)
downloadFreeBSD-src-3b970d7ccc00f84d53bef1b8094f2907ff67b750.zip
FreeBSD-src-3b970d7ccc00f84d53bef1b8094f2907ff67b750.tar.gz
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
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/vfs_mountroot.c67
1 files changed, 50 insertions, 17 deletions
diff --git a/sys/kern/vfs_mountroot.c b/sys/kern/vfs_mountroot.c
index aecddbd..2691a6e 100644
--- a/sys/kern/vfs_mountroot.c
+++ b/sys/kern/vfs_mountroot.c
@@ -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);
OpenPOWER on IntegriCloud