Index: head/sys/kern/vfs_mountroot.c =================================================================== --- head/sys/kern/vfs_mountroot.c +++ head/sys/kern/vfs_mountroot.c @@ -88,6 +88,7 @@ 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 @@ 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 @@ 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 @@ } } +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 @@ td = curthread; - vfs_mountroot_wait(); - sb = sbuf_new_auto(); vfs_mountroot_conf0(sb); sbuf_finish(sb);