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).
This commit is contained in:
Tobias Hunger 2014-10-09 21:37:17 +02:00 committed by Lennart Poettering
parent 82279e6966
commit 9f103625b1
2 changed files with 160 additions and 6 deletions

View File

@ -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>

View File

@ -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) {