Page MenuHomeFreeBSD

D3709.id9049.diff
No OneTemporary

D3709.id9049.diff

Index: etc/defaults/rc.conf
===================================================================
--- etc/defaults/rc.conf
+++ etc/defaults/rc.conf
@@ -23,6 +23,7 @@
#rc_debug="NO" # Set to YES to enable debugging output from rc.d
rc_info="NO" # Enables display of informational messages at boot.
+rc_parallel="NO" # Run startup scripts in parallel
rc_startmsgs="YES" # Show "Starting foo:" messages at boot
rcshutdown_timeout="90" # Seconds to wait before terminating rc.shutdown
early_late_divider="FILESYSTEMS" # Script that separates early/late
@@ -84,6 +85,7 @@
#geli_mirror_home_flags="-k /etc/geli/home.keys"
root_rw_mount="YES" # Set to NO to inhibit remounting root read-write.
+root_hold_delay="30" # Time to wait for root mount hold release.
fsck_y_enable="NO" # Set to YES to do fsck -y if the initial preen fails.
fsck_y_flags="" # Additional flags for fsck -y
background_fsck="YES" # Attempt to run fsck in the background where possible.
Index: etc/rc.d/mountcritlocal
===================================================================
--- etc/rc.d/mountcritlocal
+++ etc/rc.d/mountcritlocal
@@ -35,8 +35,41 @@
mount_excludes="${mount_excludes}${fstype},"
done
mount_excludes=${mount_excludes%,}
+
+ # Originally, root mount hold had to be released before mounting the root
+ # filesystem. This delayed the boot, so it was changed to only wait if
+ # the root device isn't readily available. This can result in this script
+ # executing before all the devices - such as graid(8) - are available.
+ # Thus, should the mount fail, we will wait for the root mount hold release
+ # and retry.
mount -a -t ${mount_excludes}
err=$?
+ if [ $? -ne 0 ]; then
+ echo
+ echo 'Mounting /etc/fstab filesystems failed,' \
+ ' will retry after root mount hold release'
+
+ waited=0
+ while [ ${waited} -lt ${root_hold_delay} ]; do
+ if [ $(sysctl -n vfs.root_mount_hold) = 0 ]; then
+ break;
+ fi
+
+ if [ ${waited} -eq 0 ]; then
+ echo -n "Waiting ${root_hold_delay}s for the root mount hold: "
+ else
+ echo -n .
+ fi
+ if [ ${waited} -eq ${root_hold_delay} ]; then
+ break 2
+ fi
+ sleep 1
+ waited=$(($waited + 1))
+ done
+ mount -a -t ${mount_excludes}
+ err=$?
+ fi
+
check_startmsgs && echo '.'
case ${err} in
Index: sys/kern/vfs_mountroot.c
===================================================================
--- sys/kern/vfs_mountroot.c
+++ sys/kern/vfs_mountroot.c
@@ -88,6 +88,8 @@
static int parse_mount(char **);
static struct mntarg *parse_mountroot_options(struct mntarg *, const char *);
+static int sysctl_vfs_root_mount_hold(SYSCTL_HANDLER_ARGS);
+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
@@ -129,6 +131,22 @@
static int root_mount_timeout = 3;
TUNABLE_INT("vfs.mountroot.timeout", &root_mount_timeout);
+SYSCTL_PROC(_vfs, OID_AUTO, root_mount_hold, CTLTYPE_INT | CTLFLAG_RD,
+ NULL, 0, sysctl_vfs_root_mount_hold, "I",
+ "Resets to 0 when all devices finish initialization");
+
+static int
+sysctl_vfs_root_mount_hold(SYSCTL_HANDLER_ARGS)
+{
+ int not_empty;
+
+ mtx_lock(&root_holds_mtx);
+ not_empty = !LIST_EMPTY(&root_holds);
+ mtx_unlock(&root_holds_mtx);
+
+ return (SYSCTL_OUT(req, &not_empty, sizeof(not_empty)));
+}
+
struct root_hold_token *
root_mount_hold(const char *identifier)
{
@@ -691,7 +709,7 @@
char *errmsg;
struct mntarg *ma;
char *dev, *fs, *opts, *tok;
- int delay, error, timeout;
+ int error;
error = parse_token(conf, &tok);
if (error)
@@ -728,20 +746,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);
@@ -949,6 +956,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)
{
@@ -960,8 +1012,6 @@
td = curthread;
- vfs_mountroot_wait();
-
sb = sbuf_new_auto();
vfs_mountroot_conf0(sb);
sbuf_finish(sb);

File Metadata

Mime Type
text/plain
Expires
Tue, Jan 27, 12:45 AM (13 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28047338
Default Alt Text
D3709.id9049.diff (5 KB)

Event Timeline