]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cgroup: Estimate MemoryAvailable= when DefaultMemoryAccounting=no
authorMichal Koutný <mkoutny@suse.com>
Thu, 7 Sep 2023 17:48:48 +0000 (19:48 +0200)
committerMichal Koutný <mkoutny@suse.com>
Fri, 8 Sep 2023 17:07:12 +0000 (19:07 +0200)
Without memory accounting explicitly disabled, we may not obtain current
consumption from all units on the ancestry path.
Use a descendant value as lower bound estimate for ancestors if
ancestor's consumption cannot be directly queried.

This makes MemoryAvailable= an upper bound of available values.

src/core/cgroup.c

index 9fd62b2b5b90fc23912767b6b8c41dcb9965905f..b304b39e8c1e5c5ca395572302f70dceadd0e744 100644 (file)
@@ -3751,8 +3751,7 @@ int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
 }
 
 int unit_get_memory_available(Unit *u, uint64_t *ret) {
-        uint64_t available = UINT64_MAX;
-        int r;
+        uint64_t available = UINT64_MAX, current = 0;
 
         assert(u);
         assert(ret);
@@ -3762,7 +3761,7 @@ int unit_get_memory_available(Unit *u, uint64_t *ret) {
          * and MemoryMax, and also any slice the unit might be nested below. */
 
         do {
-                uint64_t unit_current, unit_available, unit_limit = UINT64_MAX;
+                uint64_t unit_available, unit_limit = UINT64_MAX;
                 CGroupContext *unit_context;
 
                 /* No point in continuing if we can't go any lower */
@@ -3776,17 +3775,16 @@ int unit_get_memory_available(Unit *u, uint64_t *ret) {
                 if (!u->cgroup_path)
                         continue;
 
+                (void) unit_get_memory_current(u, &current);
+                /* in case of error, previous current propagates as lower bound */
+
                 if (unit_has_name(u, SPECIAL_ROOT_SLICE))
                         unit_limit = physical_memory();
                 else if (unit_context->memory_max == UINT64_MAX && unit_context->memory_high == UINT64_MAX)
                         continue;
                 unit_limit = MIN3(unit_limit, unit_context->memory_max, unit_context->memory_high);
 
-                r = unit_get_memory_current(u, &unit_current);
-                if (r < 0)
-                        continue;
-
-                unit_available = LESS_BY(unit_limit, unit_current);
+                unit_available = LESS_BY(unit_limit, current);
                 available = MIN(unit_available, available);
         } while ((u = UNIT_GET_SLICE(u)));