@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as JoinsNamespaceOf = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly as SliceOf = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as RequiresMountsFor = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Documentation = ['...', ...];
<!--property JoinsNamespaceOf is not documented!-->
+ <!--property SliceOf is not documented!-->
+
<!--property FreezerState is not documented!-->
<!--property DropInPaths is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="JoinsNamespaceOf"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="SliceOf"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="RequiresMountsFor"/>
<variablelist class="dbus-property" generated="True" extra-ref="Documentation"/>
[UNIT_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf",
[UNIT_REFERENCES] = "References",
[UNIT_REFERENCED_BY] = "ReferencedBy",
+ [UNIT_IN_SLICE] = "InSlice",
+ [UNIT_SLICE_OF] = "SliceOf",
};
DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);
UNIT_REFERENCES, /* Inverse of 'references' is 'referenced_by' */
UNIT_REFERENCED_BY,
+ /* Slice= */
+ UNIT_IN_SLICE,
+ UNIT_SLICE_OF,
+
_UNIT_DEPENDENCY_MAX,
_UNIT_DEPENDENCY_INVALID = -EINVAL,
} UnitDependency;
if (u->type == UNIT_SLICE) {
Unit *member;
- UNIT_FOREACH_DEPENDENCY(member, u, UNIT_ATOM_BEFORE) {
- if (UNIT_DEREF(member->slice) != u)
- continue;
-
+ UNIT_FOREACH_DEPENDENCY(member, u, UNIT_ATOM_SLICE_OF)
u->cgroup_members_mask |= unit_get_subtree_mask(member); /* note that this calls ourselves again, for the children */
- }
}
u->cgroup_members_mask_valid = true;
if (u->type != UNIT_SLICE)
return 0;
- UNIT_FOREACH_DEPENDENCY(m, u, UNIT_ATOM_BEFORE) {
+ UNIT_FOREACH_DEPENDENCY(m, u, UNIT_ATOM_SLICE_OF) {
CGroupMask target_mask, enable_mask, new_target_mask, new_enable_mask;
int r;
- if (UNIT_DEREF(m->slice) != u)
- continue;
-
/* The cgroup for this unit might not actually be fully realised yet, in which case it isn't
* holding any controllers open anyway. */
if (!m->cgroup_realized)
/* Children of u likely changed when we're called */
u->cgroup_members_mask_valid = false;
- UNIT_FOREACH_DEPENDENCY(m, u, UNIT_ATOM_BEFORE) {
-
- /* Skip units that have a dependency on the slice but aren't actually in it. */
- if (UNIT_DEREF(m->slice) != u)
- continue;
+ UNIT_FOREACH_DEPENDENCY(m, u, UNIT_ATOM_SLICE_OF) {
/* No point in doing cgroup application for units without active processes. */
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(m)))
if (u->type == UNIT_SLICE) {
Unit *member;
- UNIT_FOREACH_DEPENDENCY(member, u, UNIT_ATOM_BEFORE) {
- if (UNIT_DEREF(member->slice) != u)
- continue;
-
+ UNIT_FOREACH_DEPENDENCY(member, u, UNIT_ATOM_SLICE_OF)
unit_invalidate_cgroup_bpf(member);
- }
}
}
SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SliceOf", "as", property_get_dependencies, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RequiresMountsFor", "as", property_get_requires_mounts_for, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST),
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit name '%s' is not a slice", s);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- r = unit_set_slice(u, slice);
+ r = unit_set_slice(u, slice, UNIT_DEPENDENCY_FILE);
if (r < 0)
return r;
return 0;
}
- r = unit_set_slice(u, slice);
+ r = unit_set_slice(u, slice, UNIT_DEPENDENCY_FILE);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to assign slice %s to unit %s, ignoring: %m", slice->id, u->id);
return 0;
}
static int slice_add_parent_slice(Slice *s) {
- Unit *u = UNIT(s), *parent;
+ Unit *u = UNIT(s);
_cleanup_free_ char *a = NULL;
int r;
if (r <= 0) /* 0 means root slice */
return r;
- r = manager_load_unit(u->manager, a, NULL, NULL, &parent);
- if (r < 0)
- return r;
-
- unit_ref_set(&u->slice, u, parent);
- return 0;
+ return unit_add_dependency_by_name(u, UNIT_IN_SLICE, a, true, UNIT_DEPENDENCY_IMPLICIT);
}
static int slice_add_default_dependencies(Slice *s) {
static bool slice_freezer_action_supported_by_children(Unit *s) {
Unit *member;
+ int r;
assert(s);
- UNIT_FOREACH_DEPENDENCY(member, s, UNIT_ATOM_BEFORE) {
- int r;
-
- if (UNIT_DEREF(member->slice) != s)
- continue;
+ UNIT_FOREACH_DEPENDENCY(member, s, UNIT_ATOM_SLICE_OF) {
if (member->type == UNIT_SLICE) {
r = slice_freezer_action_supported_by_children(member);
return 0;
}
- UNIT_FOREACH_DEPENDENCY(member, s, UNIT_ATOM_BEFORE) {
- if (UNIT_DEREF(member->slice) != s)
- continue;
-
+ UNIT_FOREACH_DEPENDENCY(member, s, UNIT_ATOM_SLICE_OF) {
if (action == FREEZER_FREEZE)
r = UNIT_VTABLE(member)->freeze(member);
else
[UNIT_JOINS_NAMESPACE_OF] = UNIT_ATOM_JOINS_NAMESPACE_OF,
[UNIT_REFERENCES] = UNIT_ATOM_REFERENCES,
[UNIT_REFERENCED_BY] = UNIT_ATOM_REFERENCED_BY,
+ [UNIT_IN_SLICE] = UNIT_ATOM_IN_SLICE,
+ [UNIT_SLICE_OF] = UNIT_ATOM_SLICE_OF,
/* These are dependency types without effect on our state engine. We maintain them only to make
* things discoverable/debuggable as they are the inverse dependencies to some of the above. As they
case UNIT_ATOM_REFERENCED_BY:
return UNIT_REFERENCED_BY;
+ case UNIT_ATOM_IN_SLICE:
+ return UNIT_IN_SLICE;
+
+ case UNIT_ATOM_SLICE_OF:
+ return UNIT_SLICE_OF;
+
default:
return _UNIT_DEPENDENCY_INVALID;
}
UNIT_ATOM_JOINS_NAMESPACE_OF = UINT64_C(1) << 29,
UNIT_ATOM_REFERENCES = UINT64_C(1) << 30,
UNIT_ATOM_REFERENCED_BY = UINT64_C(1) << 31,
- _UNIT_DEPENDENCY_ATOM_MAX = (UINT64_C(1) << 32) - 1,
+ UNIT_ATOM_IN_SLICE = UINT64_C(1) << 32,
+ UNIT_ATOM_SLICE_OF = UINT64_C(1) << 33,
+ _UNIT_DEPENDENCY_ATOM_MAX = (UINT64_C(1) << 34) - 1,
_UNIT_DEPENDENCY_ATOM_INVALID = -EINVAL,
} UnitDependencyAtom;
job_free(j);
}
- unit_clear_dependencies(u);
-
/* A unit is being dropped from the tree, make sure our family is realized properly. Do this after we
* detach the unit from slice tree in order to eliminate its effect on controller masks. */
slice = UNIT_GET_SLICE(u);
+ unit_clear_dependencies(u);
if (slice)
unit_add_family_to_cgroup_realize_queue(slice);
unit_unwatch_all_pids(u);
- unit_ref_unset(&u->slice);
while (u->refs_by_target)
unit_ref_unset(u->refs_by_target);
[UNIT_PROPAGATES_RELOAD_TO] = UNIT_RELOAD_PROPAGATED_FROM,
[UNIT_RELOAD_PROPAGATED_FROM] = UNIT_PROPAGATES_RELOAD_TO,
[UNIT_JOINS_NAMESPACE_OF] = UNIT_JOINS_NAMESPACE_OF, /* symmetric! 👓 */
+ [UNIT_IN_SLICE] = UNIT_SLICE_OF,
+ [UNIT_SLICE_OF] = UNIT_IN_SLICE,
};
Unit *original_u = u, *original_other = other;
UnitDependencyAtom a;
return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL),
"Requested dependency TriggeredBy=%s refused (%s units cannot trigger other units).", other->id, unit_type_to_string(other->type));
+ if (FLAGS_SET(a, UNIT_ATOM_IN_SLICE) && other->type != UNIT_SLICE)
+ return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL),
+ "Requested dependency Slice=%s refused (%s is not a slice unit).", other->id, other->id);
+ if (FLAGS_SET(a, UNIT_ATOM_SLICE_OF) && u->type != UNIT_SLICE)
+ return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL),
+ "Requested dependency SliceOf=%s refused (%s is not a slice unit).", other->id, u->id);
+
+ if (FLAGS_SET(a, UNIT_ATOM_IN_SLICE) && !UNIT_HAS_CGROUP_CONTEXT(u))
+ return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL),
+ "Requested dependency Slice=%s refused (%s is not a cgroup unit).", other->id, u->id);
+
+ if (FLAGS_SET(a, UNIT_ATOM_SLICE_OF) && !UNIT_HAS_CGROUP_CONTEXT(other))
+ return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL),
+ "Requested dependency SliceOf=%s refused (%s is not a cgroup unit).", other->id, other->id);
+
r = unit_add_dependency_hashmap(&u->dependencies, d, other, mask, 0);
if (r < 0)
return r;
return r;
}
-int unit_set_slice(Unit *u, Unit *slice) {
+int unit_set_slice(Unit *u, Unit *slice, UnitDependencyMask mask) {
+ int r;
+
assert(u);
assert(slice);
- /* Sets the unit slice if it has not been set before. Is extra
- * careful, to only allow this for units that actually have a
- * cgroup context. Also, we don't allow to set this for slices
- * (since the parent slice is derived from the name). Make
- * sure the unit we set is actually a slice. */
+ /* Sets the unit slice if it has not been set before. Is extra careful, to only allow this for units
+ * that actually have a cgroup context. Also, we don't allow to set this for slices (since the parent
+ * slice is derived from the name). Make sure the unit we set is actually a slice. */
if (!UNIT_HAS_CGROUP_CONTEXT(u))
return -EOPNOTSUPP;
if (UNIT_GET_SLICE(u) && u->cgroup_realized)
return -EBUSY;
- unit_ref_set(&u->slice, u, slice);
+ r = unit_add_dependency(u, UNIT_IN_SLICE, slice, true, mask);
+ if (r < 0)
+ return r;
+
return 1;
}
if (r < 0)
return r;
- return unit_set_slice(u, slice);
+ return unit_set_slice(u, slice, UNIT_DEPENDENCY_FILE);
}
const char *unit_slice_name(Unit *u) {
dual_timestamp active_exit_timestamp;
dual_timestamp inactive_enter_timestamp;
- UnitRef slice;
-
/* Per type list */
LIST_FIELDS(Unit, units_by_type);
}
static inline Unit* UNIT_GET_SLICE(const Unit *u) {
- assert(u);
- return u->slice.target;
+ return unit_has_dependency(u, UNIT_ATOM_IN_SLICE, NULL);
}
Unit* unit_new(Manager *m, size_t size);
int unit_load_fragment_and_dropin(Unit *u, bool fragment_required);
int unit_load(Unit *unit);
-int unit_set_slice(Unit *u, Unit *slice);
+int unit_set_slice(Unit *u, Unit *slice, UnitDependencyMask mask);
int unit_set_default_slice(Unit *u);
const char *unit_description(Unit *u) _pure_;