diff --git a/hotspot/src/os/linux/vm/cgroupSubsystem_linux.hpp b/hotspot/src/os/linux/vm/cgroupSubsystem_linux.hpp index 63b0c4b8154..0cc0d5b6287 100644 --- a/hotspot/src/os/linux/vm/cgroupSubsystem_linux.hpp +++ b/hotspot/src/os/linux/vm/cgroupSubsystem_linux.hpp @@ -269,12 +269,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/hotspot/src/os/linux/vm/cgroupV1Subsystem_linux.cpp b/hotspot/src/os/linux/vm/cgroupV1Subsystem_linux.cpp index bac3edb0051..b5c14173f6f 100644 --- a/hotspot/src/os/linux/vm/cgroupV1Subsystem_linux.cpp +++ b/hotspot/src/os/linux/vm/cgroupV1Subsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, 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 @@ -201,6 +201,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/hotspot/src/os/linux/vm/cgroupV1Subsystem_linux.hpp b/hotspot/src/os/linux/vm/cgroupV1Subsystem_linux.hpp index 568268867a4..bdce7b56315 100644 --- a/hotspot/src/os/linux/vm/cgroupV1Subsystem_linux.hpp +++ b/hotspot/src/os/linux/vm/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(); @@ -87,6 +92,8 @@ class CgroupV1Subsystem: public CgroupSubsystem { int cpu_shares(); + void print_version_specific_info(outputStream* st); + const char * container_type() { return "cgroupv1"; } diff --git a/hotspot/src/os/linux/vm/cgroupV2Subsystem_linux.cpp b/hotspot/src/os/linux/vm/cgroupV2Subsystem_linux.cpp index 2fc555bce8c..840042b2475 100644 --- a/hotspot/src/os/linux/vm/cgroupV2Subsystem_linux.cpp +++ b/hotspot/src/os/linux/vm/cgroupV2Subsystem_linux.cpp @@ -194,6 +194,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. @@ -242,6 +252,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/hotspot/src/os/linux/vm/cgroupV2Subsystem_linux.hpp b/hotspot/src/os/linux/vm/cgroupV2Subsystem_linux.hpp index 84e0615b60d..22199dc29cc 100644 --- a/hotspot/src/os/linux/vm/cgroupV2Subsystem_linux.hpp +++ b/hotspot/src/os/linux/vm/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(); jlong limit_from_str(char* limit_str); @@ -77,8 +78,12 @@ 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(); + + void print_version_specific_info(outputStream* st); + const char * container_type() { return "cgroupv2"; } diff --git a/hotspot/src/os/linux/vm/osContainer_linux.cpp b/hotspot/src/os/linux/vm/osContainer_linux.cpp index 95c83e49fd9..33a7442ea81 100644 --- a/hotspot/src/os/linux/vm/osContainer_linux.cpp +++ b/hotspot/src/os/linux/vm/osContainer_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, 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 @@ -104,6 +104,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(); @@ -133,3 +138,16 @@ int OSContainer::cpu_shares() { assert(cgroup_subsystem != NULL, "cgroup subsystem not available"); return cgroup_subsystem->cpu_shares(); } + +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/hotspot/src/os/linux/vm/osContainer_linux.hpp b/hotspot/src/os/linux/vm/osContainer_linux.hpp index 53e792ee0aa..eb2f53f2a43 100644 --- a/hotspot/src/os/linux/vm/osContainer_linux.hpp +++ b/hotspot/src/os/linux/vm/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/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index b6fd444a012..9b42126ec49 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2292,19 +2292,6 @@ void os::Linux::print_full_memory_info(outputStream* st) { st->cr(); } -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"); - } -} - void os::Linux::print_container_info(outputStream* st) { if (!OSContainer::is_containerized()) { return; @@ -2355,11 +2342,14 @@ void os::Linux::print_container_info(outputStream* st) { st->print("%s\n", 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); + st->cr(); } diff --git a/hotspot/test/runtime/containers/docker/TestMisc.java b/hotspot/test/runtime/containers/docker/TestMisc.java index efd52278cb9..ead0d781b9f 100644 --- a/hotspot/test/runtime/containers/docker/TestMisc.java +++ b/hotspot/test/runtime/containers/docker/TestMisc.java @@ -108,6 +108,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"); + } + } } }