]> git.proxmox.com Git - mirror_zfs.git/commitdiff
rootdelay on zfs should be adaptive
authorGeorge Wilson <george.wilson@delphix.com>
Thu, 2 Feb 2023 23:11:35 +0000 (18:11 -0500)
committerGitHub <noreply@github.com>
Thu, 2 Feb 2023 23:11:35 +0000 (15:11 -0800)
The 'rootdelay' boot option currently pauses the boot for a specified
amount of time. The original intent was to ensure that slower
configurations would have ample time to enumerate the devices to make
importing the root pool successful. This, however, causes unnecessary
boot delay for environments like Azure which set this parameter by
default.

This commit changes the initramfs logic to pause until it can
successfully load the 'zfs' module. The timeout specified by
'rootdelay' now becomes the maximum amount of time that initramfs will
wait before failing the boot.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Prakash Surya <prakash.surya@delphix.com>
Signed-off-by: George Wilson <gwilson@delphix.com>
Closes #14430

contrib/initramfs/scripts/zfs

index c724f0c2cf57a12f9d1b15ab9e97b5969c0e6ebb..41a4d96f87321356e127292e23584a95441a29d9 100644 (file)
@@ -272,30 +272,46 @@ import_pool()
 # with more logging etc.
 load_module_initrd()
 {
-       [ -n "$ROOTDELAY" ] && ZFS_INITRD_PRE_MOUNTROOT_SLEEP="$ROOTDELAY"
+       ZFS_INITRD_PRE_MOUNTROOT_SLEEP=${ROOTDELAY:-0}
 
-       if [ "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP" -gt 0 ] 2>/dev/null
-       then
-               if [ "$quiet" != "y" ]; then
-                       zfs_log_begin_msg "Sleeping for" \
-                               "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP seconds..."
-               fi
-               sleep "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP"
-               [ "$quiet" != "y" ] && zfs_log_end_msg
+       if [ "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP" -gt 0 ]; then
+               [ "$quiet" != "y" ] && zfs_log_begin_msg "Delaying for up to '${ZFS_INITRD_PRE_MOUNTROOT_SLEEP}' seconds."
        fi
 
-       # Wait for all of the /dev/{hd,sd}[a-z] device nodes to appear.
-       if command -v wait_for_udev > /dev/null 2>&1 ; then
-               wait_for_udev 10
-       elif command -v wait_for_dev > /dev/null 2>&1 ; then
-               wait_for_dev
-       fi
+       START=$(/bin/date -u +%s)
+       END=$((START+ZFS_INITRD_PRE_MOUNTROOT_SLEEP))
+       while true; do
+
+               # Wait for all of the /dev/{hd,sd}[a-z] device nodes to appear.
+               if command -v wait_for_udev > /dev/null 2>&1 ; then
+                       wait_for_udev 10
+               elif command -v wait_for_dev > /dev/null 2>&1 ; then
+                       wait_for_dev
+               fi
+
+               #
+               # zpool import refuse to import without a valid
+               # /proc/self/mounts
+               #
+               [ ! -f /proc/self/mounts ] && mount proc /proc
+
+               # Load the module
+               if load_module "zfs"; then
+                       ret=0
+                       break
+               else
+                       ret=1
+               fi
 
-       # zpool import refuse to import without a valid /proc/self/mounts
-       [ ! -f /proc/self/mounts ] && mount proc /proc
+               [ "$(/bin/date -u +%s)" -gt "$END" ] && break
+               sleep 1
+
+       done
+       if [ "$ZFS_INITRD_PRE_MOUNTROOT_SLEEP" -gt 0 ]; then
+               [ "$quiet" != "y" ] && zfs_log_end_msg
+       fi
 
-       # Load the module
-       load_module "zfs" || return 1
+       [ "$ret" -ne 0 ] && return 1
 
        if [ "$ZFS_INITRD_POST_MODPROBE_SLEEP" -gt 0 ] 2>/dev/null
        then