]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
oomd: get memory total and free as part of system context
authorAnita Zhang <the.anitazha@gmail.com>
Thu, 24 Jun 2021 10:11:07 +0000 (03:11 -0700)
committerAnita Zhang <the.anitazha@gmail.com>
Wed, 30 Jun 2021 10:50:35 +0000 (03:50 -0700)
src/oom/oomd-util.c
src/oom/oomd-util.h
src/oom/test-oomd-util.c

index bb77c848072837a54b114a7ee224292f255f95c1..04d2bfe0bdef9c6b29633d944f2c6bd590a8c5ef 100644 (file)
@@ -122,6 +122,16 @@ uint64_t oomd_pgscan_rate(const OomdCGroupContext *c) {
         return c->pgscan - last_pgscan;
 }
 
+bool oomd_mem_free_below(const OomdSystemContext *ctx, int threshold_permyriad) {
+        uint64_t mem_threshold;
+
+        assert(ctx);
+        assert(threshold_permyriad <= 10000);
+
+        mem_threshold = ctx->mem_total * threshold_permyriad / (uint64_t) 10000;
+        return (ctx->mem_total - ctx->mem_used) < mem_threshold;
+}
+
 bool oomd_swap_free_below(const OomdSystemContext *ctx, int threshold_permyriad) {
         uint64_t swap_threshold;
 
@@ -362,7 +372,7 @@ int oomd_system_context_acquire(const char *proc_meminfo_path, OomdSystemContext
         _cleanup_fclose_ FILE *f = NULL;
         unsigned field_filled = 0;
         OomdSystemContext ctx = {};
-        uint64_t swap_free;
+        uint64_t mem_free, swap_free;
         int r;
 
         assert(proc_meminfo_path);
@@ -382,11 +392,17 @@ int oomd_system_context_acquire(const char *proc_meminfo_path, OomdSystemContext
                 if (r == 0)
                         return -EINVAL;
 
-                if ((word = startswith(line, "SwapTotal:"))) {
+                if ((word = startswith(line, "MemTotal:"))) {
                         field_filled |= 1U << 0;
+                        r = convert_meminfo_value_to_uint64_bytes(word, &ctx.mem_total);
+                } else if ((word = startswith(line, "MemFree:"))) {
+                        field_filled |= 1U << 1;
+                        r = convert_meminfo_value_to_uint64_bytes(word, &mem_free);
+                } else if ((word = startswith(line, "SwapTotal:"))) {
+                        field_filled |= 1U << 2;
                         r = convert_meminfo_value_to_uint64_bytes(word, &ctx.swap_total);
                 } else if ((word = startswith(line, "SwapFree:"))) {
-                        field_filled |= 1U << 1;
+                        field_filled |= 1U << 3;
                         r = convert_meminfo_value_to_uint64_bytes(word, &swap_free);
                 } else
                         continue;
@@ -394,19 +410,26 @@ int oomd_system_context_acquire(const char *proc_meminfo_path, OomdSystemContext
                 if (r < 0)
                         return log_debug_errno(r, "Error converting '%s' from %s to uint64_t: %m", line, proc_meminfo_path);
 
-                if (field_filled == 3U)
+                if (field_filled == 15U)
                         break;
         }
 
-        if (field_filled != 3U)
+        if (field_filled != 15U)
                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "%s is missing expected fields", proc_meminfo_path);
 
+        if (mem_free > ctx.mem_total)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "MemFree (%" PRIu64 ") cannot be greater than MemTotal (%" PRIu64 ") %m",
+                                       mem_free,
+                                       ctx.mem_total);
+
         if (swap_free > ctx.swap_total)
                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "SwapFree (%" PRIu64 ") cannot be greater than SwapTotal (%" PRIu64 ") %m",
                                        swap_free,
                                        ctx.swap_total);
 
+        ctx.mem_used = ctx.mem_total - mem_free;
         ctx.swap_used = ctx.swap_total - swap_free;
 
         *ret = ctx;
@@ -525,14 +548,19 @@ void oomd_dump_memory_pressure_cgroup_context(const OomdCGroupContext *ctx, FILE
 }
 
 void oomd_dump_system_context(const OomdSystemContext *ctx, FILE *f, const char *prefix) {
-        char used[FORMAT_BYTES_MAX], total[FORMAT_BYTES_MAX];
+        char mem_used[FORMAT_BYTES_MAX], mem_total[FORMAT_BYTES_MAX];
+        char swap_used[FORMAT_BYTES_MAX], swap_total[FORMAT_BYTES_MAX];
 
         assert(ctx);
         assert(f);
 
         fprintf(f,
+                "%sMemory: Used: %s Total: %s\n"
                 "%sSwap: Used: %s Total: %s\n",
                 strempty(prefix),
-                format_bytes(used, sizeof(used), ctx->swap_used),
-                format_bytes(total, sizeof(total), ctx->swap_total));
+                format_bytes(mem_used, sizeof(mem_used), ctx->mem_used),
+                format_bytes(mem_total, sizeof(mem_total), ctx->mem_total),
+                strempty(prefix),
+                format_bytes(swap_used, sizeof(swap_used), ctx->swap_used),
+                format_bytes(swap_total, sizeof(swap_total), ctx->swap_total));
 }
