diff options
author | Lennart Poettering <lennart@poettering.net> | 2016-06-08 18:56:20 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2016-06-14 19:50:38 +0200 |
commit | d9ab2bcf0591b496f1a4750c7ff790b33f9c7e59 (patch) | |
tree | bf6ba42e885a9cd8e6baa55a8629f6bb28678eae | |
parent | 1d7100298c2a696d99f6fbd6ab858762aeb51ac7 (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.c | 35 | ||||
-rw-r--r-- | src/test/test-util.c | 14 |
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; } |