summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--man/systemd.unit.xml42
-rw-r--r--src/dbus-unit.h6
-rw-r--r--src/load-fragment.c2
-rw-r--r--src/manager.c8
-rw-r--r--src/mount.c3
-rw-r--r--src/unit.c50
-rw-r--r--src/unit.h5
-rw-r--r--units/fsck@.service.in2
-rw-r--r--units/getty@.service.m42
-rw-r--r--units/serial-getty@.service.m42
11 files changed, 73 insertions, 51 deletions
diff --git a/TODO b/TODO
index a01f2a9953..0d6ac5fb26 100644
--- a/TODO
+++ b/TODO
@@ -70,7 +70,7 @@
* only add quotacheck deps to .mount units which mention grpquota/usrquota in the mount flags
-* Introduce weaker Conflicts.
+* Introduce weaker Conflicts. get rid of ignore_dependency_failure
External:
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 14da607a95..ff1b47f9fb 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -281,7 +281,6 @@
services.</para></listitem>
</varlistentry>
-
<varlistentry>
<term><varname>RequiresOverridable=</varname></term>
@@ -341,6 +340,23 @@
</varlistentry>
<varlistentry>
+ <term><varname>BindTo=</varname></term>
+
+ <listitem><para>Configures requirement
+ dependencies, very similar in style to
+ <varname>Requires=</varname>, however
+ in addition to this behaviour it also
+ declares that this unit is stopped
+ when any of the units listed suddenly
+ disappears. Units can suddenly,
+ unexpectedly disappear if a service
+ terminates on its own choice, a device
+ is unplugged or a mount point
+ unmounted with involvement of
+ systemd.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>Conflicts=</varname></term>
<listitem><para>Configures negative
@@ -441,28 +457,6 @@
</varlistentry>
<varlistentry>
- <term><varname>StopRetroactively=</varname></term>
-
- <listitem><para>Takes a boolean
- argument. If <option>true</option> and
- a unit this unit requires stops
- without this being requested by the
- user, this unit will be stopped as
- well. (e.g. if a service exits or
- crashes on its own behalf, units this
- flag is set for that require it will
- be stopped.) Note that normally if a
- unit stops without a user request,
- units depending on it will not be
- terminated. Only if the user requested
- shutdown of a unit, all units
- depending on that unit will be shut
- down as well and at the same
- time. Defaults to
- <option>false</option>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
<term><varname>StopWhenUnneeded=</varname></term>
<listitem><para>Takes a boolean
@@ -630,7 +624,7 @@
side matching. If multiple conditions
are specified the unit will be
executed iff at least one of them
- apply (i.e. a logical OR is
+ applies (i.e. a logical OR is
applied).</para></listitem>
</varlistentry>
</variablelist>
diff --git a/src/dbus-unit.h b/src/dbus-unit.h
index 4a4d23e173..d897ef8ca7 100644
--- a/src/dbus-unit.h
+++ b/src/dbus-unit.h
@@ -70,9 +70,11 @@
" <property name=\"Requisite\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"RequisiteOverridable\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"Wants\" type=\"as\" access=\"read\"/>\n" \
+ " <property name=\"BindTo\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"RequiredBy\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"RequiredByOverridable\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"WantedBy\" type=\"as\" access=\"read\"/>\n" \
+ " <property name=\"BoundBy\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"Conflicts\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"ConflictedBy\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"Before\" type=\"as\" access=\"read\"/>\n" \
@@ -92,7 +94,6 @@
" <property name=\"CanStop\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"CanIsolate\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"Job\" type=\"(uo)\" access=\"read\"/>\n" \
- " <property name=\"StopRetroactively\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"StopWhenUnneeded\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"RefuseManualStart\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"RefuseManualStop\" type=\"b\" access=\"read\"/>\n" \
@@ -112,9 +113,11 @@
{ "org.freedesktop.systemd1.Unit", "Requisite", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_REQUISITE] }, \
{ "org.freedesktop.systemd1.Unit", "RequisiteOverridable", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_REQUISITE_OVERRIDABLE] }, \
{ "org.freedesktop.systemd1.Unit", "Wants", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_WANTS] }, \
+ { "org.freedesktop.systemd1.Unit", "BindTo", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_BIND_TO] }, \
{ "org.freedesktop.systemd1.Unit", "RequiredBy", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_REQUIRED_BY] }, \
{ "org.freedesktop.systemd1.Unit", "RequiredByOverridable",bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_REQUIRED_BY_OVERRIDABLE] }, \
{ "org.freedesktop.systemd1.Unit", "WantedBy", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_WANTED_BY] }, \
+ { "org.freedesktop.systemd1.Unit", "BoundBy", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_BOUND_BY] }, \
{ "org.freedesktop.systemd1.Unit", "Conflicts", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_CONFLICTS] }, \
{ "org.freedesktop.systemd1.Unit", "ConflictedBy", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_CONFLICTED_BY] }, \
{ "org.freedesktop.systemd1.Unit", "Before", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_BEFORE] }, \
@@ -134,7 +137,6 @@
{ "org.freedesktop.systemd1.Unit", "CanReload", bus_unit_append_can_reload, "b", u }, \
{ "org.freedesktop.systemd1.Unit", "CanIsolate", bus_unit_append_can_isolate, "b", u }, \
{ "org.freedesktop.systemd1.Unit", "Job", bus_unit_append_job, "(uo)", u }, \
- { "org.freedesktop.systemd1.Unit", "StopRetroactively", bus_property_append_bool, "b", &u->meta.stop_retroactively }, \
{ "org.freedesktop.systemd1.Unit", "StopWhenUnneeded", bus_property_append_bool, "b", &u->meta.stop_when_unneeded }, \
{ "org.freedesktop.systemd1.Unit", "RefuseManualStart", bus_property_append_bool, "b", &u->meta.refuse_manual_start }, \
{ "org.freedesktop.systemd1.Unit", "RefuseManualStop", bus_property_append_bool, "b", &u->meta.refuse_manual_stop }, \
diff --git a/src/load-fragment.c b/src/load-fragment.c
index bc34451064..828b8d2a98 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -1765,11 +1765,11 @@ static int load_from_path(Unit *u, const char *path) {
{ "Requisite", config_parse_deps, UINT_TO_PTR(UNIT_REQUISITE), "Unit" },
{ "RequisiteOverridable", config_parse_deps, UINT_TO_PTR(UNIT_REQUISITE_OVERRIDABLE), "Unit" },
{ "Wants", config_parse_deps, UINT_TO_PTR(UNIT_WANTS), "Unit" },
+ { "BindTo", config_parse_deps, UINT_TO_PTR(UNIT_BIND_TO), "Unit" },
{ "Conflicts", config_parse_deps, UINT_TO_PTR(UNIT_CONFLICTS), "Unit" },
{ "Before", config_parse_deps, UINT_TO_PTR(UNIT_BEFORE), "Unit" },
{ "After", config_parse_deps, UINT_TO_PTR(UNIT_AFTER), "Unit" },
{ "OnFailure", config_parse_deps, UINT_TO_PTR(UNIT_ON_FAILURE), "Unit" },
- { "StopRetroactively", config_parse_bool, &u->meta.stop_retroactively, "Unit" },
{ "StopWhenUnneeded", config_parse_bool, &u->meta.stop_when_unneeded, "Unit" },
{ "RefuseManualStart", config_parse_bool, &u->meta.refuse_manual_start, "Unit" },
{ "RefuseManualStop", config_parse_bool, &u->meta.refuse_manual_stop, "Unit" },
diff --git a/src/manager.c b/src/manager.c
index 667be2fdcf..796d3cbebe 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -1446,6 +1446,10 @@ static int transaction_add_job_and_dependencies(
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, true, override, false, e, NULL)) < 0 && r != -EBADR)
goto fail;
+ SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_BIND_TO], i)
+ if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, true, override, false, e, NULL)) < 0 && r != -EBADR)
+ goto fail;
+
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, !override, override, false, e, NULL)) < 0 && r != -EBADR) {
log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r));
@@ -1487,6 +1491,10 @@ static int transaction_add_job_and_dependencies(
SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUIRED_BY], i)
if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, true, override, false, e, NULL)) < 0 && r != -EBADR)
goto fail;
+
+ SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_BOUND_BY], i)
+ if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, true, override, false, e, NULL)) < 0 && r != -EBADR)
+ goto fail;
}
/* JOB_VERIFY_STARTED, JOB_RELOAD require no dependency handling */
diff --git a/src/mount.c b/src/mount.c
index 0b67fbed5d..d62ce8f408 100644
--- a/src/mount.c
+++ b/src/mount.c
@@ -70,9 +70,6 @@ static void mount_init(Unit *u) {
* already trying to comply its last one. */
m->exec_context.same_pgrp = true;
- /* Make sure we unmount when the devices we require go away */
- m->meta.stop_retroactively = true;
-
m->timer_watch.type = WATCH_INVALID;
m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
diff --git a/src/unit.c b/src/unit.c
index f080e7bef3..fb5583bfb2 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -652,13 +652,11 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
if (u->meta.load_state == UNIT_LOADED) {
fprintf(f,
- "%s\tStopRetroactively: %s\n"
"%s\tStopWhenUnneeded: %s\n"
"%s\tRefuseManualStart: %s\n"
"%s\tRefuseManualStop: %s\n"
"%s\tDefaultDependencies: %s\n"
"%s\tIgnoreDependencyFailure: %s\n",
- prefix, yes_no(u->meta.stop_retroactively),
prefix, yes_no(u->meta.stop_when_unneeded),
prefix, yes_no(u->meta.refuse_manual_start),
prefix, yes_no(u->meta.refuse_manual_stop),
@@ -768,6 +766,10 @@ static int unit_add_default_dependencies(Unit *u) {
if ((r = unit_add_default_target_dependency(u, target)) < 0)
return r;
+ SET_FOREACH(target, u->meta.dependencies[UNIT_BOUND_BY], i)
+ if ((r = unit_add_default_target_dependency(u, target)) < 0)
+ return r;
+
return 0;
}
@@ -966,6 +968,10 @@ static void unit_check_unneeded(Unit *u) {
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
return;
+ SET_FOREACH(other, u->meta.dependencies[UNIT_BOUND_BY], i)
+ if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
+ return;
+
log_info("Service %s is not needed anymore. Stopping.", u->meta.id);
/* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
@@ -980,27 +986,36 @@ static void retroactively_start_dependencies(Unit *u) {
assert(UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)));
SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRES], i)
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ if (!set_get(u->meta.dependencies[UNIT_AFTER], other) &&
+ !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
+
+ SET_FOREACH(other, u->meta.dependencies[UNIT_BIND_TO], i)
+ if (!set_get(u->meta.dependencies[UNIT_AFTER], other) &&
+ !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ if (!set_get(u->meta.dependencies[UNIT_AFTER], other) &&
+ !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_START, other, JOB_FAIL, false, NULL, NULL);
SET_FOREACH(other, u->meta.dependencies[UNIT_REQUISITE], i)
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ if (!set_get(u->meta.dependencies[UNIT_AFTER], other) &&
+ !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
SET_FOREACH(other, u->meta.dependencies[UNIT_WANTS], i)
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ if (!set_get(u->meta.dependencies[UNIT_AFTER], other) &&
+ !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_START, other, JOB_FAIL, false, NULL, NULL);
SET_FOREACH(other, u->meta.dependencies[UNIT_CONFLICTS], i)
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
SET_FOREACH(other, u->meta.dependencies[UNIT_CONFLICTED_BY], i)
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
}
@@ -1011,10 +1026,9 @@ static void retroactively_stop_dependencies(Unit *u) {
assert(u);
assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)));
- /* Pull down units which need us recursively if enabled */
- SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRED_BY], i)
- if (other->meta.stop_retroactively &&
- !UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
+ /* Pull down units which are bound to us recursively if enabled */
+ SET_FOREACH(other, u->meta.dependencies[UNIT_BOUND_BY], i)
+ if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
/* Garbage collect services that might not be needed anymore, if enabled */
@@ -1033,6 +1047,9 @@ static void retroactively_stop_dependencies(Unit *u) {
SET_FOREACH(other, u->meta.dependencies[UNIT_REQUISITE_OVERRIDABLE], i)
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
unit_check_unneeded(other);
+ SET_FOREACH(other, u->meta.dependencies[UNIT_BIND_TO], i)
+ if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
+ unit_check_unneeded(other);
}
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
@@ -1397,9 +1414,11 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen
[UNIT_WANTS] = UNIT_WANTED_BY,
[UNIT_REQUISITE] = UNIT_REQUIRED_BY,
[UNIT_REQUISITE_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE,
+ [UNIT_BIND_TO] = UNIT_BOUND_BY,
[UNIT_REQUIRED_BY] = _UNIT_DEPENDENCY_INVALID,
[UNIT_REQUIRED_BY_OVERRIDABLE] = _UNIT_DEPENDENCY_INVALID,
[UNIT_WANTED_BY] = _UNIT_DEPENDENCY_INVALID,
+ [UNIT_BOUND_BY] = UNIT_BIND_TO,
[UNIT_CONFLICTS] = UNIT_CONFLICTED_BY,
[UNIT_CONFLICTED_BY] = UNIT_CONFLICTS,
[UNIT_BEFORE] = UNIT_AFTER,
@@ -1426,7 +1445,8 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen
(d == UNIT_REQUIRES ||
d == UNIT_REQUIRES_OVERRIDABLE ||
d == UNIT_REQUISITE ||
- d == UNIT_REQUISITE_OVERRIDABLE)) {
+ d == UNIT_REQUISITE_OVERRIDABLE ||
+ d == UNIT_BIND_TO)) {
return -EINVAL;
}
@@ -2129,7 +2149,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) {
if (r < 0)
return r;
- if ((r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, device, true)) < 0)
+ if ((r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_BIND_TO, device, true)) < 0)
return r;
if (wants)
@@ -2313,9 +2333,11 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
[UNIT_REQUISITE_OVERRIDABLE] = "RequisiteOverridable",
[UNIT_REQUIRED_BY] = "RequiredBy",
[UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable",
+ [UNIT_BIND_TO] = "BindTo",
[UNIT_WANTED_BY] = "WantedBy",
[UNIT_CONFLICTS] = "Conflicts",
[UNIT_CONFLICTED_BY] = "ConflictedBy",
+ [UNIT_BOUND_BY] = "BoundBy",
[UNIT_BEFORE] = "Before",
[UNIT_AFTER] = "After",
[UNIT_REFERENCES] = "References",
diff --git a/src/unit.h b/src/unit.h
index 8b6b58e53b..ff11511898 100644
--- a/src/unit.h
+++ b/src/unit.h
@@ -102,11 +102,13 @@ enum UnitDependency {
UNIT_REQUISITE,
UNIT_REQUISITE_OVERRIDABLE,
UNIT_WANTS,
+ UNIT_BIND_TO,
/* Inverse of the above */
UNIT_REQUIRED_BY, /* inverse of 'requires' and 'requisite' is 'required_by' */
UNIT_REQUIRED_BY_OVERRIDABLE, /* inverse of 'requires_overridable' and 'requisite_overridable' is 'soft_required_by' */
UNIT_WANTED_BY, /* inverse of 'wants' */
+ UNIT_BOUND_BY, /* inverse of 'bind_to' */
/* Negative dependencies */
UNIT_CONFLICTS, /* inverse of 'conflicts' is 'conflicted_by' */
@@ -191,9 +193,6 @@ struct Meta {
/* Error code when we didn't manage to load the unit (negative) */
int load_error;
- /* If some required dep goes down, pull down ourselves, too */
- bool stop_retroactively;
-
/* Garbage collect us we nobody wants or requires us anymore */
bool stop_when_unneeded;
diff --git a/units/fsck@.service.in b/units/fsck@.service.in
index 54caa3c965..38815414fa 100644
--- a/units/fsck@.service.in
+++ b/units/fsck@.service.in
@@ -8,7 +8,7 @@
[Unit]
Description=File System Check on %f
DefaultDependencies=no
-Requires=%i.device
+BindTo=%i.device
After=systemd-readahead-collect.service systemd-readahead-replay.service %i.device
Before=local-fs.target shutdown.target
diff --git a/units/getty@.service.m4 b/units/getty@.service.m4
index 98c6a88213..1edcad9f0e 100644
--- a/units/getty@.service.m4
+++ b/units/getty@.service.m4
@@ -14,7 +14,7 @@ m4_ifdef(`TARGET_ARCH', `m4_define(`GETTY', `/sbin/agetty -8 38400')')m4_dnl
m4_dnl
[Unit]
Description=Getty on %I
-Requires=dev-%i.device
+BindTo=dev-%i.device
After=dev-%i.device
m4_ifdef(`TARGET_FEDORA',
After=rc-local.service
diff --git a/units/serial-getty@.service.m4 b/units/serial-getty@.service.m4
index 9a70db0f21..da9bd1946b 100644
--- a/units/serial-getty@.service.m4
+++ b/units/serial-getty@.service.m4
@@ -7,7 +7,7 @@
[Unit]
Description=Serial Getty on %I
-Requires=dev-%i.device
+BindTo=dev-%i.device
After=dev-%i.device
m4_ifdef(`TARGET_FEDORA',
After=rc-local.service