]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cgroup: analyze: Report memory configurations that deviate from systemd 13690/head
authorChris Down <chris@chrisdown.name>
Thu, 3 Oct 2019 12:21:29 +0000 (13:21 +0100)
committerChris Down <chris@chrisdown.name>
Thu, 3 Oct 2019 14:06:25 +0000 (15:06 +0100)
This is the most basic consumer of the new systemd-vs-kernel checker,
both acting as a reasonable standalone exerciser of the code, and also
as a way for easy inspection of deviations from systemd internal state.

src/core/cgroup.c
src/core/cgroup.h
src/core/mount.c
src/core/scope.c
src/core/service.c
src/core/slice.c
src/core/socket.c
src/core/swap.c

index 5477f9d2b10e413f4c16b728f92b578c3909035a..c67ecc37c53a08999065fa629f2e1e29ce8e3e02 100644 (file)
@@ -328,7 +328,38 @@ static int unit_compare_memory_limit(Unit *u, const char *property_name, uint64_
         return *ret_kernel_value == *ret_unit_value;
 }
 
-void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
+#define FORMAT_CGROUP_DIFF_MAX 128
+
+static char *format_cgroup_memory_limit_comparison(char *buf, size_t l, Unit *u, const char *property_name) {
+        uint64_t kval, sval;
+        int r;
+
+        assert(u);
+        assert(buf);
+        assert(l > 0);
+
+        r = unit_compare_memory_limit(u, property_name, &sval, &kval);
+
+        /* memory.swap.max is special in that it relies on CONFIG_MEMCG_SWAP (and the default swapaccount=1).
+         * In the absence of reliably being able to detect whether memcg swap support is available or not,
+         * only complain if the error is not ENOENT. */
+        if (r > 0 || IN_SET(r, -ENODATA, -EOWNERDEAD) ||
+            (r == -ENOENT && streq(property_name, "MemorySwapMax"))) {
+                buf[0] = 0;
+                return buf;
+        }
+
+        if (r < 0) {
+                snprintf(buf, l, " (error getting kernel value: %s)", strerror_safe(r));
+                return buf;
+        }
+
+        snprintf(buf, l, " (different value in kernel: %" PRIu64 ")", kval);
+
+        return buf;
+}
+
+void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
         _cleanup_free_ char *disable_controllers_str = NULL;
         _cleanup_free_ char *cpuset_cpus = NULL;
         _cleanup_free_ char *cpuset_mems = NULL;
@@ -338,14 +369,24 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
         CGroupBlockIODeviceBandwidth *b;
         CGroupBlockIODeviceWeight *w;
         CGroupDeviceAllow *a;
+        CGroupContext *c;
         IPAddressAccessItem *iaai;
         char **path;
-        char u[FORMAT_TIMESPAN_MAX];
+        char q[FORMAT_TIMESPAN_MAX];
         char v[FORMAT_TIMESPAN_MAX];
 
-        assert(c);
+        char cda[FORMAT_CGROUP_DIFF_MAX];
+        char cdb[FORMAT_CGROUP_DIFF_MAX];
+        char cdc[FORMAT_CGROUP_DIFF_MAX];
+        char cdd[FORMAT_CGROUP_DIFF_MAX];
+        char cde[FORMAT_CGROUP_DIFF_MAX];
+
+        assert(u);
         assert(f);
 
+        c = unit_get_cgroup_context(u);
+        assert(c);
+
         prefix = strempty(prefix);
 
         (void) cg_mask_to_string(c->disable_controllers, &disable_controllers_str);
@@ -374,11 +415,11 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
                 "%sStartupBlockIOWeight: %" PRIu64 "\n"
                 "%sDefaultMemoryMin: %" PRIu64 "\n"
                 "%sDefaultMemoryLow: %" PRIu64 "\n"
-                "%sMemoryMin: %" PRIu64 "\n"
-                "%sMemoryLow: %" PRIu64 "\n"
-                "%sMemoryHigh: %" PRIu64 "\n"
-                "%sMemoryMax: %" PRIu64 "\n"
-                "%sMemorySwapMax: %" PRIu64 "\n"
+                "%sMemoryMin: %" PRIu64 "%s\n"
+                "%sMemoryLow: %" PRIu64 "%s\n"
+                "%sMemoryHigh: %" PRIu64 "%s\n"
+                "%sMemoryMax: %" PRIu64 "%s\n"
+                "%sMemorySwapMax: %" PRIu64 "%s\n"
                 "%sMemoryLimit: %" PRIu64 "\n"
                 "%sTasksMax: %" PRIu64 "\n"
                 "%sDevicePolicy: %s\n"
@@ -394,7 +435,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
                 prefix, c->startup_cpu_weight,
                 prefix, c->cpu_shares,
                 prefix, c->startup_cpu_shares,
-                prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
+                prefix, format_timespan(q, sizeof(q), c->cpu_quota_per_sec_usec, 1),
                 prefix, format_timespan(v, sizeof(v), c->cpu_quota_period_usec, 1),
                 prefix, cpuset_cpus,
                 prefix, cpuset_mems,
@@ -404,11 +445,11 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
                 prefix, c->startup_blockio_weight,
                 prefix, c->default_memory_min,
                 prefix, c->default_memory_low,
