summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2010-10-28 23:18:47 +0200
committerLennart Poettering <lennart@poettering.net>2010-10-29 00:45:46 +0200
commitb81884e7466b8e8bc1261b1b1a722d11694b8c54 (patch)
treea974af7656baa8eadb0bb0fec0bfe44e4885bb8c
parent941a4041bdb9d91e9d5033005263efe029621e4f (diff)
unit: replace StopRetroactively= by BindTo= dependencies
The property StopRetroactively= needs to be per-dependency, not per-unit, in order to properly express dependencies between .mount units and its .device and fsck .service units. If the .device unit is unplugged the mount should go away, but if the fsck process terminates the .mount should stay.
-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