8300645: Handle julong values in logging of GET_CONTAINER_INFO macros

Reviewed-by: iklam
This commit is contained in:
Severin Gehwolf
2023-02-16 10:08:54 +00:00
parent c77f64420a
commit 53ae4c07fd
5 changed files with 51 additions and 22 deletions

View File

@@ -159,8 +159,10 @@ template <typename T> int subsystem_file_line_contents(CgroupController* c,
}
PRAGMA_DIAG_POP
// log_fmt can be different than scan_fmt. For example
// cpu_period() for cgv2 uses log_fmt='%d' and scan_fmt='%*s %d'
#define GET_CONTAINER_INFO(return_type, subsystem, filename, \
logstring, scan_fmt, variable) \
logstring, log_fmt, scan_fmt, variable) \
return_type variable; \
{ \
int err; \
@@ -170,11 +172,11 @@ PRAGMA_DIAG_POP
scan_fmt, \
&variable); \
if (err != 0) { \
log_trace(os, container)(logstring, (return_type) OSCONTAINER_ERROR); \
log_trace(os, container)(logstring "%d", OSCONTAINER_ERROR); \
return (return_type) OSCONTAINER_ERROR; \
} \
\
log_trace(os, container)(logstring, variable); \
log_trace(os, container)(logstring log_fmt, variable); \
}
#define GET_CONTAINER_INFO_CPTR(return_type, subsystem, filename, \

View File