-                prefix, c->memory_min,
-                prefix, c->memory_low,
-                prefix, c->memory_high,
-                prefix, c->memory_max,
-                prefix, c->memory_swap_max,
+                prefix, c->memory_min, format_cgroup_memory_limit_comparison(cda, sizeof(cda), u, "MemoryMin"),
+                prefix, c->memory_low, format_cgroup_memory_limit_comparison(cdb, sizeof(cdb), u, "MemoryLow"),
+                prefix, c->memory_high, format_cgroup_memory_limit_comparison(cdc, sizeof(cdc), u, "MemoryHigh"),
+                prefix, c->memory_max, format_cgroup_memory_limit_comparison(cdd, sizeof(cdd), u, "MemoryMax"),
+                prefix, c->memory_swap_max, format_cgroup_memory_limit_comparison(cde, sizeof(cde), u, "MemorySwapMax"),
                 prefix, c->memory_limit,
                 prefix, c->tasks_max,
                 prefix, cgroup_device_policy_to_string(c->device_policy),
@@ -444,7 +485,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
                         "%sIODeviceLatencyTargetSec: %s %s\n",
                         prefix,
                         l->path,
-                        format_timespan(u, sizeof(u), l->target_usec, 1));
+                        format_timespan(q, sizeof(q), l->target_usec, 1));
 
         LIST_FOREACH(device_limits, il, c->io_device_limits) {
                 char buf[FORMAT_BYTES_MAX];
index bca53fb9809b63d495e88f38d74d57226f1eaee8..a66c70212562d6dcf053d4efac6690963c6b879d 100644 (file)
@@ -166,7 +166,7 @@ usec_t cgroup_cpu_adjust_period(usec_t period, usec_t quota, usec_t resolution,
 
 void cgroup_context_init(CGroupContext *c);
 void cgroup_context_done(CGroupContext *c);
-void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix);
+void cgroup_context_dump(Unit *u, FILE* f, const char *prefix);
 
 void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a);
 void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w);
index 8a0c8be120e2ad7d05bac30348da81ccf7ddf881..09d08f3990fd5523fa469534c6d44ef70eba320e 100644 (file)
@@ -769,7 +769,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
 
         exec_context_dump(&m->exec_context, f, prefix);
         kill_context_dump(&m->kill_context, f, prefix);
-        cgroup_context_dump(&m->cgroup_context, f, prefix);
+        cgroup_context_dump(UNIT(m), f, prefix);
 }
 
 static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
index bb1e60dd11fa56ab4b589f01ab43afbeb6b5931d..79470a0a9beb89afe31cde591248405bad1f2af4 100644 (file)
@@ -234,7 +234,7 @@ static void scope_dump(Unit *u, FILE *f, const char *prefix) {
                 prefix, scope_state_to_string(s->state),
                 prefix, scope_result_to_string(s->result));
 
-        cgroup_context_dump(&s->cgroup_context, f, prefix);
+        cgroup_context_dump(UNIT(s), f, prefix);
         kill_context_dump(&s->kill_context, f, prefix);
 }
 
index 1c677b4355604be3d4b2521ec0c11835145870a0..ada25e634a063f5c169968f134456590948863e8 100644 (file)
@@ -905,7 +905,7 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
                         prefix, s->n_fd_store_max,
                         prefix, s->n_fd_store);
 
-        cgroup_context_dump(&s->cgroup_context, f, prefix);
+        cgroup_context_dump(UNIT(s), f, prefix);
 }
 
 static int service_is_suitable_main_pid(Service *s, pid_t pid, int prio) {
index 489d5ace6a1d70d756abb7c13921cef1ee9f1b5a..c12328b3b736daad43607709a5aa33f1b544fc07 100644 (file)
@@ -215,7 +215,7 @@ static void slice_dump(Unit *u, FILE *f, const char *prefix) {
                 "%sSlice State: %s\n",
                 prefix, slice_state_to_string(t->state));
 
-        cgroup_context_dump(&t->cgroup_context, f, prefix);
+        cgroup_context_dump(UNIT(t), f, prefix);
 }
 
 static int slice_start(Unit *u) {
index 7696490f8ac19ae7bf2c9e9521808343039cce9a..f31d3bd971d64b5e16cc6d9b895b1a09c47fbb57 100644 (file)
@@ -843,7 +843,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                 exec_command_dump_list(s->exec_command[c], f, prefix2);
         }
 
-        cgroup_context_dump(&s->cgroup_context, f, prefix);
+        cgroup_context_dump(UNIT(s), f, prefix);
 }
 
 static int instance_from_socket(int fd, unsigned nr, char **instance) {
index 0924b35050e8981ac82703987bb76515cb612aa8..ad1da6dddb6f977ed8fe2339c56943c25c3fa1db 100644 (file)
@@ -621,7 +621,7 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) {
 
         exec_context_dump(&s->exec_context, f, prefix);
         kill_context_dump(&s->kill_context, f, prefix);
-        cgroup_context_dump(&s->cgroup_context, f, prefix);
+        cgroup_context_dump(UNIT(s), f, prefix);
 }
 
 static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {