X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Funit.c;h=a5f6b2ead071fdf3a86ee310dbabebb955597f7f;hp=ea55c709b016752f17853ea69419c91fda96a5eb;hb=d1fab3fe88ae873b26b50359758776ad9e31968e;hpb=95ae05c0e79868c22b3e8e6fbc53432786876730;ds=sidebyside diff --git a/src/core/unit.c b/src/core/unit.c index ea55c709b..a5f6b2ead 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -51,6 +51,7 @@ #include "dbus.h" #include "execute.h" #include "virt.h" +#include "dropin.h" const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = { [UNIT_SERVICE] = &service_vtable, @@ -68,6 +69,8 @@ const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = { [UNIT_SCOPE] = &scope_vtable }; +static int maybe_warn_about_dependency(const char *id, const char *other, UnitDependency dependency); + Unit *unit_new(Manager *m, size_t size) { Unit *u; @@ -121,7 +124,6 @@ static void unit_init(Unit *u) { cc->cpu_accounting = u->manager->default_cpu_accounting; cc->blockio_accounting = u->manager->default_blockio_accounting; cc->memory_accounting = u->manager->default_memory_accounting; - cc->cpu_quota_period_usec = u->manager->default_cpu_quota_period_usec; } ec = unit_get_exec_context(u); @@ -509,6 +511,7 @@ void unit_free(Unit *u) { } set_remove(u->manager->failed_units, u); + set_remove(u->manager->startup_units, u); free(u->description); strv_free(u->documentation); @@ -582,7 +585,7 @@ static void merge_names(Unit *u, Unit *other) { assert_se(hashmap_replace(u->manager->units, t, u) == 0); } -static void merge_dependencies(Unit *u, Unit *other, UnitDependency d) { +static void merge_dependencies(Unit *u, Unit *other, const char *other_id, UnitDependency d) { Iterator i; Unit *back; int r; @@ -596,14 +599,25 @@ static void merge_dependencies(Unit *u, Unit *other, UnitDependency d) { UnitDependency k; for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++) { - r = set_remove_and_put(back->dependencies[k], other, u); - if (r == -EEXIST) - set_remove(back->dependencies[k], other); - else - assert(r >= 0 || r == -ENOENT); + /* Do not add dependencies between u and itself */ + if (back == u) { + if (set_remove(back->dependencies[k], other)) + maybe_warn_about_dependency(u->id, other_id, k); + } else { + r = set_remove_and_put(back->dependencies[k], other, u); + if (r == -EEXIST) + set_remove(back->dependencies[k], other); + else + assert(r >= 0 || r == -ENOENT); + } } } + /* Also do not move dependencies on u to itself */ + back = set_remove(other->dependencies[d], u); + if (back) + maybe_warn_about_dependency(u->id, other_id, d); + complete_move(&u->dependencies[d], &other->dependencies[d]); set_free(other->dependencies[d]); @@ -612,6 +626,7 @@ static void merge_dependencies(Unit *u, Unit *other, UnitDependency d) { int unit_merge(Unit *u, Unit *other) { UnitDependency d; + const char *other_id = NULL; assert(u); assert(other); @@ -642,6 +657,9 @@ int unit_merge(Unit *u, Unit *other) { if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) return -EEXIST; + if (other->id) + other_id = strdupa(other->id); + /* Merge names */ merge_names(u, other); @@ -651,7 +669,7 @@ int unit_merge(Unit *u, Unit *other) { /* Merge dependencies */ for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) - merge_dependencies(u, other, d); + merge_dependencies(u, other, other_id, d); other->load_state = UNIT_MERGED; other->merged_into = u; @@ -1030,6 +1048,9 @@ static int unit_add_slice_dependencies(Unit *u) { if (UNIT_ISSET(u->slice)) return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, UNIT_DEREF(u->slice), true); + if (streq(u->id, SPECIAL_ROOT_SLICE)) + return 0; + return unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, SPECIAL_ROOT_SLICE, NULL, true); } @@ -1076,12 +1097,17 @@ static int unit_add_startup_units(Unit *u) { int r = 0; c = unit_get_cgroup_context(u); - if (c != NULL && manager_state(u->manager) == MANAGER_STARTING && - (c->startup_cpu_shares_set || c->startup_blockio_weight_set)) { - r = set_put(u->manager->startup_units, u); - if (r == -EEXIST) - r = 0; - } + if (!c) + return 0; + + if (c->startup_cpu_shares == (unsigned long) -1 && + c->startup_blockio_weight == (unsigned long) -1) + return 0; + + r = set_put(u->manager->startup_units, u); + if (r == -EEXIST) + return 0; + return r; } @@ -1569,7 +1595,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su /* Note that this is called for all low-level state changes, * even if they might map to the same high-level - * UnitActiveState! That means that ns == os is OK an expected + * UnitActiveState! That means that ns == os is an expected * behavior here. For example: if a mount point is remounted * this function will be called too! */ @@ -1592,7 +1618,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su u->active_exit_timestamp = ts; } - /* Keep track of failed of units */ + /* Keep track of failed units */ if (ns == UNIT_FAILED && os != UNIT_FAILED) set_put(u->manager->failed_units, u); else if (os == UNIT_FAILED && ns != UNIT_FAILED) @@ -1717,7 +1743,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) { if (unit_has_name(u, SPECIAL_DBUS_SERVICE)) - /* The bus just might have become available, + /* The bus might have just become available, * hence try to connect to it, if we aren't * yet connected. */ bus_init(m, true); @@ -1931,6 +1957,50 @@ bool unit_job_is_applicable(Unit *u, JobType j) { } } +static int maybe_warn_about_dependency(const char *id, const char *other, UnitDependency dependency) { + switch (dependency) { + case UNIT_REQUIRES: + case UNIT_REQUIRES_OVERRIDABLE: + case UNIT_WANTS: + case UNIT_REQUISITE: + case UNIT_REQUISITE_OVERRIDABLE: + case UNIT_BINDS_TO: + case UNIT_PART_OF: + case UNIT_REQUIRED_BY: + case UNIT_REQUIRED_BY_OVERRIDABLE: + case UNIT_WANTED_BY: + case UNIT_BOUND_BY: + case UNIT_CONSISTS_OF: + case UNIT_REFERENCES: + case UNIT_REFERENCED_BY: + case UNIT_PROPAGATES_RELOAD_TO: + case UNIT_RELOAD_PROPAGATED_FROM: + case UNIT_JOINS_NAMESPACE_OF: + return 0; + + case UNIT_CONFLICTS: + case UNIT_CONFLICTED_BY: + case UNIT_BEFORE: + case UNIT_AFTER: + case UNIT_ON_FAILURE: + case UNIT_TRIGGERS: + case UNIT_TRIGGERED_BY: + if (streq_ptr(id, other)) + log_warning_unit(id, "Dependency %s=%s dropped from unit %s", + unit_dependency_to_string(dependency), id, other); + else + log_warning_unit(id, "Dependency %s=%s dropped from unit %s merged into %s", + unit_dependency_to_string(dependency), id, + strna(other), id); + return -EINVAL; + + case _UNIT_DEPENDENCY_MAX: + case _UNIT_DEPENDENCY_INVALID: + break; + } + assert_not_reached("Invalid dependency type"); +} + int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_reference) { static const UnitDependency inverse_table[_UNIT_DEPENDENCY_MAX] = { @@ -1960,6 +2030,7 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen [UNIT_JOINS_NAMESPACE_OF] = UNIT_JOINS_NAMESPACE_OF, }; int r, q = 0, v = 0, w = 0; + Unit *orig_u = u, *orig_other = other; assert(u); assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX); @@ -1970,8 +2041,10 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen /* We won't allow dependencies on ourselves. We will not * consider them an error however. */ - if (u == other) + if (u == other) { + maybe_warn_about_dependency(orig_u->id, orig_other->id, d); return 0; + } r = set_ensure_allocated(&u->dependencies[d], trivial_hash_func, trivial_compare_func); if (r < 0) @@ -2159,11 +2232,8 @@ int unit_add_two_dependencies_by_name_inverse(Unit *u, UnitDependency d, UnitDep } int set_unit_path(const char *p) { - _cleanup_free_ char *c = NULL; - /* This is mostly for debug purposes */ - c = path_make_absolute_cwd(p); - if (setenv("SYSTEMD_UNIT_PATH", c, 0) < 0) + if (setenv("SYSTEMD_UNIT_PATH", p, 0) < 0) return -errno; return 0; @@ -2961,68 +3031,55 @@ ExecRuntime *unit_get_exec_runtime(Unit *u) { return *(ExecRuntime**) ((uint8_t*) u + offset); } -static int drop_in_file(Unit *u, UnitSetPropertiesMode mode, const char *name, char **_p, char **_q) { - _cleanup_free_ char *b = NULL; - char *p, *q; - int r; - - assert(u); - assert(name); - assert(_p); - assert(_q); - - b = xescape(name, "/."); - if (!b) - return -ENOMEM; - - if (!filename_is_safe(b)) - return -EINVAL; - +static int unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode, bool transient, char **dir) { if (u->manager->running_as == SYSTEMD_USER) { - _cleanup_free_ char *c = NULL; + int r; - r = user_config_home(&c); - if (r < 0) - return r; + r = user_config_home(dir); if (r == 0) return -ENOENT; + return r; + } - p = strjoin(c, "/", u->id, ".d", NULL); - } else if (mode == UNIT_PERSISTENT && !u->transient) - p = strjoin("/etc/systemd/system/", u->id, ".d", NULL); + if (mode == UNIT_PERSISTENT && !transient) + *dir = strdup("/etc/systemd/system"); else - p = strjoin("/run/systemd/system/", u->id, ".d", NULL); - if (!p) + *dir = strdup("/run/systemd/system"); + if (!*dir) return -ENOMEM; - q = strjoin(p, "/90-", b, ".conf", NULL); - if (!q) { - free(p); - return -ENOMEM; - } - - *_p = p; - *_q = q; return 0; } +static int unit_drop_in_file(Unit *u, + UnitSetPropertiesMode mode, const char *name, char **p, char **q) { + _cleanup_free_ char *dir = NULL; + int r; + + assert(u); + + r = unit_drop_in_dir(u, mode, u->transient, &dir); + if (r < 0) + return r; + + return drop_in_file(dir, u->id, 50, name, p, q); +} + int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) { - _cleanup_free_ char *p = NULL, *q = NULL; + + _cleanup_free_ char *dir = NULL; int r; assert(u); - assert(name); - assert(data); if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) return 0; - r = drop_in_file(u, mode, name, &p, &q); + r = unit_drop_in_dir(u, mode, u->transient, &dir); if (r < 0) return r; - mkdir_p(p, 0755); - return write_string_file_atomic_label(q, data); + return write_drop_in(dir, u->id, 50, name, data); } int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) { @@ -3098,7 +3155,7 @@ int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name) { if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) return 0; - r = drop_in_file(u, mode, name, &p, &q); + r = unit_drop_in_file(u, mode, name, &p, &q); if (r < 0) return r;