MFC: Introduce new /boot/loader.conf variable: vfs.root.mountdelay and document it. It can be used to delay mounting root partition to give a chance to GEOM providers to show up. Now, when there is no needed provider, vfs_rootmount() function will look for it every second and if it can't be find in defined time, it'll ask for root device name (before this change it was done immediately). This will allow to boot from gmirror device in degraded mode. Index: sys/kern/vfs_mount.c =================================================================== RCS file: /private/FreeBSD/src/sys/kern/vfs_mount.c,v retrieving revision 1.138 diff -u -p -r1.138 vfs_mount.c --- sys/kern/vfs_mount.c 30 Jul 2004 22:08:52 -0000 1.138 +++ sys/kern/vfs_mount.c 27 Sep 2004 13:56:33 -0000 @@ -59,7 +59,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/kern/vfs_mount.c,v 1.138 2004/07/30 22:08:52 phk Exp $"); +__FBSDID("$FreeBSD: src/sys/kern/vfs_mount.c,v 1.142 2004/09/24 09:19:03 pjd Exp $"); #include #include @@ -111,6 +111,8 @@ static int vfs_donmount(struct thread *t static int usermount = 0; SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "Unprivileged users may mount and unmount file systems"); +static int mount_root_delay = 5; +TUNABLE_INT("vfs.root.mountdelay", &mount_root_delay); MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure"); @@ -1201,73 +1203,81 @@ void vfs_mountroot(void) { char *cp; - int error, i, asked = 0; + int asked, error, i, nrootdevs; + asked = 0; + error = EDOOFUS; + nrootdevs = sizeof(rootdevnames) / sizeof(rootdevnames[0]); + if (mount_root_delay <= 0) + mount_root_delay = 1; + for (; mount_root_delay > 0; mount_root_delay--) { + /* + * Wait for GEOM to settle down + */ + g_waitidle(); - /* - * Wait for GEOM to settle down - */ - g_waitidle(); + /* + * We are booted with instructions to prompt for the root filesystem. + */ + if (boothowto & RB_ASKNAME) { + if (!vfs_mountroot_ask()) + return; + asked = 1; + } - /* - * We are booted with instructions to prompt for the root filesystem. - */ - if (boothowto & RB_ASKNAME) { - if (!vfs_mountroot_ask()) - return; - asked = 1; - } + /* + * The root filesystem information is compiled in, and we are + * booted with instructions to use it. + */ + if (ctrootdevname != NULL && (boothowto & RB_DFLTROOT)) { + if ((error = vfs_mountroot_try(ctrootdevname)) == 0) + return; + ctrootdevname = NULL; + } - /* - * The root filesystem information is compiled in, and we are - * booted with instructions to use it. - */ - if (ctrootdevname != NULL && (boothowto & RB_DFLTROOT)) { - if (!vfs_mountroot_try(ctrootdevname)) - return; - ctrootdevname = NULL; - } + /* + * We've been given the generic "use CDROM as root" flag. This is + * necessary because one media may be used in many different + * devices, so we need to search for them. + */ + if (boothowto & RB_CDROM) { + for (i = 0; cdrom_rootdevnames[i] != NULL; i++) { + error = vfs_mountroot_try(cdrom_rootdevnames[i]); + if (error == 0) + return; + } + } - /* - * We've been given the generic "use CDROM as root" flag. This is - * necessary because one media may be used in many different - * devices, so we need to search for them. - */ - if (boothowto & RB_CDROM) { - for (i = 0; cdrom_rootdevnames[i] != NULL; i++) { - if (!vfs_mountroot_try(cdrom_rootdevnames[i])) + /* + * Try to use the value read by the loader from /etc/fstab, or + * supplied via some other means. This is the preferred + * mechanism. + */ + cp = getenv("vfs.root.mountfrom"); + if (cp != NULL) { + error = vfs_mountroot_try(cp); + freeenv(cp); + if (error == 0) return; } - } - - /* - * Try to use the value read by the loader from /etc/fstab, or - * supplied via some other means. This is the preferred - * mechanism. - */ - cp = getenv("vfs.root.mountfrom"); - if (cp != NULL) { - error = vfs_mountroot_try(cp); - freeenv(cp); - if (!error) - return; - } - /* - * Try values that may have been computed by code during boot - */ - if (!vfs_mountroot_try(rootdevnames[0])) - return; - if (!vfs_mountroot_try(rootdevnames[1])) - return; + /* + * Try values that may have been computed by code during boot + */ + for (i = 0; i < nrootdevs; i++) { + if ((error = vfs_mountroot_try(rootdevnames[i])) == 0) + return; + } - /* - * If we (still) have a compiled-in default, try it. - */ - if (ctrootdevname != NULL) - if (!vfs_mountroot_try(ctrootdevname)) + /* + * If we (still) have a compiled-in default, try it. + */ + if ((error = vfs_mountroot_try(ctrootdevname)) == 0) return; + tsleep(&mount_root_delay, PRIBIO, "mroot", hz); + } + printf("Root mount failed: %d.\n", error); /* * Everything so far has failed, prompt on the console if we haven't * already tried that. @@ -1289,7 +1299,6 @@ vfs_mountroot_try(const char *mountfrom) const char *devname; int error; char patt[32]; - int s; vfsname = NULL; path = NULL; @@ -1299,9 +1308,13 @@ vfs_mountroot_try(const char *mountfrom) if (mountfrom == NULL) return (error); /* don't complain */ - s = splcam(); /* Overkill, but annoying without it */ - printf("Mounting root from %s\n", mountfrom); - splx(s); + if (bootverbose) { + int s; + + s = splcam(); /* Overkill, but annoying without it */ + printf("Trying to mount root from %s\n", mountfrom); + splx(s); + } /* parse vfs name and path */ vfsname = malloc(MFSNAMELEN, M_MOUNT, M_WAITOK); @@ -1329,8 +1342,6 @@ vfs_mountroot_try(const char *mountfrom) diskdev = getdiskbyname(path); if (diskdev != NULL) rootdev = diskdev; - else - printf("setrootbyname failed\n"); } /* If the root device is a type "memory disk", mount RW */ @@ -1350,9 +1361,7 @@ done: if (error != 0) { if (mp != NULL) vfs_mount_destroy(mp, curthread); - printf("Root mount failed: %d\n", error); } else { - /* register with list of mounted filesystems */ mtx_lock(&mountlist_mtx); TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list); @@ -1362,6 +1371,8 @@ done: inittodr(mp->mnt_time); vfs_unbusy(mp, curthread); error = VFS_START(mp, 0, curthread); + if (error == 0) + printf("Mounted root from %s.\n", mountfrom); } return (error); } @@ -1373,6 +1384,7 @@ static int vfs_mountroot_ask(void) { char name[128]; + int error; for(;;) { printf("\nManual root filesystem specification:\n"); @@ -1393,8 +1405,10 @@ vfs_mountroot_ask(void) g_dev_print(); continue; } - if (!vfs_mountroot_try(name)) + if ((error = vfs_mountroot_try(name)) == 0) return (0); + else + printf("Root mount failed: %d\n", error); } } Index: sys/ufs/ffs/ffs_vfsops.c =================================================================== RCS file: /private/FreeBSD/src/sys/ufs/ffs/ffs_vfsops.c,v retrieving revision 1.240 diff -u -p -r1.240 ffs_vfsops.c --- sys/ufs/ffs/ffs_vfsops.c 30 Jul 2004 22:08:52 -0000 1.240 +++ sys/ufs/ffs/ffs_vfsops.c 27 Sep 2004 13:55:11 -0000 @@ -30,7 +30,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/ufs/ffs/ffs_vfsops.c,v 1.240 2004/07/30 22:08:52 phk Exp $"); +__FBSDID("$FreeBSD: src/sys/ufs/ffs/ffs_vfsops.c,v 1.241 2004/09/23 10:13:18 pjd Exp $"); #include "opt_mac.h" #include "opt_quota.h" @@ -161,11 +161,8 @@ ffs_omount(struct mount *mp, char *path, * Use NULL path to indicate we are mounting the root filesystem. */ if (path == NULL) { - if ((error = bdevvp(rootdev, &rootvp))) { - printf("ffs_mountroot: can't find rootvp\n"); + if ((error = bdevvp(rootdev, &rootvp)) != 0) return (error); - } - if ((error = ffs_mountfs(rootvp, mp, td)) != 0) return (error); return (0); Index: sys/boot/common/help.common =================================================================== RCS file: /private/FreeBSD/src/sys/boot/common/help.common,v retrieving revision 1.28.2.1 diff -u -p -r1.28.2.1 help.common --- sys/boot/common/help.common 26 Sep 2004 06:32:03 -0000 1.28.2.1 +++ sys/boot/common/help.common 27 Sep 2004 13:55:11 -0000 @@ -285,6 +285,13 @@ value is 1 (default), but this may cause problems with some peripherals. Set to 0 to disable. + set vfs.root.mountdelay= + + Delay root partition mount if there is no required provider. + + value is a maximum number of seconds to wait for provider to + show up (default is 5 seconds). + ################################################################################ # Tshow DShow the values of variables Index: sys/boot/forth/loader.conf =================================================================== RCS file: /private/FreeBSD/src/sys/boot/forth/loader.conf,v retrieving revision 1.85 diff -u -p -r1.85 loader.conf --- sys/boot/forth/loader.conf 6 Aug 2004 15:06:06 -0000 1.85 +++ sys/boot/forth/loader.conf 27 Sep 2004 13:55:11 -0000 @@ -6,7 +6,7 @@ # # All arguments must be in double quotes. # -# $FreeBSD: src/sys/boot/forth/loader.conf,v 1.85 2004/08/06 15:06:06 jmg Exp $ +# $FreeBSD: src/sys/boot/forth/loader.conf,v 1.86 2004/09/24 09:33:48 pjd Exp $ ############################################################## ### Basic configuration options ############################ @@ -99,6 +99,8 @@ module_path="/boot/modules" # Set the mo #net.inet.tcp.tcbhashsize="" # Set the value of TCBHASHSIZE #vfs.root.mountfrom="" # Specify root partition in a way the # kernel understands +#vfs.root.mountdelay="5" # Delay root partition mount if there is no + # required provider #vm.kmem_size="" # Sets the size of kernel memory (bytes) #debug.ktr.cpumask="0xf" # Bitmask of CPUs to enable KTR on #debug.ktr.mask="0x1200" # Bitmask of KTR events to enable