[PATCH] Wait and retry mounting root device (revised)
From: Daniel Drake
Date: Mon Jan 17 2005 - 19:24:35 EST
Retry up to 20 times if mounting the root device fails. This fixes booting
from usb-storage devices, which no longer make their partitions immediately
available.
This should allow booting from root=/dev/sda1 and root=8:1 style parameters,
whilst not breaking booting from RAID or initrd :)
I have also cleaned up the mount_block_root() function a bit.
Based on an earlier patch from William Park <opengeometry@xxxxxxxx>
Replaces the existing waiting-10s-before-mounting-root-filesystem.patch patch
in 2.6.11-rc1-mm1
Signed-off-by: Daniel Drake <dsd@xxxxxxxxxx>
--- linux-2.6.10/init/do_mounts.c.orig 2005-01-16 19:18:57.000000000 +0000
+++ linux-2.6.10/init/do_mounts.c 2005-01-17 01:42:25.000000000 +0000
@@ -6,6 +6,7 @@
#include <linux/suspend.h>
#include <linux/root_dev.h>
#include <linux/security.h>
+#include <linux/delay.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_fs_sb.h>
@@ -261,6 +262,9 @@ static void __init get_fs_names(char *pa
static int __init do_mount_root(char *name, char *fs, int flags, void *data)
{
int err = sys_mount(name, "/root", fs, flags, data);
+ if (err == -EACCES && (flags | MS_RDONLY) == 0)
+ err = sys_mount(name, "/root", fs, flags | MS_RDONLY, data);
+
if (err)
return err;
@@ -273,38 +277,56 @@ static int __init do_mount_root(char *na
return 0;
}
+static int __init mount_root_try_all_fs(char *name, char *fs_names, int flags, void *data)
+{
+ char *p;
+ int err = -EFAULT;
+
+ for (p = fs_names; *p; p += strlen(p)+1) {
+ err = do_mount_root(name, p, flags, root_mount_data);
+ if (err != -EINVAL)
+ break;
+ }
+
+ return err;
+}
+
void __init mount_block_root(char *name, int flags)
{
char *fs_names = __getname();
- char *p;
char b[BDEVNAME_SIZE];
+ int tryagain = 20;
get_fs_names(fs_names);
-retry:
- for (p = fs_names; *p; p += strlen(p)+1) {
- int err = do_mount_root(name, p, flags, root_mount_data);
- switch (err) {
- case 0:
- goto out;
- case -EACCES:
- flags |= MS_RDONLY;
- goto retry;
- case -EINVAL:
- continue;
- }
- /*
- * Allow the user to distinguish between failed sys_open
- * and bad superblock on root device.
- */
- __bdevname(ROOT_DEV, b);
- printk("VFS: Cannot open root device \"%s\" or %s\n",
- root_device_name, b);
- printk("Please append a correct \"root=\" boot option\n");
- panic("VFS: Unable to mount root fs on %s", b);
+ while (--tryagain) {
+ int err = mount_root_try_all_fs(name, fs_names, flags, root_mount_data);
+ if (err == 0)
+ goto out;
+
+ /*
+ * The root device may not be ready yet, so we retry a number of times
+ */
+ printk(KERN_WARNING "VFS: Waiting %dsec for root device...\n",
+ tryagain);
+ ssleep(1);
+ if (!ROOT_DEV) {
+ ROOT_DEV = name_to_dev_t(saved_root_name);
+ create_dev(name, ROOT_DEV, root_device_name);
+ }
}
- panic("VFS: Unable to mount root fs on %s", __bdevname(ROOT_DEV, b));
-out:
+
+ /*
+ * Allow the user to distinguish between failed sys_open
+ * and bad superblock on root device.
+ */
+ __bdevname(ROOT_DEV, b);
+ printk(KERN_CRIT "VFS: Cannot open root device \"%s\" or %s\n",
+ root_device_name, b);
+ printk(KERN_CRIT "Please append a correct \"root=\" boot option\n");
+ panic("VFS: Unable to mount root fs on %s", b);
+
+ out:
putname(fs_names);
}