1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-05 09:17:44 +03:00

core: rework the "no_gc" unit flag to become a more generic "perpetual" flag

So far "no_gc" was set on -.slice and init.scope, to units that are always
running, cannot be stopped and never exist in an "inactive" state. Since these
units are the only users of this flag, let's remodel it and rename it
"perpetual" and let's derive more funcitonality off it. Specifically, refuse
enqueing stop jobs for these units, and report that they are "unstoppable" in
the CanStop bus property.
This commit is contained in:
Lennart Poettering 2016-10-24 21:41:54 +02:00
parent bbeea27117
commit f5869324e3
5 changed files with 36 additions and 19 deletions

View File

@ -263,10 +263,7 @@ static int property_get_can_stop(
assert(reply);
assert(u);
/* On the lower levels we assume that every unit we can start
* we can also stop */
return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_stop);
return sd_bus_message_append(reply, "b", unit_can_stop(u) && !u->refuse_manual_stop);
}
static int property_get_can_reload(
@ -760,6 +757,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),

View File

@ -154,15 +154,13 @@ static int scope_load_init_scope(Unit *u) {
return 0;
u->transient = true;
u->no_gc = true;
u->perpetual = true;
/* init.scope is a bit special, as it has to stick around forever. Because of its special semantics we
* synthesize it here, instead of relying on the unit file on disk. */
u->default_dependencies = false;
u->ignore_on_isolate = true;
u->refuse_manual_start = true;
u->refuse_manual_stop = true;
SCOPE(u)->kill_context.kill_signal = SIGRTMIN+14;
@ -580,7 +578,7 @@ static void scope_enumerate(Manager *m) {
}
u->transient = true;
u->no_gc = true;
u->perpetual = true;
SCOPE(u)->deserialized_state = SCOPE_RUNNING;
unit_add_to_load_queue(u);

View File

@ -136,15 +136,13 @@ static int slice_load_root_slice(Unit *u) {
if (!unit_has_name(u, SPECIAL_ROOT_SLICE))
return 0;
u->no_gc = true;
u->perpetual = true;
/* The root slice is a bit special. For example it is always running and cannot be terminated. Because of its
* special semantics we synthesize it here, instead of relying on the unit file on disk. */
u->default_dependencies = false;
u->ignore_on_isolate = true;
u->refuse_manual_start = true;
u->refuse_manual_stop = true;
if (!u->description)
u->description = strdup("Root Slice");
@ -302,7 +300,7 @@ static void slice_enumerate(Manager *m) {
u = manager_get_unit(m, SPECIAL_ROOT_SLICE);
if (!u) {
u = unit_new(m, sizeof(Slice));
if (!u) {
if (!u) {
log_oom();
return;
}
@ -310,12 +308,12 @@ static void slice_enumerate(Manager *m) {
r = unit_add_name(u, SPECIAL_ROOT_SLICE);
if (r < 0) {
unit_free(u);
log_error_errno(r, "Failed to add the "SPECIAL_ROOT_SLICE " name: %m");
log_error_errno(r, "Failed to add the " SPECIAL_ROOT_SLICE " name: %m");
return;
}
}
u->no_gc = true;
u->perpetual = true;
SLICE(u)->deserialized_state = SLICE_ACTIVE;
unit_add_to_load_queue(u);

View File

@ -323,7 +323,7 @@ bool unit_check_gc(Unit *u) {
if (state != UNIT_INACTIVE)
return true;
if (u->no_gc)
if (u->perpetual)
return true;
if (u->refs)
@ -924,6 +924,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
"%s\tGC Check Good: %s\n"
"%s\tNeed Daemon Reload: %s\n"
"%s\tTransient: %s\n"
"%s\tPerpetual: %s\n"
"%s\tSlice: %s\n"
"%s\tCGroup: %s\n"
"%s\tCGroup realized: %s\n"
@ -942,6 +943,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
prefix, yes_no(unit_check_gc(u)),
prefix, yes_no(unit_need_daemon_reload(u)),
prefix, yes_no(u->transient),
prefix, yes_no(u->perpetual),
prefix, strna(unit_slice_name(u)),
prefix, strna(u->cgroup_path),
prefix, yes_no(u->cgroup_realized),
@ -1616,6 +1618,18 @@ int unit_stop(Unit *u) {
return UNIT_VTABLE(u)->stop(u);
}
bool unit_can_stop(Unit *u) {
assert(u);
if (!unit_supported(u))
return false;
if (u->perpetual)
return false;
return !!UNIT_VTABLE(u)->stop;
}
/* Errors:
* -EBADR: This unit type does not support reloading.
* -ENOEXEC: Unit is not started.
@ -2150,13 +2164,20 @@ bool unit_job_is_applicable(Unit *u, JobType j) {
case JOB_VERIFY_ACTIVE:
case JOB_START:
case JOB_STOP:
case JOB_NOP:
/* Note that we don't check unit_can_start() here. That's because .device units and suchlike are not
* startable by us but may appear due to external events, and it thus makes sense to permit enqueing
* jobs for it. */
return true;
case JOB_STOP:
/* Similar as above. However, perpetual units can never be stopped (neither explicitly nor due to
* external events), hence it makes no sense to permit enqueing such a request either. */
return !u->perpetual;
case JOB_RESTART:
case JOB_TRY_RESTART:
return unit_can_start(u);
return unit_can_stop(u) && unit_can_start(u);
case JOB_RELOAD:
case JOB_TRY_RELOAD:

View File

@ -236,6 +236,9 @@ struct Unit {
/* Is this a transient unit? */
bool transient;
/* Is this a unit that is always running and cannot be stopped? */
bool perpetual;
bool in_load_queue:1;
bool in_dbus_queue:1;
bool in_cleanup_queue:1;
@ -244,8 +247,6 @@ struct Unit {
bool sent_dbus_new_signal:1;
bool no_gc:1;
bool in_audit:1;
bool cgroup_realized:1;
@ -524,6 +525,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix);
bool unit_can_reload(Unit *u) _pure_;
bool unit_can_start(Unit *u) _pure_;
bool unit_can_stop(Unit *u) _pure_;
bool unit_can_isolate(Unit *u) _pure_;
int unit_start(Unit *u);