[systemd-devel] [PATCH 1/2] fstab-generator: mount /usr in the initrd if specified on /proc/cmdline

Tom Gundersen teg at jklm.no
Fri Mar 1 09:15:36 PST 2013


This allows us to treat /usr exactly the same as /. Namely, its options
may be given on the kernel commandline rather than, say, being included in
the initramfs or being read from the rootfs.

The new options are: usr=, usrfstype=, usrwait=, usrflags=, which have
analogous semantics to their root counterparts. Moreover, the 'ro' and
'rw' options apply to root and usr both.

If someone has a desire to support separate /usr without an initramfs (and
witohut split-usr), they could easily add support for these options to the
kernel.

Cc: Harald Hoyer <harald.hoyer at gmail.com>
Cc: Dave Reisner <d at falconindy.com>
---
 src/fstab-generator/fstab-generator.c | 96 +++++++++++++++++++++++++----------
 1 file changed, 68 insertions(+), 28 deletions(-)

diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 5c34de1..a2ab585 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -438,10 +438,12 @@ finish:
 
 static int parse_new_root_from_proc_cmdline(void) {
         char *w, *state;
-        _cleanup_free_ char *what = NULL, *type = NULL, *opts = NULL, *line = NULL;
-        int r;
+        _cleanup_free_ char *line = NULL;
+        _cleanup_free_ char *root_what = NULL, *root_type = NULL, *root_opts = NULL;
+        _cleanup_free_ char *usr_what = NULL, *usr_type = NULL, *usr_opts = NULL;
+        bool root_wait = false, usr_wait = false;
+        int r = 0, k;
         size_t l;
-        bool wait = false;
 
         r = read_one_line_file("/proc/cmdline", &line);
         if (r < 0) {
@@ -449,13 +451,16 @@ static int parse_new_root_from_proc_cmdline(void) {
                 return 0;
         }
 
-        opts = strdup("ro");
-        type = strdup("auto");
-        if (!opts || !type)
+        root_opts = strdup("ro");
+        root_type = strdup("auto");
+        usr_opts = strdup("ro");
+        usr_type = strdup("auto");
+        if (!root_opts || !root_type || !usr_opts || !usr_type)
                 return log_oom();
 
-        /* root= and roofstype= may occur more than once, the last instance should take precedence.
-         * In the case of multiple rootflags= the arguments should be concatenated */
+	/* root=, usr=, roofstype=and usrfstype=  may occur more than once, the last
+         * instance should take precedence. In the case of multiple rootflags= or
+         * usrflags= the arguments should be concatenated */
         FOREACH_WORD_QUOTED(w, l, line, state) {
                 char *word, *tmp_word;
 
@@ -464,49 +469,84 @@ static int parse_new_root_from_proc_cmdline(void) {
                         return log_oom();
 
                 else if (startswith(word, "root=")) {
-                        free(what);
-                        what = fstab_node_to_udev_node(word+5);
-                        if (!what)
+                        free(root_what);
+                        root_what = fstab_node_to_udev_node(word+5);
+                        if (!root_what)
+                                return log_oom();
+
+                } else if (startswith(word, "usr=")) {
+                        free(usr_what);
+                        usr_what = fstab_node_to_udev_node(word+4);
+                        if (!usr_what)
                                 return log_oom();
 
                 } else if (startswith(word, "rootfstype=")) {
-                        free(type);
-                        type = strdup(word + 11);
-                        if (!type)
+                        free(root_type);
+                        root_type = strdup(word + 11);
+                        if (!root_type)
+                                return log_oom();
+
+                } else if (startswith(word, "usrfstype=")) {
+                        free(usr_type);
+                        usr_type = strdup(word + 10);
+                        if (!usr_type)
                                 return log_oom();
 
                 } else if (startswith(word, "rootflags=")) {
-                        tmp_word = opts;
-                        opts = strjoin(opts, ",", word + 10, NULL);
+                        tmp_word = root_opts;
+                        root_opts = strjoin(root_opts, ",", word + 10, NULL);
+                        free(tmp_word);
+                        if (!root_opts)
+                                return log_oom();
+
+                } else if (startswith(word, "usrflags=")) {
+                        tmp_word = usr_opts;
+                        usr_opts = strjoin(usr_opts, ",", word + 9, NULL);
                         free(tmp_word);
-                        if (!opts)
+                        if (!usr_opts)
                                 return log_oom();
 
                 } else if (streq(word, "ro") || streq(word, "rw")) {
-                        tmp_word = opts;
-                        opts = strjoin(opts, ",", word, NULL);
+                        tmp_word = root_opts;
+                        root_opts = strjoin(root_opts, ",", word, NULL);
+                        free(tmp_word);
+                        if (!root_opts)
+                                return log_oom();
+
+                        tmp_word = usr_opts;
+                        usr_opts = strjoin(usr_opts, ",", word, NULL);
                         free(tmp_word);
-                        if (!opts)
+                        if (!usr_opts)
                                 return log_oom();
 
                 } else if (streq(word, "rootwait"))
-                        wait = true;
+                        root_wait = true;
+
+		else if (streq(word, "usrwait"))
+                        usr_wait = true;
 
                 free(word);
         }
 
-        if (what) {
+        if (root_what) {
 
-                log_debug("Found entry what=%s where=/sysroot type=%s", what, type);
-                r = add_mount(what, "/sysroot", type, opts, 0, wait, false, false,
+                log_debug("Found entry what=%s where=/sysroot type=%s", root_what, root_type);
+                r = add_mount(root_what, "/sysroot", root_type, root_opts, 0, root_wait, false, false,
                               false, false, false, "/proc/cmdline");
-
-                if (r < 0)
-                        return r;
         } else
                 log_error("Could not find a root= entry on the kernel commandline.");
 
-        return 0;
+        if (usr_what) {
+
+                log_debug("Found entry what=%s where=/sysroot/usr type=%s", usr_what, usr_type);
+                k = add_mount(usr_what, "/sysroot/usr", usr_type, usr_opts, 0, usr_wait, false, false,
+                              false, false, false, "/proc/cmdline");
+
+                if (k < 0)
+                        r = k;
+        }
+
+        return r;
 }
 
 static int parse_proc_cmdline(void) {
-- 
1.8.1.4



More information about the systemd-devel mailing list