index 81fdc5e088c03b79a332b4ddcb15d1bf4b3a8bc5..3a91a31352e985610e583720c2fa4be878341a79 100644 (file)
@@ -39,6 +39,8 @@ struct OomdCGroupContext {
 };
 
 struct OomdSystemContext {
+        uint64_t mem_total;
+        uint64_t mem_used;
         uint64_t swap_total;
         uint64_t swap_used;
 };
@@ -57,6 +59,9 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(OomdCGroupContext*, oomd_cgroup_context_free);
  * Returns -ENOMEM for allocation errors. */
 int oomd_pressure_above(Hashmap *h, usec_t duration, Set **ret);
 
+/* Returns true if the amount of memory free is below the permyriad of memory specified by `threshold_permyriad`. */
+bool oomd_mem_free_below(const OomdSystemContext *ctx, int threshold_permyriad);
+
 /* Returns true if the amount of swap free is below the permyriad of swap specified by `threshold_permyriad`. */
 bool oomd_swap_free_below(const OomdSystemContext *ctx, int threshold_permyriad);
 
index c7d2778200aefa8a35dbfdb8917a7c78d957185e..776c65820e37c2f59aba21227ec96e5338af965a 100644 (file)
@@ -258,10 +258,6 @@ static void test_oomd_system_context_acquire(void) {
                                           "SwapFree:           7604 kB bad\n", WRITE_STRING_FILE_CREATE) == 0);
         assert_se(oomd_system_context_acquire(path, &ctx) == -EINVAL);
 
-        assert_se(oomd_system_context_acquire("/proc/meminfo", &ctx) == 0);
-        assert_se(ctx.swap_total > 0);
-        assert_se(ctx.swap_used <= ctx.swap_total);
-
         assert_se(write_string_file(path, "MemTotal:       32495256 kB\n"
                                           "MemFree:         9880512 kB\n"
                                           "MemAvailable:   21777088 kB\n"
@@ -272,6 +268,8 @@ static void test_oomd_system_context_acquire(void) {
                                           "SwapTotal:       8388604 kB\n"
                                           "SwapFree:           7604 kB\n", WRITE_STRING_FILE_CREATE) == 0);
         assert_se(oomd_system_context_acquire(path, &ctx) == 0);
+        assert_se(ctx.mem_total == 33275142144);
+        assert_se(ctx.mem_used == 23157497856);
         assert_se(ctx.swap_total == 8589930496);
         assert_se(ctx.swap_used == 8582144000);
 }
@@ -324,23 +322,32 @@ static void test_oomd_pressure_above(void) {
         assert_se(c->mem_pressure_limit_hit_start == 0);
 }
 
-static void test_oomd_swap_free_below(void) {
+static void test_oomd_mem_and_swap_free_below(void) {
         OomdSystemContext ctx = (OomdSystemContext) {
+                .mem_total = 20971512 * 1024U,
+                .mem_used = 3310136 * 1024U,
                 .swap_total = 20971512 * 1024U,
                 .swap_used = 20971440 * 1024U,
         };
+        assert_se(oomd_mem_free_below(&ctx, 2000) == false);
         assert_se(oomd_swap_free_below(&ctx, 2000) == true);
 
         ctx = (OomdSystemContext) {
+                .mem_total = 20971512 * 1024U,
+                .mem_used = 20971440 * 1024U,
                 .swap_total = 20971512 * 1024U,
                 .swap_used = 3310136 * 1024U,
         };
+        assert_se(oomd_mem_free_below(&ctx, 2000) == true);
         assert_se(oomd_swap_free_below(&ctx, 2000) == false);
 
         ctx = (OomdSystemContext) {
+                .mem_total = 0,
+                .mem_used = 0,
                 .swap_total = 0,
                 .swap_used = 0,
         };
+        assert_se(oomd_mem_free_below(&ctx, 2000) == false);
         assert_se(oomd_swap_free_below(&ctx, 2000) == false);
 }
 
@@ -440,7 +447,7 @@ int main(void) {
         test_oomd_update_cgroup_contexts_between_hashmaps();
         test_oomd_system_context_acquire();
         test_oomd_pressure_above();
-        test_oomd_swap_free_below();
+        test_oomd_mem_and_swap_free_below();
         test_oomd_sort_cgroups();
 
         /* The following tests operate on live cgroups */