@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 = '...';
<!--property SliceOf is not documented!-->
+ <!--property WantsMountsFor is not documented!-->
+
<!--property FreezerState is not documented!-->
<!--property DropInPaths is not documented!-->
<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"/>
<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>
</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>
<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>
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) {
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,
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),
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);
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);
}
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)
return 0;
}
-int config_parse_unit_requires_mounts_for(
+int config_parse_unit_mounts_for(
const char *unit,
const char *filename,
unsigned line,
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;
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;
}
}
{ 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" },
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);
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);
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) {
#include "path-lookup.h"
#include "show-status.h"
#include "unit-name.h"
+#include "unit.h"
typedef enum ManagerTestRunFlags {
MANAGER_TEST_NORMAL = 0, /* run normally */
/* 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;
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);
static int mount_add_mount_dependencies(Mount *m) {
MountParameters *pm;
- Unit *other;
- Set *s;
int r;
assert(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;
}
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;
+ }
}
}
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;
}
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;
}
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;
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;
}
}
- 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) {
}
}
-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) {
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);
/* 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;
}
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;
}
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;
}
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;
+ }
}
}
}
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
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()
.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);
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;
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;
}
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();
+ }
+}
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/socket.h>
#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"
* 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;
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);
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, ...) \
"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)
if (!res)
return log_oom();
- fprintf(f, "RequiresMountsFor=%s\n", res);
+ fprintf(f, "%s=%s\n", unit_setting, res);
return 0;
}
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;
}
if (unit_dependency_from_string(field) >= 0 ||
STR_IN_SET(field, "Documentation",
"RequiresMountsFor",
+ "WantsMountsFor",
"Markers"))
return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE);
WakeSystem=
WantedBy=
Wants=
+WantsMountsFor=
WatchdogSec=
What=
Where=
# 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