diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index b21f8575a03..23aedc8d8dc 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -189,10 +189,10 @@ Scheduler. The available CPU time is split up among all units within one slice relative to their CPU time weight. A higher weight means more CPU time, a lower weight means less. - While StartupCPUWeight= only applies to the startup phase of the system, + While StartupCPUWeight= applies to the startup and shutdown phases of the system, CPUWeight= applies to normal runtime of the system, and if the former is not set also to - the startup phase. Using StartupCPUWeight= allows prioritizing specific services at - boot-up differently than during normal runtime. + the startup and shutdown phases. Using StartupCPUWeight= allows prioritizing specific services at + boot-up and shutdown differently than during normal runtime. These settings replace CPUShares= and StartupCPUShares=. @@ -247,10 +247,10 @@ of the CPUs will be used by the processes as it may be limited by parent units. The effective configuration is reported as EffectiveCPUs=. - While StartupAllowedCPUs= only applies to the startup phase of the system, + While StartupAllowedCPUs= applies to the startup and shutdown phases of the system, AllowedCPUs= applies to normal runtime of the system, and if the former is not set also to - the startup phase. Using StartupAllowedCPUs= allows prioritizing specific services at - boot-up differently than during normal runtime. + the startup and shutdown phases. Using StartupAllowedCPUs= allows prioritizing specific services at + boot-up and shutdown differently than during normal runtime. This setting is supported only with the unified control group hierarchy. @@ -269,10 +269,10 @@ guarantee that all of the memory NUMA nodes will be used by the processes as it may be limited by parent units. The effective configuration is reported as EffectiveMemoryNodes=. - While StartupAllowedMemoryNodes= only applies to the startup phase of the system, + While StartupAllowedMemoryNodes= applies to the startup and shutdown phases of the system, AllowedMemoryNodes= applies to normal runtime of the system, and if the former is not set also to - the startup phase. Using StartupAllowedMemoryNodes= allows prioritizing specific services at - boot-up differently than during normal runtime. + the startup and shutdown phases. Using StartupAllowedMemoryNodes= allows prioritizing specific services at + boot-up and shutdown differently than during normal runtime. This setting is supported only with the unified control group hierarchy. @@ -458,12 +458,12 @@ relative to their block I/O weight. A higher weight means more I/O bandwidth, a lower weight means less. - While StartupIOWeight= only applies - to the startup phase of the system, + While StartupIOWeight= applies + to the startup and shutdown phases of the system, IOWeight= applies to the later runtime of the system, and if the former is not set also to the startup - phase. This allows prioritizing specific services at boot-up - differently than during runtime. + and shutdown phases. This allows prioritizing specific services at boot-up + and shutdown differently than during runtime. These settings replace BlockIOWeight= and StartupBlockIOWeight= and disable settings prefixed with BlockIO or StartupBlockIO. @@ -1194,10 +1194,10 @@ DeviceAllow=/dev/loop-control The available CPU time is split up among all units within one slice relative to their CPU time share weight. - While StartupCPUShares= only applies to the startup phase of the system, + While StartupCPUShares= applies to the startup and shutdown phases of the system, CPUShares= applies to normal runtime of the system, and if the former is not set also to - the startup phase. Using StartupCPUShares= allows prioritizing specific services at - boot-up differently than during normal runtime. + the startup and shutdown phases. Using StartupCPUShares= allows prioritizing specific services at + boot-up and shutdown differently than during normal runtime. Implies CPUAccounting=yes. @@ -1254,11 +1254,11 @@ DeviceAllow=/dev/loop-control weight. While StartupBlockIOWeight= only - applies to the startup phase of the system, + applies to the startup and shutdown phases of the system, BlockIOWeight= applies to the later runtime of the system, and if the former is not set also to the - startup phase. This allows prioritizing specific services at - boot-up differently than during runtime. + startup and shutdown phases. This allows prioritizing specific services at + boot-up and shutdown differently than during runtime. Implies BlockIOAccounting=yes. diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 17e93d7af17..c19454e8bdd 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -68,6 +68,25 @@ bool manager_owns_host_root_cgroup(Manager *m) { return empty_or_root(m->cgroup_root); } +bool unit_has_startup_cgroup_constraints(Unit *u) { + assert(u); + + /* Returns true if this unit has any directives which apply during + * startup/shutdown phases. */ + + CGroupContext *c; + + c = unit_get_cgroup_context(u); + if (!c) + return false; + + return c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID || + c->startup_io_weight != CGROUP_WEIGHT_INVALID || + c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID || + c->startup_cpuset_cpus.set || + c->startup_cpuset_mems.set; +} + bool unit_has_host_root_cgroup(Unit *u) { assert(u); @@ -844,7 +863,7 @@ static bool cgroup_context_has_allowed_mems(CGroupContext *c) { } static uint64_t cgroup_context_cpu_weight(CGroupContext *c, ManagerState state) { - if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && + if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING, MANAGER_STOPPING) && c->startup_cpu_weight != CGROUP_WEIGHT_INVALID) return c->startup_cpu_weight; else if (c->cpu_weight != CGROUP_WEIGHT_INVALID) @@ -854,7 +873,7 @@ static uint64_t cgroup_context_cpu_weight(CGroupContext *c, ManagerState state) } static uint64_t cgroup_context_cpu_shares(CGroupContext *c, ManagerState state) { - if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && + if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING, MANAGER_STOPPING) && c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID) return c->startup_cpu_shares; else if (c->cpu_shares != CGROUP_CPU_SHARES_INVALID) @@ -864,7 +883,7 @@ static uint64_t cgroup_context_cpu_shares(CGroupContext *c, ManagerState state) } static CPUSet *cgroup_context_allowed_cpus(CGroupContext *c, ManagerState state) { - if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && + if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING, MANAGER_STOPPING) && c->startup_cpuset_cpus.set) return &c->startup_cpuset_cpus; else @@ -872,7 +891,7 @@ static CPUSet *cgroup_context_allowed_cpus(CGroupContext *c, ManagerState state) } static CPUSet *cgroup_context_allowed_mems(CGroupContext *c, ManagerState state) { - if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && + if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING, MANAGER_STOPPING) && c->startup_cpuset_mems.set) return &c->startup_cpuset_mems; else @@ -993,7 +1012,7 @@ static bool cgroup_context_has_blockio_config(CGroupContext *c) { } static uint64_t cgroup_context_io_weight(CGroupContext *c, ManagerState state) { - if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && + if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING, MANAGER_STOPPING) && c->startup_io_weight != CGROUP_WEIGHT_INVALID) return c->startup_io_weight; else if (c->io_weight != CGROUP_WEIGHT_INVALID) @@ -1003,7 +1022,7 @@ static uint64_t cgroup_context_io_weight(CGroupContext *c, ManagerState state) { } static uint64_t cgroup_context_blkio_weight(CGroupContext *c, ManagerState state) { - if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && + if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING, MANAGER_STOPPING) && c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID) return c->startup_blockio_weight; else if (c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID) @@ -3971,7 +3990,7 @@ void manager_invalidate_startup_units(Manager *m) { assert(m); SET_FOREACH(u, m->startup_units) - unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_BLKIO); + unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_BLKIO|CGROUP_MASK_CPUSET); } static int unit_get_nice(Unit *u) { diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 951ddda525a..8795f2724eb 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -311,6 +311,8 @@ int unit_reset_accounting(Unit *u); bool manager_owns_host_root_cgroup(Manager *m); bool unit_has_host_root_cgroup(Unit *u); +bool unit_has_startup_cgroup_constraints(Unit *u); + int manager_notify_cgroup_empty(Manager *m, const char *group); void unit_invalidate_cgroup(Unit *u, CGroupMask m); diff --git a/src/core/job.c b/src/core/job.c index 6eb135785b1..6dd01a6f49d 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -1335,6 +1335,8 @@ void job_shutdown_magic(Job *j) { /* In case messages on console has been disabled on boot */ j->unit->manager->no_console_output = false; + manager_invalidate_startup_units(j->unit->manager); + if (detect_container() > 0) return; diff --git a/src/core/unit.c b/src/core/unit.c index 1a76abf8a16..4fd499a4f1d 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1557,15 +1557,7 @@ static int unit_add_oomd_dependencies(Unit *u) { } static int unit_add_startup_units(Unit *u) { - CGroupContext *c; - - c = unit_get_cgroup_context(u); - if (!c) - return 0; - - if (c->startup_cpu_shares == CGROUP_CPU_SHARES_INVALID && - c->startup_io_weight == CGROUP_WEIGHT_INVALID && - c->startup_blockio_weight == CGROUP_BLKIO_WEIGHT_INVALID) + if (!unit_has_startup_cgroup_constraints(u)) return 0; return set_ensure_put(&u->manager->startup_units, NULL, u); diff --git a/test/fuzz/fuzz-unit-file/directives.mount b/test/fuzz/fuzz-unit-file/directives.mount index da33c99de35..33c44c79c5d 100644 --- a/test/fuzz/fuzz-unit-file/directives.mount +++ b/test/fuzz/fuzz-unit-file/directives.mount @@ -1,9 +1,7 @@ mount [Mount] AllowedCPUs= -StartupAllowedCPUs= AllowedMemoryNodes= -StartupAllowedMemoryNodes= AmbientCapabilities= AppArmorProfile= BPFProgram= @@ -174,6 +172,8 @@ StandardInput= StandardInputData= StandardInputText= StandardOutput= +StartupAllowedCPUs= +StartupAllowedMemoryNodes= StartupBlockIOWeight= StartupCPUShares= StartupCPUWeight= diff --git a/test/fuzz/fuzz-unit-file/directives.scope b/test/fuzz/fuzz-unit-file/directives.scope index d8ea9fcfb54..aa91ebbf588 100644 --- a/test/fuzz/fuzz-unit-file/directives.scope +++ b/test/fuzz/fuzz-unit-file/directives.scope @@ -1,9 +1,7 @@ scope [Scope] AllowedCPUs= -StartupAllowedCPUs= AllowedMemoryNodes= -StartupAllowedMemoryNodes= BPFProgram= BlockIOAccounting= BlockIODeviceWeight= @@ -57,6 +55,8 @@ SendSIGKILL= Slice= SocketBindAllow= SocketBindDeny= +StartupAllowedCPUs= +StartupAllowedMemoryNodes= StartupBlockIOWeight= StartupCPUShares= StartupCPUWeight= diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service index 7318c5f9d69..d92d90e1181 100644 --- a/test/fuzz/fuzz-unit-file/directives.service +++ b/test/fuzz/fuzz-unit-file/directives.service @@ -115,9 +115,7 @@ RequiredBy= WantedBy= [Service] AllowedCPUs= -StartupAllowedCPUs= AllowedMemoryNodes= -StartupAllowedMemoryNodes= AmbientCapabilities= AppArmorProfile= BindPaths= @@ -308,6 +306,8 @@ StandardOutput= StartLimitAction= StartLimitBurst= StartLimitInterval= +StartupAllowedCPUs= +StartupAllowedMemoryNodes= StartupBlockIOWeight= StartupCPUShares= StartupCPUWeight= diff --git a/test/fuzz/fuzz-unit-file/directives.slice b/test/fuzz/fuzz-unit-file/directives.slice index 1a209876987..ab77070c5ea 100644 --- a/test/fuzz/fuzz-unit-file/directives.slice +++ b/test/fuzz/fuzz-unit-file/directives.slice @@ -1,9 +1,7 @@ slice [Slice] AllowedCPUs= -StartupAllowedCPUs= AllowedMemoryNodes= -StartupAllowedMemoryNodes= BPFProgram= BlockIOAccounting= BlockIODeviceWeight= @@ -50,6 +48,8 @@ RestrictNetworkInterfaces= Slice= SocketBindAllow= SocketBindDeny= +StartupAllowedCPUs= +StartupAllowedMemoryNodes= StartupBlockIOWeight= StartupCPUShares= StartupCPUWeight= diff --git a/test/fuzz/fuzz-unit-file/directives.socket b/test/fuzz/fuzz-unit-file/directives.socket index 02b909f00d2..fa28ff10421 100644 --- a/test/fuzz/fuzz-unit-file/directives.socket +++ b/test/fuzz/fuzz-unit-file/directives.socket @@ -2,9 +2,7 @@ socket [Socket] Accept= AllowedCPUs= -StartupAllowedCPUs= AllowedMemoryNodes= -StartupAllowedMemoryNodes= AmbientCapabilities= AppArmorProfile= BPFProgram= @@ -220,6 +218,8 @@ StandardInput= StandardInputData= StandardInputText= StandardOutput= +StartupAllowedCPUs= +StartupAllowedMemoryNodes= StartupBlockIOWeight= StartupCPUShares= StartupCPUWeight= diff --git a/test/fuzz/fuzz-unit-file/directives.swap b/test/fuzz/fuzz-unit-file/directives.swap index b7598fdf06f..abb3cd54e71 100644 --- a/test/fuzz/fuzz-unit-file/directives.swap +++ b/test/fuzz/fuzz-unit-file/directives.swap @@ -1,9 +1,7 @@ swap [Swap] AllowedCPUs= -StartupAllowedCPUs= AllowedMemoryNodes= -StartupAllowedMemoryNodes= AmbientCapabilities= AppArmorProfile= BPFProgram= @@ -170,6 +168,8 @@ StandardInput= StandardInputData= StandardInputText= StandardOutput= +StartupAllowedCPUs= +StartupAllowedMemoryNodes= StartupBlockIOWeight= StartupCPUShares= StartupCPUWeight=