From 99958d935d414c2902c4ab87070a3d928ad562eb Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 28 Apr 2022 07:59:20 -0700 Subject: [PATCH] Update omrsysinfo_cgroup_subsystem_iterator functions for cgroup v2 Update cgroup iterator functions to retrieve metrics from cgroup v2 files. Issue: #1281 Signed-off-by: Eric Yang --- port/unix/omrsysinfo.c | 59 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/port/unix/omrsysinfo.c b/port/unix/omrsysinfo.c index 53574101741..015fd65c6ec 100644 --- a/port/unix/omrsysinfo.c +++ b/port/unix/omrsysinfo.c @@ -430,6 +430,16 @@ static struct OMRCgroupMetricInfoElement oomControlMetricElementList[] = { { "Under OOM", "under_oom", NULL, FALSE } }; +static struct OMRCgroupMetricInfoElement memEventsMetricElementList[] = { + { "Approached memory limit count", "max", NULL, FALSE }, + { "Reached memory limit count", "oom", NULL, FALSE } +}; + +static struct OMRCgroupMetricInfoElement swapEventsMetricElementList[] = { + { "Approached swap limit count", "max", NULL, FALSE }, + { "Swap alloc failed count", "fail", NULL, FALSE } +}; + static struct OMRCgroupMetricInfoElement cpuStatMetricElementList[] = { { "Period intervals elapsed count", "nr_periods", NULL, FALSE }, { "Throttled count", "nr_throttled", NULL, FALSE }, @@ -442,7 +452,9 @@ typedef struct OMRCgroupSubsystemMetricMap { int32_t metricElementsCount; } OMRCgroupSubsystemMetricMap; -static struct OMRCgroupSubsystemMetricMap omrCgroupMemoryMetricMap[] = { +static OMRCgroupSubsystemMetricMap *omrCgroupMemoryMetricMap; + +static struct OMRCgroupSubsystemMetricMap omrCgroupMemoryMetricMapV1[] = { { "memory.limit_in_bytes", &(OMRCgroupMetricInfoElement){ "Memory Limit", NULL, "bytes", TRUE }, SINGLE_CGROUP_METRIC }, { "memory.memsw.limit_in_bytes", &(OMRCgroupMetricInfoElement){ "Memory + Swap Limit", NULL, "bytes", TRUE }, SINGLE_CGROUP_METRIC }, { "memory.usage_in_bytes", &(OMRCgroupMetricInfoElement){ "Memory Usage", NULL, "bytes", FALSE }, SINGLE_CGROUP_METRIC }, @@ -453,6 +465,17 @@ static struct OMRCgroupSubsystemMetricMap omrCgroupMemoryMetricMap[] = { { "memory.memsw.failcnt", &(OMRCgroupMetricInfoElement){ "Memory + Swap limit exceeded count", NULL, NULL, FALSE }, SINGLE_CGROUP_METRIC }, { "memory.oom_control", &oomControlMetricElementList[0], sizeof(oomControlMetricElementList)/sizeof(oomControlMetricElementList[0]) } }; +#define OMR_CGROUP_MEMORY_METRIC_MAP_V1_SIZE sizeof(omrCgroupMemoryMetricMapV1) / sizeof(omrCgroupMemoryMetricMapV1[0]) + +static struct OMRCgroupSubsystemMetricMap omrCgroupMemoryMetricMapV2[] = { + { "memory.max", &(OMRCgroupMetricInfoElement){ "Memory Limit", NULL, "bytes", TRUE }, SINGLE_CGROUP_METRIC }, + { "memory.swap.max", &(OMRCgroupMetricInfoElement){ "Memory + Swap Limit", NULL, "bytes", TRUE }, SINGLE_CGROUP_METRIC }, + { "memory.current", &(OMRCgroupMetricInfoElement){ "Memory Usage", NULL, "bytes", FALSE }, SINGLE_CGROUP_METRIC }, + { "memory.swap.current", &(OMRCgroupMetricInfoElement){ "Memory + Swap Usage", NULL, "bytes", FALSE }, SINGLE_CGROUP_METRIC }, + { "memory.events", &memEventsMetricElementList[0], sizeof(memEventsMetricElementList)/sizeof(swapEventsMetricElementList[0]) }, + { "memory.swap.events", &swapEventsMetricElementList[0], sizeof(swapEventsMetricElementList)/sizeof(swapEventsMetricElementList[0]) } +}; +#define OMR_CGROUP_MEMORY_METRIC_MAP_V2_SIZE sizeof(omrCgroupMemoryMetricMapV2) / sizeof(omrCgroupMemoryMetricMapV2[0]) static struct OMRCgroupSubsystemMetricMap omrCgroupCpuMetricMap[] = { { "cpu.cfs_period_us", &(OMRCgroupMetricInfoElement){ "CPU Period", NULL, "microseconds", FALSE }, SINGLE_CGROUP_METRIC }, @@ -6569,12 +6592,23 @@ omrsysinfo_cgroup_subsystem_iterator_init(struct OMRPortLibrary *portLibrary, ui Assert_PRT_true(NULL != state); int32_t rc = OMRPORT_ERROR_SYSINFO_CGROUP_UNSUPPORTED_PLATFORM; #if defined(LINUX) && !defined(OMRZTPF) + size_t omrCgroupMemoryMetricMapSize = 0; state->count = 0; state->subsystemid = subsystem; state->fileMetricCounter = 0; + if (OMR_ARE_ANY_BITS_SET(PPG_sysinfoControlFlags, OMRPORT_SYSINFO_CGROUP_V1_AVAILABLE)) { + omrCgroupMemoryMetricMap = omrCgroupMemoryMetricMapV1; + omrCgroupMemoryMetricMapSize = OMR_CGROUP_MEMORY_METRIC_MAP_V1_SIZE; + } else if (OMR_ARE_ANY_BITS_SET(PPG_sysinfoControlFlags, OMRPORT_SYSINFO_CGROUP_V2_AVAILABLE)) { + omrCgroupMemoryMetricMap = omrCgroupMemoryMetricMapV2; + omrCgroupMemoryMetricMapSize = OMR_CGROUP_MEMORY_METRIC_MAP_V2_SIZE; + } else { + Trc_PRT_Assert_ShouldNeverHappen(); + } + switch (subsystem) { case OMR_CGROUP_SUBSYSTEM_MEMORY : - state->numElements = sizeof(omrCgroupMemoryMetricMap) / sizeof(omrCgroupMemoryMetricMap[0]); + state->numElements = omrCgroupMemoryMetricMapSize; break; case OMR_CGROUP_SUBSYSTEM_CPU : state->numElements = sizeof(omrCgroupCpuMetricMap) / sizeof(omrCgroupCpuMetricMap[0]); @@ -6664,6 +6698,7 @@ omrsysinfo_cgroup_subsystem_iterator_next(struct OMRPortLibrary *portLibrary, st subsystemMetricMapElement = &subsystemMetricMap[state->count]; currentElement = subsystemMetricMapElement->metricInfoElementList; if (NULL == state->fileContent) { + Assert_PRT_true(0 == state->fileMetricCounter); rc = readCgroupMetricFromFile(portLibrary, state->subsystemid, subsystemMetricMapElement->metricFileName, currentElement->metricKeyInFile, &(state->fileContent), metricElement->value); /* In error condition or single metric condition we increment the counter to continue to next metric */ @@ -6672,8 +6707,6 @@ omrsysinfo_cgroup_subsystem_iterator_next(struct OMRPortLibrary *portLibrary, st state->count += 1; goto _end; } - - state->fileMetricCounter = 0; } if (state->fileMetricCounter < subsystemMetricMapElement->metricElementsCount) { @@ -6718,6 +6751,9 @@ omrsysinfo_cgroup_subsystem_iterator_next(struct OMRPortLibrary *portLibrary, st state->fileContent = NULL; } state->count += 1; + /* Reset fileMetricCounter here so that a call to omrsysinfo_cgroup_subsystem_iterator_metricKey + * immediately after won't fail. */ + state->fileMetricCounter = 0; } _end: @@ -6733,7 +6769,20 @@ omrsysinfo_cgroup_subsystem_iterator_next(struct OMRPortLibrary *portLibrary, st } if (currentElement->isValueToBeChecked) { int64_t result = 0; - sscanf(metricElement->value, "%" PRId64, &result); + if (OMR_ARE_ANY_BITS_SET(PPG_sysinfoControlFlags, OMRPORT_SYSINFO_CGROUP_V1_AVAILABLE)) { + sscanf(metricElement->value, "%" PRId64, &result); + } else if (OMR_ARE_ANY_BITS_SET(PPG_sysinfoControlFlags, OMRPORT_SYSINFO_CGROUP_V2_AVAILABLE)) { + uint64_t uresult = 0; + scanCgroupIntOrMax(portLibrary, metricElement->value, &uresult); + if (UINT_MAX == uresult) { + result = -1; + } else { + result = (int64_t)uresult; + } + } else { + Trc_PRT_Assert_ShouldNeverHappen(); + } + /* Check that the limit metric is set (not -1) and that it is a reasonable value */ if ((result > (MAX_DEFAULT_VALUE_CHECK)) || (result < 0)) { metricElement->units = NULL; strcpy(metricElement->value, "Not Set");