Skip to content

Commit 0187567

Browse files
author
Harold Seigel
committed
8250984: Memory Docker tests fail on some Linux kernels w/o cgroupv1 …
Reviewed-by: bobv, sgehwolf
1 parent a75edc2 commit 0187567

File tree

8 files changed

+104
-59
lines changed

8 files changed

+104
-59
lines changed

src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1MemorySubSystemController.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
public class CgroupV1MemorySubSystemController extends CgroupV1SubsystemController {
2929

3030
private boolean hierarchical;
31+
private boolean swapenabled;
3132

3233
public CgroupV1MemorySubSystemController(String root, String mountPoint) {
3334
super(root, mountPoint);
@@ -41,4 +42,11 @@ void setHierarchical(boolean hierarchical) {
4142
this.hierarchical = hierarchical;
4243
}
4344

44-
}
45+
boolean isSwapEnabled() {
46+
return swapenabled;
47+
}
48+
49+
void setSwapEnabled(boolean swapenabled) {
50+
this.swapenabled = swapenabled;
51+
}
52+
}

src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ private static void setSubSystemControllerPath(CgroupV1Subsystem subsystem, Stri
199199
CgroupV1MemorySubSystemController memorySubSystem = (CgroupV1MemorySubSystemController)controller;
200200
boolean isHierarchial = getHierarchical(memorySubSystem);
201201
memorySubSystem.setHierarchical(isHierarchial);
202+
boolean isSwapEnabled = getSwapEnabled(memorySubSystem);
203+
memorySubSystem.setSwapEnabled(isSwapEnabled);
202204
}
203205
subsystem.setActiveSubSystems();
204206
}
@@ -208,6 +210,12 @@ private static void setSubSystemControllerPath(CgroupV1Subsystem subsystem, Stri
208210
}
209211

210212

