[klibc] [PATCH 16/16] Support for multiple devices specified on the root= cmdline.

Mike Waychison mikew at google.com
Mon Mar 1 23:46:50 PST 2010


In order to handle multiple root devices, such as root=/dev/hda1,/dev/sda1, we
introduce a new internal dev_t called Root_MULTI.  This device is returned if
name_to_dev sees a comma in the root line.

When handling multiple roots, we are careful to not support running linuxrc as
mixing multiple roots together with linuxrc doesn't make a lot of sense.

When we get to mounting and we have a Root_MULTI dev_t, we parse the comma
seperated tokens out of the cmdline argument and try each in succession,
stopping when we have a successful mount.

Signed-off-by: Mike Waychison <mikew at google.com>
---
 usr/kinit/do_mounts.c   |   26 ++++++++++++++++++++++++++
 usr/kinit/do_mounts.h   |    1 +
 usr/kinit/initrd.c      |    6 ++++++
 usr/kinit/name_to_dev.c |    3 +++
 4 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/usr/kinit/do_mounts.c b/usr/kinit/do_mounts.c
index 967e881..3f63870 100644
--- a/usr/kinit/do_mounts.c
+++ b/usr/kinit/do_mounts.c
@@ -139,6 +139,30 @@ mount_block_root(int argc, char *argv[], dev_t root_dev,
 	return 0;
 }
 
+static int
+mount_roots(int argc, char *argv[], const char *root_dev_name)
+{
+	char *roots = strdup(root_dev_name);
+	char *root;
+	const char *sep = ",";
+	char *saveptr;
+	int ret = -ESRCH;
+
+	root = strtok_r(roots, sep, &saveptr);
+	while (root) {
+		dev_t root_dev;
+
+		DEBUG(("kinit: trying to mount %s\n", root));
+		root_dev = name_to_dev_t(root);
+		ret = mount_root(argc, argv, root_dev, root);
+		if (!ret)
+			break;
+		root = strtok_r(NULL, sep, &saveptr);
+	}
+	free(roots);
+	return ret;
+}
+
 int
 mount_root(int argc, char *argv[], dev_t root_dev, const char *root_dev_name)
 {
@@ -217,5 +241,7 @@ int do_mounts(int argc, char *argv[])
 			root_dev = Root_RAM0;
 	}
 
+	if (root_dev == Root_MULTI)
+		return mount_roots(argc, argv, root_dev_name);
 	return mount_root(argc, argv, root_dev, root_dev_name);
 }
diff --git a/usr/kinit/do_mounts.h b/usr/kinit/do_mounts.h
index 2024e86..c309289 100644
--- a/usr/kinit/do_mounts.h
+++ b/usr/kinit/do_mounts.h
@@ -14,6 +14,7 @@
 /* These device numbers are only used internally */
 #define Root_NFS	__makedev(0,255)
 #define Root_MTD	__makedev(0,254)
+#define Root_MULTI	__makedev(0,253)
 
 int create_dev(const char *name, dev_t dev);
 
diff --git a/usr/kinit/initrd.c b/usr/kinit/initrd.c
index dc3af1a..86f8d91 100644
--- a/usr/kinit/initrd.c
+++ b/usr/kinit/initrd.c
@@ -182,6 +182,12 @@ int initrd_load(int argc, char *argv[], dev_t root_dev)
 
 	DEBUG(("kinit: initrd copied\n"));
 
+	if (root_dev == Root_MULTI) {
+		DEBUG(("kinit: skipping linuxrc: incompatible with multiple roots\n"));
+		/* Mounting initrd as ordinary root */
+		return 0;
+	}
+
 	if (root_dev != Root_RAM0) {
 		int err;
 		DEBUG(("kinit: running linuxrc\n"));
diff --git a/usr/kinit/name_to_dev.c b/usr/kinit/name_to_dev.c
index e5ad1cc..fbe3c27 100644
--- a/usr/kinit/name_to_dev.c
+++ b/usr/kinit/name_to_dev.c
@@ -107,6 +107,9 @@ static inline dev_t name_to_dev_t_real(const char *name)
 	char *cptr, *e1, *e2;
 	int major_num, minor_num;
 
+	/* Are we a multi root line? */
+	if (strchr(name, ','))
+		return Root_MULTI;
 
 	if (name[0] == '/') {
 		devname = name;



More information about the klibc mailing list