diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp index db5eb59edd3..d4efc0f3d83 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp @@ -252,12 +252,15 @@ class CgroupSubsystem: public CHeapObj { virtual jlong memory_and_swap_limit_in_bytes() = 0; virtual jlong memory_soft_limit_in_bytes() = 0; virtual jlong memory_max_usage_in_bytes() = 0; + virtual char * cpu_cpuset_cpus() = 0; virtual char * cpu_cpuset_memory_nodes() = 0; virtual jlong read_memory_limit_in_bytes() = 0; virtual const char * container_type() = 0; virtual CachingCgroupController* memory_controller() = 0; virtual CachingCgroupController* cpu_controller() = 0; + + virtual void print_version_specific_info(outputStream* st) = 0; }; // Utility class for storing info retrieved from /proc/cgroups, diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index 17f54d7d0db..79dd256ac61 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -212,6 +212,38 @@ jlong CgroupV1Subsystem::memory_max_usage_in_bytes() { return memmaxusage; } + +jlong CgroupV1Subsystem::kernel_memory_usage_in_bytes() { + GET_CONTAINER_INFO(jlong, _memory->controller(), "/memory.kmem.usage_in_bytes", + "Kernel Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, kmem_usage); + return kmem_usage; +} + +jlong CgroupV1Subsystem::kernel_memory_limit_in_bytes() { + GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.kmem.limit_in_bytes", + "Kernel Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, kmem_limit); + if (kmem_limit >= os::Linux::physical_memory()) { + return (jlong)-1; + } + return (jlong)kmem_limit; +} + +jlong CgroupV1Subsystem::kernel_memory_max_usage_in_bytes() { + GET_CONTAINER_INFO(jlong, _memory->controller(), "/memory.kmem.max_usage_in_bytes", + "Maximum Kernel Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, kmem_max_usage); + return kmem_max_usage; +} + +void CgroupV1Subsystem::print_version_specific_info(outputStream* st) { + jlong kmem_usage = kernel_memory_usage_in_bytes(); + jlong kmem_limit = kernel_memory_limit_in_bytes(); + jlong kmem_max_usage = kernel_memory_max_usage_in_bytes(); + + OSContainer::print_container_helper(st, kmem_usage, "kernel_memory_usage_in_bytes"); + OSContainer::print_container_helper(st, kmem_limit, "kernel_memory_max_usage_in_bytes"); + OSContainer::print_container_helper(st, kmem_max_usage, "kernel_memory_limit_in_bytes"); +} + char * CgroupV1Subsystem::cpu_cpuset_cpus() { GET_CONTAINER_INFO_CPTR(cptr, _cpuset, "/cpuset.cpus", "cpuset.cpus is: %s", "%1023s", cpus, 1024); diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp index ce92deb0084..07fac4a9461 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp @@ -79,6 +79,11 @@ class CgroupV1Subsystem: public CgroupSubsystem { jlong memory_soft_limit_in_bytes(); jlong memory_usage_in_bytes(); jlong memory_max_usage_in_bytes(); + + jlong kernel_memory_usage_in_bytes(); + jlong kernel_memory_limit_in_bytes(); + jlong kernel_memory_max_usage_in_bytes(); + char * cpu_cpuset_cpus(); char * cpu_cpuset_memory_nodes(); @@ -90,6 +95,8 @@ class CgroupV1Subsystem: public CgroupSubsystem { jlong pids_max(); jlong pids_current(); + void print_version_specific_info(outputStream* st); + const char * container_type() { return "cgroupv1"; } diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index 0b1bc9c6cdd..b1035f89bf0 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -182,6 +182,16 @@ char* CgroupV2Subsystem::mem_swp_limit_val() { return os::strdup(mem_swp_limit_str); } +// memory.swap.current : total amount of swap currently used by the cgroup and its descendants +char* CgroupV2Subsystem::mem_swp_current_val() { + GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.swap.current", + "Swap currently used is: %s", "%s", mem_swp_current_str, 1024); + if (mem_swp_current_str == NULL) { + return NULL; + } + return os::strdup(mem_swp_current_str); +} + /* memory_limit_in_bytes * * Return the limit of available memory for this process. @@ -212,6 +222,17 @@ char* CgroupV2Subsystem::mem_limit_val() { return os::strdup(mem_limit_str); } +void CgroupV2Subsystem::print_version_specific_info(outputStream* st) { + char* mem_swp_current_str = mem_swp_current_val(); + jlong swap_current = limit_from_str(mem_swp_current_str); + + char* mem_swp_limit_str = mem_swp_limit_val(); + jlong swap_limit = limit_from_str(mem_swp_limit_str); + + OSContainer::print_container_helper(st, swap_current, "memory_swap_current_in_bytes"); + OSContainer::print_container_helper(st, swap_limit, "memory_swap_max_limit_in_bytes"); +} + char* CgroupV2Controller::construct_path(char* mount_path, char *cgroup_path) { char buf[MAXPATHLEN+1]; int buflen; diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp index beb78c21743..bda5872bbbc 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Red Hat Inc. + * Copyright (c) 2020, 2022, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,6 +58,7 @@ class CgroupV2Subsystem: public CgroupSubsystem { char *mem_limit_val(); char *mem_swp_limit_val(); + char *mem_swp_current_val(); char *mem_soft_limit_val(); char *cpu_quota_val(); char *pids_max_val(); @@ -77,11 +78,14 @@ class CgroupV2Subsystem: public CgroupSubsystem { jlong memory_soft_limit_in_bytes(); jlong memory_usage_in_bytes(); jlong memory_max_usage_in_bytes(); + char * cpu_cpuset_cpus(); char * cpu_cpuset_memory_nodes(); jlong pids_max(); jlong pids_current(); + void print_version_specific_info(outputStream* st); + const char * container_type() { return "cgroupv2"; } diff --git a/src/hotspot/os/linux/osContainer_linux.cpp b/src/hotspot/os/linux/osContainer_linux.cpp index fc01ef09b55..52e6ab86c71 100644 --- a/src/hotspot/os/linux/osContainer_linux.cpp +++ b/src/hotspot/os/linux/osContainer_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,6 +91,11 @@ jlong OSContainer::memory_max_usage_in_bytes() { return cgroup_subsystem->memory_max_usage_in_bytes(); } +void OSContainer::print_version_specific_info(outputStream* st) { + assert(cgroup_subsystem != NULL, "cgroup subsystem not available"); + cgroup_subsystem->print_version_specific_info(st); +} + char * OSContainer::cpu_cpuset_cpus() { assert(cgroup_subsystem != NULL, "cgroup subsystem not available"); return cgroup_subsystem->cpu_cpuset_cpus(); @@ -130,3 +135,16 @@ jlong OSContainer::pids_current() { assert(cgroup_subsystem != NULL, "cgroup subsystem not available"); return cgroup_subsystem->pids_current(); } + +void OSContainer::print_container_helper(outputStream* st, jlong j, const char* metrics) { + st->print("%s: ", metrics); + if (j > 0) { + if (j >= 1024) { + st->print_cr(UINT64_FORMAT " k", uint64_t(j) / 1024); + } else { + st->print_cr(UINT64_FORMAT, uint64_t(j)); + } + } else { + st->print_cr("%s", j == OSCONTAINER_ERROR ? "not supported" : "unlimited"); + } +} diff --git a/src/hotspot/os/linux/osContainer_linux.hpp b/src/hotspot/os/linux/osContainer_linux.hpp index 940bc0e3874..ecf9dc5459a 100644 --- a/src/hotspot/os/linux/osContainer_linux.hpp +++ b/src/hotspot/os/linux/osContainer_linux.hpp @@ -27,6 +27,7 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" +#include "utilities/ostream.hpp" #include "memory/allocation.hpp" #define OSCONTAINER_ERROR (-2) @@ -43,6 +44,9 @@ class OSContainer: AllStatic { public: static void init(); + static void print_version_specific_info(outputStream* st); + static void print_container_helper(outputStream* st, jlong j, const char* metrics); + static inline bool is_containerized(); static const char * container_type(); diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 3f750687ef7..65b3ed46698 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2278,19 +2278,6 @@ void os::Linux::print_uptime_info(outputStream* st) { } } -static void print_container_helper(outputStream* st, jlong j, const char* metrics) { - st->print("%s: ", metrics); - if (j > 0) { - if (j >= 1024) { - st->print_cr(UINT64_FORMAT " k", uint64_t(j) / 1024); - } else { - st->print_cr(UINT64_FORMAT, uint64_t(j)); - } - } else { - st->print_cr("%s", j == OSCONTAINER_ERROR ? "not supported" : "unlimited"); - } -} - bool os::Linux::print_container_info(outputStream* st) { if (!OSContainer::is_containerized()) { st->print_cr("container information not found."); @@ -2346,11 +2333,13 @@ bool os::Linux::print_container_info(outputStream* st) { st->print_cr("%s", i == OSCONTAINER_ERROR ? "not supported" : "no shares"); } - print_container_helper(st, OSContainer::memory_limit_in_bytes(), "memory_limit_in_bytes"); - print_container_helper(st, OSContainer::memory_and_swap_limit_in_bytes(), "memory_and_swap_limit_in_bytes"); - print_container_helper(st, OSContainer::memory_soft_limit_in_bytes(), "memory_soft_limit_in_bytes"); - print_container_helper(st, OSContainer::memory_usage_in_bytes(), "memory_usage_in_bytes"); - print_container_helper(st, OSContainer::memory_max_usage_in_bytes(), "memory_max_usage_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::memory_limit_in_bytes(), "memory_limit_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::memory_and_swap_limit_in_bytes(), "memory_and_swap_limit_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::memory_soft_limit_in_bytes(), "memory_soft_limit_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::memory_usage_in_bytes(), "memory_usage_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::memory_max_usage_in_bytes(), "memory_max_usage_in_bytes"); + + OSContainer::print_version_specific_info(st); jlong j = OSContainer::pids_max(); st->print("maximum number of tasks: "); diff --git a/test/hotspot/jtreg/containers/docker/TestMisc.java b/test/hotspot/jtreg/containers/docker/TestMisc.java index 5625fe828bb..5b54c13897b 100644 --- a/test/hotspot/jtreg/containers/docker/TestMisc.java +++ b/test/hotspot/jtreg/containers/docker/TestMisc.java @@ -123,6 +123,19 @@ private static void checkContainerInfo(OutputAnalyzer out) throws Exception { for (String s : expectedToContain) { out.shouldContain(s); } + String str = out.getOutput(); + if (str.contains("cgroupv1")) { + out.shouldContain("kernel_memory_usage_in_bytes"); + out.shouldContain("kernel_memory_max_usage_in_bytes"); + out.shouldContain("kernel_memory_limit_in_bytes"); + } else { + if (str.contains("cgroupv2")) { + out.shouldContain("memory_swap_current_in_bytes"); + out.shouldContain("memory_swap_max_limit_in_bytes"); + } else { + throw new RuntimeException("Output has to contain information about cgroupv1 or cgroupv2"); + } + } } }