@@ -76,7 +76,7 @@ void CgroupV1Controller::set_subsystem_path(char *cgroup_path) {
*/
jlong CgroupV1MemoryController::uses_mem_hierarchy() {
GET_CONTAINER_INFO(jlong, this, "/memory.use_hierarchy",
"Use Hierarchy is: " JLONG_FORMAT, JLONG_FORMAT, use_hierarchy);
"Use Hierarchy is: ", JLONG_FORMAT, JLONG_FORMAT, use_hierarchy);
return use_hierarchy;
}
@@ -90,7 +90,7 @@ void CgroupV1MemoryController::set_subsystem_path(char *cgroup_path) {
jlong CgroupV1Subsystem::read_memory_limit_in_bytes() {
GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.limit_in_bytes",
"Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit);
"Memory Limit is: ", JULONG_FORMAT, JULONG_FORMAT, memlimit);
if (memlimit >= os::Linux::physical_memory()) {
log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited");
@@ -114,7 +114,7 @@ jlong CgroupV1Subsystem::read_memory_limit_in_bytes() {
jlong CgroupV1Subsystem::memory_and_swap_limit_in_bytes() {
julong host_total_memsw;
GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.memsw.limit_in_bytes",
"Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit);
"Memory and Swap Limit is: ", JULONG_FORMAT, JULONG_FORMAT, memswlimit);
host_total_memsw = os::Linux::host_swap() + os::Linux::physical_memory();
if (memswlimit >= host_total_memsw) {
log_trace(os, container)("Non-Hierarchical Memory and Swap Limit is: Unlimited");
@@ -151,13 +151,13 @@ jlong CgroupV1Subsystem::memory_and_swap_limit_in_bytes() {
jlong CgroupV1Subsystem::read_mem_swappiness() {
GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.swappiness",
"Swappiness is: " JULONG_FORMAT, JULONG_FORMAT, swappiness);
"Swappiness is: ", JULONG_FORMAT, JULONG_FORMAT, swappiness);
return swappiness;
}
jlong CgroupV1Subsystem::memory_soft_limit_in_bytes() {
GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.soft_limit_in_bytes",
"Memory Soft Limit is: " JULONG_FORMAT, JULONG_FORMAT, memsoftlimit);
"Memory Soft Limit is: ", JULONG_FORMAT, JULONG_FORMAT, memsoftlimit);
if (memsoftlimit >= os::Linux::physical_memory()) {
log_trace(os, container)("Memory Soft Limit is: Unlimited");
return (jlong)-1;
@@ -177,7 +177,7 @@ jlong CgroupV1Subsystem::memory_soft_limit_in_bytes() {
*/
jlong CgroupV1Subsystem::memory_usage_in_bytes() {
GET_CONTAINER_INFO(jlong, _memory->controller(), "/memory.usage_in_bytes",
"Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memusage);
"Memory Usage is: ", JLONG_FORMAT, JLONG_FORMAT, memusage);
return memusage;
}
@@ -191,20 +191,20 @@ jlong CgroupV1Subsystem::memory_usage_in_bytes() {
*/
jlong CgroupV1Subsystem::memory_max_usage_in_bytes() {
GET_CONTAINER_INFO(jlong, _memory->controller(), "/memory.max_usage_in_bytes",
"Maximum Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memmaxusage);
"Maximum Memory Usage is: ", JLONG_FORMAT, JLONG_FORMAT, memmaxusage);
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);
"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);
"Kernel Memory Limit is: ", JULONG_FORMAT, JULONG_FORMAT, kmem_limit);
if (kmem_limit >= os::Linux::physical_memory()) {
return (jlong)-1;
}
@@ -213,7 +213,7 @@ jlong CgroupV1Subsystem::kernel_memory_limit_in_bytes() {
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);
"Maximum Kernel Memory Usage is: ", JLONG_FORMAT, JLONG_FORMAT, kmem_max_usage);
return kmem_max_usage;
}
@@ -251,13 +251,13 @@ char * CgroupV1Subsystem::cpu_cpuset_memory_nodes() {
*/
int CgroupV1Subsystem::cpu_quota() {
GET_CONTAINER_INFO(int, _cpu->controller(), "/cpu.cfs_quota_us",
"CPU Quota is: %d", "%d", quota);
"CPU Quota is: ", "%d", "%d", quota);
return quota;
}
int CgroupV1Subsystem::cpu_period() {
GET_CONTAINER_INFO(int, _cpu->controller(), "/cpu.cfs_period_us",
"CPU Period is: %d", "%d", period);
"CPU Period is: ", "%d", "%d", period);
return period;
}
@@ -273,7 +273,7 @@ int CgroupV1Subsystem::cpu_period() {
*/
int CgroupV1Subsystem::cpu_shares() {
GET_CONTAINER_INFO(int, _cpu->controller(), "/cpu.shares",
"CPU Shares is: %d", "%d", shares);
"CPU Shares is: ", "%d", "%d", shares);
// Convert 1024 to no shares setup
if (shares == 1024) return -1;
@@ -313,6 +313,6 @@ jlong CgroupV1Subsystem::pids_max() {
jlong CgroupV1Subsystem::pids_current() {
if (_pids == nullptr) return OSCONTAINER_ERROR;
GET_CONTAINER_INFO(jlong, _pids, "/pids.current",
"Current number of tasks is: " JLONG_FORMAT, JLONG_FORMAT, pids_current);
"Current number of tasks is: ", JLONG_FORMAT, JLONG_FORMAT, pids_current);
return pids_current;
}

View File

@@ -36,7 +36,7 @@
*/
int CgroupV2Subsystem::cpu_shares() {
GET_CONTAINER_INFO(int, _unified, "/cpu.weight",
"Raw value for CPU Shares is: %d", "%d", shares);
"Raw value for CPU Shares is: ", "%d", "%d", shares);
// Convert default value of 100 to no shares setup
if (shares == 100) {
log_debug(os, container)("CPU Shares is: %d", -1);
@@ -109,7 +109,7 @@ char * CgroupV2Subsystem::cpu_cpuset_memory_nodes() {
int CgroupV2Subsystem::cpu_period() {
GET_CONTAINER_INFO(int, _unified, "/cpu.max",
"CPU Period is: %d", "%*s %d", period);
"CPU Period is: ", "%d", "%*s %d", period);
return period;
}
@@ -124,7 +124,7 @@ int CgroupV2Subsystem::cpu_period() {
*/
jlong CgroupV2Subsystem::memory_usage_in_bytes() {
GET_CONTAINER_INFO(jlong, _unified, "/memory.current",
"Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memusage);
"Memory Usage is: ", JLONG_FORMAT, JLONG_FORMAT, memusage);
return memusage;
}
@@ -158,6 +158,7 @@ jlong CgroupV2Subsystem::memory_and_swap_limit_in_bytes() {
assert(memory_limit >= 0, "swap limit without memory limit?");
return memory_limit + swap_limit;
}
log_trace(os, container)("Memory and Swap Limit is: " JLONG_FORMAT, swap_limit);
return swap_limit;
}
@@ -251,6 +252,6 @@ jlong CgroupV2Subsystem::pids_max() {
*/
jlong CgroupV2Subsystem::pids_current() {
GET_CONTAINER_INFO(jlong, _unified, "/pids.current",
"Current number of tasks is: " JLONG_FORMAT, JLONG_FORMAT, pids_current);
"Current number of tasks is: ", JLONG_FORMAT, JLONG_FORMAT, pids_current);
return pids_current;
}

View File

@@ -75,6 +75,7 @@ public class TestMemoryAwareness {
testMemorySoftLimit("500m", "524288000");
testMemorySoftLimit("1g", "1073741824");
testMemorySwapLimitSanity();
// Add extra 10 Mb to allocator limit, to be sure to cause OOM
testOOM("256m", 256 + 10);
@@ -153,6 +154,31 @@ public class TestMemoryAwareness {
.shouldMatch("Memory Soft Limit.*" + expectedTraceValue);
}
/*
* This test verifies that no confusingly large positive numbers get printed on
* systems with swapaccount=0 kernel option. On some systems -2 were converted
* to unsigned long and printed that way. Ensure this oddity doesn't occur.
*/
private static void testMemorySwapLimitSanity() throws Exception {
String valueToSet = "500m";
String expectedTraceValue = "524288000";
Common.logNewTestCase("memory swap sanity: " + valueToSet);
DockerRunOptions opts = Common.newOpts(imageName, "PrintContainerInfo");
Common.addWhiteBoxOpts(opts);
opts.addDockerOpts("--memory=" + valueToSet);
opts.addDockerOpts("--memory-swap=" + valueToSet);
String neg2InUnsignedLong = "18446744073709551614";
Common.run(opts)
.shouldMatch("Memory Limit is:.*" + expectedTraceValue)
// Either for cgroup v1: a_1) same as memory limit, or b_1) -2 on systems with swapaccount=0
// Either for cgroup v2: a_2) 0, or b_2) -2 on systems with swapaccount=0
.shouldMatch("Memory and Swap Limit is:.*(" + expectedTraceValue + "|-2|0)")
.shouldNotMatch("Memory and Swap Limit is:.*" + neg2InUnsignedLong);
}
// provoke OOM inside the container, see how VM reacts
private static void testOOM(String dockerMemLimit, int sizeToAllocInMb) throws Exception {

View File

@@ -83,7 +83,7 @@ public class TestMemoryWithCgroupV1 {
OutputAnalyzer out = Common.run(opts);
// in case of warnings like : "Your kernel does not support swap limit
// capabilities or the cgroup is not mounted. Memory limited without swap."
// we only have Memory and Swap Limit is: <huge integer> in the output
// we only have 'Memory and Swap Limit is: -2' in the output
try {
if (out.getOutput().contains("memory_and_swap_limit_in_bytes: not supported")) {
System.out.println("memory_and_swap_limit_in_bytes not supported, avoiding Memory and Swap Limit check");