static int slice_add_parent_slice(Slice *s) { char *a, *dash; Unit *parent; int r; assert(s); if (UNIT_ISSET(UNIT(s)->slice)) return 0; if (unit_has_name(UNIT(s), SPECIAL_ROOT_SLICE)) return 0; a = strdupa(UNIT(s)->id); dash = strrchr(a, '-'); if (dash) strcpy(dash, ".slice"); else a = (char*) SPECIAL_ROOT_SLICE; r = manager_load_unit(UNIT(s)->manager, a, NULL, NULL, &parent); if (r < 0) return r; unit_ref_set(&UNIT(s)->slice, parent); return 0; }
int scope_abandon(Scope *s) { assert(s); if (unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) return -EPERM; if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED)) return -ESTALE; s->controller = mfree(s->controller); /* The client is no longer watching the remaining processes, * so let's step in here, under the assumption that the * remaining processes will be sooner or later reassigned to * us as parent. */ unit_tidy_watch_pids(UNIT(s), 0, 0); unit_watch_all_pids(UNIT(s)); /* If the PID set is empty now, then let's finish this off */ if (set_isempty(UNIT(s)->pids)) scope_notify_cgroup_empty_event(UNIT(s)); else scope_set_state(s, SCOPE_ABANDONED); return 0; }
static int slice_verify(Slice *s) { assert(s); if (UNIT(s)->load_state != UNIT_LOADED) return 0; if (UNIT_DEREF(UNIT(s)->slice)) { char *a, *dash; a = strdupa(UNIT(s)->id); dash = strrchr(a, '-'); if (dash) strcpy(dash, ".slice"); else a = (char*) SPECIAL_ROOT_SLICE; if (!unit_has_name(UNIT_DEREF(UNIT(s)->slice), a)) { log_unit_error(UNIT(s)->id, "%s located outside its parent slice. Refusing.", UNIT(s)->id); return -EINVAL; } } return 0; }
static int automount_verify(Automount *a) { bool b; char *e; assert(a); if (UNIT(a)->load_state != UNIT_LOADED) return 0; if (path_equal(a->where, "/")) { log_error_unit(UNIT(a)->id, "Cannot have an automount unit for the root directory. Refusing."); return -EINVAL; } e = unit_name_from_path(a->where, ".automount"); if (!e) return -ENOMEM; b = unit_has_name(UNIT(a), e); free(e); if (!b) { log_error_unit(UNIT(a)->id, "%s's Where setting doesn't match unit name. Refusing.", UNIT(a)->id); return -EINVAL; } return 0; }
static int slice_verify(Slice *s) { _cleanup_free_ char *parent = NULL; int r; assert(s); if (UNIT(s)->load_state != UNIT_LOADED) return 0; if (!slice_name_is_valid(UNIT(s)->id)) { log_unit_error(UNIT(s), "Slice name %s is not valid. Refusing.", UNIT(s)->id); return -EINVAL; } r = slice_build_parent_slice(UNIT(s)->id, &parent); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Failed to determine parent slice: %m"); if (parent ? !unit_has_name(UNIT_DEREF(UNIT(s)->slice), parent) : UNIT_ISSET(UNIT(s)->slice)) { log_unit_error(UNIT(s), "Located outside of parent slice. Refusing."); return -EINVAL; } return 0; }
static int automount_verify(Automount *a) { _cleanup_free_ char *e = NULL; int r; assert(a); if (UNIT(a)->load_state != UNIT_LOADED) return 0; if (path_equal(a->where, "/")) { log_unit_error(UNIT(a), "Cannot have an automount unit for the root directory. Refusing."); return -EINVAL; } r = unit_name_from_path(a->where, ".automount", &e); if (r < 0) return log_unit_error(UNIT(a), "Failed to generate unit name from path: %m"); if (!unit_has_name(UNIT(a), e)) { log_unit_error(UNIT(a), "Where= setting doesn't match unit name. Refusing."); return -EINVAL; } return 0; }
static int scope_verify(Scope *s) { assert(s); if (UNIT(s)->load_state != UNIT_LOADED) return 0; if (set_isempty(UNIT(s)->pids) && !MANAGER_IS_RELOADING(UNIT(s)->manager) && !unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) { log_unit_error(UNIT(s), "Scope has no PIDs. Refusing."); return -ENOENT; } return 0; }
static int scope_verify(Scope *s) { assert(s); if (UNIT(s)->load_state != UNIT_LOADED) return 0; if (set_isempty(UNIT(s)->pids) && !manager_is_reloading_or_reexecuting(UNIT(s)->manager) && !unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) { log_unit_error(UNIT(s), "Scope has no PIDs. Refusing."); return -EINVAL; } return 0; }
static int scope_start(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); if (unit_has_name(u, SPECIAL_INIT_SCOPE)) return -EPERM; if (s->state == SCOPE_FAILED) return -EPERM; /* We can't fulfill this right now, please try again later */ if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) return -EAGAIN; assert(s->state == SCOPE_DEAD); if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) return -ENOENT; (void) bus_scope_track_controller(s); r = unit_acquire_invocation_id(u); if (r < 0) return r; (void) unit_realize_cgroup(u); (void) unit_reset_cpu_accounting(u); (void) unit_reset_ip_accounting(u); unit_export_state_files(UNIT(s)); r = unit_attach_pids_to_cgroup(u, UNIT(s)->pids, NULL); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to add PIDs to scope's control group: %m"); scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); return r; } s->result = SCOPE_SUCCESS; scope_set_state(s, SCOPE_RUNNING); /* Start watching the PIDs currently in the scope */ (void) unit_enqueue_rewatch_pids(UNIT(s)); return 1; }
static int busname_verify(BusName *n) { char *e; assert(n); if (UNIT(n)->load_state != UNIT_LOADED) return 0; if (!service_name_is_valid(n->name)) { log_unit_error(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id); return -EINVAL; } e = strjoina(n->name, ".busname"); if (!unit_has_name(UNIT(n), e)) { log_unit_error(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id); return -EINVAL; } return 0; }
int scope_abandon(Scope *s) { assert(s); if (unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) return -EPERM; if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED)) return -ESTALE; s->was_abandoned = true; s->controller = mfree(s->controller); s->controller_track = sd_bus_track_unref(s->controller_track); scope_set_state(s, SCOPE_ABANDONED); /* The client is no longer watching the remaining processes, so let's step in here, under the assumption that * the remaining processes will be sooner or later reassigned to us as parent. */ (void) unit_enqueue_rewatch_pids(UNIT(s)); return 0; }
static int scope_load_init_scope(Unit *u) { assert(u); if (!unit_has_name(u, SPECIAL_INIT_SCOPE)) return 0; u->transient = true; u->perpetual = true; /* init.scope is a bit special, as it has to stick around forever. Because of its special semantics we * synthesize it here, instead of relying on the unit file on disk. */ u->default_dependencies = false; /* Prettify things, if we can. */ if (!u->description) u->description = strdup("System and Service Manager"); if (!u->documentation) (void) strv_extend(&u->documentation, "man:systemd(1)"); return 1; }
static int scope_start(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); if (unit_has_name(u, SPECIAL_INIT_SCOPE)) return -EPERM; if (s->state == SCOPE_FAILED) return -EPERM; /* We can't fulfill this right now, please try again later */ if (s->state == SCOPE_STOP_SIGTERM || s->state == SCOPE_STOP_SIGKILL) return -EAGAIN; assert(s->state == SCOPE_DEAD); if (!u->transient && !manager_is_reloading_or_reexecuting(u->manager)) return -ENOENT; (void) unit_realize_cgroup(u); (void) unit_reset_cpu_usage(u); r = unit_attach_pids_to_cgroup(u); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to add PIDs to scope's control group: %m"); scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); return r; } s->result = SCOPE_SUCCESS; scope_set_state(s, SCOPE_RUNNING); return 1; }