1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-03 05:18:09 +03:00

core: allow fstab-style nodes in mount/swap What=

Closes #28989
This commit is contained in:
Mike Yuan 2024-01-09 22:29:18 +08:00
parent e195a5c1e9
commit 435e1098ee
No known key found for this signature in database
GPG Key ID: 417471C0A40F58B3
6 changed files with 77 additions and 7 deletions

View File

@ -516,8 +516,8 @@
<varlistentry>
<term><varname>What=</varname></term>
<listitem><para>Takes an absolute path of a device node, file or other resource to mount. See
<citerefentry
<listitem><para>Takes an absolute path or a fstab-style identifier of a device node, file or
other resource to mount. See <citerefentry
project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
details. If this refers to a device node, a dependency on the respective device unit is automatically
created. (See

View File

@ -191,7 +191,8 @@
<varlistentry>
<term><varname>What=</varname></term>
<listitem><para>Takes an absolute path of a device node or file to use for paging. See <citerefentry
<listitem><para>Takes an absolute path or a fstab-style identifier of a device node or file to use
for paging. See <citerefentry
project='man-pages'><refentrytitle>swapon</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
details. If this refers to a device node, a dependency on the respective device unit is automatically
created. (See

View File

@ -6,6 +6,7 @@
#include "dbus-kill.h"
#include "dbus-mount.h"
#include "dbus-util.h"
#include "fstab-util.h"
#include "mount.h"
#include "string-util.h"
#include "unit.h"
@ -88,6 +89,7 @@ static int bus_mount_set_transient_property(
sd_bus_error *error) {
Unit *u = UNIT(m);
int r;
assert(m);
assert(name);
@ -98,8 +100,31 @@ static int bus_mount_set_transient_property(
if (streq(name, "Where"))
return bus_set_transient_path(u, name, &m->where, message, flags, error);
if (streq(name, "What"))
return bus_set_transient_string(u, name, &m->parameters_fragment.what, message, flags, error);
if (streq(name, "What")) {
_cleanup_free_ char *path = NULL;
const char *v;
r = sd_bus_message_read(message, "s", &v);
if (r < 0)
return r;
if (!isempty(v)) {
path = fstab_node_to_udev_node(v);
if (!path)
return -ENOMEM;
/* path_is_valid is not used - see the comment for config_parse_mount_node */
if (strlen(path) >= PATH_MAX)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Resolved What=%s too long", path);
}
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
free_and_replace(m->parameters_fragment.what, path);
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "What=%s", strempty(m->parameters_fragment.what));
}
return 1;
}
if (streq(name, "Options"))
return bus_set_transient_string(u, name, &m->parameters_fragment.options, message, flags, error);

View File

@ -531,7 +531,7 @@ Socket.SELinuxContextFromNet, config_parse_warn_compat,
{{ EXEC_CONTEXT_CONFIG_ITEMS('Socket') }}
{{ CGROUP_CONTEXT_CONFIG_ITEMS('Socket') }}
{{ KILL_CONTEXT_CONFIG_ITEMS('Socket') }}
Mount.What, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.what)
Mount.What, config_parse_mount_node, 0, offsetof(Mount, parameters_fragment.what)
Mount.Where, config_parse_unit_path_printf, 0, offsetof(Mount, where)
Mount.Options, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.options)
Mount.Type, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.fstype)
@ -548,7 +548,7 @@ Automount.Where, config_parse_unit_path_printf,
Automount.ExtraOptions, config_parse_unit_string_printf, 0, offsetof(Automount, extra_options)
Automount.DirectoryMode, config_parse_mode, 0, offsetof(Automount, directory_mode)
Automount.TimeoutIdleSec, config_parse_sec_fix_0, 0, offsetof(Automount, timeout_idle_usec)
Swap.What, config_parse_unit_path_printf, 0, offsetof(Swap, parameters_fragment.what)
Swap.What, config_parse_mount_node, 0, offsetof(Swap, parameters_fragment.what)
Swap.Priority, config_parse_swap_priority, 0, 0
Swap.Options, config_parse_unit_string_printf, 0, offsetof(Swap, parameters_fragment.options)
Swap.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Swap, timeout_usec)

View File

@ -38,6 +38,7 @@
#include "fileio.h"
#include "firewall-util.h"
#include "fs-util.h"
#include "fstab-util.h"
#include "hexdecoct.h"
#include "iovec-util.h"
#include "ioprio-util.h"
@ -6113,6 +6114,47 @@ int config_parse_restrict_network_interfaces(
return 0;
}
int config_parse_mount_node(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
const Unit *u = ASSERT_PTR(userdata);
_cleanup_free_ char *resolved = NULL, *path = NULL;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
r = unit_full_printf(u, rvalue, &resolved);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
path = fstab_node_to_udev_node(resolved);
if (!path)
return log_oom();
/* The source passed is not necessarily something we understand, and we pass it as-is to mount/swapon,
* so path_is_valid is not used. But let's check for basic sanety, i.e. if the source is longer than
* PATH_MAX, you're likely doing something wrong. */
if (strlen(path) >= PATH_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Resolved mount path '%s' too long, ignoring.", path);
return 0;
}
return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, path, data, userdata);
}
static int merge_by_names(Unit *u, Set *names, const char *id) {
char *k;
int r;
@ -6365,6 +6407,7 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_job_mode_isolate, "BOOLEAN" },
{ config_parse_personality, "PERSONALITY" },
{ config_parse_log_filter_patterns, "REGEX" },
{ config_parse_mount_node, "NODE" },
};
const char *prev = NULL;

View File

@ -159,6 +159,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_log_filter_patterns);
CONFIG_PARSER_PROTOTYPE(config_parse_open_file);
CONFIG_PARSER_PROTOTYPE(config_parse_memory_pressure_watch);
CONFIG_PARSER_PROTOTYPE(config_parse_cgroup_nft_set);
CONFIG_PARSER_PROTOTYPE(config_parse_mount_node);
/* gperf prototypes */
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);