summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
}