Skip to content

Commit 1d5e944

Browse files
committed
Backport 824af4cc8d7810d337098c05d748ec6b41caa802
1 parent 524170d commit 1d5e944

File tree

5 files changed

+93
-17
lines changed

5 files changed

+93
-17
lines changed

src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,19 @@ jlong CgroupV1Subsystem::read_memory_limit_in_bytes() {
113113
}
114114
}
115115

116-
jlong CgroupV1Subsystem::memory_and_swap_limit_in_bytes() {
116+
/* read_mem_swap
117+
*
118+
* Determine the memory and swap limit metric. Returns a positive limit value strictly
119+
* lower than the physical memory and swap limit iff there is a limit. Otherwise a
120+
* negative value is returned indicating the determined status.
121+
*
122+
* returns:
123+
* * A number > 0 if the limit is available and lower than a physical upper bound.
124+
* * OSCONTAINER_ERROR if the limit cannot be retrieved (i.e. not supported) or
125+
* * -1 if there isn't any limit in place (note: includes values which exceed a physical
126+
* upper bound)
127+
*/
128+
jlong CgroupV1Subsystem::read_mem_swap() {
117129
julong host_total_memsw;
118130
GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.memsw.limit_in_bytes",
119131
"Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit);
@@ -129,29 +141,36 @@ jlong CgroupV1Subsystem::memory_and_swap_limit_in_bytes() {
129141
if (hier_memswlimit >= host_total_memsw) {
130142
log_trace(os, container)("Hierarchical Memory and Swap Limit is: Unlimited");
131143
} else {
132-
jlong swappiness = read_mem_swappiness();
133-
if (swappiness == 0) {
134-
const char* matchmemline = "hierarchical_memory_limit";
135-
GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", matchmemline,
136-
"Hierarchical Memory Limit is : " JULONG_FORMAT, format, hier_memlimit)
137-
log_trace(os, container)("Memory and Swap Limit has been reset to " JULONG_FORMAT " because swappiness is 0", hier_memlimit);
138-
return (jlong)hier_memlimit;
139-
}
140144
return (jlong)hier_memswlimit;
141145
}
142146
}
143147
return (jlong)-1;
144148
} else {
145-
jlong swappiness = read_mem_swappiness();
146-
if (swappiness == 0) {
147-
jlong memlimit = read_memory_limit_in_bytes();
148-
log_trace(os, container)("Memory and Swap Limit has been reset to " JULONG_FORMAT " because swappiness is 0", memlimit);
149-
return memlimit;
150-
}
151149
return (jlong)memswlimit;
152150
}
153151
}
154152

153+
jlong CgroupV1Subsystem::memory_and_swap_limit_in_bytes() {
154+
jlong memory_swap = read_mem_swap();
155+
if (memory_swap == -1) {
156+
return memory_swap;
157+
}
158+
// If there is a swap limit, but swappiness == 0, reset the limit
159+
// to the memory limit. Do the same for cases where swap isn't
160+
// supported.
161+
jlong swappiness = read_mem_swappiness();
162+
if (swappiness == 0 || memory_swap == OSCONTAINER_ERROR) {
163+
jlong memlimit = read_memory_limit_in_bytes();
164+
if (memory_swap == OSCONTAINER_ERROR) {
165+
log_trace(os, container)("Memory and Swap Limit has been reset to " JLONG_FORMAT " because swap is not supported", memlimit);
166+
} else {
167+
log_trace(os, container)("Memory and Swap Limit has been reset to " JLONG_FORMAT " because swappiness is 0", memlimit);
168+
}
169+
return memlimit;
170+
}
171+
return memory_swap;
172+
}
173+
155174
jlong CgroupV1Subsystem::read_mem_swappiness() {
156175
GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.swappiness",
157176
"Swappiness is: " JULONG_FORMAT, JULONG_FORMAT, swappiness);

