8253727: [cgroups v2] Memory and swap limits reported incorrectly

Account for interface files for swap and memory being reported independently.
The cgroup v1-like value is now reported by adding the memory.max value to
the memory.swap.max value, and memory.current and memory.swap.current
respectively.

Reviewed-by: bobv, shade
This commit is contained in:
Severin Gehwolf 2020-10-01 09:28:40 +00:00
parent 7779ce9fb4
commit 3e96721cd9
3 changed files with 47 additions and 5 deletions
src
hotspot/os/linux
java.base/linux/classes/jdk/internal/platform/cgroupv2
test/lib/jdk/test/lib/containers/cgroup

@ -157,9 +157,20 @@ char* CgroupV2Subsystem::mem_soft_limit_val() {
return os::strdup(mem_soft_limit_str);
}
// Note that for cgroups v2 the actual limits set for swap and
// memory live in two different files, memory.swap.max and memory.max
// respectively. In order to properly report a cgroup v1 like
// compound value we need to sum the two values. Setting a swap limit
// without also setting a memory limit is not allowed.
jlong CgroupV2Subsystem::memory_and_swap_limit_in_bytes() {
char* mem_swp_limit_str = mem_swp_limit_val();
return limit_from_str(mem_swp_limit_str);
jlong swap_limit = limit_from_str(mem_swp_limit_str);
if (swap_limit >= 0) {
jlong memory_limit = read_memory_limit_in_bytes();
assert(memory_limit >= 0, "swap limit without memory limit?");
return memory_limit + swap_limit;
}
return swap_limit;
}
char* CgroupV2Subsystem::mem_swp_limit_val() {

@ -274,15 +274,37 @@ public class CgroupV2Subsystem implements CgroupSubsystem {
return CgroupV2SubsystemController.getLongEntry(unified, "memory.stat", "sock");
}
/**
* Note that for cgroups v2 the actual limits set for swap and
* memory live in two different files, memory.swap.max and memory.max
* respectively. In order to properly report a cgroup v1 like
* compound value we need to sum the two values. Setting a swap limit
* without also setting a memory limit is not allowed.
*/
@Override
public long getMemoryAndSwapLimit() {
String strVal = CgroupSubsystemController.getStringValue(unified, "memory.swap.max");
return limitFromString(strVal);
long swapLimit = limitFromString(strVal);
if (swapLimit >= 0) {
long memoryLimit = getMemoryLimit();
assert memoryLimit >= 0;
return memoryLimit + swapLimit;
}
return swapLimit;
}
/**
* Note that for cgroups v2 the actual values set for swap usage and
* memory usage live in two different files, memory.current and memory.swap.current
* respectively. In order to properly report a cgroup v1 like
* compound value we need to sum the two values. Setting a swap limit
* without also setting a memory limit is not allowed.
*/
@Override
public long getMemoryAndSwapUsage() {
return getLongVal("memory.swap.current");
long swapUsage = getLongVal("memory.swap.current");
long memoryUsage = getMemoryUsage();
return memoryUsage + swapUsage;
}
@Override

@ -240,13 +240,22 @@ public class MetricsTesterCgroupV2 implements CgroupMetricsTester {
}
oldVal = metrics.getMemoryAndSwapLimit();
newVal = getLongLimitValueFromFile("memory.swap.max");
long valSwap = getLongLimitValueFromFile("memory.swap.max");
long valMemory = getLongLimitValueFromFile("memory.max");
if (valSwap == UNLIMITED) {
newVal = valSwap;
} else {
assert valMemory >= 0;
newVal = valSwap + valMemory;
}
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
fail("memory.swap.max", oldVal, newVal);
}
oldVal = metrics.getMemoryAndSwapUsage();
newVal = getLongValueFromFile("memory.swap.current");
long swapUsage = getLongValueFromFile("memory.swap.current");
long memUsage = getLongValueFromFile("memory.current");
newVal = swapUsage + memUsage;
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
fail("memory.swap.current", oldVal, newVal);
}