changeset 14324:17c2b3fda521

8250984: Memory Docker tests fail on some Linux kernels w/o cgroupv1 swap limit capabilities Reviewed-by: bobv, sgehwolf, phh
author hseigel
date Fri, 25 Sep 2020 17:16:38 +0000
parents e9cd2dd86b79
children e587e2d238a0
files src/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java src/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java test/jdk/internal/platform/docker/MetricsMemoryTester.java test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java
diffstat 4 files changed, 79 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/src/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java	Tue Sep 29 19:59:26 2020 +0000
+++ b/src/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java	Fri Sep 25 17:16:38 2020 +0000
@@ -220,6 +220,8 @@
                 MemorySubSystem memorySubSystem = (MemorySubSystem)subsystem;
                 boolean isHierarchial = getHierarchical(memorySubSystem);
                 memorySubSystem.setHierarchical(isHierarchial);
+                boolean isSwapEnabled = getSwapEnabled(memorySubSystem);
+                memorySubSystem.setSwapEnabled(isSwapEnabled);
             }
             metric.setActiveSubSystems();
         }
@@ -231,6 +233,11 @@
         return hierarchical > 0;
     }
 
+    private static boolean getSwapEnabled(MemorySubSystem subsystem) {
+        long retval = SubSystem.getLongValue(subsystem, "memory.memsw.limit_in_bytes");
+        return retval > 0;
+    }
+
     private void setActiveSubSystems() {
         activeSubSystems = true;
     }
