X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Funit.c;h=15e0a820209e7b66a4f6c484aad21f26193957b7;hb=2f38577f3040eedebfe1ace05d5b5a779a588af1;hp=27119b0cd72880797ed770d762b6dc30dc827c36;hpb=68eda4bd168306f51c90e5d22824c494d709289e;p=elogind.git diff --git a/src/core/unit.c b/src/core/unit.c index 27119b0cd..15e0a8202 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -171,7 +171,7 @@ int unit_add_name(Unit *u, const char *text) { u->id = s; u->instance = i; - LIST_PREPEND(Unit, units_by_type, u->manager->units_by_type[t], u); + LIST_PREPEND(units_by_type, u->manager->units_by_type[t], u); if (UNIT_VTABLE(u)->init) UNIT_VTABLE(u)->init(u); @@ -284,7 +284,7 @@ void unit_add_to_load_queue(Unit *u) { if (u->load_state != UNIT_STUB || u->in_load_queue) return; - LIST_PREPEND(Unit, load_queue, u->manager->load_queue, u); + LIST_PREPEND(load_queue, u->manager->load_queue, u); u->in_load_queue = true; } @@ -294,7 +294,7 @@ void unit_add_to_cleanup_queue(Unit *u) { if (u->in_cleanup_queue) return; - LIST_PREPEND(Unit, cleanup_queue, u->manager->cleanup_queue, u); + LIST_PREPEND(cleanup_queue, u->manager->cleanup_queue, u); u->in_cleanup_queue = true; } @@ -307,7 +307,7 @@ void unit_add_to_gc_queue(Unit *u) { if (unit_check_gc(u)) return; - LIST_PREPEND(Unit, gc_queue, u->manager->gc_queue, u); + LIST_PREPEND(gc_queue, u->manager->gc_queue, u); u->in_gc_queue = true; u->manager->n_in_gc_queue ++; @@ -326,7 +326,7 @@ void unit_add_to_dbus_queue(Unit *u) { return; } - LIST_PREPEND(Unit, dbus_queue, u->manager->dbus_unit_queue, u); + LIST_PREPEND(dbus_queue, u->manager->dbus_unit_queue, u); u->in_dbus_queue = true; } @@ -374,6 +374,34 @@ static void unit_remove_transient(Unit *u) { } } +static void unit_free_requires_mounts_for(Unit *u) { + char **j; + + STRV_FOREACH(j, u->requires_mounts_for) { + char s[strlen(*j) + 1]; + + PATH_FOREACH_PREFIX_MORE(s, *j) { + char *y; + Set *x; + + x = hashmap_get2(u->manager->units_requiring_mounts_for, s, (void**) &y); + if (!x) + continue; + + set_remove(x, u); + + if (set_isempty(x)) { + hashmap_remove(u->manager->units_requiring_mounts_for, y); + free(y); + set_free(x); + } + } + } + + strv_free(u->requires_mounts_for); + u->requires_mounts_for = NULL; +} + void unit_free(Unit *u) { UnitDependency d; Iterator i; @@ -390,6 +418,8 @@ void unit_free(Unit *u) { if (UNIT_VTABLE(u)->done) UNIT_VTABLE(u)->done(u); + unit_free_requires_mounts_for(u); + SET_FOREACH(t, u->names, i) hashmap_remove_value(u->manager->units, t, u); @@ -408,30 +438,25 @@ void unit_free(Unit *u) { 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); + LIST_REMOVE(units_by_type, u->manager->units_by_type[u->type], u); if (u->in_load_queue) - LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u); + LIST_REMOVE(load_queue, u->manager->load_queue, u); if (u->in_dbus_queue) - LIST_REMOVE(Unit, dbus_queue, u->manager->dbus_unit_queue, u); + LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u); if (u->in_cleanup_queue) - LIST_REMOVE(Unit, cleanup_queue, u->manager->cleanup_queue, u); + LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u); if (u->in_gc_queue) { - LIST_REMOVE(Unit, gc_queue, u->manager->gc_queue, u); + LIST_REMOVE(gc_queue, u->manager->gc_queue, u); u->manager->n_in_gc_queue--; } if (u->in_cgroup_queue) - LIST_REMOVE(Unit, cgroup_queue, u->manager->cgroup_queue, u); + LIST_REMOVE(cgroup_queue, u->manager->cgroup_queue, u); if (u->cgroup_path) { hashmap_remove(u->manager->cgroup_unit, u->cgroup_path); @@ -921,13 +946,51 @@ static int unit_add_default_dependencies(Unit *u) { return 0; } +static int unit_add_mount_links(Unit *u) { + char **i; + int r; + + assert(u); + + STRV_FOREACH(i, u->requires_mounts_for) { + char prefix[strlen(*i) + 1]; + + PATH_FOREACH_PREFIX_MORE(prefix, *i) { + Unit *m; + + r = manager_get_unit_by_path(u->manager, prefix, ".mount", &m); + if (r < 0) + return r; + if (r == 0) + continue; + if (m == u) + continue; + + if (m->load_state != UNIT_LOADED) + continue; + + r = unit_add_dependency(u, UNIT_AFTER, m, true); + if (r < 0) + return r; + + if (m->fragment_path) { + r = unit_add_dependency(u, UNIT_REQUIRES, m, true); + if (r < 0) + return r; + } + } + } + + return 0; +} + int unit_load(Unit *u) { int r; assert(u); if (u->in_load_queue) { - LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u); + LIST_REMOVE(load_queue, u->manager->load_queue, u); u->in_load_queue = false; } @@ -990,7 +1053,7 @@ fail: return r; } -bool unit_condition_test(Unit *u) { +static bool unit_condition_test(Unit *u) { assert(u); dual_timestamp_get(&u->condition_timestamp); @@ -1429,7 +1492,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su if (m->n_on_console == 0) /* unset no_console_output flag, since the console is free */ - m->no_console_output = 0; + m->no_console_output = false; } else m->n_on_console ++; } @@ -2093,28 +2156,6 @@ int unit_load_related_unit(Unit *u, const char *type, Unit **_found) { return r; } -int unit_get_related_unit(Unit *u, const char *type, Unit **_found) { - _cleanup_free_ char *t = NULL; - Unit *found; - - assert(u); - assert(type); - assert(_found); - - t = unit_name_change_suffix(u->id, type); - if (!t) - return -ENOMEM; - - assert(!unit_has_name(u, t)); - - found = manager_get_unit(u->manager, t); - if (!found) - return -ENOENT; - - *_found = found; - return 0; -} - int unit_watch_bus_name(Unit *u, const char *name) { assert(u); assert(name); @@ -2329,7 +2370,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { free(u->cgroup_path); u->cgroup_path = s; - hashmap_put(u->manager->cgroup_unit, s, u); + assert(hashmap_put(u->manager->cgroup_unit, s, u) == 1); continue; } @@ -2645,7 +2686,7 @@ Unit* unit_ref_set(UnitRef *ref, Unit *u) { unit_ref_unset(ref); ref->unit = u; - LIST_PREPEND(UnitRef, refs, u->refs, ref); + LIST_PREPEND(refs, u->refs, ref); return u; } @@ -2655,49 +2696,10 @@ void unit_ref_unset(UnitRef *ref) { if (!ref->unit) return; - LIST_REMOVE(UnitRef, refs, ref->unit->refs, ref); + LIST_REMOVE(refs, ref->unit->refs, 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; -} - int unit_exec_context_defaults(Unit *u, ExecContext *c) { unsigned i; int r; @@ -2884,6 +2886,9 @@ int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name) { return 0; r = drop_in_file(u, mode, name, &p, &q); + if (r < 0) + return r; + if (unlink(q) < 0) r = errno == ENOENT ? 0 : -errno; else @@ -3012,6 +3017,86 @@ int unit_kill_context( return wait_for_exit; } +int unit_require_mounts_for(Unit *u, const char *path) { + char prefix[strlen(path) + 1], *p; + int r; + + assert(u); + assert(path); + + /* Registers a unit for requiring a certain path and all its + * prefixes. We keep a simple array of these paths in the + * unit, since its usually short. However, we build a prefix + * table for all possible prefixes so that new appearing mount + * units can easily determine which units to make themselves a + * dependency of. */ + + p = strdup(path); + if (!p) + return -ENOMEM; + + path_kill_slashes(p); + + if (!path_is_absolute(p)) { + free(p); + return -EINVAL; + } + + if (!path_is_safe(p)) { + free(p); + return -EPERM; + } + + if (strv_contains(u->requires_mounts_for, p)) { + free(p); + return 0; + } + + r = strv_push(&u->requires_mounts_for, p); + if (r < 0) { + free(p); + return r; + } + + PATH_FOREACH_PREFIX_MORE(prefix, p) { + Set *x; + + x = hashmap_get(u->manager->units_requiring_mounts_for, prefix); + if (!x) { + char *q; + + if (!u->manager->units_requiring_mounts_for) { + u->manager->units_requiring_mounts_for = hashmap_new(string_hash_func, string_compare_func); + if (!u->manager->units_requiring_mounts_for) + return -ENOMEM; + } + + q = strdup(prefix); + if (!q) + return -ENOMEM; + + x = set_new(NULL, NULL); + if (!x) { + free(q); + return -ENOMEM; + } + + r = hashmap_put(u->manager->units_requiring_mounts_for, q, x); + if (r < 0) { + free(q); + set_free(x); + return r; + } + } + + r = set_put(x, u); + if (r < 0) + return r; + } + + return 0; +} + static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = { [UNIT_ACTIVE] = "active", [UNIT_RELOADING] = "reloading",