mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 02:03:37 +08:00
core: add WantsMountsFor=
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
This commit is contained in:
parent
5fae156103
commit
9e615fa3aa
@ -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>
|
||||
|
@ -255,13 +255,14 @@
|
||||
</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>
|
||||
|
||||
|
@ -919,6 +919,16 @@
|
||||
<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>
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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" },
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
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);
|
||||
|
||||
if (other->load_state != UNIT_LOADED)
|
||||
continue;
|
||||
SET_FOREACH(other, s) {
|
||||
if (other->load_state != UNIT_LOADED)
|
||||
continue;
|
||||
|
||||
if (other == UNIT(m))
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
||||
|
156
src/core/unit.c
156
src/core/unit.c
@ -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->fragment_path) {
|
||||
r = unit_add_dependency(u, UNIT_REQUIRES, m, true, di.origin_mask);
|
||||
if (m->load_state != UNIT_LOADED)
|
||||
continue;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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, ...) \
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -276,6 +276,7 @@ User=
|
||||
WakeSystem=
|
||||
WantedBy=
|
||||
Wants=
|
||||
WantsMountsFor=
|
||||
WatchdogSec=
|
||||
What=
|
||||
Where=
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user