Skip to contentSkip to conversation

Wait and retry mounting root device

PATCH In review Daniel Drake 2 participants 3 messages Jan 4, 2005 – Jan 5, 2005 VFS

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Wait and retry mounting root device

This is based a patch by William Park <[email protected]> included in 2.6.10-mm1, in order to fix booting from usb-storage devices which no longer make their partitions immediately available.

While William's patch fixed the situation where you boot from a "root=8:1" parameter (to correspond to /dev/sda1), it does not allow you to use "root=/dev/sda1" (which apparently worked in 2.6.9 and earlier), because the name-->dev_t discovery is done before the "retry" loop starts, and is not retried during the loop.

This patch, which replaces William's, solves the above problems.

init/do_mounts.c renamed from init/do_mounts.c.orig +45 -16
@@ -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>
@@ -136,10 +137,12 @@
 
 dev_t __init name_to_dev_t(char *name)
 {
-	char s[32];
+	char fullname[32], devname[32], absname[32];
 	char *p;
 	dev_t res = 0;
-	int part;
+	int part = 0;
+	int tryabs = 0;
+	int tryagain = 20;
 
 #ifdef CONFIG_SYSFS
 	int mkdir_err = sys_mkdir("/sys", 0700);
@@ -171,28 +174,54 @@
 
 	if (strlen(name) > 31)
 		goto fail;
-	strcpy(s, name);
-	for (p = s; *p; p++)
+
+	strcpy(absname, name);
+	for (p = absname; *p; p++)
 		if (*p == '/')
 			*p = '!';
-	res = try_name(s, 0);
+
+	strcpy(fullname, absname);
+
+	while (p > absname && isdigit(p[-1]))
+		p--;
+
+	if (p > absname && *p && *p != '0') {
+		part = simple_strtoul(p, NULL, 10);
+		*p = '\0';		
+	}
+
+	strcpy(devname, absname);
+
+	if (p >= absname + 2 && isdigit(p[-2]) && p[-1] == 'p') {
+		p[-1] = '\0';
+		tryabs = 1;
+	}
+
+retry:
+	res = try_name(fullname, 0);
 	if (res)
 		goto done;
 
-	while (p > s && isdigit(p[-1]))
-		p--;
-	if (p == s || !*p || *p == '0')
-		goto fail;
-	part = simple_strtoul(p, NULL, 10);
-	*p = '\0';
-	res = try_name(s, part);
+	if (!part)
+		goto next;
+	
+	res = try_name(devname, part);
 	if (res)
 		goto done;
 
-	if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
-		goto fail;
-	p[-1] = '\0';
-	res = try_name(s, part);
+	if (!tryabs)
+		goto next;
+
+	res = try_name(absname, part);
+	if (res)
+		goto done;
+
+next:
+	if (--tryagain) {
+		printk(KERN_WARNING "VFS: Root device '%s' not available, waiting %dsec\n", name, tryagain);
+		ssleep(1);
+		goto retry;
+	}
 done:
 #ifdef CONFIG_SYSFS
 	sys_umount("/sys", 0);
#1 lore raw
Quoted 11 lines · Daniel Drake

This is based a patch by William Park <[email protected]> included in 2.6.10-mm1, in order to fix booting from usb-storage devices which no longer make their partitions immediately available.

While William's patch fixed the situation where you boot from a "root=8:1" parameter (to correspond to /dev/sda1), it does not allow you to use "root=/dev/sda1" (which apparently worked in 2.6.9 and earlier), because the name-->dev_t discovery is done before the "retry" loop starts, and is not retried during the loop.

This patch, which replaces William's, solves the above problems.

It's funny... Your patch does the opposite. It works for

    root=/dev/sda1

from the kernel command line, but not from Lilo or 'root=8:1' on command line. :-)

Signature · 3 lines
William Park <[email protected]>
Open Geometry Consulting, Toronto, Canada
Linux solution for data processing. 
#2 lore raw

Hi William,

Quoted 4 lines · William Park

It's funny... Your patch does the opposite. It works for

    root=/dev/sda1

from the kernel command line, but not from Lilo or 'root=8:1' on command line. :-)

Ah, yes :/

I found a simpler way to do it (but I'm not sure if it is 'clean' enough). I've attached an incremental patch against your first patch. This works with root=8:1 and root=/dev/sda1 for me.

Andrew, how does this look? I've also attached the new full patch so that you can also see the context.

Thanks,
Daniel

Applies on top of William Park's wait/retry mounting root device patch. Allows usage of "root=/dev/sda1" style arguments, which was not possible in the first version.

init/do_mounts.c +4 -0
@@ -283,6 +283,10 @@
 
 	get_fs_names(fs_names);
 retry:
+	if (!ROOT_DEV) {
+		ROOT_DEV = name_to_dev_t(saved_root_name);
+		create_dev(name, ROOT_DEV, root_device_name);
+	}
 	for (p = fs_names; *p; p += strlen(p)+1) {
 		int err = do_mount_root(name, p, flags, root_mount_data);
 		switch (err) {

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.

From: William Park <[email protected]>

init/do_mounts.c +13 -3
@@ -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>
@@ -278,9 +279,14 @@
 	char *fs_names = __getname();
 	char *p;
 	char b[BDEVNAME_SIZE];
+	int tryagain = 20;
 
 	get_fs_names(fs_names);
 retry:
+	if (!ROOT_DEV) {
+		ROOT_DEV = name_to_dev_t(saved_root_name);
+		create_dev(name, ROOT_DEV, root_device_name);
+	}
 	for (p = fs_names; *p; p += strlen(p)+1) {
 		int err = do_mount_root(name, p, flags, root_mount_data);
 		switch (err) {
@@ -297,9 +303,13 @@
 		 * 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");
+		if (--tryagain) {
+		    printk (KERN_WARNING "VFS: Waiting %dsec for root device...\n", tryagain);
+		    ssleep (1);
+		    goto retry;
+		}
+		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);
 	}