mirror of
https://github.com/systemd/systemd.git
synced 2024-11-24 10:43:35 +08:00
fstab-generator: support defining mount units through kernel command line
Now, the following kernel command line options are supported: systemd.mount-extra=what:where:fstype:options systemd.swap-extra=what:options Closes #27260.
This commit is contained in:
parent
2646f18445
commit
55365b0a23
@ -239,6 +239,33 @@
|
||||
any swap devices configured in <filename>/etc/fstab</filename>.
|
||||
Defaults to enabled.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.mount-extra=<replaceable>WHAT</replaceable>:<replaceable>WHERE</replaceable>[:<replaceable>FSTYPE</replaceable>[:<replaceable>OPTIONS</replaceable>]]</varname></term>
|
||||
|
||||
<listitem>
|
||||
<para>Specifies the mount unit. Takes at least two and at most four fields separated with a colon
|
||||
(<literal>:</literal>). Each field is handled as the corresponding fstab field. This option can be
|
||||
specified multiple times.</para>
|
||||
<para>Example:
|
||||
<programlisting>
|
||||
systemd.mount-extra=/dev/sda1:/mount-point:ext4:rw,noatime</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.swap-extra=<replaceable>WHAT</replaceable>[:<replaceable>OPTIONS</replaceable>]</varname></term>
|
||||
|
||||
<listitem>
|
||||
<para>Specifies the swap unit. Takes the block device to be used as a swap device, and optionally
|
||||
takes mount options followed by a colon (<literal>:</literal>).</para>
|
||||
<para>Example:
|
||||
<programlisting>
|
||||
systemd.swap=/dev/sda2:x-systemd.makefs</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "mount-setup.h"
|
||||
#include "mount-util.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "nulstr-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "proc-cmdline.h"
|
||||
@ -45,6 +46,15 @@ typedef enum MountPointFlags {
|
||||
MOUNT_PCRFS = 1 << 6,
|
||||
} MountPointFlags;
|
||||
|
||||
typedef struct Mount {
|
||||
char *what;
|
||||
char *where;
|
||||
char *fstype;
|
||||
char *options;
|
||||
} Mount;
|
||||
|
||||
static void mount_array_free(Mount *mounts, size_t n);
|
||||
|
||||
static bool arg_sysroot_check = false;
|
||||
static const char *arg_dest = NULL;
|
||||
static const char *arg_dest_late = NULL;
|
||||
@ -61,6 +71,8 @@ static char *arg_usr_options = NULL;
|
||||
static char *arg_usr_hash = NULL;
|
||||
static VolatileMode arg_volatile_mode = _VOLATILE_MODE_INVALID;
|
||||
static bool arg_verity = true;
|
||||
static Mount *arg_mounts = NULL;
|
||||
static size_t arg_n_mounts = 0;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_root_what, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_root_fstype, freep);
|
||||
@ -70,6 +82,101 @@ STATIC_DESTRUCTOR_REGISTER(arg_usr_what, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_usr_fstype, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_usr_options, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_usr_hash, freep);
|
||||
STATIC_ARRAY_DESTRUCTOR_REGISTER(arg_mounts, arg_n_mounts, mount_array_free);
|
||||
|
||||
static void mount_done(Mount *m) {
|
||||
assert(m);
|
||||
|
||||
free(m->what);
|
||||
free(m->where);
|
||||
free(m->fstype);
|
||||
free(m->options);
|
||||
}
|
||||
|
||||
static void mount_array_free(Mount *mounts, size_t n) {
|
||||
FOREACH_ARRAY(m, mounts, n)
|
||||
mount_done(m);
|
||||
|
||||
free(mounts);
|
||||
}
|
||||
|
||||
static int mount_array_add_internal(char *in_what, char *in_where, const char *in_fstype, const char *in_options) {
|
||||
_cleanup_free_ char *what = NULL, *where = NULL, *fstype = NULL, *options = NULL;
|
||||
int r;
|
||||
|
||||
/* This takes what and where. */
|
||||
|
||||
what = ASSERT_PTR(in_what);
|
||||
where = in_where;
|
||||
|
||||
fstype = strdup(isempty(in_fstype) ? "auto" : in_fstype);
|
||||
if (!fstype)
|
||||
return -ENOMEM;
|
||||
|
||||
if (streq(fstype, "swap"))
|
||||
where = mfree(where);
|
||||
|
||||
if (!isempty(in_options)) {
|
||||
_cleanup_strv_free_ char **options_strv = NULL;
|
||||
|
||||
r = strv_split_full(&options_strv, in_options, ",", 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = strv_make_nulstr(options_strv, &options, NULL);
|
||||
} else
|
||||
r = strv_make_nulstr(STRV_MAKE("defaults"), &options, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!GREEDY_REALLOC(arg_mounts, arg_n_mounts + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
arg_mounts[arg_n_mounts++] = (Mount) {
|
||||
.what = TAKE_PTR(what),
|
||||
.where = TAKE_PTR(where),
|
||||
.fstype = TAKE_PTR(fstype),
|
||||
.options = TAKE_PTR(options),
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mount_array_add(const char *str) {
|
||||
_cleanup_free_ char *what = NULL, *where = NULL, *fstype = NULL, *options = NULL;
|
||||
int r;
|
||||
|
||||
assert(str);
|
||||
|
||||
r = extract_many_words(&str, ":", EXTRACT_CUNESCAPE | EXTRACT_DONT_COALESCE_SEPARATORS,
|
||||
&what, &where, &fstype, &options, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r < 2)
|
||||
return -EINVAL;
|
||||
if (!isempty(str))
|
||||
return -EINVAL;
|
||||
|
||||
return mount_array_add_internal(TAKE_PTR(what), TAKE_PTR(where), fstype, options);
|
||||
}
|
||||
|
||||
static int mount_array_add_swap(const char *str) {
|
||||
_cleanup_free_ char *what = NULL, *options = NULL;
|
||||
int r;
|
||||
|
||||
assert(str);
|
||||
|
||||
r = extract_many_words(&str, ":", EXTRACT_CUNESCAPE | EXTRACT_DONT_COALESCE_SEPARATORS,
|
||||
&what, &options, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r < 1)
|
||||
return -EINVAL;
|
||||
if (!isempty(str))
|
||||
return -EINVAL;
|
||||
|
||||
return mount_array_add_internal(TAKE_PTR(what), NULL, "swap", options);
|
||||
}
|
||||
|
||||
static int write_options(FILE *f, const char *options) {
|
||||
_cleanup_free_ char *o = NULL;
|
||||
@ -112,12 +219,12 @@ static int add_swap(
|
||||
assert(what);
|
||||
|
||||
if (access("/proc/swaps", F_OK) < 0) {
|
||||
log_info("Swap not supported, ignoring fstab swap entry for %s.", what);
|
||||
log_info("Swap not supported, ignoring swap entry for %s.", what);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (detect_container() > 0) {
|
||||
log_info("Running in a container, ignoring fstab swap entry for %s.", what);
|
||||
log_info("Running in a container, ignoring swap entry for %s.", what);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -698,7 +805,8 @@ static int parse_fstab_one(
|
||||
const char *fstype,
|
||||
const char *options,
|
||||
int passno,
|
||||
bool initrd) {
|
||||
bool initrd,
|
||||
bool use_swap_enabled) {
|
||||
|
||||
_cleanup_free_ char *what = NULL, *where = NULL;
|
||||
MountPointFlags flags;
|
||||
@ -713,7 +821,7 @@ static int parse_fstab_one(
|
||||
return 0;
|
||||
|
||||
is_swap = streq_ptr(fstype, "swap");
|
||||
if (is_swap && !arg_swap_enabled) {
|
||||
if (is_swap && use_swap_enabled && !arg_swap_enabled) {
|
||||
log_info("Swap unit generation disabled on kernel command line, ignoring swap entry for %s.", what);
|
||||
return 0;
|
||||
}
|
||||
@ -841,7 +949,9 @@ static int parse_fstab(bool initrd) {
|
||||
}
|
||||
|
||||
while ((me = getmntent(f))) {
|
||||
r = parse_fstab_one(fstab, me->mnt_fsname, me->mnt_dir, me->mnt_type, me->mnt_opts, me->mnt_passno, initrd);
|
||||
r = parse_fstab_one(fstab,
|
||||
me->mnt_fsname, me->mnt_dir, me->mnt_type, me->mnt_opts, me->mnt_passno,
|
||||
initrd, /* use_swap_enabled = */ true);
|
||||
if (r < 0 && ret >= 0)
|
||||
ret = r;
|
||||
if (arg_sysroot_check && r > 0)
|
||||
@ -1149,6 +1259,28 @@ static int add_volatile_var(void) {
|
||||
SPECIAL_LOCAL_FS_TARGET);
|
||||
}
|
||||
|
||||
static int add_mounts_from_cmdline(void) {
|
||||
int r, ret = 0;
|
||||
|
||||
/* Handle each entries found in cmdline as a fstab entry. */
|
||||
|
||||
FOREACH_ARRAY(m, arg_mounts, arg_n_mounts) {
|
||||
r = parse_fstab_one(
|
||||
"/proc/cmdline",
|
||||
m->what,
|
||||
m->where,
|
||||
m->fstype,
|
||||
m->options,
|
||||
/* passno = */ 0,
|
||||
/* initrd = */ false,
|
||||
/* use_swap_enabled = */ false);
|
||||
if (r < 0 && ret >= 0)
|
||||
ret = r;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
|
||||
int r;
|
||||
|
||||
@ -1253,6 +1385,24 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
||||
log_warning("Failed to parse systemd.verity= kernel command line switch %s. Ignoring.", value);
|
||||
else
|
||||
arg_verity = r;
|
||||
|
||||
} else if (streq(key, "systemd.mount-extra")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = mount_array_add(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse systemd.mount-extra= option, ignoring: %s", value);
|
||||
|
||||
} else if (streq(key, "systemd.swap-extra")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = mount_array_add_swap(value);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse systemd.swap-extra= option, ignoring: %s", value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1349,6 +1499,10 @@ static int run_generator(void) {
|
||||
ret = r;
|
||||
}
|
||||
|
||||
r = add_mounts_from_cmdline();
|
||||
if (r < 0 && ret >= 0)
|
||||
ret = r;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user