145 lines
9 KiB
C
145 lines
9 KiB
C
/* SPDX-License-Identifier: LGPL-2.1+ */
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "cgroup.h"
|
|
#include "manager.h"
|
|
#include "rm-rf.h"
|
|
#include "tests.h"
|
|
#include "unit.h"
|
|
|
|
static int test_default_memory_low(void) {
|
|
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
|
|
_cleanup_(manager_freep) Manager *m = NULL;
|
|
Unit *root, *dml,
|
|
*dml_passthrough, *dml_passthrough_empty, *dml_passthrough_set_dml, *dml_passthrough_set_ml,
|
|
*dml_override, *dml_override_empty,
|
|
*dml_discard, *dml_discard_empty, *dml_discard_set_ml;
|
|
uint64_t dml_tree_default;
|
|
int r;
|
|
|
|
r = enter_cgroup_subroot(NULL);
|
|
if (r == -ENOMEDIUM)
|
|
return log_tests_skipped("cgroupfs not available");
|
|
|
|
assert_se(set_unit_path(get_testdata_dir()) >= 0);
|
|
assert_se(runtime_dir = setup_fake_runtime_dir());
|
|
r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m);
|
|
if (IN_SET(r, -EPERM, -EACCES)) {
|
|
log_error_errno(r, "manager_new: %m");
|
|
return log_tests_skipped("cannot create manager");
|
|
}
|
|
|
|
assert_se(r >= 0);
|
|
assert_se(manager_startup(m, NULL, NULL) >= 0);
|
|
|
|
/* dml.slice has DefaultMemoryLow=50. Beyond that, individual subhierarchies look like this:
|
|
*
|
|
* 1. dml-passthrough.slice sets MemoryLow=100. This should not affect its children, as only
|
|
* DefaultMemoryLow is propagated, not MemoryLow. As such, all leaf services should end up with
|
|
* memory.low as 50, inherited from dml.slice, *except* for dml-passthrough-set-ml.service, which
|
|
* should have the value of 0, as it has MemoryLow explicitly set.
|
|
*
|
|
* ┌───────────┐
|
|
* │ dml.slice │
|
|
* └─────┬─────┘
|
|
* MemoryLow=100
|
|
* ┌───────────┴───────────┐
|
|
* │ dml-passthrough.slice │
|
|
* └───────────┬───────────┘
|
|
* ┌───────────────────────────────────┼───────────────────────────────────┐
|
|
* no new settings DefaultMemoryLow=15 MemoryLow=0
|
|
* ┌───────────────┴───────────────┐ ┌────────────────┴────────────────┐ ┌───────────────┴────────────────┐
|
|
* │ dml-passthrough-empty.service │ │ dml-passthrough-set-dml.service │ │ dml-passthrough-set-ml.service │
|
|
* └───────────────────────────────┘ └─────────────────────────────────┘ └────────────────────────────────┘
|
|
*
|
|
* 2. dml-override.slice sets DefaultMemoryLow=10. As such, dml-override-empty.service should also
|
|
* end up with a memory.low of 10. dml-override.slice should still have a memory.low of 50.
|
|
*
|
|
* ┌───────────┐
|
|
* │ dml.slice │
|
|
* └─────┬─────┘
|
|
* DefaultMemoryLow=10
|
|
* ┌─────────┴──────────┐
|
|
* │ dml-override.slice │
|
|
* └─────────┬──────────┘
|
|
* no new settings
|
|
* ┌─────────────┴──────────────┐
|
|
* │ dml-override-empty.service │
|
|
* └────────────────────────────┘
|
|
*
|
|
* 3. dml-discard.slice sets DefaultMemoryLow= with no rvalue. As such,
|
|
* dml-discard-empty.service should end up with a value of 0.
|
|
* dml-discard-explicit-ml.service sets MemoryLow=70, and as such should have that override the
|
|
* reset DefaultMemoryLow value. dml-discard.slice should still have an eventual memory.low of 50.
|
|
*
|
|
* ┌───────────┐
|
|
* │ dml.slice │
|
|
* └─────┬─────┘
|
|
* DefaultMemoryLow=
|
|
* ┌─────────┴─────────┐
|
|
* │ dml-discard.slice │
|
|
* └─────────┬─────────┘
|
|
* ┌──────────────┴───────────────┐
|
|
* no new settings MemoryLow=15
|
|
* ┌─────────────┴─────────────┐ ┌─────────────┴──────────────┐
|
|
* │ dml-discard-empty.service │ │ dml-discard-set-ml.service │
|
|
* └───────────────────────────┘ └────────────────────────────┘
|
|
*/
|
|
assert_se(manager_load_startable_unit_or_warn(m, "dml.slice", NULL, &dml) >= 0);
|
|
|
|
assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough.slice", NULL, &dml_passthrough) >= 0);
|
|
assert_se(UNIT_DEREF(dml_passthrough->slice) == dml);
|
|
assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough-empty.service", NULL, &dml_passthrough_empty) >= 0);
|
|
assert_se(UNIT_DEREF(dml_passthrough_empty->slice) == dml_passthrough);
|
|
assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough-set-dml.service", NULL, &dml_passthrough_set_dml) >= 0);
|
|
assert_se(UNIT_DEREF(dml_passthrough_set_dml->slice) == dml_passthrough);
|
|
assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough-set-ml.service", NULL, &dml_passthrough_set_ml) >= 0);
|
|
assert_se(UNIT_DEREF(dml_passthrough_set_ml->slice) == dml_passthrough);
|
|
|
|
assert_se(manager_load_startable_unit_or_warn(m, "dml-override.slice", NULL, &dml_override) >= 0);
|
|
assert_se(UNIT_DEREF(dml_override->slice) == dml);
|
|
assert_se(manager_load_startable_unit_or_warn(m, "dml-override-empty.service", NULL, &dml_override_empty) >= 0);
|
|
assert_se(UNIT_DEREF(dml_override_empty->slice) == dml_override);
|
|
|
|
assert_se(manager_load_startable_unit_or_warn(m, "dml-discard.slice", NULL, &dml_discard) >= 0);
|
|
assert_se(UNIT_DEREF(dml_discard->slice) == dml);
|
|
assert_se(manager_load_startable_unit_or_warn(m, "dml-discard-empty.service", NULL, &dml_discard_empty) >= 0);
|
|
assert_se(UNIT_DEREF(dml_discard_empty->slice) == dml_discard);
|
|
assert_se(manager_load_startable_unit_or_warn(m, "dml-discard-set-ml.service", NULL, &dml_discard_set_ml) >= 0);
|
|
assert_se(UNIT_DEREF(dml_discard_set_ml->slice) == dml_discard);
|
|
|
|
root = UNIT_DEREF(dml->slice);
|
|
assert_se(!UNIT_ISSET(root->slice));
|
|
|
|
assert_se(unit_get_ancestor_memory_low(root) == CGROUP_LIMIT_MIN);
|
|
|
|
assert_se(unit_get_ancestor_memory_low(dml) == CGROUP_LIMIT_MIN);
|
|
dml_tree_default = unit_get_cgroup_context(dml)->default_memory_low;
|
|
assert_se(dml_tree_default == 50);
|
|
|
|
assert_se(unit_get_ancestor_memory_low(dml_passthrough) == 100);
|
|
assert_se(unit_get_ancestor_memory_low(dml_passthrough_empty) == dml_tree_default);
|
|
assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_dml) == 50);
|
|
assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_ml) == 0);
|
|
|
|
assert_se(unit_get_ancestor_memory_low(dml_override) == dml_tree_default);
|
|
assert_se(unit_get_ancestor_memory_low(dml_override_empty) == 10);
|
|
|
|
assert_se(unit_get_ancestor_memory_low(dml_discard) == dml_tree_default);
|
|
assert_se(unit_get_ancestor_memory_low(dml_discard_empty) == CGROUP_LIMIT_MIN);
|
|
assert_se(unit_get_ancestor_memory_low(dml_discard_set_ml) == 15);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
int rc = EXIT_SUCCESS;
|
|
|
|
test_setup_logging(LOG_DEBUG);
|
|
|
|
TEST_REQ_RUNNING_SYSTEMD(rc = test_default_memory_low());
|
|
|
|
return rc;
|
|
}
|