((u->cgroup_enabled_mask | enable_mask) & CGROUP_MASK_V2) == (u->cgroup_enabled_mask & CGROUP_MASK_V2);
}
-void unit_add_to_cgroup_realize_queue(Unit *u) {
+static void unit_add_to_cgroup_realize_queue(Unit *u) {
assert(u);
if (u->in_cgroup_realize_queue)
return n;
}
-static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) {
+void unit_add_siblings_to_cgroup_realize_queue(Unit *u) {
Unit *slice;
+ Unit *p = u;
/* This adds the path from the specified unit to root slice to the queue and siblings at each level.
+ * The unit itself is excluded (assuming it's handled separately).
*
* Propagation of realization "side-ways" (i.e. towards siblings) is relevant on cgroup-v1 where
* scheduling becomes very weird if two units that own processes reside in the same slice, but one is
* at all are always realized in *all* their hierarchies, and it is sufficient for a unit's sibling
* to be realized for the unit itself to be realized too. */
- while ((slice = UNIT_DEREF(u->slice))) {
+ while ((slice = UNIT_DEREF(p->slice))) {
Iterator i;
Unit *m;
void *v;
/* Skip units that have a dependency on the slice but aren't actually in it. */
if (UNIT_DEREF(m->slice) != slice)
continue;
+ /* The origin must be handled separately by caller */
+ if (m == u)
+ continue;
/* No point in doing cgroup application for units without active processes. */
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(m)))
unit_add_to_cgroup_realize_queue(m);
}
- u = slice;
+ p = slice;
}
/* Root slice comes last */
- unit_add_to_cgroup_realize_queue(u);
+ if (p != u)
+ unit_add_to_cgroup_realize_queue(p);
}
int unit_realize_cgroup(Unit *u) {
void unit_invalidate_cgroup_members_masks(Unit *u);
-void unit_add_to_cgroup_realize_queue(Unit *u);
+void unit_add_siblings_to_cgroup_realize_queue(Unit *u);
const char *unit_get_realized_cgroup_path(Unit *u, CGroupMask mask);
char *unit_default_cgroup_path(const Unit *u);
if (!u)
return;
- if (UNIT_ISSET(u->slice)) {
- /* A unit is being dropped from the tree, make sure our parent slice recalculates the member mask */
- unit_invalidate_cgroup_members_masks(UNIT_DEREF(u->slice));
-
- /* And make sure the parent is realized again, updating cgroup memberships */
- unit_add_to_cgroup_realize_queue(UNIT_DEREF(u->slice));
- }
-
u->transient_file = safe_fclose(u->transient_file);
if (!MANAGER_IS_RELOADING(u->manager))
for (UnitDependency d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
bidi_set_free(u, u->dependencies[d]);
+ /* A unit is being dropped from the tree, make sure our siblings and ancestor slices are realized
+ * properly. Do this after we detach the unit from slice tree in order to eliminate its effect on
+ * controller masks. */
+ if (UNIT_ISSET(u->slice)) {
+ unit_invalidate_cgroup_members_masks(UNIT_DEREF(u->slice));
+ unit_add_siblings_to_cgroup_realize_queue(u);
+ }
+
if (u->on_console)
manager_unref_console(u->manager);