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