summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-06-08 18:56:20 +0200
committerLennart Poettering <lennart@poettering.net>2016-06-14 19:50:38 +0200
commitd9ab2bcf0591b496f1a4750c7ff790b33f9c7e59 (patch)
treebf6ba42e885a9cd8e6baa55a8629f6bb28678eae
parent1d7100298c2a696d99f6fbd6ab858762aeb51ac7 (diff)
util: when determining the amount of memory on this system, take cgroup limit into account
When determining the amount of RAM in the system, let's make sure we also read the root-level cgroup memory limit into account. This isn't particularly useful on the host, but in containers it makes sure that whatever memory the container got assigned is actually used for RAM size calculations.
-rw-r--r--src/basic/util.c35
-rw-r--r--src/test/test-util.c14
2 files changed, 43 insertions, 6 deletions
diff --git a/src/basic/util.c b/src/basic/util.c
index f2f92fb3b7..88d58cd94a 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -36,6 +36,7 @@
#include "alloc-util.h"
#include "build.h"
+#include "cgroup-util.h"
#include "def.h"
#include "dirent-util.h"
#include "fd-util.h"
@@ -771,15 +772,37 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
}
uint64_t physical_memory(void) {
- long mem;
+ _cleanup_free_ char *root = NULL, *value = NULL;
+ uint64_t mem, lim;
+ size_t ps;
+ long sc;
- /* We return this as uint64_t in case we are running as 32bit
- * process on a 64bit kernel with huge amounts of memory */
+ /* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
+ * memory.
+ *
+ * In order to support containers nicely that have a configured memory limit we'll take the minimum of the
+ * physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
+
+ sc = sysconf(_SC_PHYS_PAGES);
+ assert(sc > 0);
+
+ ps = page_size();
+ mem = (uint64_t) sc * (uint64_t) ps;
+
+ if (cg_get_root_path(&root) < 0)
+ return mem;
+
+ if (cg_get_attribute("memory", root, "memory.limit_in_bytes", &value))
+ return mem;
+
+ if (safe_atou64(value, &lim) < 0)
+ return mem;
- mem = sysconf(_SC_PHYS_PAGES);
- assert(mem > 0);
+ /* Make sure the limit is a multiple of our own page size */
+ lim /= ps;
+ lim *= ps;
- return (uint64_t) mem * (uint64_t) page_size();
+ return MIN(mem, lim);
}
int update_reboot_parameter_and_warn(const char *param) {
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 9b6d2a7968..5b3fbcff53 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -26,6 +26,7 @@
#include "def.h"
#include "fileio.h"
#include "fs-util.h"
+#include "parse-util.h"
#include "raw-clone.h"
#include "rm-rf.h"
#include "string-util.h"
@@ -263,6 +264,18 @@ static void test_raw_clone(void) {
}
}
+static void test_physical_memory(void) {
+ uint64_t p;
+ char buf[FORMAT_BYTES_MAX];
+
+ p = physical_memory();
+ assert_se(p > 0);
+ assert_se(p < UINT64_MAX);
+ assert_se(p % page_size() == 0);
+
+ log_info("Memory: %s", format_bytes(buf, sizeof(buf), p));
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
@@ -277,6 +290,7 @@ int main(int argc, char *argv[]) {
test_log2i();
test_execute_directory();
test_raw_clone();
+ test_physical_memory();
return 0;
}