[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