]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: allow fstab-style nodes in mount/swap What= 30853/head
authorMike Yuan <me@yhndnzj.com>
Tue, 9 Jan 2024 14:29:18 +0000 (22:29 +0800)
committerMike Yuan <me@yhndnzj.com>
Tue, 9 Jan 2024 18:07:18 +0000 (02:07 +0800)
Closes #28989

man/systemd.mount.xml
man/systemd.swap.xml
src/core/dbus-mount.c
src/core/load-fragment-gperf.gperf.in
src/core/load-fragment.c
src/core/load-fragment.h

index 85eb79426987d96211047e7c38b8620a251061d2..307acc4ce9e7936db450ce4feffd3071aee8306d 100644 (file)
 
       <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
index 8b35a9469a65da233b966e6ba1b9941d72950d28..2b3305ccdeb4af322034c487cfa25ae7d8e0deaa 100644 (file)
 
       <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
index 7dbbdd07f50870609fea6dd2dfb9c129fcd67149..2278c3ee2fa4c15f3e3da71e036f67455d1d27b2 100644 (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);
index ed19c846975319ec76f873bdd6c0289bce06a185..92d5fc4cc3ffc69f1f3f1b19e013cc4b68ea361b 100644 (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)
index 5bfb8a6d1e45b53bc261b88f05e2b8c898d07126..6fc6bb360980e59af70425a3cb0d873c3a9aa2fa 100644 (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;
index c001397ff2cedff1f2e2f7ca3bda6191c3fb67bd..9394347d683aabd1a70afeb28e28b00d2dae71c4 100644 (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);