X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Funit.c;h=fea75e88fe6fa4dbaafd0ea50588d73ef64c1d37;hb=e677bf7ef610acdc5068b9d5d4c79556a236e52f;hp=9e33701c8f4886b0af60a3c31aaee61d0da34142;hpb=b30e2f4c18ad81b04e4314fd191a5d458553773c;p=elogind.git diff --git a/src/core/unit.c b/src/core/unit.c index 9e33701c8..fea75e88f 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ @@ -249,6 +249,9 @@ bool unit_check_gc(Unit *u) { if (u->job) return true; + if (u->nop_job) + return true; + if (unit_active_state(u) != UNIT_INACTIVE) return true; @@ -352,12 +355,26 @@ void unit_free(Unit *u) { SET_FOREACH(t, u->names, i) hashmap_remove_value(u->manager->units, t, u); - if (u->job) - job_free(u->job); + if (u->job) { + Job *j = u->job; + job_uninstall(j); + job_free(j); + } + + if (u->nop_job) { + Job *j = u->nop_job; + job_uninstall(j); + job_free(j); + } for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) bidi_set_free(u, u->dependencies[d]); + if (u->requires_mounts_for) { + LIST_REMOVE(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u); + strv_free(u->requires_mounts_for); + } + if (u->type != _UNIT_TYPE_INVALID) LIST_REMOVE(Unit, units_by_type, u->manager->units_by_type[u->type], u); @@ -498,6 +515,9 @@ int unit_merge(Unit *u, Unit *other) { if (other->job) return -EEXIST; + if (other->nop_job) + return -EEXIST; + if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) return -EEXIST; @@ -676,6 +696,18 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { fprintf(f, "%s\t%s: %s\n", prefix, unit_dependency_to_string(d), other->id); } + if (!strv_isempty(u->requires_mounts_for)) { + char **j; + + fprintf(f, + "%s\tRequiresMountsFor:", prefix); + + STRV_FOREACH(j, u->requires_mounts_for) + fprintf(f, " %s", *j); + + fputs("\n", f); + } + if (u->load_state == UNIT_LOADED) { CGroupBonding *b; CGroupAttribute *a; @@ -726,6 +758,9 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { if (u->job) job_dump(u->job, f, prefix2); + if (u->nop_job) + job_dump(u->nop_job, f, prefix2); + free(p2); } @@ -851,6 +886,12 @@ int unit_load(Unit *u) { if ((r = unit_add_default_dependencies(u)) < 0) goto fail; + if (u->load_state == UNIT_LOADED) { + r = unit_add_mount_links(u); + if (r < 0) + return r; + } + if (u->on_failure_isolate && set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) { @@ -1223,12 +1264,12 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su case JOB_VERIFY_ACTIVE: if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) - job_finish_and_invalidate(u->job, JOB_DONE); + job_finish_and_invalidate(u->job, JOB_DONE, true); else if (u->job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) { unexpected = true; if (UNIT_IS_INACTIVE_OR_FAILED(ns)) - job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE); + job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true); } break; @@ -1238,12 +1279,12 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su if (u->job->state == JOB_RUNNING) { if (ns == UNIT_ACTIVE) - job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED); + job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED, true); else if (ns != UNIT_ACTIVATING && ns != UNIT_RELOADING) { unexpected = true; if (UNIT_IS_INACTIVE_OR_FAILED(ns)) - job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE); + job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true); } } @@ -1254,10 +1295,10 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su case JOB_TRY_RESTART: if (UNIT_IS_INACTIVE_OR_FAILED(ns)) - job_finish_and_invalidate(u->job, JOB_DONE); + job_finish_and_invalidate(u->job, JOB_DONE, true); else if (u->job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) { unexpected = true; - job_finish_and_invalidate(u->job, JOB_FAILED); + job_finish_and_invalidate(u->job, JOB_FAILED, true); } break; @@ -1504,6 +1545,7 @@ bool unit_job_is_applicable(Unit *u, JobType j) { case JOB_VERIFY_ACTIVE: case JOB_START: case JOB_STOP: + case JOB_NOP: return true; case JOB_RESTART: @@ -2285,8 +2327,15 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds) { if ((r = UNIT_VTABLE(u)->serialize(u, f, fds)) < 0) return r; - if (u->job) - unit_serialize_item(u, f, "job", job_type_to_string(u->job->type)); + if (u->job) { + fprintf(f, "job\n"); + job_serialize(u->job, f, fds); + } + + if (u->nop_job) { + fprintf(f, "job\n"); + job_serialize(u->nop_job, f, fds); + } dual_timestamp_serialize(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp); dual_timestamp_serialize(f, "active-enter-timestamp", &u->active_enter_timestamp); @@ -2365,13 +2414,38 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { v = l+k; if (streq(l, "job")) { - JobType type; + if (v[0] == '\0') { + /* new-style serialized job */ + Job *j = job_new_raw(u); + if (!j) + return -ENOMEM; + + r = job_deserialize(j, f, fds); + if (r < 0) { + job_free(j); + return r; + } - if ((type = job_type_from_string(v)) < 0) - log_debug("Failed to parse job type value %s", v); - else - u->deserialized_job = type; + r = hashmap_put(u->manager->jobs, UINT32_TO_PTR(j->id), j); + if (r < 0) { + job_free(j); + return r; + } + r = job_install_deserialized(j); + if (r < 0) { + hashmap_remove(u->manager->jobs, UINT32_TO_PTR(j->id)); + job_free(j); + return r; + } + } else { + /* legacy */ + JobType type = job_type_from_string(v); + if (type < 0) + log_debug("Failed to parse job type value %s", v); + else + u->deserialized_job = type; + } continue; } else if (streq(l, "inactive-exit-timestamp")) { dual_timestamp_deserialize(v, &u->inactive_exit_timestamp); @@ -2447,8 +2521,14 @@ int unit_coldplug(Unit *u) { if ((r = UNIT_VTABLE(u)->coldplug(u)) < 0) return r; - if (u->deserialized_job >= 0) { - if ((r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL)) < 0) + if (u->job) { + r = job_coldplug(u->job); + if (r < 0) + return r; + } 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; @@ -2628,6 +2708,45 @@ void unit_ref_unset(UnitRef *ref) { ref->unit = NULL; } +int unit_add_one_mount_link(Unit *u, Mount *m) { + char **i; + + assert(u); + assert(m); + + if (u->load_state != UNIT_LOADED || + UNIT(m)->load_state != UNIT_LOADED) + return 0; + + STRV_FOREACH(i, u->requires_mounts_for) { + + if (UNIT(m) == u) + continue; + + if (!path_startswith(*i, m->where)) + continue; + + return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true); + } + + return 0; +} + +int unit_add_mount_links(Unit *u) { + Unit *other; + int r; + + assert(u); + + LIST_FOREACH(units_by_type, other, u->manager->units_by_type[UNIT_MOUNT]) { + r = unit_add_one_mount_link(u, MOUNT(other)); + if (r < 0) + return r; + } + + return 0; +} + static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = { [UNIT_STUB] = "stub", [UNIT_LOADED] = "loaded",