Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <stdio.h>
4 : :
5 : : #include "cgroup.h"
6 : : #include "manager.h"
7 : : #include "rm-rf.h"
8 : : #include "test-helper.h"
9 : : #include "tests.h"
10 : : #include "unit.h"
11 : :
12 : 4 : static int test_default_memory_low(void) {
13 : 4 : _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
14 : 4 : _cleanup_(manager_freep) Manager *m = NULL;
15 : : Unit *root, *dml,
16 : : *dml_passthrough, *dml_passthrough_empty, *dml_passthrough_set_dml, *dml_passthrough_set_ml,
17 : : *dml_override, *dml_override_empty,
18 : : *dml_discard, *dml_discard_empty, *dml_discard_set_ml;
19 : : uint64_t dml_tree_default;
20 : : int r;
21 : :
22 : 4 : r = enter_cgroup_subroot();
23 [ - + ]: 4 : if (r == -ENOMEDIUM)
24 : 0 : return log_tests_skipped("cgroupfs not available");
25 : :
26 [ - + ]: 4 : assert_se(set_unit_path(get_testdata_dir()) >= 0);
27 [ - + ]: 4 : assert_se(runtime_dir = setup_fake_runtime_dir());
28 : 4 : r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m);
29 [ - + - + ]: 4 : if (IN_SET(r, -EPERM, -EACCES)) {
30 [ # # ]: 0 : log_error_errno(r, "manager_new: %m");
31 : 0 : return log_tests_skipped("cannot create manager");
32 : : }
33 : :
34 [ - + ]: 4 : assert_se(r >= 0);
35 [ - + ]: 4 : assert_se(manager_startup(m, NULL, NULL) >= 0);
36 : :
37 : : /* dml.slice has DefaultMemoryLow=50. Beyond that, individual subhierarchies look like this:
38 : : *
39 : : * 1. dml-passthrough.slice sets MemoryLow=100. This should not affect its children, as only
40 : : * DefaultMemoryLow is propagated, not MemoryLow. As such, all leaf services should end up with
41 : : * memory.low as 50, inherited from dml.slice, *except* for dml-passthrough-set-ml.service, which
42 : : * should have the value of 0, as it has MemoryLow explicitly set.
43 : : *
44 : : * ┌───────────┐
45 : : * │ dml.slice │
46 : : * └─────┬─────┘
47 : : * MemoryLow=100
48 : : * ┌───────────┴───────────┐
49 : : * │ dml-passthrough.slice │
50 : : * └───────────┬───────────┘
51 : : * ┌───────────────────────────────────┼───────────────────────────────────┐
52 : : * no new settings DefaultMemoryLow=15 MemoryLow=0
53 : : * ┌───────────────┴───────────────┐ ┌────────────────┴────────────────┐ ┌───────────────┴────────────────┐
54 : : * │ dml-passthrough-empty.service │ │ dml-passthrough-set-dml.service │ │ dml-passthrough-set-ml.service │
55 : : * └───────────────────────────────┘ └─────────────────────────────────┘ └────────────────────────────────┘
56 : : *
57 : : * 2. dml-override.slice sets DefaultMemoryLow=10. As such, dml-override-empty.service should also
58 : : * end up with a memory.low of 10. dml-override.slice should still have a memory.low of 50.
59 : : *
60 : : * ┌───────────┐
61 : : * │ dml.slice │
62 : : * └─────┬─────┘
63 : : * DefaultMemoryLow=10
64 : : * ┌─────────┴──────────┐
65 : : * │ dml-override.slice │
66 : : * └─────────┬──────────┘
67 : : * no new settings
68 : : * ┌─────────────┴──────────────┐
69 : : * │ dml-override-empty.service │
70 : : * └────────────────────────────┘
71 : : *
72 : : * 3. dml-discard.slice sets DefaultMemoryLow= with no rvalue. As such,
73 : : * dml-discard-empty.service should end up with a value of 0.
74 : : * dml-discard-explicit-ml.service sets MemoryLow=70, and as such should have that override the
75 : : * reset DefaultMemoryLow value. dml-discard.slice should still have an eventual memory.low of 50.
76 : : *
77 : : * ┌───────────┐
78 : : * │ dml.slice │
79 : : * └─────┬─────┘
80 : : * DefaultMemoryLow=
81 : : * ┌─────────┴─────────┐
82 : : * │ dml-discard.slice │
83 : : * └─────────┬─────────┘
84 : : * ┌──────────────┴───────────────┐
85 : : * no new settings MemoryLow=15
86 : : * ┌─────────────┴─────────────┐ ┌─────────────┴──────────────┐
87 : : * │ dml-discard-empty.service │ │ dml-discard-set-ml.service │
88 : : * └───────────────────────────┘ └────────────────────────────┘
89 : : */
90 [ - + ]: 4 : assert_se(manager_load_startable_unit_or_warn(m, "dml.slice", NULL, &dml) >= 0);
91 : :
92 [ - + ]: 4 : assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough.slice", NULL, &dml_passthrough) >= 0);
93 [ - + ]: 4 : assert_se(UNIT_DEREF(dml_passthrough->slice) == dml);
94 [ - + ]: 4 : assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough-empty.service", NULL, &dml_passthrough_empty) >= 0);
95 [ - + ]: 4 : assert_se(UNIT_DEREF(dml_passthrough_empty->slice) == dml_passthrough);
96 [ - + ]: 4 : assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough-set-dml.service", NULL, &dml_passthrough_set_dml) >= 0);
97 [ - + ]: 4 : assert_se(UNIT_DEREF(dml_passthrough_set_dml->slice) == dml_passthrough);
98 [ - + ]: 4 : assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough-set-ml.service", NULL, &dml_passthrough_set_ml) >= 0);
99 [ - + ]: 4 : assert_se(UNIT_DEREF(dml_passthrough_set_ml->slice) == dml_passthrough);
100 : :
101 [ - + ]: 4 : assert_se(manager_load_startable_unit_or_warn(m, "dml-override.slice", NULL, &dml_override) >= 0);
102 [ - + ]: 4 : assert_se(UNIT_DEREF(dml_override->slice) == dml);
103 [ - + ]: 4 : assert_se(manager_load_startable_unit_or_warn(m, "dml-override-empty.service", NULL, &dml_override_empty) >= 0);
104 [ - + ]: 4 : assert_se(UNIT_DEREF(dml_override_empty->slice) == dml_override);
105 : :
106 [ - + ]: 4 : assert_se(manager_load_startable_unit_or_warn(m, "dml-discard.slice", NULL, &dml_discard) >= 0);
107 [ - + ]: 4 : assert_se(UNIT_DEREF(dml_discard->slice) == dml);
108 [ - + ]: 4 : assert_se(manager_load_startable_unit_or_warn(m, "dml-discard-empty.service", NULL, &dml_discard_empty) >= 0);
109 [ - + ]: 4 : assert_se(UNIT_DEREF(dml_discard_empty->slice) == dml_discard);
110 [ - + ]: 4 : assert_se(manager_load_startable_unit_or_warn(m, "dml-discard-set-ml.service", NULL, &dml_discard_set_ml) >= 0);
111 [ - + ]: 4 : assert_se(UNIT_DEREF(dml_discard_set_ml->slice) == dml_discard);
112 : :
113 : 4 : root = UNIT_DEREF(dml->slice);
114 [ - + ]: 4 : assert_se(!UNIT_ISSET(root->slice));
115 : :
116 [ - + ]: 4 : assert_se(unit_get_ancestor_memory_low(root) == CGROUP_LIMIT_MIN);
117 : :
118 [ - + ]: 4 : assert_se(unit_get_ancestor_memory_low(dml) == CGROUP_LIMIT_MIN);
119 : 4 : dml_tree_default = unit_get_cgroup_context(dml)->default_memory_low;
120 [ - + ]: 4 : assert_se(dml_tree_default == 50);
121 : :
122 [ - + ]: 4 : assert_se(unit_get_ancestor_memory_low(dml_passthrough) == 100);
123 [ - + ]: 4 : assert_se(unit_get_ancestor_memory_low(dml_passthrough_empty) == dml_tree_default);
124 [ - + ]: 4 : assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_dml) == 50);
125 [ - + ]: 4 : assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_ml) == 0);
126 : :
127 [ - + ]: 4 : assert_se(unit_get_ancestor_memory_low(dml_override) == dml_tree_default);
128 [ - + ]: 4 : assert_se(unit_get_ancestor_memory_low(dml_override_empty) == 10);
129 : :
130 [ - + ]: 4 : assert_se(unit_get_ancestor_memory_low(dml_discard) == dml_tree_default);
131 [ - + ]: 4 : assert_se(unit_get_ancestor_memory_low(dml_discard_empty) == CGROUP_LIMIT_MIN);
132 [ - + ]: 4 : assert_se(unit_get_ancestor_memory_low(dml_discard_set_ml) == 15);
133 : :
134 : 4 : return 0;
135 : : }
136 : :
137 : 4 : int main(int argc, char* argv[]) {
138 : 4 : int rc = EXIT_SUCCESS;
139 : :
140 : 4 : test_setup_logging(LOG_DEBUG);
141 : :
142 [ + - ]: 4 : TEST_REQ_RUNNING_SYSTEMD(rc = test_default_memory_low());
143 : :
144 : 4 : return rc;
145 : : }
|