@@ -460,10 +467,16 @@
     }
 
     public long getMemoryAndSwapFailCount() {
+        if (!memory.isSwapEnabled()) {
+            return getMemoryFailCount();
+        }
         return SubSystem.getLongValue(memory, "memory.memsw.failcnt");
     }
 
     public long getMemoryAndSwapLimit() {
+        if (!memory.isSwapEnabled()) {
+            return getMemoryLimit();
+        }
         long retval = SubSystem.getLongValue(memory, "memory.memsw.limit_in_bytes");
         if (retval > unlimited_minimum) {
             if (memory.isHierarchical()) {
@@ -480,10 +493,16 @@
     }
 
     public long getMemoryAndSwapMaxUsage() {
+        if (!memory.isSwapEnabled()) {
+            return getMemoryMaxUsage();
+        }
         return SubSystem.getLongValue(memory, "memory.memsw.max_usage_in_bytes");
     }
 
     public long getMemoryAndSwapUsage() {
+        if (!memory.isSwapEnabled()) {
+            return getMemoryUsage();
+        }
         return SubSystem.getLongValue(memory, "memory.memsw.usage_in_bytes");
     }
 
--- a/src/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java	Tue Sep 29 19:59:26 2020 +0000
+++ b/src/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java	Fri Sep 25 17:16:38 2020 +0000
@@ -257,6 +257,7 @@
     public static class MemorySubSystem extends SubSystem {
 
         private boolean hierarchical;
+        private boolean swapenabled;
 
         public MemorySubSystem(String root, String mountPoint) {
             super(root, mountPoint);
@@ -270,5 +271,13 @@
             this.hierarchical = hierarchical;
         }
 
+        boolean isSwapEnabled() {
+            return swapenabled;
+        }
+
+        void setSwapEnabled(boolean swapenabled) {
+            this.swapenabled = swapenabled;
+        }
+
     }
 }
--- a/test/jdk/internal/platform/docker/MetricsMemoryTester.java	Tue Sep 29 19:59:26 2020 +0000
+++ b/test/jdk/internal/platform/docker/MetricsMemoryTester.java	Fri Sep 25 17:16:38 2020 +0000
@@ -61,26 +61,34 @@
     }
 
     private static void testMemoryFailCount() {
-        long count = Metrics.systemMetrics().getMemoryFailCount();
+        long memAndSwapLimit = Metrics.systemMetrics().getMemoryAndSwapLimit();
+        long memLimit = Metrics.systemMetrics().getMemoryLimit();
+
+        // We need swap to execute this test or will SEGV
+        if (memAndSwapLimit <= memLimit) {
+            System.out.println("No swap memory limits, test case skipped");
+        } else {
+            long count = Metrics.systemMetrics().getMemoryFailCount();
 
-        // Allocate 512M of data
-        byte[][] bytes = new byte[64][];
-        for (int i = 0; i < 64; i++) {
-            try {
-                bytes[i] = new byte[8 * 1024 * 1024];
-                // Break out as soon as we see an increase in failcount
-                // to avoid getting killed by the OOM killer.
-                if (Metrics.systemMetrics().getMemoryFailCount() > count) {
+            // Allocate 512M of data
+            byte[][] bytes = new byte[64][];
+            for (int i = 0; i < 64; i++) {
+                try {
+                    bytes[i] = new byte[8 * 1024 * 1024];
+                    // Break out as soon as we see an increase in failcount
+                    // to avoid getting killed by the OOM killer.
+                    if (Metrics.systemMetrics().getMemoryFailCount() > count) {
+                        break;
+                    }
+                } catch (Error e) { // OOM error
                     break;
                 }
-            } catch (Error e) { // OOM error
-                break;
             }
-        }
-        if (Metrics.systemMetrics().getMemoryFailCount() <= count) {
-            throw new RuntimeException("Memory fail count : new : ["
-                    + Metrics.systemMetrics().getMemoryFailCount() + "]"
-                    + ", old : [" + count + "]");
+            if (Metrics.systemMetrics().getMemoryFailCount() <= count) {
+                throw new RuntimeException("Memory fail count : new : ["
+                        + Metrics.systemMetrics().getMemoryFailCount() + "]"
+                        + ", old : [" + count + "]");
+            }
         }
         System.out.println("TEST PASSED!!!");
     }
@@ -111,10 +119,12 @@
     private static void testMemoryAndSwapLimit(String memory, String memAndSwap) {
         long expectedMem = getMemoryValue(memory);
         long expectedMemAndSwap = getMemoryValue(memAndSwap);
+        long actualMemAndSwap = Metrics.systemMetrics().getMemoryAndSwapLimit();
 
         if (expectedMem != Metrics.systemMetrics().getMemoryLimit()
-                || expectedMemAndSwap != Metrics.systemMetrics().getMemoryAndSwapLimit()) {
-            System.err.println("Memory and swap limit not equal, expected : ["
+                || (expectedMemAndSwap != actualMemAndSwap
+                && expectedMem != actualMemAndSwap)) {
+            throw new RuntimeException("Memory and swap limit not equal, expected : ["
                     + expectedMem + ", " + expectedMemAndSwap + "]"
                     + ", got : [" + Metrics.systemMetrics().getMemoryLimit()
                     + ", " + Metrics.systemMetrics().getMemoryAndSwapLimit() + "]");
--- a/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java	Tue Sep 29 19:59:26 2020 +0000
+++ b/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java	Fri Sep 25 17:16:38 2020 +0000
@@ -291,29 +291,32 @@
         }
 
         //  Memory and Swap
-        oldVal = metrics.getMemoryAndSwapFailCount();
-        newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.failcnt");
-        if (!compareWithErrorMargin(oldVal, newVal)) {
-            fail(SubSystem.MEMORY, "memory.memsw.failcnt", oldVal, newVal);
-        }
+        // Skip swap tests if no swap is configured.
+        if (metrics.getMemoryAndSwapLimit() > metrics.getMemoryLimit()) {
+            oldVal = metrics.getMemoryAndSwapFailCount();
+            newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.failcnt");
+            if (!compareWithErrorMargin(oldVal, newVal)) {
+                fail(SubSystem.MEMORY, "memory.memsw.failcnt", oldVal, newVal);
+            }
 
-        oldVal = metrics.getMemoryAndSwapLimit();
-        newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.limit_in_bytes");
-        newVal = newVal > unlimited_minimum ? -1L : newVal;
-        if (!compareWithErrorMargin(oldVal, newVal)) {
-            fail(SubSystem.MEMORY, "memory.memsw.limit_in_bytes", oldVal, newVal);
-        }
+            oldVal = metrics.getMemoryAndSwapLimit();
+            newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.limit_in_bytes");
+            newVal = newVal > unlimited_minimum ? -1L : newVal;
+            if (!compareWithErrorMargin(oldVal, newVal)) {
+                fail(SubSystem.MEMORY, "memory.memsw.limit_in_bytes", oldVal, newVal);
+            }
 
-        oldVal = metrics.getMemoryAndSwapMaxUsage();
-        newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes");
-        if (!compareWithErrorMargin(oldVal, newVal)) {
-            fail(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes", oldVal, newVal);
-        }
+            oldVal = metrics.getMemoryAndSwapMaxUsage();
+            newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes");
+            if (!compareWithErrorMargin(oldVal, newVal)) {
+                fail(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes", oldVal, newVal);
+            }
 
-        oldVal = metrics.getMemoryAndSwapUsage();
-        newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.usage_in_bytes");
-        if (!compareWithErrorMargin(oldVal, newVal)) {
-            fail(SubSystem.MEMORY, "memory.memsw.usage_in_bytes", oldVal, newVal);
+            oldVal = metrics.getMemoryAndSwapUsage();
+            newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.usage_in_bytes");
+            if (!compareWithErrorMargin(oldVal, newVal)) {
+                fail(SubSystem.MEMORY, "memory.memsw.usage_in_bytes", oldVal, newVal);
+            }
         }
 
         oldVal = metrics.getMemorySoftLimit();