X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Funit.c;h=ec4fa82ec184259acb4b159d44f7c1c109a5f9eb;hb=f5b51ea7fcb0b6380c3ceb4d4f3f22f647c6fd32;hp=a2f37282dbc54b0ef79e3fe00a6225b6aa3d77b5;hpb=1a7f1b385cd9de8a0da934fadc379860f914ef33;p=elogind.git diff --git a/src/core/unit.c b/src/core/unit.c index a2f37282d..ec4fa82ec 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -19,12 +19,8 @@ along with systemd; If not, see . ***/ -#include #include #include -#include -#include -#include #include #include #include @@ -45,12 +41,10 @@ #include "cgroup-util.h" #include "missing.h" #include "mkdir.h" -#include "label.h" #include "fileio-label.h" #include "bus-common-errors.h" #include "dbus.h" #include "execute.h" -#include "virt.h" #include "dropin.h" const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = { @@ -278,21 +272,32 @@ int unit_set_description(Unit *u, const char *description) { } bool unit_check_gc(Unit *u) { + UnitActiveState state; assert(u); - if (UNIT_VTABLE(u)->no_gc) + if (u->job) return true; - if (u->no_gc) + if (u->nop_job) return true; - if (u->job) + state = unit_active_state(u); + + /* If the unit is inactive and failed and no job is queued for + * it, then release its runtime resources */ + if (UNIT_IS_INACTIVE_OR_FAILED(state) && + UNIT_VTABLE(u)->release_resources) + UNIT_VTABLE(u)->release_resources(u); + + /* But we keep the unit object around for longer when it is + * referenced or configured to not be gc'ed */ + if (state != UNIT_INACTIVE) return true; - if (u->nop_job) + if (UNIT_VTABLE(u)->no_gc) return true; - if (unit_active_state(u) != UNIT_INACTIVE) + if (u->no_gc) return true; if (u->refs) @@ -511,7 +516,7 @@ void unit_free(Unit *u) { free(u->cgroup_path); } - set_remove(u->manager->failed_units, u); + manager_update_failed_units(u->manager, u, false); set_remove(u->manager->startup_units, u); free(u->description); @@ -609,7 +614,7 @@ static int reserve_dependencies(Unit *u, Unit *other, UnitDependency d) { /* * If u does not have this dependency set allocated, there is no need - * to reserve anything. In that case other's set will be transfered + * to reserve anything. In that case other's set will be transferred * as a whole to u by complete_move(). */ if (!u->dependencies[d]) @@ -857,7 +862,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { assert(u->type >= 0); prefix = strempty(prefix); - prefix2 = strappenda(prefix, "\t"); + prefix2 = strjoina(prefix, "\t"); fprintf(f, "%s-> Unit %s:\n" @@ -1388,7 +1393,6 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { DISABLE_WARNING_FORMAT_NONLITERAL; snprintf(buf, sizeof(buf), format, unit_description(u)); - char_array_0(buf); REENABLE_WARNING; mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING : @@ -1412,6 +1416,7 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { int unit_start(Unit *u) { UnitActiveState state; Unit *following; + int r; assert(u); @@ -1450,9 +1455,6 @@ int unit_start(Unit *u) { return unit_start(following); } - unit_status_log_starting_stopping_reloading(u, JOB_START); - unit_status_print_starting_stopping(u, JOB_START); - if (UNIT_VTABLE(u)->supported && !UNIT_VTABLE(u)->supported(u->manager)) return -ENOTSUP; @@ -1468,7 +1470,14 @@ int unit_start(Unit *u) { unit_add_to_dbus_queue(u); - return UNIT_VTABLE(u)->start(u); + r = UNIT_VTABLE(u)->start(u); + if (r <= 0) + return r; + + /* Log if the start function actually did something */ + unit_status_log_starting_stopping_reloading(u, JOB_START); + unit_status_print_starting_stopping(u, JOB_START); + return r; } bool unit_can_start(Unit *u) { @@ -1492,6 +1501,7 @@ bool unit_can_isolate(Unit *u) { int unit_stop(Unit *u) { UnitActiveState state; Unit *following; + int r; assert(u); @@ -1505,15 +1515,18 @@ int unit_stop(Unit *u) { return unit_stop(following); } - unit_status_log_starting_stopping_reloading(u, JOB_STOP); - unit_status_print_starting_stopping(u, JOB_STOP); - if (!UNIT_VTABLE(u)->stop) return -EBADR; unit_add_to_dbus_queue(u); - return UNIT_VTABLE(u)->stop(u); + r = UNIT_VTABLE(u)->stop(u); + if (r <= 0) + return r; + + unit_status_log_starting_stopping_reloading(u, JOB_STOP); + unit_status_print_starting_stopping(u, JOB_STOP); + return r; } /* Errors: @@ -1524,6 +1537,7 @@ int unit_stop(Unit *u) { int unit_reload(Unit *u) { UnitActiveState state; Unit *following; + int r; assert(u); @@ -1548,10 +1562,14 @@ int unit_reload(Unit *u) { return unit_reload(following); } - unit_status_log_starting_stopping_reloading(u, JOB_RELOAD); - unit_add_to_dbus_queue(u); - return UNIT_VTABLE(u)->reload(u); + + r = UNIT_VTABLE(u)->reload(u); + if (r <= 0) + return r; + + unit_status_log_starting_stopping_reloading(u, JOB_RELOAD); + return r; } bool unit_can_reload(Unit *u) { @@ -1624,12 +1642,14 @@ static void unit_check_binds_to(Unit *u) { continue; stop = true; + break; } if (!stop) return; - log_unit_info(u->id, "Unit %s is bound to inactive service. Stopping, too.", u->id); + assert(other); + log_unit_info(u->id, "Unit %s is bound to inactive unit %s. Stopping, too.", u->id, other->id); /* A unit we need to run is gone. Sniff. Let's stop this. */ manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL); @@ -1777,10 +1797,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su } /* Keep track of failed units */ - if (ns == UNIT_FAILED) - set_put(u->manager->failed_units, u); - else - set_remove(u->manager->failed_units, u); + manager_update_failed_units(u->manager, u, ns == UNIT_FAILED); /* Make sure the cgroup is always removed when we become inactive */ if (UNIT_IS_INACTIVE_OR_FAILED(ns)) @@ -2585,6 +2602,7 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { unit_serialize_item(u, f, "assert-result", yes_no(u->assert_result)); unit_serialize_item(u, f, "transient", yes_no(u->transient)); + unit_serialize_item_format(u, f, "cpuacct-usage-base", "%" PRIu64, u->cpuacct_usage_base); if (u->cgroup_path) unit_serialize_item(u, f, "cgroup", u->cgroup_path); @@ -2674,7 +2692,9 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { if (streq(l, "job")) { if (v[0] == '\0') { /* new-style serialized job */ - Job *j = job_new_raw(u); + Job *j; + + j = job_new_raw(u); if (!j) return -ENOMEM; @@ -2696,12 +2716,11 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { job_free(j); return r; } - - if (j->state == JOB_RUNNING) - u->manager->n_running_jobs++; } else { /* legacy */ - JobType type = job_type_from_string(v); + JobType type; + + type = job_type_from_string(v); if (type < 0) log_debug("Failed to parse job type value %s", v); else @@ -2758,6 +2777,12 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { u->transient = b; continue; + } else if (streq(l, "cpuacct-usage-base")) { + + r = safe_atou64(v, &u->cpuacct_usage_base); + if (r < 0) + log_debug("Failed to parse CPU usage %s", v); + } else if (streq(l, "cgroup")) { char *s; @@ -2769,8 +2794,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { void *p; p = hashmap_remove(u->manager->cgroup_unit, u->cgroup_path); - log_info("Removing cgroup_path %s from hashmap (%p)", - u->cgroup_path, p); + log_info("Removing cgroup_path %s from hashmap (%p)", u->cgroup_path, p); free(u->cgroup_path); } @@ -2816,11 +2840,10 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) { return -ENOMEM; r = manager_load_unit(u->manager, e, NULL, NULL, &device); - if (r < 0) return r; - r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_BINDS_TO, device, true); + r = unit_add_two_dependencies(u, UNIT_AFTER, u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_BINDS_TO : UNIT_WANTS, device, true); if (r < 0) return r; @@ -2833,27 +2856,34 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) { return 0; } -int unit_coldplug(Unit *u) { +static int unit_add_deserialized_job_coldplug(Unit *u) { + int r; + + r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL); + if (r < 0) + return r; + + u->deserialized_job = _JOB_TYPE_INVALID; + + return 0; +} + +int unit_coldplug(Unit *u, Hashmap *deferred_work) { int r; assert(u); if (UNIT_VTABLE(u)->coldplug) - if ((r = UNIT_VTABLE(u)->coldplug(u)) < 0) + if ((r = UNIT_VTABLE(u)->coldplug(u, deferred_work)) < 0) return r; if (u->job) { r = job_coldplug(u->job); if (r < 0) return r; - } else if (u->deserialized_job >= 0) { + } else if (u->deserialized_job >= 0) /* legacy */ - r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL); - if (r < 0) - return r; - - u->deserialized_job = _JOB_TYPE_INVALID; - } + hashmap_put(deferred_work, u, &unit_add_deserialized_job_coldplug); return 0; } @@ -3153,6 +3183,10 @@ int unit_patch_contexts(Unit *u) { r = get_home_dir(&ec->working_directory); if (r < 0) return r; + + /* Allow user services to run, even if the + * home directory is missing */ + ec->working_directory_missing_ok = true; } if (u->manager->running_as == SYSTEMD_USER &&