diff options
Diffstat (limited to 'src/core/unit.c')
-rw-r--r-- | src/core/unit.c | 302 |
1 files changed, 164 insertions, 138 deletions
diff --git a/src/core/unit.c b/src/core/unit.c index 8c07c6140d..e3ab74b8fa 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -125,6 +125,7 @@ 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->tasks_accounting = u->manager->default_tasks_accounting; } ec = unit_get_exec_context(u); @@ -445,13 +446,13 @@ static void unit_free_requires_mounts_for(Unit *u) { } } - strv_free(u->requires_mounts_for); - u->requires_mounts_for = NULL; + u->requires_mounts_for = strv_free(u->requires_mounts_for); } static void unit_done(Unit *u) { ExecContext *ec; CGroupContext *cc; + int r; assert(u); @@ -468,6 +469,10 @@ static void unit_done(Unit *u) { cc = unit_get_cgroup_context(u); if (cc) cgroup_context_done(cc); + + r = unit_remove_from_netclass_cgroup(u); + if (r < 0) + log_warning_errno(r, "Unable to remove unit from netclass group: %m"); } void unit_free(Unit *u) { @@ -528,7 +533,7 @@ void unit_free(Unit *u) { unit_release_cgroup(u); - manager_update_failed_units(u->manager, u, false); + (void) manager_update_failed_units(u->manager, u, false); set_remove(u->manager->startup_units, u); free(u->description); @@ -674,8 +679,7 @@ static void merge_dependencies(Unit *u, Unit *other, const char *other_id, UnitD /* The move cannot fail. The caller must have performed a reservation. */ assert_se(complete_move(&u->dependencies[d], &other->dependencies[d]) == 0); - set_free(other->dependencies[d]); - other->dependencies[d] = NULL; + other->dependencies[d] = set_free(other->dependencies[d]); } int unit_merge(Unit *u, Unit *other) { @@ -1125,12 +1129,12 @@ static int unit_add_slice_dependencies(Unit *u) { return 0; if (UNIT_ISSET(u->slice)) - return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, UNIT_DEREF(u->slice), true); + return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT_DEREF(u->slice), true); - if (streq(u->id, SPECIAL_ROOT_SLICE)) + if (unit_has_name(u, SPECIAL_ROOT_SLICE)) return 0; - return unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, SPECIAL_ROOT_SLICE, NULL, true); + return unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_ROOT_SLICE, NULL, true); } static int unit_add_mount_dependencies(Unit *u) { @@ -1143,13 +1147,23 @@ static int unit_add_mount_dependencies(Unit *u) { char prefix[strlen(*i) + 1]; PATH_FOREACH_PREFIX_MORE(prefix, *i) { + _cleanup_free_ char *p = NULL; Unit *m; - r = manager_get_unit_by_path(u->manager, prefix, ".mount", &m); + r = unit_name_from_path(prefix, ".mount", &p); if (r < 0) return r; - if (r == 0) + + m = manager_get_unit(u->manager, p); + if (!m) { + /* Make sure to load the mount unit if + * it exists. If so the dependencies + * on this unit will be added later + * during the loading of the mount + * unit. */ + (void) manager_load_unit_prepare(u->manager, p, NULL, NULL, &m); continue; + } if (m == u) continue; @@ -1173,15 +1187,20 @@ static int unit_add_mount_dependencies(Unit *u) { static int unit_add_startup_units(Unit *u) { CGroupContext *c; + int r; c = unit_get_cgroup_context(u); if (!c) return 0; - if (c->startup_cpu_shares == (unsigned long) -1 && - c->startup_blockio_weight == (unsigned long) -1) + if (c->startup_cpu_shares == CGROUP_CPU_SHARES_INVALID && + c->startup_blockio_weight == CGROUP_BLKIO_WEIGHT_INVALID) return 0; + r = set_ensure_allocated(&u->manager->startup_units, NULL); + if (r < 0) + return r; + return set_put(u->manager->startup_units, u); } @@ -1237,6 +1256,14 @@ int unit_load(Unit *u) { } unit_update_cgroup_members_masks(u); + + /* If we are reloading, we need to wait for the deserializer + * to restore the net_cls ids that have been set previously */ + if (u->manager->n_reloading <= 0) { + r = unit_add_to_netclass_cgroup(u); + if (r < 0) + return r; + } } assert((u->load_state != UNIT_MERGED) == !u->merged_into); @@ -1416,6 +1443,7 @@ int unit_start(Unit *u) { assert(u); + /* Units that aren't loaded cannot be started */ if (u->load_state != UNIT_LOADED) return -EINVAL; @@ -1444,6 +1472,15 @@ int unit_start(Unit *u) { return -EPROTO; } + /* Units of types that aren't supported cannot be + * started. Note that we do this test only after the condition + * checks, so that we rather return condition check errors + * (which are usually not considered a true failure) than "not + * supported" errors (which are considered a failure). + */ + if (!unit_supported(u)) + return -EOPNOTSUPP; + /* Forward to the main object, if we aren't it. */ following = unit_following(u); if (following) { @@ -1451,9 +1488,6 @@ int unit_start(Unit *u) { return unit_start(following); } - if (!unit_supported(u)) - return -EOPNOTSUPP; - /* If it is stopped, but we cannot start it, then fail */ if (!UNIT_VTABLE(u)->start) return -EBADR; @@ -1472,6 +1506,12 @@ int unit_start(Unit *u) { bool unit_can_start(Unit *u) { assert(u); + if (u->load_state != UNIT_LOADED) + return false; + + if (!unit_supported(u)) + return false; + return !!UNIT_VTABLE(u)->start; } @@ -1795,7 +1835,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su } /* Keep track of failed units */ - manager_update_failed_units(u->manager, u, ns == UNIT_FAILED); + (void) 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)) @@ -1995,16 +2035,16 @@ int unit_watch_pid(Unit *u, pid_t pid) { if (r < 0) return r; - r = hashmap_put(u->manager->watch_pids1, LONG_TO_PTR(pid), u); + r = hashmap_put(u->manager->watch_pids1, PID_TO_PTR(pid), u); if (r == -EEXIST) { r = hashmap_ensure_allocated(&u->manager->watch_pids2, NULL); if (r < 0) return r; - r = hashmap_put(u->manager->watch_pids2, LONG_TO_PTR(pid), u); + r = hashmap_put(u->manager->watch_pids2, PID_TO_PTR(pid), u); } - q = set_put(u->pids, LONG_TO_PTR(pid)); + q = set_put(u->pids, PID_TO_PTR(pid)); if (q < 0) return q; @@ -2015,16 +2055,16 @@ void unit_unwatch_pid(Unit *u, pid_t pid) { assert(u); assert(pid >= 1); - (void) hashmap_remove_value(u->manager->watch_pids1, LONG_TO_PTR(pid), u); - (void) hashmap_remove_value(u->manager->watch_pids2, LONG_TO_PTR(pid), u); - (void) set_remove(u->pids, LONG_TO_PTR(pid)); + (void) hashmap_remove_value(u->manager->watch_pids1, PID_TO_PTR(pid), u); + (void) hashmap_remove_value(u->manager->watch_pids2, PID_TO_PTR(pid), u); + (void) set_remove(u->pids, PID_TO_PTR(pid)); } void unit_unwatch_all_pids(Unit *u) { assert(u); while (!set_isempty(u->pids)) - unit_unwatch_pid(u, PTR_TO_LONG(set_first(u->pids))); + unit_unwatch_pid(u, PTR_TO_PID(set_first(u->pids))); u->pids = set_free(u->pids); } @@ -2038,7 +2078,7 @@ void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2) { /* Cleans dead PIDs from our list */ SET_FOREACH(e, u->pids, i) { - pid_t pid = PTR_TO_LONG(e); + pid_t pid = PTR_TO_PID(e); if (pid == except1 || pid == except2) continue; @@ -2280,44 +2320,6 @@ int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency return unit_add_two_dependencies(u, d, e, other, add_reference); } -int unit_add_dependency_by_name_inverse(Unit *u, UnitDependency d, const char *name, const char *path, bool add_reference) { - _cleanup_free_ char *buf = NULL; - Unit *other; - int r; - - assert(u); - assert(name || path); - - r = resolve_template(u, name, path, &buf, &name); - if (r < 0) - return r; - - r = manager_load_unit(u->manager, name, path, NULL, &other); - if (r < 0) - return r; - - return unit_add_dependency(other, d, u, add_reference); -} - -int unit_add_two_dependencies_by_name_inverse(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) { - _cleanup_free_ char *buf = NULL; - Unit *other; - int r; - - assert(u); - assert(name || path); - - r = resolve_template(u, name, path, &buf, &name); - if (r < 0) - return r; - - r = manager_load_unit(u->manager, name, path, NULL, &other); - if (r < 0) - return r; - - return unit_add_two_dependencies(other, d, e, u, add_reference); -} - int set_unit_path(const char *p) { /* This is mostly for debug purposes */ if (setenv("SYSTEMD_UNIT_PATH", p, 0) < 0) @@ -2468,26 +2470,23 @@ static int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd return 0; } -int unit_install_bus_match(sd_bus *bus, Unit *u, const char *name) { - _cleanup_free_ char *match = NULL; - Manager *m = u->manager; +int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) { + const char *match; - assert(m); + assert(u); + assert(bus); + assert(name); if (u->match_bus_slot) return -EBUSY; - match = strjoin("type='signal'," + match = strjoina("type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," - "arg0='", - name, - "'", + "arg0='", name, "'", NULL); - if (!match) - return -ENOMEM; return sd_bus_add_match(bus, &u->match_bus_slot, match, signal_name_owner_changed, u); } @@ -2504,7 +2503,7 @@ int unit_watch_bus_name(Unit *u, const char *name) { if (u->manager->api_bus) { /* If the bus is already available, install the match directly. * Otherwise, just put the name in the list. bus_setup_api() will take care later. */ - r = unit_install_bus_match(u->manager->api_bus, u, name); + r = unit_install_bus_match(u, u->manager->api_bus, name); if (r < 0) return log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m"); } @@ -2574,6 +2573,9 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { unit_serialize_item(u, f, "cgroup", u->cgroup_path); unit_serialize_item(u, f, "cgroup-realized", yes_no(u->cgroup_realized)); + if (u->cgroup_netclass_id) + unit_serialize_item_format(u, f, "netclass-id", "%" PRIu32, u->cgroup_netclass_id); + if (serialize_jobs) { if (u->job) { fprintf(f, "job\n"); @@ -2591,6 +2593,62 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { return 0; } +int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) { + assert(u); + assert(f); + assert(key); + + if (!value) + return 0; + + fputs(key, f); + fputc('=', f); + fputs(value, f); + fputc('\n', f); + + return 1; +} + +int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value) { + _cleanup_free_ char *c = NULL; + + assert(u); + assert(f); + assert(key); + + if (!value) + return 0; + + c = cescape(value); + if (!c) + return -ENOMEM; + + fputs(key, f); + fputc('=', f); + fputs(c, f); + fputc('\n', f); + + return 1; +} + +int unit_serialize_item_fd(Unit *u, FILE *f, FDSet *fds, const char *key, int fd) { + int copy; + + assert(u); + assert(f); + assert(key); + + if (fd < 0) + return 0; + + copy = fdset_put_dup(fds, fd); + if (copy < 0) + return copy; + + fprintf(f, "%s=%i\n", key, copy); + return 1; +} + void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *format, ...) { va_list ap; @@ -2609,15 +2667,6 @@ void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *f fputc('\n', f); } -void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) { - assert(u); - assert(f); - assert(key); - assert(value); - - fprintf(f, "%s=%s\n", key, value); -} - int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { ExecRuntime **rt = NULL; size_t offset; @@ -2761,6 +2810,17 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { u->cgroup_realized = b; continue; + } else if (streq(l, "netclass-id")) { + r = safe_atou32(v, &u->cgroup_netclass_id); + if (r < 0) + log_unit_debug(u, "Failed to parse netclass ID %s, ignoring.", v); + else { + r = unit_add_to_netclass_cgroup(u); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to add unit to netclass cgroup, ignoring: %m"); + } + + continue; } if (unit_can_serialize(u)) { @@ -2993,13 +3053,13 @@ static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) { /* Exclude the main/control pids from being killed via the cgroup */ if (main_pid > 0) { - r = set_put(pid_set, LONG_TO_PTR(main_pid)); + r = set_put(pid_set, PID_TO_PTR(main_pid)); if (r < 0) goto fail; } if (control_pid > 0) { - r = set_put(pid_set, LONG_TO_PTR(control_pid)); + r = set_put(pid_set, PID_TO_PTR(control_pid)); if (r < 0) goto fail; } @@ -3020,32 +3080,39 @@ int unit_kill_common( sd_bus_error *error) { int r = 0; + bool killed = false; - if (who == KILL_MAIN) { + if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL)) { if (main_pid < 0) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type)); else if (main_pid == 0) return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill"); } - if (who == KILL_CONTROL) { + if (IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL)) { if (control_pid < 0) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type)); else if (control_pid == 0) return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill"); } - if (who == KILL_CONTROL || who == KILL_ALL) - if (control_pid > 0) + if (IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL, KILL_ALL, KILL_ALL_FAIL)) + if (control_pid > 0) { if (kill(control_pid, signo) < 0) r = -errno; + else + killed = true; + } - if (who == KILL_MAIN || who == KILL_ALL) - if (main_pid > 0) + if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL, KILL_ALL, KILL_ALL_FAIL)) + if (main_pid > 0) { if (kill(main_pid, signo) < 0) r = -errno; + else + killed = true; + } - if (who == KILL_ALL && u->cgroup_path) { + if (IN_SET(who, KILL_ALL, KILL_ALL_FAIL) && u->cgroup_path) { _cleanup_set_free_ Set *pid_set = NULL; int q; @@ -3057,8 +3124,13 @@ int unit_kill_common( q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, false, false, pid_set); if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT) r = q; + else + killed = true; } + if (r == 0 && !killed && IN_SET(who, KILL_ALL_FAIL, KILL_CONTROL_FAIL, KILL_ALL_FAIL)) + return -ESRCH; + return r; } @@ -3255,19 +3327,6 @@ static int unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode, bool transient, 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 *dir = NULL, *p = NULL, *q = NULL; @@ -3366,28 +3425,6 @@ int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const return unit_write_drop_in_private(u, mode, name, p); } -int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name) { - _cleanup_free_ char *p = NULL, *q = NULL; - int r; - - assert(u); - - if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) - return 0; - - r = unit_drop_in_file(u, mode, name, &p, &q); - if (r < 0) - return r; - - if (unlink(q) < 0) - r = errno == ENOENT ? 0 : -errno; - else - r = 1; - - rmdir(p); - return r; -} - int unit_make_transient(Unit *u) { assert(u); @@ -3497,7 +3534,7 @@ int unit_kill_context( * them.*/ if (cg_unified() > 0 || - (detect_container(NULL) == 0 && !unit_cgroup_delegate(u))) + (detect_container() == 0 && !unit_cgroup_delegate(u))) wait_for_exit = true; if (c->send_sighup && k != KILL_KILL) { @@ -3673,14 +3710,3 @@ int unit_fail_if_symlink(Unit *u, const char* where) { return -ELOOP; } - -static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = { - [UNIT_ACTIVE] = "active", - [UNIT_RELOADING] = "reloading", - [UNIT_INACTIVE] = "inactive", - [UNIT_FAILED] = "failed", - [UNIT_ACTIVATING] = "activating", - [UNIT_DEACTIVATING] = "deactivating" -}; - -DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState); |