From 5de9682cd647f07f043254fde70e62e1aa837476 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2010 00:58:47 +0200 Subject: [PATCH] unit: introduce OnFailure dependencies to activate units on failure of other units, as a way to implement an automatic rescue shell --- src/dbus-unit.h | 2 ++ src/unit.c | 34 +++++++++++++++++++++++----------- src/unit.h | 3 +++ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/dbus-unit.h b/src/dbus-unit.h index d4af5a8b2..e93d65892 100644 --- a/src/dbus-unit.h +++ b/src/dbus-unit.h @@ -70,6 +70,7 @@ " \n" \ " \n" \ " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ @@ -105,6 +106,7 @@ { "org.freedesktop.systemd1.Unit", "Conflicts", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_CONFLICTS] }, \ { "org.freedesktop.systemd1.Unit", "Before", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_BEFORE] }, \ { "org.freedesktop.systemd1.Unit", "After", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_AFTER] }, \ + { "org.freedesktop.systemd1.Unit", "OnFailure", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_ON_FAILURE] }, \ { "org.freedesktop.systemd1.Unit", "Description", bus_unit_append_description, "s", u }, \ { "org.freedesktop.systemd1.Unit", "LoadState", bus_unit_append_load_state, "s", &u->meta.load_state }, \ { "org.freedesktop.systemd1.Unit", "ActiveState", bus_unit_append_active_state, "s", u }, \ diff --git a/src/unit.c b/src/unit.c index e46182ada..44dc81163 100644 --- a/src/unit.c +++ b/src/unit.c @@ -987,9 +987,6 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) { else if (UNIT_IS_ACTIVE_OR_RELOADING(os) && !UNIT_IS_ACTIVE_OR_RELOADING(ns)) u->meta.active_exit_timestamp = ts; - if (ns != os && ns == UNIT_MAINTENANCE) - log_notice("Unit %s entered maintenance state.", u->meta.id); - if (UNIT_IS_INACTIVE_OR_MAINTENANCE(ns)) cgroup_bonding_trim_list(u->meta.cgroup_bondings, true); @@ -1072,6 +1069,16 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) { retroactively_stop_dependencies(u); } + if (ns != os && ns == UNIT_MAINTENANCE) { + Iterator i; + Unit *other; + + SET_FOREACH(other, u->meta.dependencies[UNIT_ON_FAILURE], i) + manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL); + + log_notice("Unit %s entered maintenance state.", u->meta.id); + } + /* Some names are special */ if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) { if (unit_has_name(u, SPECIAL_DBUS_SERVICE)) { @@ -1294,6 +1301,7 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen [UNIT_CONFLICTS] = UNIT_CONFLICTS, [UNIT_BEFORE] = UNIT_AFTER, [UNIT_AFTER] = UNIT_BEFORE, + [UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID, [UNIT_REFERENCES] = UNIT_REFERENCED_BY, [UNIT_REFERENCED_BY] = UNIT_REFERENCES }; @@ -1301,7 +1309,6 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen assert(u); assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX); - assert(inverse_table[d] != _UNIT_DEPENDENCY_INVALID); assert(other); /* We won't allow dependencies on ourselves. We will not @@ -1317,10 +1324,13 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen return -EINVAL; } - if ((r = set_ensure_allocated(&u->meta.dependencies[d], trivial_hash_func, trivial_compare_func)) < 0 || - (r = set_ensure_allocated(&other->meta.dependencies[inverse_table[d]], trivial_hash_func, trivial_compare_func)) < 0) + if ((r = set_ensure_allocated(&u->meta.dependencies[d], trivial_hash_func, trivial_compare_func)) < 0) return r; + if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID) + if ((r = set_ensure_allocated(&other->meta.dependencies[inverse_table[d]], trivial_hash_func, trivial_compare_func)) < 0) + return r; + if (add_reference) if ((r = set_ensure_allocated(&u->meta.dependencies[UNIT_REFERENCES], trivial_hash_func, trivial_compare_func)) < 0 || (r = set_ensure_allocated(&other->meta.dependencies[UNIT_REFERENCED_BY], trivial_hash_func, trivial_compare_func)) < 0) @@ -1329,10 +1339,11 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen if ((q = set_put(u->meta.dependencies[d], other)) < 0) return q; - if ((v = set_put(other->meta.dependencies[inverse_table[d]], u)) < 0) { - r = v; - goto fail; - } + if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID) + if ((v = set_put(other->meta.dependencies[inverse_table[d]], u)) < 0) { + r = v; + goto fail; + } if (add_reference) { if ((w = set_put(u->meta.dependencies[UNIT_REFERENCES], other)) < 0) { @@ -2097,7 +2108,8 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = { [UNIT_BEFORE] = "Before", [UNIT_AFTER] = "After", [UNIT_REFERENCES] = "References", - [UNIT_REFERENCED_BY] = "ReferencedBy" + [UNIT_REFERENCED_BY] = "ReferencedBy", + [UNIT_ON_FAILURE] = "OnFailure" }; DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency); diff --git a/src/unit.h b/src/unit.h index d3a00797f..55fe0fa60 100644 --- a/src/unit.h +++ b/src/unit.h @@ -114,6 +114,9 @@ enum UnitDependency { UNIT_BEFORE, /* inverse of 'before' is 'after' and vice versa */ UNIT_AFTER, + /* On Failure */ + UNIT_ON_FAILURE, + /* Reference information for GC logic */ UNIT_REFERENCES, /* Inverse of 'references' is 'referenced_by' */ UNIT_REFERENCED_BY, -- 2.30.2