core: Rework recursive freeze/thaw
This commit overhauls the way freeze/thaw works recursively: First, it introduces new FreezerActions that are like the existing FREEZE and THAW but indicate that the action was initiated by a parent unit. We also refactored the code to pass these FreezerActions through the whole call stack so that we can make use of them. FreezerState was extended similarly, to be able to differentiate between a unit that's frozen manually and a unit that's frozen because a parent is frozen. Next, slices were changed to check recursively that all their child units can be frozen before it attempts to freeze them. This is different from the previous behavior, that would just check if the unit's type supported freezing at all. This cleans up the code, and also ensures that the behavior of slices corresponds to the unit's actual ability to be frozen Next, we make it so that if you FREEZE a slice, it'll PARENT_FREEZE all of its children. Similarly, if you THAW a slice it will PARENT_THAW its children. Finally, we use the new states available to us to refactor the code that actually does the cgroup freezing. The code now looks at the unit's existing freezer state and the action being requested, and decides what next state is most appropriate. Then it puts the unit in that state. For instance, a RUNNING unit with a request to PARENT_FREEZE will put the unit into the PARENT_FREEZING state. As another example, a FROZEN unit who's parent is also FROZEN will transition to PARENT_FROZEN in response to a request to THAW. Fixes https://github.com/systemd/systemd/issues/30640 Fixes https://github.com/systemd/systemd/issues/15850
This commit is contained in:
+23
-4
@@ -117,14 +117,33 @@ static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
|
||||
DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
|
||||
|
||||
static const char* const freezer_state_table[_FREEZER_STATE_MAX] = {
|
||||
[FREEZER_RUNNING] = "running",
|
||||
[FREEZER_FREEZING] = "freezing",
|
||||
[FREEZER_FROZEN] = "frozen",
|
||||
[FREEZER_THAWING] = "thawing",
|
||||
[FREEZER_RUNNING] = "running",
|
||||
[FREEZER_FREEZING] = "freezing",
|
||||
[FREEZER_FREEZING_BY_PARENT] = "freezing-by-parent",
|
||||
[FREEZER_FROZEN] = "frozen",
|
||||
[FREEZER_FROZEN_BY_PARENT] = "frozen-by-parent",
|
||||
[FREEZER_THAWING] = "thawing",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(freezer_state, FreezerState);
|
||||
|
||||
/* Maps in-progress freezer states to the corresponding finished state */
|
||||
static const FreezerState freezer_state_finish_table[_FREEZER_STATE_MAX] = {
|
||||
[FREEZER_FREEZING] = FREEZER_FROZEN,
|
||||
[FREEZER_FREEZING_BY_PARENT] = FREEZER_FROZEN_BY_PARENT,
|
||||
[FREEZER_THAWING] = FREEZER_RUNNING,
|
||||
|
||||
/* Finished states trivially map to themselves */
|
||||
[FREEZER_RUNNING] = FREEZER_RUNNING,
|
||||
[FREEZER_FROZEN] = FREEZER_FROZEN,
|
||||
[FREEZER_FROZEN_BY_PARENT] = FREEZER_FROZEN_BY_PARENT,
|
||||
};
|
||||
|
||||
FreezerState freezer_state_finish(FreezerState state) {
|
||||
assert(state >= 0 && state < _FREEZER_STATE_MAX);
|
||||
return freezer_state_finish_table[state];
|
||||
}
|
||||
|
||||
static const char* const unit_marker_table[_UNIT_MARKER_MAX] = {
|
||||
[UNIT_MARKER_NEEDS_RELOAD] = "needs-reload",
|
||||
[UNIT_MARKER_NEEDS_RESTART] = "needs-restart",
|
||||
|
||||
@@ -53,8 +53,10 @@ typedef enum UnitActiveState {
|
||||
|
||||
typedef enum FreezerState {
|
||||
FREEZER_RUNNING,
|
||||
FREEZER_FREEZING,
|
||||
FREEZER_FREEZING, /* freezing due to user request */
|
||||
FREEZER_FROZEN,
|
||||
FREEZER_FREEZING_BY_PARENT, /* freezing as a result of parent slice freezing */
|
||||
FREEZER_FROZEN_BY_PARENT,
|
||||
FREEZER_THAWING,
|
||||
_FREEZER_STATE_MAX,
|
||||
_FREEZER_STATE_INVALID = -EINVAL,
|
||||
@@ -297,6 +299,7 @@ UnitActiveState unit_active_state_from_string(const char *s) _pure_;
|
||||
|
||||
const char *freezer_state_to_string(FreezerState i) _const_;
|
||||
FreezerState freezer_state_from_string(const char *s) _pure_;
|
||||
FreezerState freezer_state_finish(FreezerState i) _const_;
|
||||
|
||||
const char *unit_marker_to_string(UnitMarker m) _const_;
|
||||
UnitMarker unit_marker_from_string(const char *s) _pure_;
|
||||
|
||||
Reference in New Issue
Block a user