src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ class CgroupV1Subsystem: public CgroupSubsystem {
114114
char * pids_max_val();
115115

116116
jlong read_mem_swappiness();
117+
jlong read_mem_swap();
117118

118119
public:
119120
CgroupV1Subsystem(CgroupV1Controller* cpuset,

src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,12 @@ char* CgroupV2Subsystem::mem_soft_limit_val() {
164164
// without also setting a memory limit is not allowed.
165165
jlong CgroupV2Subsystem::memory_and_swap_limit_in_bytes() {
166166
char* mem_swp_limit_str = mem_swp_limit_val();
167+
if (mem_swp_limit_str == nullptr) {
168+
// Some container tests rely on this trace logging to happen.
169+
log_trace(os, container)("Memory and Swap Limit is: %d", OSCONTAINER_ERROR);
170+
// swap disabled at kernel level, treat it as no swap
171+
return read_memory_limit_in_bytes();
172+
}
167173
jlong swap_limit = limit_from_str(mem_swp_limit_str);
168174
if (swap_limit >= 0) {
169175
jlong memory_limit = read_memory_limit_in_bytes();

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

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ public static void main(String[] args) throws Exception {
7676
testMemorySoftLimit("500m", "524288000");
7777
testMemorySoftLimit("1g", "1073741824");
7878

79+
testMemorySwapNotSupported("500m", "520m", "512000 k", "532480 k");
80+
7981
// Add extra 10 Mb to allocator limit, to be sure to cause OOM
8082
testOOM("256m", 256 + 10);
8183

@@ -153,6 +155,54 @@ private static void testMemorySoftLimit(String valueToSet, String expectedTraceV
153155
.shouldMatch("Memory Soft Limit.*" + expectedTraceValue);
154156
}
155157

158+
/*
159+
* Verifies that PrintContainerInfo prints the memory
160+
* limit - without swap - iff swap is disabled (e.g. via swapaccount=0). It must
161+
* not print 'not supported' for that value in that case. It'll always pass
162+
* on systems with swap accounting enabled.
163+
*/
164+
private static void testMemorySwapNotSupported(String valueToSet, String swapToSet, String expectedMem, String expectedSwap)
165+
throws Exception {
166+
Common.logNewTestCase("memory swap not supported: " + valueToSet);
167+
168+
DockerRunOptions opts = Common.newOpts(imageName, "PrintContainerInfo");
169+
Common.addWhiteBoxOpts(opts);
170+
opts.addDockerOpts("--memory=" + valueToSet);
171+
opts.addDockerOpts("--memory-swap=" + swapToSet);
172+
173+
Common.run(opts)
174+
.shouldMatch("memory_limit_in_bytes:.*" + expectedMem)
175+
.shouldNotMatch("memory_and_swap_limit_in_bytes:.*not supported")
176+
// On systems with swapaccount=0 this returns the memory limit.
177+
// On systems with swapaccount=1 this returns the set memory+swap value.
178+
.shouldMatch("memory_and_swap_limit_in_bytes:.*(" + expectedMem + "|" + expectedSwap + ")");
179+
}
180+
181+
/*
182+
* This test verifies that no confusingly large positive numbers get printed on
183+
* systems with swapaccount=0 kernel option. On some systems -2 were converted
184+
* to unsigned long and printed that way. Ensure this oddity doesn't occur.
185+
*/
186+
private static void testMemorySwapLimitSanity() throws Exception {
187+
String valueToSet = "500m";
188+
String expectedTraceValue = "524288000";
189+
Common.logNewTestCase("memory swap sanity: " + valueToSet);
190+
191+
DockerRunOptions opts = Common.newOpts(imageName, "PrintContainerInfo");
192+
Common.addWhiteBoxOpts(opts);
193+
opts.addDockerOpts("--memory=" + valueToSet);
194+
opts.addDockerOpts("--memory-swap=" + valueToSet);
195+
196+
String neg2InUnsignedLong = "18446744073709551614";
197+
198+
Common.run(opts)
199+
.shouldMatch("Memory Limit is:.*" + expectedTraceValue)
200+
// Either for cgroup v1: a_1) same as memory limit, or b_1) -2 on systems with swapaccount=0
201+
// Either for cgroup v2: a_2) 0, or b_2) -2 on systems with swapaccount=0
202+
.shouldMatch("Memory and Swap Limit is:.*(" + expectedTraceValue + "|-2|0)")
203+
.shouldNotMatch("Memory and Swap Limit is:.*" + neg2InUnsignedLong);
204+
}
205+
156206

157207
// provoke OOM inside the container, see how VM reacts
158208
private static void testOOM(String dockerMemLimit, int sizeToAllocInMb) throws Exception {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ private static void testMemoryLimitWithSwappiness(String dockerMemLimit, String
8585
// capabilities or the cgroup is not mounted. Memory limited without swap."
8686
// we only have Memory and Swap Limit is: <huge integer> in the output
8787
try {
88-
if (out.getOutput().contains("memory_and_swap_limit_in_bytes: not supported")) {
89-
System.out.println("memory_and_swap_limit_in_bytes not supported, avoiding Memory and Swap Limit check");
88+
if (out.getOutput().contains("Memory and Swap Limit is: -2")) {
89+
System.out.println("System doesn't seem to allow swap, avoiding Memory and Swap Limit check");
9090
} else {
9191
out.shouldContain("Memory and Swap Limit is: " + expectedReadLimit)
9292
.shouldContain(

0 commit comments

Comments
 (0)