]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add WantsMountsFor=
authorLuca Boccassi <bluca@debian.org>
Sat, 25 Nov 2023 03:16:36 +0000 (03:16 +0000)
committerLuca Boccassi <bluca@debian.org>
Wed, 29 Nov 2023 11:04:59 +0000 (11:04 +0000)
This is the equivalent of RequiresMountsFor=, but adds Wants= instead
of Requires=. It will be useful for example for the autogenerated
systemd-cryptsetup units.

Fixes https://github.com/systemd/systemd/issues/11646

22 files changed:
man/org.freedesktop.systemd1.xml
man/systemd.mount.xml
man/systemd.unit.xml
src/core/automount.c
src/core/dbus-unit.c
src/core/load-fragment-gperf.gperf.in
src/core/load-fragment.c
src/core/load-fragment.h
src/core/manager.c
src/core/manager.h
src/core/mount.c
src/core/path.c
src/core/socket.c
src/core/swap.c
src/core/timer.c
src/core/unit-serialize.c
src/core/unit.c
src/core/unit.h
src/fstab-generator/fstab-generator.c
src/shared/bus-unit-util.c
test/fuzz/fuzz-unit-file/directives-all.service
test/test-path/basic.target

index 9d37e44d288462564cdc1eeab6e71ca9c046c600..014a5cc8833bba70da92104be6c4443bd12e1e5f 100644 (file)
@@ -1979,6 +1979,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly as RequiresMountsFor = ['...', ...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly as WantsMountsFor = ['...', ...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly as Documentation = ['...', ...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s Description = '...';
@@ -2135,6 +2137,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <!--property SliceOf is not documented!-->
 
+    <!--property WantsMountsFor is not documented!-->
+
     <!--property FreezerState is not documented!-->
 
     <!--property DropInPaths is not documented!-->
@@ -2295,6 +2299,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <variablelist class="dbus-property" generated="True" extra-ref="RequiresMountsFor"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="WantsMountsFor"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="Documentation"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="Description"/>
@@ -11829,6 +11835,7 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
       <varname>ActivationDetails</varname> were added in version 252.</para>
       <para><function>QueueSignal()</function> was added in version 254.</para>
       <para><varname>SurviveFinalKillSignal</varname> was added in version 255.</para>
+      <para><varname>WantsMountsFor</varname> was added in version 256.</para>
     </refsect2>
     <refsect2>
       <title>Service Unit Objects</title>
index c2e470e7dcbe6f26952a1ab7608d6e2859dccee2..790022193561691fcd623a2f574bf9a68afdf1e3 100644 (file)
       </varlistentry>
 
       <varlistentry>
+        <term><option>x-systemd.wants-mounts-for=</option></term>
         <term><option>x-systemd.requires-mounts-for=</option></term>
 
         <listitem><para>Configures a
-        <varname>RequiresMountsFor=</varname> dependency between the
-        created mount unit and other mount units. The argument must be
-        an absolute path. This option may be specified more than once.
-        See <varname>RequiresMountsFor=</varname> in
+        <varname>RequiresMountsFor=</varname> or <varname>WantsMountsFor=</varname>
+        dependency between the created mount unit and other mount units. The
+        argument must be an absolute path. This option may be specified more than
+        once. See <varname>RequiresMountsFor=</varname> or <varname>WantsMountsFor=</varname> in
         <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
         for details.</para>
 
index 301fe77ce9381d7977ec737d73a98026ea9a52bd..190d4c1d2f76ab1f5389c77daab633907469c49c 100644 (file)
         <xi:include href="version-info.xml" xpointer="v201"/></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>WantsMountsFor=</varname></term>
+
+        <listitem><para>Same as <varname>RequiresMountsFor=</varname>,
+        but adds dependencies of type <varname>Wants=</varname> instead
+        of <varname>Requires=</varname>.</para>
+
+        <xi:include href="version-info.xml" xpointer="v256"/></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>OnSuccessJobMode=</varname></term>
         <term><varname>OnFailureJobMode=</varname></term>
index 14bf7e6998fcded26f195e6280b7776eeaabb49c..4cbb3727e585c2b4b74437e1e74dc2d5badc8627 100644 (file)
@@ -126,7 +126,7 @@ static int automount_add_mount_dependencies(Automount *a) {
         if (r < 0)
                 return r;
 
-        return unit_require_mounts_for(UNIT(a), parent, UNIT_DEPENDENCY_IMPLICIT);
+        return unit_add_mounts_for(UNIT(a), parent, UNIT_DEPENDENCY_IMPLICIT, UNIT_MOUNT_REQUIRES);
 }
 
 static int automount_add_default_dependencies(Automount *a) {
index 1a037b70357caf4ac2c1f3780533c70cc2322541..48b7e10ea56cdf63ab06df32603bb72fed2b98d3 100644 (file)
@@ -177,7 +177,7 @@ static int property_get_dependencies(
         return sd_bus_message_close_container(reply);
 }
 
-static int property_get_requires_mounts_for(
+static int property_get_mounts_for(
                 sd_bus *bus,
                 const char *path,
                 const char *interface,
@@ -879,7 +879,8 @@ const sd_bus_vtable bus_unit_vtable[] = {
         SD_BUS_PROPERTY("StopPropagatedFrom", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("SliceOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("RequiresMountsFor", "as", property_get_requires_mounts_for, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("RequiresMountsFor", "as", property_get_mounts_for, offsetof(Unit, mounts_for[UNIT_MOUNT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("WantsMountsFor", "as", property_get_mounts_for, offsetof(Unit, mounts_for[UNIT_MOUNT_WANTS]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("AccessSELinuxContext", "s", NULL, offsetof(Unit, access_selinux_context), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -2308,7 +2309,7 @@ static int bus_unit_set_transient_property(
 
                 return 1;
 
-        } else if (streq(name, "RequiresMountsFor")) {
+        } else if (STR_IN_SET(name, "RequiresMountsFor", "WantsMountsFor")) {
                 _cleanup_strv_free_ char **l = NULL;
 
                 r = sd_bus_message_read_strv(message, &l);
@@ -2328,9 +2329,9 @@ static int bus_unit_set_transient_property(
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not normalized: %s", name, *p);
 
                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-                                r = unit_require_mounts_for(u, *p, UNIT_DEPENDENCY_FILE);
+                                r = unit_add_mounts_for(u, *p, UNIT_DEPENDENCY_FILE, unit_mount_dependency_type_from_string(name));
                                 if (r < 0)
-                                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to add required mount \"%s\": %m", *p);
+                                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to add requested mount \"%s\": %m", *p);
 
                                 unit_write_settingf(u, flags, name, "%s=%s", name, *p);
                         }
index 45f9ab03c4cce926f29c4f76597b1e3924edbed5..ed19c846975319ec76f873bdd6c0289bce06a185 100644 (file)
@@ -309,7 +309,8 @@ Unit.PartOf,                             config_parse_unit_deps,
 Unit.JoinsNamespaceOf,                   config_parse_unit_deps,                      UNIT_JOINS_NAMESPACE_OF,            0
 Unit.RequiresOverridable,                config_parse_obsolete_unit_deps,             UNIT_REQUIRES,                      0
 Unit.RequisiteOverridable,               config_parse_obsolete_unit_deps,             UNIT_REQUISITE,                     0
-Unit.RequiresMountsFor,                  config_parse_unit_requires_mounts_for,       0,                                  0
+Unit.RequiresMountsFor,                  config_parse_unit_mounts_for,                0,                                  0
+Unit.WantsMountsFor,                     config_parse_unit_mounts_for,                0,                                  0
 Unit.StopWhenUnneeded,                   config_parse_bool,                           0,                                  offsetof(Unit, stop_when_unneeded)
 Unit.RefuseManualStart,                  config_parse_bool,                           0,                                  offsetof(Unit, refuse_manual_start)
 Unit.RefuseManualStop,                   config_parse_bool,                           0,                                  offsetof(Unit, refuse_manual_stop)
index 6e3a22bc161927165fe55a17a6512bb72e65b9bb..d8ce2d62607f05a6648edd3e02282273ebeed6b2 100644 (file)
@@ -3152,7 +3152,7 @@ int config_parse_unit_condition_string(
         return 0;
 }
 
-int config_parse_unit_requires_mounts_for(
+int config_parse_unit_mounts_for(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -3171,6 +3171,7 @@ int config_parse_unit_requires_mounts_for(
         assert(lvalue);
         assert(rvalue);
         assert(data);
+        assert(STR_IN_SET(lvalue, "RequiresMountsFor", "WantsMountsFor"));
 
         for (const char *p = rvalue;;) {
                 _cleanup_free_ char *word = NULL, *resolved = NULL;
@@ -3196,9 +3197,9 @@ int config_parse_unit_requires_mounts_for(
                 if (r < 0)
                         continue;
 
-                r = unit_require_mounts_for(u, resolved, UNIT_DEPENDENCY_FILE);
+                r = unit_add_mounts_for(u, resolved, UNIT_DEPENDENCY_FILE, unit_mount_dependency_type_from_string(lvalue));
                 if (r < 0) {
-                        log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to add required mount '%s', ignoring: %m", resolved);
+                        log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to add requested mount '%s', ignoring: %m", resolved);
                         continue;
                 }
         }
@@ -6301,8 +6302,7 @@ void unit_dump_config_items(FILE *f) {
                 { config_parse_nsec,                  "NANOSECONDS" },
                 { config_parse_namespace_path_strv,   "PATH [...]" },
                 { config_parse_bind_paths,            "PATH[:PATH[:OPTIONS]] [...]" },
-                { config_parse_unit_requires_mounts_for,
-                                                      "PATH [...]" },
+                { config_parse_unit_mounts_for,       "PATH [...]" },
                 { config_parse_exec_mount_propagation_flag,
                                                       "MOUNTFLAG" },
                 { config_parse_unit_string_printf,    "STRING" },
index 69198050eadde6365affb6439a821ba4beb0602f..c001397ff2cedff1f2e2f7ca3bda6191c3fb67bd 100644 (file)
@@ -71,7 +71,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_string);
 CONFIG_PARSER_PROTOTYPE(config_parse_kill_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_notify_access);
 CONFIG_PARSER_PROTOTYPE(config_parse_emergency_action);
-CONFIG_PARSER_PROTOTYPE(config_parse_unit_requires_mounts_for);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_mounts_for);
 CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter);
 CONFIG_PARSER_PROTOTYPE(config_parse_syscall_archs);
 CONFIG_PARSER_PROTOTYPE(config_parse_syscall_errno);
index 37e4f70950083af0968f35f6ab52e90b148d6605..6ca643e6932b341239b688c7aa2800f13d7378c1 100644 (file)
@@ -1691,8 +1691,10 @@ Manager* manager_free(Manager *m) {
 
         unit_defaults_done(&m->defaults);
 
-        assert(hashmap_isempty(m->units_requiring_mounts_for));
-        hashmap_free(m->units_requiring_mounts_for);
+        FOREACH_ARRAY(map, m->units_needing_mounts_for, _UNIT_MOUNT_DEPENDENCY_TYPE_MAX) {
+                assert(hashmap_isempty(*map));
+                hashmap_free(*map);
+        }
 
         hashmap_free(m->uid_refs);
         hashmap_free(m->gid_refs);
@@ -4478,14 +4480,15 @@ void manager_status_printf(Manager *m, StatusType type, const char *status, cons
         va_end(ap);
 }
 
-Set* manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
+Set* manager_get_units_needing_mounts_for(Manager *m, const char *path, UnitMountDependencyType t) {
         assert(m);
         assert(path);
+        assert(t >= 0 && t < _UNIT_MOUNT_DEPENDENCY_TYPE_MAX);
 
         if (path_equal(path, "/"))
                 path = "";
 
-        return hashmap_get(m->units_requiring_mounts_for, path);
+        return hashmap_get(m->units_needing_mounts_for[t], path);
 }
 
 int manager_update_failed_units(Manager *m, Unit *u, bool failed) {
index d96eb7b995febec3f938f7681f1a2572e99bd2ae..d7bc6e761d40ce740a601fc2540ffc2f7c28886d 100644 (file)
@@ -137,6 +137,7 @@ typedef enum WatchdogType {
 #include "path-lookup.h"
 #include "show-status.h"
 #include "unit-name.h"
+#include "unit.h"
 
 typedef enum ManagerTestRunFlags {
         MANAGER_TEST_NORMAL                  = 0,       /* run normally */
@@ -438,10 +439,9 @@ struct Manager {
         /* This is true before and after switching root. */
         bool switching_root;
 
-        /* This maps all possible path prefixes to the units needing
-         * them. It's a hashmap with a path string as key and a Set as
-         * value where Unit objects are contained. */
-        Hashmap *units_requiring_mounts_for;
+        /* These map all possible path prefixes to the units needing them. They are hashmaps with a path
+         * string as key, and a Set as value where Unit objects are contained. */
+        Hashmap *units_needing_mounts_for[_UNIT_MOUNT_DEPENDENCY_TYPE_MAX];
 
         /* Used for processing polkit authorization responses */
         Hashmap *polkit_registry;
@@ -596,7 +596,7 @@ double manager_get_progress(Manager *m);
 
 void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) _printf_(4,5);
 
-Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path);
+Set* manager_get_units_needing_mounts_for(Manager *m, const char *path, UnitMountDependencyType t);
 
 ManagerState manager_state(Manager *m);
 
index ded322d33230535bb9f8deb79a0bd0093ea517b9..f364b2ab0b7ae5aafb291b144c1870cb9142b477 100644 (file)
@@ -281,8 +281,6 @@ static int update_parameters_proc_self_mountinfo(
 
 static int mount_add_mount_dependencies(Mount *m) {
         MountParameters *pm;
-        Unit *other;
-        Set *s;
         int r;
 
         assert(m);
@@ -296,7 +294,7 @@ static int mount_add_mount_dependencies(Mount *m) {
                 if (r < 0)
                         return r;
 
-                r = unit_require_mounts_for(UNIT(m), parent, UNIT_DEPENDENCY_IMPLICIT);
+                r = unit_add_mounts_for(UNIT(m), parent, UNIT_DEPENDENCY_IMPLICIT, UNIT_MOUNT_REQUIRES);
                 if (r < 0)
                         return r;
         }
@@ -308,30 +306,43 @@ static int mount_add_mount_dependencies(Mount *m) {
             path_is_absolute(pm->what) &&
             (mount_is_bind(pm) || mount_is_loop(pm) || !mount_is_network(pm))) {
 
-                r = unit_require_mounts_for(UNIT(m), pm->what, UNIT_DEPENDENCY_FILE);
+                r = unit_add_mounts_for(UNIT(m), pm->what, UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES);
                 if (r < 0)
                         return r;
         }
 
         /* Adds in dependencies to other units that use this path or paths further down in the hierarchy */
-        s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where);
-        SET_FOREACH(other, s) {
-
-                if (other->load_state != UNIT_LOADED)
-                        continue;
-
-                if (other == UNIT(m))
-                        continue;
-
-                r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true, UNIT_DEPENDENCY_PATH);
-                if (r < 0)
-                        return r;
-
-                if (UNIT(m)->fragment_path) {
-                        /* If we have fragment configuration, then make this dependency required */
-                        r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true, UNIT_DEPENDENCY_PATH);
+        for (UnitMountDependencyType t = 0; t < _UNIT_MOUNT_DEPENDENCY_TYPE_MAX; ++t) {
+                Unit *other;
+                Set *s = manager_get_units_needing_mounts_for(UNIT(m)->manager, m->where, t);
+
+                SET_FOREACH(other, s) {
+                        if (other->load_state != UNIT_LOADED)
+                                continue;
+
+                        if (other == UNIT(m))
+                                continue;
+
+                        r = unit_add_dependency(
+                                        other,
+                                        UNIT_AFTER,
+                                        UNIT(m),
+                                        /* add_reference= */ true,
+                                        UNIT_DEPENDENCY_PATH);
                         if (r < 0)
                                 return r;
+
+                        if (UNIT(m)->fragment_path) {
+                                /* If we have fragment configuration, then make this dependency required/wanted */
+                                r = unit_add_dependency(
+                                                other,
+                                                unit_mount_dependency_type_to_dependency_type(t),
+                                                UNIT(m),
+                                                /* add_reference= */ true,
+                                                UNIT_DEPENDENCY_PATH);
+                                if (r < 0)
+                                        return r;
+                        }
                 }
         }
 
index 44481a95d588dc2e1fd24e849870b4d72878949d..471d159d81de0e1a05af16eee033524d3abb2f57 100644 (file)
@@ -309,7 +309,7 @@ static int path_add_mount_dependencies(Path *p) {
         assert(p);
 
         LIST_FOREACH(spec, s, p->specs) {
-                r = unit_require_mounts_for(UNIT(p), s->path, UNIT_DEPENDENCY_FILE);
+                r = unit_add_mounts_for(UNIT(p), s->path, UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES);
                 if (r < 0)
                         return r;
         }
index 388be62318488ff4e3a32d06690ff73f1e782323..c42a94d046dccccdd1b944a67d10cd63dedfa212 100644 (file)
@@ -221,7 +221,7 @@ static int socket_add_mount_dependencies(Socket *s) {
                 if (!path)
                         continue;
 
-                r = unit_require_mounts_for(UNIT(s), path, UNIT_DEPENDENCY_FILE);
+                r = unit_add_mounts_for(UNIT(s), path, UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES);
                 if (r < 0)
                         return r;
         }
index 488b1719c53c4b5c16e5509001b0d68f96ec8264..ce35a5c4413adcad0c1dd06e78c765944b9e7be4 100644 (file)
@@ -321,7 +321,7 @@ static int swap_add_extras(Swap *s) {
                         return r;
         }
 
-        r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
+        r = unit_add_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT, UNIT_MOUNT_REQUIRES);
         if (r < 0)
                 return r;
 
index 3c41a250b03f99a5db21299044139b29bc3c9bc3..19358c766547918f9ab16be4e5f2f002f57445df 100644 (file)
@@ -141,7 +141,7 @@ static int timer_setup_persistent(Timer *t) {
 
         if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) {
 
-                r = unit_require_mounts_for(UNIT(t), "/var/lib/systemd/timers", UNIT_DEPENDENCY_FILE);
+                r = unit_add_mounts_for(UNIT(t), "/var/lib/systemd/timers", UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES);
                 if (r < 0)
                         return r;
 
index fe4221ca46be4b39090daa29d517615c81315e9b..40cdb615be4d960a58144dd99efa3127550766ee 100644 (file)
@@ -831,21 +831,26 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                 }
         }
 
-        if (!hashmap_isempty(u->requires_mounts_for)) {
-                UnitDependencyInfo di;
-                const char *path;
+        for (UnitMountDependencyType type = 0; type < _UNIT_MOUNT_DEPENDENCY_TYPE_MAX; type++)
+                if (!hashmap_isempty(u->mounts_for[type])) {
+                        UnitDependencyInfo di;
+                        const char *path;
 
-                HASHMAP_FOREACH_KEY(di.data, path, u->requires_mounts_for) {
-                        bool space = false;
+                        HASHMAP_FOREACH_KEY(di.data, path, u->mounts_for[type]) {
+                                bool space = false;
 
-                        fprintf(f, "%s\tRequiresMountsFor: %s (", prefix, path);
+                                fprintf(f,
+                                        "%s\t%s: %s (",
+                                        prefix,
+                                        unit_mount_dependency_type_to_string(type),
+                                        path);
 
-                        print_unit_dependency_mask(f, "origin", di.origin_mask, &space);
-                        print_unit_dependency_mask(f, "destination", di.destination_mask, &space);
+                                print_unit_dependency_mask(f, "origin", di.origin_mask, &space);
+                                print_unit_dependency_mask(f, "destination", di.destination_mask, &space);
 
-                        fputs(")\n", f);
+                                fputs(")\n", f);
+                        }
                 }
-        }
 
         if (u->load_state == UNIT_LOADED) {
 
index 41f3bdb226a4cc80adfecbc58be3d9daefbf5f17..5b852bcc13e96eaf01e0bbf28f1864cc3a25c61d 100644 (file)
@@ -689,38 +689,39 @@ static void unit_remove_transient(Unit *u) {
         }
 }
 
-static void unit_free_requires_mounts_for(Unit *u) {
+static void unit_free_mounts_for(Unit *u) {
         assert(u);
 
-        for (;;) {
-                _cleanup_free_ char *path = NULL;
+        for (UnitMountDependencyType t = 0; t < _UNIT_MOUNT_DEPENDENCY_TYPE_MAX; ++t) {
+                for (;;) {
+                        _cleanup_free_ char *path = NULL;
+
+                        path = hashmap_steal_first_key(u->mounts_for[t]);
+                        if (!path)
+                                break;
 
-                path = hashmap_steal_first_key(u->requires_mounts_for);
-                if (!path)
-                        break;
-                else {
                         char s[strlen(path) + 1];
 
                         PATH_FOREACH_PREFIX_MORE(s, path) {
                                 char *y;
                                 Set *x;
 
-                                x = hashmap_get2(u->manager->units_requiring_mounts_for, s, (void**) &y);
+                                x = hashmap_get2(u->manager->units_needing_mounts_for[t], s, (void**) &y);
                                 if (!x)
                                         continue;
 
                                 (void) set_remove(x, u);
 
                                 if (set_isempty(x)) {
-                                        (void) hashmap_remove(u->manager->units_requiring_mounts_for, y);
+                                        assert_se(hashmap_remove(u->manager->units_needing_mounts_for[t], y));
                                         free(y);
                                         set_free(x);
                                 }
                         }
                 }
-        }
 
-        u->requires_mounts_for = hashmap_free(u->requires_mounts_for);
+                u->mounts_for[t] = hashmap_free(u->mounts_for[t]);
+        }
 }
 
 static void unit_done(Unit *u) {
@@ -769,7 +770,7 @@ Unit* unit_free(Unit *u) {
         u->deserialized_refs = strv_free(u->deserialized_refs);
         u->pending_freezer_invocation = sd_bus_message_unref(u->pending_freezer_invocation);
 
-        unit_free_requires_mounts_for(u);
+        unit_free_mounts_for(u);
 
         SET_FOREACH(t, u->aliases)
                 hashmap_remove_value(u->manager->units, t, u);
@@ -1278,19 +1279,19 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
         /* Unlike unit_add_dependency() or friends, this always returns 0 on success. */
 
         if (c->working_directory && !c->working_directory_missing_ok) {
-                r = unit_require_mounts_for(u, c->working_directory, UNIT_DEPENDENCY_FILE);
+                r = unit_add_mounts_for(u, c->working_directory, UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES);
                 if (r < 0)
                         return r;
         }
 
         if (c->root_directory) {
-                r = unit_require_mounts_for(u, c->root_directory, UNIT_DEPENDENCY_FILE);
+                r = unit_add_mounts_for(u, c->root_directory, UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES);
                 if (r < 0)
                         return r;
         }
 
         if (c->root_image) {
-                r = unit_require_mounts_for(u, c->root_image, UNIT_DEPENDENCY_FILE);
+                r = unit_add_mounts_for(u, c->root_image, UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES);
                 if (r < 0)
                         return r;
         }
@@ -1306,7 +1307,7 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
                         if (!p)
                                 return -ENOMEM;
 
-                        r = unit_require_mounts_for(u, p, UNIT_DEPENDENCY_FILE);
+                        r = unit_add_mounts_for(u, p, UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES);
                         if (r < 0)
                                 return r;
                 }
@@ -1335,7 +1336,7 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
                 if (r < 0)
                         return r;
 
-                r = unit_require_mounts_for(u, "/var/tmp", UNIT_DEPENDENCY_FILE);
+                r = unit_add_mounts_for(u, "/var/tmp", UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES);
                 if (r < 0)
                         return r;
 
@@ -1536,51 +1537,72 @@ static int unit_add_slice_dependencies(Unit *u) {
 }
 
 static int unit_add_mount_dependencies(Unit *u) {
-        UnitDependencyInfo di;
-        const char *path;
         bool changed = false;
         int r;
 
         assert(u);
 
-        HASHMAP_FOREACH_KEY(di.data, path, u->requires_mounts_for) {
-                char prefix[strlen(path) + 1];
+        for (UnitMountDependencyType t = 0; t < _UNIT_MOUNT_DEPENDENCY_TYPE_MAX; ++t) {
+                UnitDependencyInfo di;
+                const char *path;
 
-                PATH_FOREACH_PREFIX_MORE(prefix, path) {
-                        _cleanup_free_ char *p = NULL;
-                        Unit *m;
+                HASHMAP_FOREACH_KEY(di.data, path, u->mounts_for[t]) {
 
-                        r = unit_name_from_path(prefix, ".mount", &p);
-                        if (r == -EINVAL)
-                                continue; /* If the path cannot be converted to a mount unit name, then it's
-                                           * not manageable as a unit by systemd, and hence we don't need a
-                                           * dependency on it. Let's thus silently ignore the issue. */
-                        if (r < 0)
-                                return r;
+                        char prefix[strlen(ASSERT_PTR(path)) + 1];
 
-                        m = manager_get_unit(u->manager, p);
-                        if (!m) {
-                                /* Make sure to load the mount unit if it exists. If so the dependencies on
-                                 * this unit will be added later during the loading of the mount unit. */
-                                (void) manager_load_unit_prepare(u->manager, p, NULL, NULL, &m);
-                                continue;
-                        }
-                        if (m == u)
-                                continue;
+                        PATH_FOREACH_PREFIX_MORE(prefix, path) {
+                                _cleanup_free_ char *p = NULL;
+                                Unit *m;
 
-                        if (m->load_state != UNIT_LOADED)
-                                continue;
+                                r = unit_name_from_path(prefix, ".mount", &p);
+                                if (r == -EINVAL)
+                                        continue; /* If the path cannot be converted to a mount unit name,
+                                                   * then it's not manageable as a unit by systemd, and
+                                                   * hence we don't need a dependency on it. Let's thus
+                                                   * silently ignore the issue. */
+                                if (r < 0)
+                                        return r;
 
-                        r = unit_add_dependency(u, UNIT_AFTER, m, true, di.origin_mask);
-                        if (r < 0)
-                                return r;
-                        changed = changed || r > 0;
+                                m = manager_get_unit(u->manager, p);
+                                if (!m) {
+                                        /* Make sure to load the mount unit if it exists. If so the
+                                         * dependencies on this unit will be added later during the loading
+                                         * of the mount unit. */
+                                        (void) manager_load_unit_prepare(
+                                                        u->manager,
+                                                        p,
+                                                        /* path= */NULL,
+                                                        /* e= */NULL,
+                                                        &m);
+                                        continue;
+                                }
+                                if (m == u)
+                                        continue;
+
+                                if (m->load_state != UNIT_LOADED)
+                                        continue;
 
-                        if (m->fragment_path) {
-                                r = unit_add_dependency(u, UNIT_REQUIRES, m, true, di.origin_mask);
+                                r = unit_add_dependency(
+                                                u,
+                                                UNIT_AFTER,
+                                                m,
+                                                /* add_reference= */ true,
+                                                di.origin_mask);
                                 if (r < 0)
                                         return r;
                                 changed = changed || r > 0;
+
+                                if (m->fragment_path) {
+                                        r = unit_add_dependency(
+                                                        u,
+                                                        unit_mount_dependency_type_to_dependency_type(t),
+                                                        m,
+                                                        /* add_reference= */ true,
+                                                        di.origin_mask);
+                                        if (r < 0)
+                                                return r;
+                                        changed = changed || r > 0;
+                                }
                         }
                 }
         }
@@ -4942,11 +4964,16 @@ int unit_kill_context(
         return wait_for_exit;
 }
 
-int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask) {
+int unit_add_mounts_for(Unit *u, const char *path, UnitDependencyMask mask, UnitMountDependencyType type) {
+        Hashmap **unit_map, **manager_map;
         int r;
 
         assert(u);
         assert(path);
+        assert(type >= 0 && type < _UNIT_MOUNT_DEPENDENCY_TYPE_MAX);
+
+        unit_map = &u->mounts_for[type];
+        manager_map = &u->manager->units_needing_mounts_for[type];
 
         /* Registers a unit for requiring a certain path and all its prefixes. We keep a hashtable of these
          * paths in the unit (from the path to the UnitDependencyInfo structure indicating how to the
@@ -4956,7 +4983,7 @@ int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask)
         if (!path_is_absolute(path))
                 return -EINVAL;
 
-        if (hashmap_contains(u->requires_mounts_for, path)) /* Exit quickly if the path is already covered. */
+        if (hashmap_contains(*unit_map, path)) /* Exit quickly if the path is already covered. */
                 return 0;
 
         /* Use the canonical form of the path as the stored key. We call path_is_normalized()
@@ -4975,7 +5002,7 @@ int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask)
                 .origin_mask = mask
         };
 
-        r = hashmap_ensure_put(&u->requires_mounts_for, &path_hash_ops, p, di.data);
+        r = hashmap_ensure_put(unit_map, &path_hash_ops, p, di.data);
         if (r < 0)
                 return r;
         assert(r > 0);
@@ -4985,11 +5012,11 @@ int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask)
         PATH_FOREACH_PREFIX_MORE(prefix, path) {
                 Set *x;
 
-                x = hashmap_get(u->manager->units_requiring_mounts_for, prefix);
+                x = hashmap_get(*manager_map, prefix);
                 if (!x) {
                         _cleanup_free_ char *q = NULL;
 
-                        r = hashmap_ensure_allocated(&u->manager->units_requiring_mounts_for, &path_hash_ops);
+                        r = hashmap_ensure_allocated(manager_map, &path_hash_ops);
                         if (r < 0)
                                 return r;
 
@@ -5001,7 +5028,7 @@ int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask)
                         if (!x)
                                 return -ENOMEM;
 
-                        r = hashmap_put(u->manager->units_requiring_mounts_for, q, x);
+                        r = hashmap_put(*manager_map, q, x);
                         if (r < 0) {
                                 set_free(x);
                                 return r;
@@ -6615,3 +6642,24 @@ int activation_details_append_pair(ActivationDetails *details, char ***strv) {
 }
 
 DEFINE_TRIVIAL_REF_UNREF_FUNC(ActivationDetails, activation_details, activation_details_free);
+
+static const char* const unit_mount_dependency_type_table[_UNIT_MOUNT_DEPENDENCY_TYPE_MAX] = {
+        [UNIT_MOUNT_WANTS]    = "WantsMountsFor",
+        [UNIT_MOUNT_REQUIRES] = "RequiresMountsFor",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(unit_mount_dependency_type, UnitMountDependencyType);
+
+UnitDependency unit_mount_dependency_type_to_dependency_type(UnitMountDependencyType t) {
+        switch (t) {
+
+        case UNIT_MOUNT_WANTS:
+                return UNIT_WANTS;
+
+        case UNIT_MOUNT_REQUIRES:
+                return UNIT_REQUIRES;
+
+        default:
+                assert_not_reached();
+        }
+}
index 60bc2e3d35007b498905bf9e866421a41600b878..fdaa3b8a8ef42cbecbf8ec77c8fbfbd2a27d2599 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include <errno.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <sys/socket.h>
@@ -8,6 +9,14 @@
 
 #include "sd-id128.h"
 
+/* Circular dependency with manager.h, needs to be defined before local includes */
+typedef enum UnitMountDependencyType {
+        UNIT_MOUNT_WANTS,
+        UNIT_MOUNT_REQUIRES,
+        _UNIT_MOUNT_DEPENDENCY_TYPE_MAX,
+        _UNIT_MOUNT_DEPENDENCY_TYPE_INVALID = -EINVAL,
+} UnitMountDependencyType;
+
 #include "bpf-program.h"
 #include "cgroup.h"
 #include "condition.h"
@@ -216,9 +225,9 @@ typedef struct Unit {
          * Hashmap(UnitDependency → Hashmap(Unit* → UnitDependencyInfo)) */
         Hashmap *dependencies;
 
-        /* Similar, for RequiresMountsFor= path dependencies. The key is the path, the value the
-         * UnitDependencyInfo type */
-        Hashmap *requires_mounts_for;
+        /* Similar, for RequiresMountsFor= and WantsMountsFor= path dependencies. The key is the path, the
+         * value the UnitDependencyInfo type */
+        Hashmap *mounts_for[_UNIT_MOUNT_DEPENDENCY_TYPE_MAX];
 
         char *description;
         char **documentation;
@@ -1001,7 +1010,7 @@ int unit_kill_context(Unit *u, KillContext *c, KillOperation k, PidRef *main_pid
 
 int unit_make_transient(Unit *u);
 
-int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask);
+int unit_add_mounts_for(Unit *u, const char *path, UnitDependencyMask mask, UnitMountDependencyType type);
 
 bool unit_type_supported(UnitType t);
 
@@ -1101,6 +1110,10 @@ int unit_arm_timer(Unit *u, sd_event_source **source, bool relative, usec_t usec
 
 int unit_compare_priority(Unit *a, Unit *b);
 
+UnitMountDependencyType unit_mount_dependency_type_from_string(const char *s) _const_;
+const char* unit_mount_dependency_type_to_string(UnitMountDependencyType t) _const_;
+UnitDependency unit_mount_dependency_type_to_dependency_type(UnitMountDependencyType t) _pure_;
+
 /* Macros which append UNIT= or USER_UNIT= to the message */
 
 #define log_unit_full_errno_zerook(unit, level, error, ...)             \
index 016f3baa7f849fe566763ba0e2c83c696601a647..fd1a78aed2f37847cae190d3603228a78c6730be 100644 (file)
@@ -416,15 +416,17 @@ static int write_before(FILE *f, const char *opts) {
                                 "x-systemd.before\0", "Before=%1$s\n");
 }
 
-static int write_requires_mounts_for(FILE *f, const char *opts) {
+static int write_mounts_for(const char *x_opt, const char *unit_setting, FILE *f, const char *opts) {
         _cleanup_strv_free_ char **paths = NULL, **paths_escaped = NULL;
         _cleanup_free_ char *res = NULL;
         int r;
 
+        assert(x_opt);
+        assert(unit_setting);
         assert(f);
         assert(opts);
 
-        r = fstab_filter_options(opts, "x-systemd.requires-mounts-for\0", NULL, NULL, &paths, NULL);
+        r = fstab_filter_options(opts, x_opt, NULL, NULL, &paths, NULL);
         if (r < 0)
                 return log_warning_errno(r, "Failed to parse options: %m");
         if (r == 0)
@@ -438,7 +440,7 @@ static int write_requires_mounts_for(FILE *f, const char *opts) {
         if (!res)
                 return log_oom();
 
-        fprintf(f, "RequiresMountsFor=%s\n", res);
+        fprintf(f, "%s=%s\n", unit_setting, res);
 
         return 0;
 }
@@ -458,7 +460,10 @@ static int write_extra_dependencies(FILE *f, const char *opts) {
                 r = write_before(f, opts);
                 if (r < 0)
                         return r;
-                r = write_requires_mounts_for(f, opts);
+                r = write_mounts_for("x-systemd.requires-mounts-for\0", "RequiresMountsFor", f, opts);
+                if (r < 0)
+                        return r;
+                r = write_mounts_for("x-systemd.wants-mounts-for\0", "WantsMountsFor", f, opts);
                 if (r < 0)
                         return r;
         }
index 4ee9706847d93231d1dc3fefd56b26d7f1d9a8fe..bba040112d2cba34c8e95a2ea2c444028b6248e7 100644 (file)
@@ -2643,6 +2643,7 @@ static int bus_append_unit_property(sd_bus_message *m, const char *field, const
         if (unit_dependency_from_string(field) >= 0 ||
             STR_IN_SET(field, "Documentation",
                               "RequiresMountsFor",
+                              "WantsMountsFor",
                               "Markers"))
                 return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE);
 
index 4bdc48a59b823ffbfe6d504d97a40eec5383f968..d5877f930cc232e58d7e1fbff726c1090a8c1ab7 100644 (file)
@@ -276,6 +276,7 @@ User=
 WakeSystem=
 WantedBy=
 Wants=
+WantsMountsFor=
 WatchdogSec=
 What=
 Where=
index 45f71aac981f9712dbb621731f41e69a08e43e66..c4b04c4da1244df23e8d6f1160d6c70d37ad3ab3 100644 (file)
@@ -12,4 +12,4 @@ After=sysinit.target sockets.target paths.target slices.target tmp.mount
 # require /var and /var/tmp, but only add a Wants= type dependency on /tmp, as
 # we support that unit being masked, and this should not be considered an error.
 RequiresMountsFor=/var /var/tmp
-Wants=tmp.mount
+WantsMountsFor=/tmp