<div>From 681971f9cca5b3db085f47750f27f3f8d51f5036 Mon Sep 17 00:00:00 2001</div><div>From: Tobias Hunger <tobias.hunger@digia.com></div><div>Date: Wed, 24 Sep 2014 21:57:00 +0200</div><div>Subject: [PATCH] fstab-generator: Honor usr=, usrfstype= and usrflags= on</div><div> kernel command line</div><div><br></div><div>This allows to configure boot loader entries for systems where the</div><div>root and usr filesystems are in different subvolumes (or even on</div><div>different drives).</div><div>---</div><div> man/systemd-fstab-generator.xml       | 76 ++++++++++++++++++++++++++++-</div><div> src/fstab-generator/fstab-generator.c | 90 +++++++++++++++++++++++++++++++++--</div><div> 2 files changed, 160 insertions(+), 6 deletions(-)</div><div><br></div><div>diff --git a/man/systemd-fstab-generator.xml b/man/systemd-fstab-generator.xml</div><div>index e3cf5d2..63a3db5 100644</div><div>--- a/man/systemd-fstab-generator.xml</div><div>+++ b/man/systemd-fstab-generator.xml</div><div>@@ -104,9 +104,83 @@</div><div>                                 (initrd) while</div><div>                                 <varname>fstab=</varname> is</div><div>                                 honored by both the main system and</div><div>-                                the initrd.  </para></listitem></div><div>+                                the initrd.</para></listitem></div><div>                         </varlistentry></div><div>+                        <varlistentry></div><div>+                                <term><varname>root=</varname></term></div><div>+</div><div>+                                <listitem><para>Takes the root filesystem to mount</div><div>+                                in the initrd.</div><div>+                                <varname>root=</varname> is</div><div>+                                honored by the initrd.</para></listitem></div><div>+                        </varlistentry></div><div>+                        <varlistentry></div><div>+                                <term><varname>rootfstype=</varname></term></div><div>+</div><div>+                                <listitem><para>Takes the root filesystem type that</div><div>+                                will be passed to the mount command.</div><div>+                                <varname>rootfstype=</varname> is</div><div>+                                honored by the initrd.</para></listitem></div><div>+                        </varlistentry></div><div>+                        <varlistentry></div><div>+                                <term><varname>rootflags=</varname></term></div><div>+</div><div>+                                <listitem><para>Takes the root filesystem mount options</div><div>+                                to use. <varname>rootflags=</varname> is</div><div>+                                honored by the initrd.</para></listitem></div><div>+                        </varlistentry></div><div>+                        <varlistentry></div><div>+                                <term><varname>usr=</varname></term></div><div>+</div><div>+                                <listitem><para>Takes the <filename>/usr</filename></div><div>+                                filesystem to be mounted by the initrd. If</div><div>+                                <varname>usrfstype=</varname> or</div><div>+                                <varname>usrflags=</varname> is set, then</div><div>+                                <varname>usr=</varname> will default to the value set in</div><div>+                                <varname>root=</varname>.</para></div><div>+</div><div>+                                <para>Otherwise this parameter defaults to the</div><div>+                                <filename>/usr</filename> entry</div><div>+                                found in <filename>/etc/fstab</filename> on the root</div><div>+                                filesystem.</para></div><div>+</div><div>+                                <para><varname>usr=</varname> is honored by the initrd.</div><div>+                                </para></listitem></div><div>+                        </varlistentry></div><div>+                        <varlistentry></div><div>+                                <term><varname>usrfstype=</varname></term></div><div>+</div><div>+                                <listitem><para>Takes the <filename>/usr</filename></div><div>+                                filesystem type that will be passed to the mount</div><div>+                                command. If <varname>usr=</varname> or</div><div>+                                <varname>usrflags=</varname> is set, then</div><div>+                                <varname>usrfstype=</varname> will default to the value set in</div><div>+                                <varname>rootfstype=</varname>.</para></div><div>+</div><div>+                                <para>Otherwise this value will be read from the</div><div>+                                <filename>/usr</filename> entry in</div><div>+                                <filename>/etc/fstab</filename> on the root filesystem.</para></div><div>+</div><div>+                                <para><varname>usrfstype=</varname> is</div><div>+                                honored by the initrd.</para></listitem></div><div>+                        </varlistentry></div><div>+                        <varlistentry></div><div>+                                <term><varname>usrflags=</varname></term></div><div>+</div><div>+                                <listitem><para>Takes the <filename>/usr</filename></div><div>+                                filesystem mount options to use. If</div><div>+                                <varname>usr=</varname> or</div><div>+                                <varname>usrfstype=</varname> is set, then</div><div>+                                <varname>usrflages=</varname> will default to the value set in</div><div>+                                <varname>rootflags=</varname>.</para></div><div> </div><div>+                                <para>Otherwise this value will be read from the</div><div>+                                <filename>/usr</filename> entry in</div><div>+                                <filename>/etc/fstab</filename> on the root filesystem.</para></div><div>+</div><div>+                                <para><varname>usrflags=</varname> is</div><div>+                                honored by the initrd.</para></listitem></div><div>+                        </varlistentry></div><div>                 </variablelist></div><div>         </refsect1></div><div> </div><div>diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c</div><div>index b75bbb7..b84256e 100644</div><div>--- a/src/fstab-generator/fstab-generator.c</div><div>+++ b/src/fstab-generator/fstab-generator.c</div><div>@@ -43,6 +43,9 @@ static char *arg_root_what = NULL;</div><div> static char *arg_root_fstype = NULL;</div><div> static char *arg_root_options = NULL;</div><div> static int arg_root_rw = -1;</div><div>+static char *arg_usr_what = NULL;</div><div>+static char *arg_usr_fstype = NULL;</div><div>+static char *arg_usr_options = NULL;</div><div> </div><div> </div><div> static int mount_find_pri(struct mntent *me, int *ret) {</div><div>@@ -494,12 +497,64 @@ static int add_root_mount(void) {</div><div>                          "/proc/cmdline");</div><div> }</div><div> </div><div>+static int add_usr_mount(void) {</div><div>+        _cleanup_free_ char *what = NULL;</div><div>+        const char *opts;</div><div>+</div><div>+        if (!arg_usr_what && !arg_usr_fstype && !arg_usr_options)</div><div>+                return 0;</div><div>+</div><div>+        if (arg_root_what && !arg_usr_what) {</div><div>+                arg_usr_what = strdup(arg_root_what);</div><div>+</div><div>+                if (!arg_usr_what)</div><div>+                        return log_oom();</div><div>+        }</div><div>+</div><div>+        if (arg_root_fstype && !arg_usr_fstype) {</div><div>+                arg_usr_fstype = strdup(arg_root_fstype);</div><div>+</div><div>+                if (!arg_usr_fstype)</div><div>+                        return log_oom();</div><div>+        }</div><div>+</div><div>+        if (arg_root_options && !arg_usr_options) {</div><div>+                arg_usr_options = strdup(arg_root_options);</div><div>+</div><div>+                if (!arg_usr_options)</div><div>+                        return log_oom();</div><div>+        }</div><div>+</div><div>+        if (!arg_usr_what || !arg_usr_options)</div><div>+                return 0;</div><div>+</div><div>+        what = fstab_node_to_udev_node(arg_usr_what);</div><div>+        if (!path_is_absolute(what)) {</div><div>+                log_debug("Skipping entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype));</div><div>+                return -1;</div><div>+        }</div><div>+</div><div>+        opts = arg_usr_options;</div><div>+</div><div>+        log_debug("Found entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype));</div><div>+        return add_mount(what,</div><div>+                         "/sysroot/usr",</div><div>+                         arg_usr_fstype,</div><div>+                         opts,</div><div>+                         1,</div><div>+                         false,</div><div>+                         false,</div><div>+                         false,</div><div>+                         SPECIAL_INITRD_ROOT_FS_TARGET,</div><div>+                         "/proc/cmdline");</div><div>+}</div><div>+</div><div> static int parse_proc_cmdline_item(const char *key, const char *value) {</div><div>         int r;</div><div> </div><div>-        /* root= and roofstype= may occur more than once, the last</div><div>-         * instance should take precedence.  In the case of multiple</div><div>-         * rootflags= the arguments should be concatenated */</div><div>+        /* root=, usr=, usrfstype= and roofstype= may occur more than once, the last</div><div>+         * instance should take precedence.  In the case of multiple rootflags=</div><div>+         * or usrflags= the arguments should be concatenated */</div><div> </div><div>         if (STR_IN_SET(key, "fstab", "rd.fstab") && value) {</div><div> </div><div>@@ -531,6 +586,28 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {</div><div>                 free(arg_root_options);</div><div>                 arg_root_options = o;</div><div> </div><div>+        } else if (streq(key, "usr") && value) {</div><div>+</div><div>+                if (free_and_strdup(&arg_usr_what, value) < 0)</div><div>+                        return log_oom();</div><div>+</div><div>+        } else if (streq(key, "usrfstype") && value) {</div><div>+</div><div>+                if (free_and_strdup(&arg_usr_fstype, value) < 0)</div><div>+                        return log_oom();</div><div>+</div><div>+        } else if (streq(key, "usrflags") && value) {</div><div>+                char *o;</div><div>+</div><div>+                o = arg_usr_options ?</div><div>+                        strjoin(arg_usr_options, ",", value, NULL) :</div><div>+                        strdup(value);</div><div>+                if (!o)</div><div>+                        return log_oom();</div><div>+</div><div>+                free(arg_usr_options);</div><div>+                arg_usr_options = o;</div><div>+</div><div>         } else if (streq(key, "rw") && !value)</div><div>                 arg_root_rw = true;</div><div>         else if (streq(key, "ro") && !value)</div><div>@@ -559,9 +636,12 @@ int main(int argc, char *argv[]) {</div><div>         if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)</div><div>                 return EXIT_FAILURE;</div><div> </div><div>-        /* Always honour root= in the kernel command line if we are in an initrd */</div><div>-        if (in_initrd())</div><div>+        /* Always honour root= and usr= in the kernel command line if we are in an initrd */</div><div>+        if (in_initrd()) {</div><div>                 r = add_root_mount();</div><div>+                if (r == 0)</div><div>+                        r = add_usr_mount();</div><div>+        }</div><div> </div><div>         /* Honour /etc/fstab only when that's enabled */</div><div>         if (arg_fstab_enabled) {</div><div>-- </div><div>2.0.1</div><div><br></div>