]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add new OnSuccess= dependency type
authorLennart Poettering <lennart@poettering.net>
Wed, 14 Apr 2021 12:36:15 +0000 (14:36 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 25 May 2021 14:03:03 +0000 (16:03 +0200)
This is similar to OnFailure= but is activated whenever a unit returns
into inactive state successfully.

I was always afraid of adding this, since it effectively allows building
loops and makes our engine Turing complete, but it pretty much already
was it was just hidden.

Given that we have per-unit ratelimits as well as an event loop global
ratelimit I feel safe to add this finally, given it actually is useful.

Fixes: #13386
13 files changed:
man/org.freedesktop.systemd1.xml
man/systemd.unit.xml
src/basic/unit-def.c
src/basic/unit-def.h
src/core/dbus-unit.c
src/core/job.c
src/core/load-fragment-gperf.gperf.in
src/core/unit-dependency-atom.c
src/core/unit-dependency-atom.h
src/core/unit-serialize.c
src/core/unit.c
src/core/unit.h
test/fuzz/fuzz-unit-file/directives.service

index 13322746fa52092a2f3e3f7171b887a9668484ea..d55f3c8f9bdb9545492a55975a81d9b9fa218ac4 100644 (file)
@@ -1632,6 +1632,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly as OnFailureOf = ['...', ...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly as OnSuccess = ['...', ...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly as OnSuccessOf = ['...', ...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly as Triggers = ['...', ...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly as TriggeredBy = ['...', ...];
@@ -1702,6 +1706,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly b DefaultDependencies = ...;
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s OnSuccesJobMode = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s OnFailureJobMode = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly b IgnoreOnIsolate = ...;
@@ -1781,6 +1787,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <!--property OnFailureOf is not documented!-->
 
+    <!--property OnSuccess is not documented!-->
+
+    <!--property OnSuccessOf is not documented!-->
+
     <!--property ReloadPropagatedFrom is not documented!-->
 
     <!--property PropagatesStopTo is not documented!-->
@@ -1805,6 +1815,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <!--property CanFreeze is not documented!-->
 
+    <!--property OnSuccesJobMode is not documented!-->
+
     <!--property OnFailureJobMode is not documented!-->
 
     <!--property JobRunningTimeoutUSec is not documented!-->
@@ -1919,6 +1931,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <variablelist class="dbus-property" generated="True" extra-ref="OnFailureOf"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="OnSuccess"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="OnSuccessOf"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="Triggers"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="TriggeredBy"/>
@@ -2003,6 +2019,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <variablelist class="dbus-property" generated="True" extra-ref="DefaultDependencies"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="OnSuccesJobMode"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="OnFailureJobMode"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="IgnoreOnIsolate"/>
index 07ea21a6e7fd002e01aa4d319a0cd7dd7b62aae6..d1d7a9f6e0f5beac25ee52a5bf3a6ea58daf9c54 100644 (file)
       <varlistentry>
         <term><varname>OnFailure=</varname></term>
 
-        <listitem><para>A space-separated list of one or more units
-        that are activated when this unit enters the
-        <literal>failed</literal> state.  A service unit using
-        <varname>Restart=</varname> enters the failed state only after
-        the start limits are reached.</para></listitem>
+        <listitem><para>A space-separated list of one or more units that are activated when this unit enters
+        the <literal>failed</literal> state.  A service unit using <varname>Restart=</varname> enters the
+        failed state only after the start limits are reached.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>OnSuccess=</varname></term>
+
+        <listitem><para>A space-separated list of one or more units that are activated when this unit enters
+        the <literal>inactive</literal> state.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 32be5219fcedf91719f2996e1acb9ee8cf19d7d9..f83e398a4b12d6de9ed232bd202b336f43963dab 100644 (file)
@@ -274,6 +274,8 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
         [UNIT_CONFLICTED_BY] = "ConflictedBy",
         [UNIT_BEFORE] = "Before",
         [UNIT_AFTER] = "After",
+        [UNIT_ON_SUCCESS] = "OnSuccess",
+        [UNIT_ON_SUCCESS_OF] = "OnSuccessOf",
         [UNIT_ON_FAILURE] = "OnFailure",
         [UNIT_ON_FAILURE_OF] = "OnFailureOf",
         [UNIT_TRIGGERS] = "Triggers",
index dc5aa5555d70e410580a62881a30552c6a98b540..92b40e8a3de0fc9123084691f131664e44dc5ce1 100644 (file)
@@ -227,7 +227,9 @@ typedef enum UnitDependency {
         UNIT_BEFORE,                  /* inverse of 'before' is 'after' and vice versa */
         UNIT_AFTER,
 
-        /* On Failure */
+        /* OnSuccess= + OnFailure= */
+        UNIT_ON_SUCCESS,
+        UNIT_ON_SUCCESS_OF,
         UNIT_ON_FAILURE,
         UNIT_ON_FAILURE_OF,
 
index 5e5a0a33a1193dea9c6533d351058b0503845eaa..60f406a160a8d050cf907e3f338aedc970b35f7c 100644 (file)
@@ -866,6 +866,8 @@ const sd_bus_vtable bus_unit_vtable[] = {
         SD_BUS_PROPERTY("After", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("OnFailureOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("OnSuccess", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("OnSuccessOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -903,6 +905,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
         SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("OnSuccesJobMode", "s", property_get_job_mode, offsetof(Unit, on_success_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -2126,6 +2129,9 @@ static int bus_unit_set_transient_property(
         if (streq(name, "DefaultDependencies"))
                 return bus_set_transient_bool(u, name, &u->default_dependencies, message, flags, error);
 
+        if (streq(name, "OnSuccessJobMode"))
+                return bus_set_transient_job_mode(u, name, &u->on_success_job_mode, message, flags, error);
+
         if (streq(name, "OnFailureJobMode"))
                 return bus_set_transient_job_mode(u, name, &u->on_failure_job_mode, message, flags, error);
 
@@ -2301,6 +2307,7 @@ static int bus_unit_set_transient_property(
                             UNIT_CONFLICTS,
                             UNIT_BEFORE,
                             UNIT_AFTER,
+                            UNIT_ON_SUCCESS,
                             UNIT_ON_FAILURE,
                             UNIT_PROPAGATES_RELOAD_TO,
                             UNIT_RELOAD_PROPAGATED_FROM,
index 45bb6bfd92f429f30599bfc34278b036471fdff7..a273e4220e2a8f42a848e5ec9d3ceaa362c504a8 100644 (file)
@@ -1047,7 +1047,7 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr
                                                  job_type_to_string(t),
                                                  job_result_to_string(result)));
 
-                unit_start_on_failure(u);
+                unit_start_on_failure(u, "OnFailure=", UNIT_ATOM_ON_FAILURE, u->on_failure_job_mode);
         }
 
         unit_trigger_notify(u);
index bb3c4453df2cf0ea87c6268c15e7953687594140..25cd55e2f9ef5ace5b31ab3e0faf3a626182320a 100644 (file)
@@ -264,6 +264,7 @@ Unit.BindTo,                             config_parse_unit_deps,
 Unit.Conflicts,                          config_parse_unit_deps,                      UNIT_CONFLICTS,                     0
 Unit.Before,                             config_parse_unit_deps,                      UNIT_BEFORE,                        0
 Unit.After,                              config_parse_unit_deps,                      UNIT_AFTER,                         0
+Unit.OnSuccess,                          config_parse_unit_deps,                      UNIT_ON_SUCCESS,                    0
 Unit.OnFailure,                          config_parse_unit_deps,                      UNIT_ON_FAILURE,                    0
 Unit.PropagatesReloadTo,                 config_parse_unit_deps,                      UNIT_PROPAGATES_RELOAD_TO,          0
 Unit.PropagateReloadTo,                  config_parse_unit_deps,                      UNIT_PROPAGATES_RELOAD_TO,          0
@@ -281,6 +282,7 @@ Unit.RefuseManualStart,                  config_parse_bool,
 Unit.RefuseManualStop,                   config_parse_bool,                           0,                                  offsetof(Unit, refuse_manual_stop)
 Unit.AllowIsolate,                       config_parse_bool,                           0,                                  offsetof(Unit, allow_isolate)
 Unit.DefaultDependencies,                config_parse_bool,                           0,                                  offsetof(Unit, default_dependencies)
+Unit.OnSuccessJobMode,                   config_parse_job_mode,                       0,                                  offsetof(Unit, on_success_job_mode)
 Unit.OnFailureJobMode,                   config_parse_job_mode,                       0,                                  offsetof(Unit, on_failure_job_mode)
 {# The following is a legacy alias name for compatibility #}
 Unit.OnFailureIsolate,                   config_parse_job_mode_isolate,               0,                                  offsetof(Unit, on_failure_job_mode)
index eaeb1d389e4384fc4d809146257faddbb094142d..6bd961e92b00f008203bb34cdc157e89963ae752 100644 (file)
@@ -74,6 +74,7 @@ static const UnitDependencyAtom atom_map[_UNIT_DEPENDENCY_MAX] = {
         /* These are simple dependency types: they consist of a single atom only */
         [UNIT_BEFORE]                 = UNIT_ATOM_BEFORE,
         [UNIT_AFTER]                  = UNIT_ATOM_AFTER,
+        [UNIT_ON_SUCCESS]             = UNIT_ATOM_ON_SUCCESS,
         [UNIT_ON_FAILURE]             = UNIT_ATOM_ON_FAILURE,
         [UNIT_TRIGGERS]               = UNIT_ATOM_TRIGGERS,
         [UNIT_TRIGGERED_BY]           = UNIT_ATOM_TRIGGERED_BY,
@@ -88,6 +89,7 @@ static const UnitDependencyAtom atom_map[_UNIT_DEPENDENCY_MAX] = {
          * things discoverable/debuggable as they are the inverse dependencies to some of the above. As they
          * have no effect of their own, they all map to no atoms at all, i.e. the value 0. */
         [UNIT_RELOAD_PROPAGATED_FROM] = 0,
+        [UNIT_ON_SUCCESS_OF]          = 0,
         [UNIT_ON_FAILURE_OF]          = 0,
         [UNIT_STOP_PROPAGATED_FROM]   = 0,
 };
@@ -175,6 +177,9 @@ UnitDependency unit_dependency_from_unique_atom(UnitDependencyAtom atom) {
         case UNIT_ATOM_AFTER:
                 return UNIT_AFTER;
 
+        case UNIT_ATOM_ON_SUCCESS:
+                return UNIT_ON_SUCCESS;
+
         case UNIT_ATOM_ON_FAILURE:
                 return UNIT_ON_FAILURE;
 
index 01482215118378fb463e10d04eb290d7406db535..daa296f6012983ed87d3dc1c2b00fe65dc52b4ea 100644 (file)
@@ -62,6 +62,7 @@ typedef enum UnitDependencyAtom {
         /* The remaining atoms map 1:1 to the equally named high-level deps */
         UNIT_ATOM_BEFORE                              = UINT64_C(1) << 22,
         UNIT_ATOM_AFTER                               = UINT64_C(1) << 23,
+        UNIT_ATOM_ON_SUCCESS                          = UINT64_C(1) << 24,
         UNIT_ATOM_ON_FAILURE                          = UINT64_C(1) << 25,
         UNIT_ATOM_TRIGGERS                            = UINT64_C(1) << 26,
         UNIT_ATOM_TRIGGERED_BY                        = UINT64_C(1) << 27,
index caee3a2823b87294a7a6d30fe865d9aec79f7371..7da0d8a3dbcf453384ff4d0783ebecacd6ac8cb2 100644 (file)
@@ -774,12 +774,14 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                         "%s\tRefuseManualStart: %s\n"
                         "%s\tRefuseManualStop: %s\n"
                         "%s\tDefaultDependencies: %s\n"
+                        "%s\tOnSuccessJobMode: %s\n"
                         "%s\tOnFailureJobMode: %s\n"
                         "%s\tIgnoreOnIsolate: %s\n",
                         prefix, yes_no(u->stop_when_unneeded),
                         prefix, yes_no(u->refuse_manual_start),
                         prefix, yes_no(u->refuse_manual_stop),
                         prefix, yes_no(u->default_dependencies),
+                        prefix, job_mode_to_string(u->on_success_job_mode),
                         prefix, job_mode_to_string(u->on_failure_job_mode),
                         prefix, yes_no(u->ignore_on_isolate));
 
index ed6f87d96096cfec5d3cb6ebc48845b922b33486..6892930d7bb9ee0696c0df81150cdde711d8e227 100644 (file)
@@ -101,6 +101,7 @@ Unit* unit_new(Manager *m, size_t size) {
         u->unit_file_state = _UNIT_FILE_STATE_INVALID;
         u->unit_file_preset = -1;
         u->on_failure_job_mode = JOB_REPLACE;
+        u->on_success_job_mode = JOB_FAIL;
         u->cgroup_control_inotify_wd = -1;
         u->cgroup_memory_inotify_wd = -1;
         u->job_timeout = USEC_INFINITY;
@@ -896,6 +897,7 @@ static void unit_maybe_warn_about_dependency(
                     UNIT_CONFLICTED_BY,
                     UNIT_BEFORE,
                     UNIT_AFTER,
+                    UNIT_ON_SUCCESS,
                     UNIT_ON_FAILURE,
                     UNIT_TRIGGERS,
                     UNIT_TRIGGERED_BY))
@@ -1507,6 +1509,31 @@ static int unit_add_startup_units(Unit *u) {
         return set_ensure_put(&u->manager->startup_units, NULL, u);
 }
 
+static int unit_validate_on_failure_job_mode(
+                Unit *u,
+                const char *job_mode_setting,
+                JobMode job_mode,
+                const char *dependency_name,
+                UnitDependencyAtom atom) {
+
+        Unit *other, *found = NULL;
+
+        if (job_mode != JOB_ISOLATE)
+                return 0;
+
+        UNIT_FOREACH_DEPENDENCY(other, u, atom) {
+                if (!found)
+                        found = other;
+                else if (found != other)
+                        return log_unit_error_errno(
+                                        u, SYNTHETIC_ERRNO(ENOEXEC),
+                                        "More than one %s dependencies specified but %sisolate set. Refusing.",
+                                        dependency_name, job_mode_setting);
+        }
+
+        return 0;
+}
+
 int unit_load(Unit *u) {
         int r;
 
@@ -1560,19 +1587,13 @@ int unit_load(Unit *u) {
                 if (r < 0)
                         goto fail;
 
-                if (u->on_failure_job_mode == JOB_ISOLATE) {
-                        Unit *other, *found = NULL;
+                r = unit_validate_on_failure_job_mode(u, "OnSuccessJobMode=", u->on_success_job_mode, "OnSuccess=", UNIT_ATOM_ON_SUCCESS);
+                if (r < 0)
+                        goto fail;
 
-                        UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_ON_FAILURE) {
-                                if (!found)
-                                        found = other;
-                                else if (found != other) {
-                                        r = log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOEXEC),
-                                                                 "More than one OnFailure= dependencies specified but OnFailureJobMode=isolate set. Refusing.");
-                                        goto fail;
-                                }
-                        }
-                }
+                r = unit_validate_on_failure_job_mode(u, "OnFailureJobMode=", u->on_failure_job_mode, "OnFailure=", UNIT_ATOM_ON_FAILURE);
+                if (r < 0)
+                        goto fail;
 
                 if (u->job_running_timeout != USEC_INFINITY && u->job_running_timeout > u->job_timeout)
                         log_unit_warning(u, "JobRunningTimeoutSec= is greater than JobTimeoutSec=, it has no effect.");
@@ -2082,25 +2103,39 @@ static void retroactively_stop_dependencies(Unit *u) {
                         manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL, NULL);
 }
 
-void unit_start_on_failure(Unit *u) {
+void unit_start_on_failure(
+                Unit *u,
+                const char *dependency_name,
+                UnitDependencyAtom atom,
+                JobMode job_mode) {
+
         bool logged = false;
         Unit *other;
         int r;
 
         assert(u);
+        assert(dependency_name);
+        assert(IN_SET(atom, UNIT_ATOM_ON_SUCCESS, UNIT_ATOM_ON_FAILURE));
+
+        /* Act on OnFailure= and OnSuccess= dependencies */
 
-        UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_ON_FAILURE) {
+        UNIT_FOREACH_DEPENDENCY(other, u, atom) {
                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 if (!logged) {
-                        log_unit_info(u, "Triggering OnFailure= dependencies.");
+                        log_unit_info(u, "Triggering %s dependencies.", dependency_name);
                         logged = true;
                 }
 
-                r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, NULL, &error, NULL);
+                r = manager_add_job(u->manager, JOB_START, other, job_mode, NULL, &error, NULL);
                 if (r < 0)
-                        log_unit_warning_errno(u, r, "Failed to enqueue OnFailure= job, ignoring: %s", bus_error_message(&error, r));
+                        log_unit_warning_errno(
+                                        u, r, "Failed to enqueue %s job, ignoring: %s",
+                                        dependency_name, bus_error_message(&error, r));
         }
+
+        if (logged)
+                log_unit_debug(u, "Triggering %s dependencies done.", dependency_name);
 }
 
 void unit_trigger_notify(Unit *u) {
@@ -2568,7 +2603,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag
                         log_unit_debug(u, "Unit entered failed state.");
 
                         if (!(flags & UNIT_NOTIFY_WILL_AUTO_RESTART))
-                                unit_start_on_failure(u);
+                                unit_start_on_failure(u, "OnFailure=", UNIT_ATOM_ON_FAILURE, u->on_failure_job_mode);
                 }
 
                 if (UNIT_IS_ACTIVE_OR_RELOADING(ns) && !UNIT_IS_ACTIVE_OR_RELOADING(os)) {
@@ -2584,6 +2619,10 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag
                         unit_emit_audit_stop(u, ns);
                         unit_log_resources(u);
                 }
+
+                if (ns == UNIT_INACTIVE && !IN_SET(os, UNIT_FAILED, UNIT_INACTIVE, UNIT_MAINTENANCE) &&
+                    !(flags & UNIT_NOTIFY_WILL_AUTO_RESTART))
+                        unit_start_on_failure(u, "OnSuccess=", UNIT_ATOM_ON_SUCCESS, u->on_success_job_mode);
         }
 
         manager_recheck_journal(m);
@@ -2871,6 +2910,8 @@ int unit_add_dependency(
                 [UNIT_CONFLICTED_BY] = UNIT_CONFLICTS,
                 [UNIT_BEFORE] = UNIT_AFTER,
                 [UNIT_AFTER] = UNIT_BEFORE,
+                [UNIT_ON_SUCCESS] = UNIT_ON_SUCCESS_OF,
+                [UNIT_ON_SUCCESS_OF] = UNIT_ON_SUCCESS,
                 [UNIT_ON_FAILURE] = UNIT_ON_FAILURE_OF,
                 [UNIT_ON_FAILURE_OF] = UNIT_ON_FAILURE,
                 [UNIT_REFERENCES] = UNIT_REFERENCED_BY,
index 6b3f48596f14f37559bab937734567f24d803a3d..1a3aaa5020b8cd7af267ddee5436151220a46151 100644 (file)
@@ -334,7 +334,8 @@ typedef struct Unit {
          * ones which might have appeared. */
         sd_event_source *rewatch_pids_event_source;
 
-        /* How to start OnFailure units */
+        /* How to start OnSuccess=/OnFailure= units */
+        JobMode on_success_job_mode;
         JobMode on_failure_job_mode;
 
         /* Tweaking the GC logic */
@@ -828,7 +829,7 @@ bool unit_will_restart(Unit *u);
 
 int unit_add_default_target_dependency(Unit *u, Unit *target);
 
-void unit_start_on_failure(Unit *u);
+void unit_start_on_failure(Unit *u, const char *dependency_name, UnitDependencyAtom atom, JobMode job_mode);
 void unit_trigger_notify(Unit *u);
 
 UnitFileState unit_get_unit_file_state(Unit *u);
index 95ab9a1c32a116386f7955eb1a7276d5e975a6ff..50b4b4b7f6f9921921234bac70df6ad168aefbf8 100644 (file)
@@ -76,6 +76,8 @@ JoinsNamespaceOf=
 OnFailure=
 OnFailureIsolate=
 OnFailureJobMode=
+OnSuccess=
+OnSuccessJobMode=
 PartOf=
 PropagateReloadFrom=
 PropagateReloadTo=