diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index f1f433bbac..8d16d6618d 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -413,6 +413,8 @@ node /org/freedesktop/systemd1 { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly u NFailedJobs = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly at TransactionsWithOrderingCycle = [...]; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly d Progress = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly as Environment = ['...', ...]; @@ -1103,6 +1105,8 @@ node /org/freedesktop/systemd1 { + + @@ -1809,6 +1813,9 @@ node /org/freedesktop/systemd1 { NFailedJobs encodes how many jobs have ever failed in total. + TransactionsWithOrderingCycle encodes IDs of transactions that encountered + ordering cycle. + Progress encodes boot progress as a floating point value between 0.0 and 1.0. This value begins at 0.0 at early-boot and ends at 1.0 when boot is finished and is based on the number of executed and queued jobs. After startup, this field is always 1.0 indicating a finished @@ -12465,6 +12472,7 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ DefaultRestrictSUIDSGID, RemoveSubgroupFromUnit(), and KillUnitSubgroup() were added in version 258. + TransactionsWithOrderingCycle was added in version 259. Unit Objects diff --git a/man/systemctl.xml b/man/systemctl.xml index 8fb17e284d..a290e990e5 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -225,8 +225,8 @@ Sun 2017-02-26 20:57:49 EST 2h 3min left Sun 2017-02-26 11:56:36 EST 6h ago Check whether any of the specified units is in the "failed" state. If no unit is specified, - check whether there are any failed units, which corresponds to the degraded state - returned by is-system-running. Returns an exit code 0 + check whether there are any failed units or ordering cycles, which corresponds to the degraded + state returned by is-system-running. Returns an exit code 0 if at least one has failed, non-zero otherwise. Unless is specified, this will also print the current unit or system state to standard output. diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 2610442384..ac203f2971 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -455,6 +455,35 @@ static int property_get_oom_score_adjust( return sd_bus_message_append(reply, "i", n); } +static int property_get_transactions_with_cycle( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = ASSERT_PTR(userdata); + int r; + + assert(bus); + assert(reply); + + r = sd_bus_message_open_container(reply, 'a', "t"); + if (r < 0) + return r; + + uint64_t *id; + SET_FOREACH(id, m->transactions_with_cycle) { + r = sd_bus_message_append_basic(reply, 't', id); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) { Unit *u; int r; @@ -2870,6 +2899,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_PROPERTY("NJobs", "u", property_get_hashmap_size, offsetof(Manager, jobs), 0), SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0), SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0), + SD_BUS_PROPERTY("TransactionsWithOrderingCycle", "at", property_get_transactions_with_cycle, 0, 0), SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0), SD_BUS_PROPERTY("Environment", "as", property_get_environment, 0, 0), SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), SD_BUS_VTABLE_PROPERTY_CONST), diff --git a/src/core/manager.c b/src/core/manager.c index 0a6ea1658f..acf837941e 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -3675,6 +3675,8 @@ void manager_reset_failed(Manager *m) { HASHMAP_FOREACH(u, m->units) unit_reset_failed(u); + + m->transactions_with_cycle = set_free(m->transactions_with_cycle); } bool manager_unit_inactive_or_pending(Manager *m, const char *name) { @@ -4623,8 +4625,8 @@ ManagerState manager_state(Manager *m) { return MANAGER_MAINTENANCE; } - /* Are there any failed units? If so, we are in degraded mode */ - if (!set_isempty(m->failed_units)) + /* Are there any failed units or ordering cycles? If so, we are in degraded mode */ + if (!set_isempty(m->failed_units) || !set_isempty(m->transactions_with_cycle)) return MANAGER_DEGRADED; return MANAGER_RUNNING; diff --git a/src/core/varlink-manager.c b/src/core/varlink-manager.c index 3414ccb9ed..951e0b4b96 100644 --- a/src/core/varlink-manager.c +++ b/src/core/varlink-manager.c @@ -112,6 +112,24 @@ static int manager_context_build_json(sd_json_variant **ret, const char *name, v JSON_BUILD_PAIR_STRING_NON_EMPTY("ControlGroup", m->cgroup_root)); } +static int transactions_with_cycle_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + const Set *ids = userdata; + int r; + + assert(ret); + + uint64_t *id; + SET_FOREACH(id, ids) { + r = sd_json_variant_append_arrayb(&v, SD_JSON_BUILD_UNSIGNED(*id)); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + static int manager_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata) { Manager *m = ASSERT_PTR(userdata); dual_timestamp watchdog_last_ping; @@ -154,6 +172,7 @@ static int manager_runtime_build_json(sd_json_variant **ret, const char *name, v SD_JSON_BUILD_PAIR_UNSIGNED("NJobs", hashmap_size(m->jobs)), SD_JSON_BUILD_PAIR_UNSIGNED("NInstalledJobs", m->n_installed_jobs), SD_JSON_BUILD_PAIR_UNSIGNED("NFailedJobs", m->n_failed_jobs), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("TransactionsWithOrderingCycle", transactions_with_cycle_build_json, m->transactions_with_cycle), SD_JSON_BUILD_PAIR_REAL("Progress", manager_get_progress(m)), JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("WatchdogLastPingTimestamp", watchdog_get_last_ping_as_dual_timestamp(&watchdog_last_ping)), SD_JSON_BUILD_PAIR_STRING("SystemState", manager_state_to_string(manager_state(m))), diff --git a/src/shared/varlink-io.systemd.Manager.c b/src/shared/varlink-io.systemd.Manager.c index cdcaa53b71..a31e0e688b 100644 --- a/src/shared/varlink-io.systemd.Manager.c +++ b/src/shared/varlink-io.systemd.Manager.c @@ -155,6 +155,8 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(NInstalledJobs, SD_VARLINK_INT, 0), SD_VARLINK_FIELD_COMMENT("The total amount of failed jobs"), SD_VARLINK_DEFINE_FIELD(NFailedJobs, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("IDs of transactions that encountered ordering cycle"), + SD_VARLINK_DEFINE_FIELD(TransactionsWithOrderingCycle, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Boot progress as a floating point value between 0.0 and 1.0"), SD_VARLINK_DEFINE_FIELD(Progress, SD_VARLINK_FLOAT, 0), SD_VARLINK_FIELD_COMMENT("Timestamp when the hardware watchdog was last pinged"),