From be7d9ff730cb88d7c6a869dd5c47754c78ceaef2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 May 2015 01:24:28 +0200 Subject: [PATCH] core: introduce seperate reverse dependencies for Requires= and Requisite= This allows us to ensure that Requisite= dependencies never cause propagation between units, while Requires= dependencies might. http://lists.freedesktop.org/archives/systemd-devel/2015-May/031742.html --- src/core/dbus-unit.c | 2 ++ src/core/job.c | 57 +++++++++++++++++++----------------------- src/core/unit.c | 51 +++++++++++++++++++++---------------- src/shared/unit-name.c | 2 ++ src/shared/unit-name.h | 6 +++-- 5 files changed, 63 insertions(+), 55 deletions(-) diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index a4ece2adb5..6d80ea95fa 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -561,6 +561,8 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RequisiteOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OF]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OF_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), SD_BUS_VTABLE_PROPERTY_CONST), diff --git a/src/core/job.c b/src/core/job.c index 9ad1f735f0..198e3b6423 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -790,6 +790,24 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { NULL); } +static void job_fail_dependencies(Unit *u, UnitDependency d) { + Unit *other; + Iterator i; + + assert(u); + + SET_FOREACH(other, u->dependencies[d], i) { + Job *j = other->job; + + if (!j) + continue; + if (!IN_SET(j->type, JOB_START, JOB_VERIFY_ACTIVE)) + continue; + + job_finish_and_invalidate(j, JOB_DEPENDENCY, true); + } +} + int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) { Unit *u; Unit *other; @@ -831,37 +849,14 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) { /* Fail depending jobs on failure */ if (result != JOB_DONE && recursive) { - - if (t == JOB_START || - t == JOB_VERIFY_ACTIVE) { - - SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i) - if (other->job && - (other->job->type == JOB_START || - other->job->type == JOB_VERIFY_ACTIVE)) - job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true); - - SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i) - if (other->job && - (other->job->type == JOB_START || - other->job->type == JOB_VERIFY_ACTIVE)) - job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true); - - SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i) - if (other->job && - !other->job->override && - (other->job->type == JOB_START || - other->job->type == JOB_VERIFY_ACTIVE)) - job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true); - - } else if (t == JOB_STOP) { - - SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i) - if (other->job && - (other->job->type == JOB_START || - other->job->type == JOB_VERIFY_ACTIVE)) - job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true); - } + if (IN_SET(t, JOB_START, JOB_VERIFY_ACTIVE)) { + job_fail_dependencies(u, UNIT_REQUIRED_BY); + job_fail_dependencies(u, UNIT_REQUISITE_OF); + job_fail_dependencies(u, UNIT_BOUND_BY); + job_fail_dependencies(u, UNIT_REQUIRED_BY_OVERRIDABLE); + job_fail_dependencies(u, UNIT_REQUISITE_OF_OVERRIDABLE); + } else if (t == JOB_STOP) + job_fail_dependencies(u, UNIT_CONFLICTED_BY); } /* Trigger OnFailure dependencies that are not generated by diff --git a/src/core/unit.c b/src/core/unit.c index 1c1d9cf896..42c7566be4 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1092,6 +1092,8 @@ static int unit_add_target_dependencies(Unit *u) { static const UnitDependency deps[] = { UNIT_REQUIRED_BY, UNIT_REQUIRED_BY_OVERRIDABLE, + UNIT_REQUISITE_OF, + UNIT_REQUISITE_OF_OVERRIDABLE, UNIT_WANTED_BY, UNIT_BOUND_BY }; @@ -1589,8 +1591,20 @@ bool unit_can_reload(Unit *u) { } static void unit_check_unneeded(Unit *u) { - Iterator i; + + static const UnitDependency needed_dependencies[] = { + UNIT_REQUIRED_BY, + UNIT_REQUIRED_BY_OVERRIDABLE, + UNIT_REQUISITE, + UNIT_REQUISITE_OF_OVERRIDABLE, + UNIT_WANTED_BY, + UNIT_BOUND_BY, + }; + Unit *other; + Iterator i; + unsigned j; + int r; assert(u); @@ -1603,26 +1617,17 @@ static void unit_check_unneeded(Unit *u) { if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) return; - SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i) - if (unit_active_or_pending(other)) - return; - - SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i) - if (unit_active_or_pending(other)) - return; - - SET_FOREACH(other, u->dependencies[UNIT_WANTED_BY], i) - if (unit_active_or_pending(other)) - return; - - SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i) - if (unit_active_or_pending(other)) - return; + for (j = 0; j < ELEMENTSOF(needed_dependencies); j++) + SET_FOREACH(other, u->dependencies[j], i) + if (unit_active_or_pending(other)) + return; log_unit_info(u, "Unit not needed anymore. Stopping."); /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ - manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL); + r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %m"); } static void unit_check_binds_to(Unit *u) { @@ -2163,13 +2168,15 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen [UNIT_REQUIRES] = UNIT_REQUIRED_BY, [UNIT_REQUIRES_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE, [UNIT_WANTS] = UNIT_WANTED_BY, - [UNIT_REQUISITE] = UNIT_REQUIRED_BY, - [UNIT_REQUISITE_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE, + [UNIT_REQUISITE] = UNIT_REQUISITE_OF, + [UNIT_REQUISITE_OVERRIDABLE] = UNIT_REQUISITE_OF_OVERRIDABLE, [UNIT_BINDS_TO] = UNIT_BOUND_BY, [UNIT_PART_OF] = UNIT_CONSISTS_OF, - [UNIT_REQUIRED_BY] = _UNIT_DEPENDENCY_INVALID, - [UNIT_REQUIRED_BY_OVERRIDABLE] = _UNIT_DEPENDENCY_INVALID, - [UNIT_WANTED_BY] = _UNIT_DEPENDENCY_INVALID, + [UNIT_REQUIRED_BY] = UNIT_REQUIRES, + [UNIT_REQUIRED_BY_OVERRIDABLE] = UNIT_REQUIRES_OVERRIDABLE, + [UNIT_REQUISITE_OF] = UNIT_REQUISITE, + [UNIT_REQUISITE_OF_OVERRIDABLE] = UNIT_REQUISITE_OVERRIDABLE, + [UNIT_WANTED_BY] = UNIT_WANTS, [UNIT_BOUND_BY] = UNIT_BINDS_TO, [UNIT_CONSISTS_OF] = UNIT_PART_OF, [UNIT_CONFLICTS] = UNIT_CONFLICTED_BY, diff --git a/src/shared/unit-name.c b/src/shared/unit-name.c index b23e47a2e6..bf52463d81 100644 --- a/src/shared/unit-name.c +++ b/src/shared/unit-name.c @@ -812,6 +812,8 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = { [UNIT_PART_OF] = "PartOf", [UNIT_REQUIRED_BY] = "RequiredBy", [UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable", + [UNIT_REQUISITE_OF] = "RequisiteOf", + [UNIT_REQUISITE_OF_OVERRIDABLE] = "RequisiteOfOverridable", [UNIT_WANTED_BY] = "WantedBy", [UNIT_BOUND_BY] = "BoundBy", [UNIT_CONSISTS_OF] = "ConsistsOf", diff --git a/src/shared/unit-name.h b/src/shared/unit-name.h index c2f31e3f90..b2043d0870 100644 --- a/src/shared/unit-name.h +++ b/src/shared/unit-name.h @@ -71,8 +71,10 @@ enum UnitDependency { UNIT_PART_OF, /* 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_REQUIRED_BY, /* inverse of 'requires' is 'required_by' */ + UNIT_REQUIRED_BY_OVERRIDABLE, /* inverse of 'requires_overridable' is 'required_by_overridable' */ + UNIT_REQUISITE_OF, /* inverse of 'requisite' is 'requisite_of' */ + UNIT_REQUISITE_OF_OVERRIDABLE,/* inverse of 'requisite_overridable' is 'requisite_of_overridable' */ UNIT_WANTED_BY, /* inverse of 'wants' */ UNIT_BOUND_BY, /* inverse of 'binds_to' */ UNIT_CONSISTS_OF, /* inverse of 'part_of' */