Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143103474
D3709.id9049.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D3709.id9049.diff
View Options
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, ¬_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
Details
Attached
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)
Attached To
Mode
D3709: Make root mount wait smarter.
Attached
Detach File
Event Timeline
Log In to Comment