213+
private static boolean getSwapEnabled(CgroupV1MemorySubSystemController controller) {
214+
long retval = getLongValue(controller, "memory.memsw.limit_in_bytes");
215+
return retval > 0;
216+
}
217+
218+
211219
private static boolean getHierarchical(CgroupV1MemorySubSystemController controller) {
212220
long hierarchical = getLongValue(controller, "memory.use_hierarchy");
213221
return hierarchical > 0;
@@ -438,10 +446,16 @@ public long getTcpMemoryUsage() {
438446
}
439447

440448
public long getMemoryAndSwapFailCount() {
449+
if (!memory.isSwapEnabled()) {
450+
return getMemoryFailCount();
451+
}
441452
return getLongValue(memory, "memory.memsw.failcnt");
442453
}
443454

444455
public long getMemoryAndSwapLimit() {
456+
if (!memory.isSwapEnabled()) {
457+
return getMemoryLimit();
458+
}
445459
long retval = getLongValue(memory, "memory.memsw.limit_in_bytes");
446460
if (retval > CgroupV1SubsystemController.UNLIMITED_MIN) {
447461
if (memory.isHierarchical()) {
@@ -457,10 +471,16 @@ public long getMemoryAndSwapLimit() {
457471
}
458472

459473
public long getMemoryAndSwapMaxUsage() {
474+
if (!memory.isSwapEnabled()) {
475+
return getMemoryMaxUsage();
476+
}
460477
return getLongValue(memory, "memory.memsw.max_usage_in_bytes");
461478
}
462479

463480
public long getMemoryAndSwapUsage() {
481+
if (!memory.isSwapEnabled()) {
482+
return getMemoryUsage();
483+
}
464484
return getLongValue(memory, "memory.memsw.usage_in_bytes");
465485
}
466486

test/hotspot/jtreg/ProblemList.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ runtime/cds/DeterministicDump.java 8253495 generic-all
8686
runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java 8253081 generic-all
8787
runtime/jni/terminatedThread/TestTerminatedThread.java 8219652 aix-ppc64
8888
runtime/ReservedStack/ReservedStackTest.java 8231031 generic-all
89-
containers/docker/TestMemoryAwareness.java 8250984 linux-5.4.0-1019-oracle
9089

9190
#############################################################################
9291

test/hotspot/jtreg/containers/cgroup/PlainRead.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static public void noMatch(OutputAnalyzer oa, String what, String value) {
4545
oa.shouldNotMatch("^.*" + what + " *" + value + ".*$");
4646
}
4747

48-
static final String good_value = "(\\d+|-1|Unlimited)";
48+
static final String good_value = "(\\d+|-1|-2|Unlimited)";
4949
static final String bad_value = "(failed)";
5050

5151
static final String[] variables = {"Memory Limit is:", "CPU Shares is:", "CPU Quota is:", "CPU Period is:", "active_processor_count:"};

test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,24 @@ private static void testOperatingSystemMXBeanAwareness(String memoryAllocation,
153153
out.shouldHaveExitValue(0)
154154
.shouldContain("Checking OperatingSystemMXBean")
155155
.shouldContain("OperatingSystemMXBean.getTotalPhysicalMemorySize: " + expectedMemory)
156-
.shouldMatch("OperatingSystemMXBean\\.getFreePhysicalMemorySize: [1-9][0-9]+")
157156
.shouldContain("OperatingSystemMXBean.getTotalMemorySize: " + expectedMemory)
158157
.shouldMatch("OperatingSystemMXBean\\.getFreeMemorySize: [1-9][0-9]+")
159-
.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: [1-9][0-9]+");
160-
// in case of warnings like : "Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap."
161-
// the getTotalSwapSpaceSize returns the system values as the container setup isn't supported in that case.
158+
.shouldMatch("OperatingSystemMXBean\\.getFreePhysicalMemorySize: [1-9][0-9]+");
159+
160+
// in case of warnings like : "Your kernel does not support swap limit capabilities
161+
// or the cgroup is not mounted. Memory limited without swap."
162+
// the getTotalSwapSpaceSize and getFreeSwapSpaceSize return the system
163+
// values as the container setup isn't supported in that case.
162164
try {
163165
out.shouldContain("OperatingSystemMXBean.getTotalSwapSpaceSize: " + expectedSwap);
164166
} catch(RuntimeException ex) {
165-
out.shouldMatch("OperatingSystemMXBean.getTotalSwapSpaceSize: [1-9][0-9]+");
166-
out.shouldContain("Metrics.getMemoryLimit() == " + expectedMemory);
167-
out.shouldContain("Metrics.getMemoryAndSwapLimit() == -1");
167+
out.shouldMatch("OperatingSystemMXBean.getTotalSwapSpaceSize: [0-9]+");
168+
}
169+
170+
try {
171+
out.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: [1-9][0-9]+");
172+
} catch(RuntimeException ex) {
173+
out.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: 0");
168174
}
169175
}
170176

test/jdk/ProblemList.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -905,8 +905,6 @@ jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-
905905

906906
# jdk_internal
907907

908-
jdk/internal/platform/docker/TestDockerMemoryMetrics.java 8250984 linux-5.4.0-1019-oracle
909-
910908
############################################################################
911909

912910
# jdk_jpackage

test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -66,34 +66,42 @@ private static void testMemoryLimit(String value) {
6666
}
6767

6868
private static void testMemoryFailCount() {
69-
long count = Metrics.systemMetrics().getMemoryFailCount();
70-
71-
// Allocate 512M of data
72-
byte[][] bytes = new byte[64][];
73-
boolean atLeastOneAllocationWorked = false;
74-
for (int i = 0; i < 64; i++) {
75-
try {
76-
bytes[i] = new byte[8 * 1024 * 1024];
77-
atLeastOneAllocationWorked = true;
78-
// Break out as soon as we see an increase in failcount
79-
// to avoid getting killed by the OOM killer.
80-
if (Metrics.systemMetrics().getMemoryFailCount() > count) {
69+
long memAndSwapLimit = Metrics.systemMetrics().getMemoryAndSwapLimit();
70+
long memLimit = Metrics.systemMetrics().getMemoryLimit();
71+
72+
// We need swap to execute this test or will SEGV
73+
if (memAndSwapLimit <= memLimit) {
74+
System.out.println("No swap memory limits, test case skipped");
75+
} else {
76+
long count = Metrics.systemMetrics().getMemoryFailCount();
77+
78+
// Allocate 512M of data
79+
byte[][] bytes = new byte[64][];
80+
boolean atLeastOneAllocationWorked = false;
81+
for (int i = 0; i < 64; i++) {
82+
try {
83+
bytes[i] = new byte[8 * 1024 * 1024];
84+
atLeastOneAllocationWorked = true;
85+
// Break out as soon as we see an increase in failcount
86+
// to avoid getting killed by the OOM killer.
87+
if (Metrics.systemMetrics().getMemoryFailCount() > count) {
88+
break;
89+
}
90+
} catch (Error e) { // OOM error
8191
break;
8292
}
83-
} catch (Error e) { // OOM error
84-
break;
8593
}
86-
}
87-
if (!atLeastOneAllocationWorked) {
88-
System.out.println("Allocation failed immediately. Ignoring test!");
89-
return;
90-
}
91-
// Be sure bytes allocations don't get optimized out
92-
System.out.println("DEBUG: Bytes allocation length 1: " + bytes[0].length);
93-
if (Metrics.systemMetrics().getMemoryFailCount() <= count) {
94-
throw new RuntimeException("Memory fail count : new : ["
95-
+ Metrics.systemMetrics().getMemoryFailCount() + "]"
96-
+ ", old : [" + count + "]");
94+
if (!atLeastOneAllocationWorked) {
95+
System.out.println("Allocation failed immediately. Ignoring test!");
96+
return;
97+
}
98+
// Be sure bytes allocations don't get optimized out
99+
System.out.println("DEBUG: Bytes allocation length 1: " + bytes[0].length);
100+
if (Metrics.systemMetrics().getMemoryFailCount() <= count) {
101+
throw new RuntimeException("Memory fail count : new : ["
102+
+ Metrics.systemMetrics().getMemoryFailCount() + "]"
103+
+ ", old : [" + count + "]");
104+
}
97105
}
98106
System.out.println("TEST PASSED!!!");
99107
}
@@ -131,10 +139,12 @@ private static void testKernelMemoryLimit(String value) {
131139
private static void testMemoryAndSwapLimit(String memory, String memAndSwap) {
132140
long expectedMem = getMemoryValue(memory);
133141
long expectedMemAndSwap = getMemoryValue(memAndSwap);
142+
long actualMemAndSwap = Metrics.systemMetrics().getMemoryAndSwapLimit();
134143

135144
if (expectedMem != Metrics.systemMetrics().getMemoryLimit()
136-
|| expectedMemAndSwap != Metrics.systemMetrics().getMemoryAndSwapLimit()) {
137-
System.err.println("Memory and swap limit not equal, expected : ["
145+
|| (expectedMemAndSwap != actualMemAndSwap
146+
&& expectedMem != actualMemAndSwap)) {
147+
throw new RuntimeException("Memory and swap limit not equal, expected : ["
138148
+ expectedMem + ", " + expectedMemAndSwap + "]"
139149
+ ", got : [" + Metrics.systemMetrics().getMemoryLimit()
140150
+ ", " + Metrics.systemMetrics().getMemoryAndSwapLimit() + "]");

test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV1.java

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -293,29 +293,33 @@ public void testMemorySubsystem() {
293293
}
294294

295295
// Memory and Swap
296-
oldVal = metrics.getMemoryAndSwapFailCount();
297-
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.failcnt");
298-
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
299-
fail(Controller.MEMORY, "memory.memsw.failcnt", oldVal, newVal);
300-
}
301296

302-
oldVal = metrics.getMemoryAndSwapLimit();
303-
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.limit_in_bytes");
304-
newVal = newVal > unlimited_minimum ? CgroupSubsystem.LONG_RETVAL_UNLIMITED : newVal;
305-
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
306-
fail(Controller.MEMORY, "memory.memsw.limit_in_bytes", oldVal, newVal);
307-
}
297+
// Skip swap tests if no swap is configured.
298+
if (metrics.getMemoryAndSwapLimit() > metrics.getMemoryLimit()) {
299+
oldVal = metrics.getMemoryAndSwapFailCount();
300+
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.failcnt");
301+
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
302+
fail(Controller.MEMORY, "memory.memsw.failcnt", oldVal, newVal);
303+
}
308304

309-
oldVal = metrics.getMemoryAndSwapMaxUsage();
310-
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.max_usage_in_bytes");
311-
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
312-
fail(Controller.MEMORY, "memory.memsw.max_usage_in_bytes", oldVal, newVal);
313-
}
305+
oldVal = metrics.getMemoryAndSwapLimit();
306+
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.limit_in_bytes");
307+
newVal = newVal > unlimited_minimum ? CgroupSubsystem.LONG_RETVAL_UNLIMITED : newVal;
308+
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
309+
fail(Controller.MEMORY, "memory.memsw.limit_in_bytes", oldVal, newVal);
310+
}
314311

315-
oldVal = metrics.getMemoryAndSwapUsage();
316-
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.usage_in_bytes");
317-
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
318-
fail(Controller.MEMORY, "memory.memsw.usage_in_bytes", oldVal, newVal);
312+
oldVal = metrics.getMemoryAndSwapMaxUsage();
313+
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.max_usage_in_bytes");
314+
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
315+
fail(Controller.MEMORY, "memory.memsw.max_usage_in_bytes", oldVal, newVal);
316+
}
317+
318+
oldVal = metrics.getMemoryAndSwapUsage();
319+
newVal = getLongValueFromFile(Controller.MEMORY, "memory.memsw.usage_in_bytes");
320+
if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
321+
fail(Controller.MEMORY, "memory.memsw.usage_in_bytes", oldVal, newVal);
322+
}
319323
}
320324

321325
oldVal = metrics.getMemorySoftLimit();

0 commit comments

Comments
 (0)