< prev index next >
src/hotspot/os/linux/osContainer_linux.cpp
Print this page
@ rev 54202 : 8217338: [Containers] Improve systemd slice memory limit support
| Summary: Use hierachical memory limit in addition to memory_limits_in_bytes
~ Reviewed-by: duke
*** 120,130 ****
}
char *subsystem_path() { return _path; }
};
! CgroupSubsystem* memory = NULL;
CgroupSubsystem* cpuset = NULL;
CgroupSubsystem* cpu = NULL;
CgroupSubsystem* cpuacct = NULL;
typedef char * cptr;
--- 120,148 ----
}
char *subsystem_path() { return _path; }
};
! class CgroupMemorySubsystem: CgroupSubsystem {
! friend class OSContainer;
!
! private:
! /* Some container runtimes set limits via cgroup
! * hierarchy. If set to true consider also memory.stat
! * file if everything else seems unlimited */
! bool _uses_mem_hierarchy;
!
! public:
! CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) {
! _uses_mem_hierarchy = false;
! }
!
! bool is_hierarchical() { return _uses_mem_hierarchy; }
! void set_hierarchical(bool value) { _uses_mem_hierarchy = value; }
! };
!
! CgroupMemorySubsystem* memory = NULL;
CgroupSubsystem* cpuset = NULL;
CgroupSubsystem* cpu = NULL;
CgroupSubsystem* cpuacct = NULL;
typedef char * cptr;
*** 179,188 ****
--- 197,265 ----
fclose(fp);
return OSCONTAINER_ERROR;
}
PRAGMA_DIAG_POP
+ PRAGMA_DIAG_PUSH
+ PRAGMA_FORMAT_NONLITERAL_IGNORED
+ template <typename T> int subsystem_file_line_contents(CgroupSubsystem* c,
+ const char *filename,
+ const char *matchline,
+ const char *scan_fmt,
+ T returnval) {
+ FILE *fp = NULL;
+ char *p;
+ char file[MAXPATHLEN+1];
+ char buf[MAXPATHLEN+1];
+ char discard[MAXPATHLEN+1];
+
+ if (c == NULL) {
+ log_debug(os, container)("subsystem_file_contents: CgroupSubsytem* is NULL");
+ return OSCONTAINER_ERROR;
+ }
+ if (c->subsystem_path() == NULL) {
+ log_debug(os, container)("subsystem_file_contents: subsystem path is NULL");
+ return OSCONTAINER_ERROR;
+ }
+
+ strncpy(file, c->subsystem_path(), MAXPATHLEN);
+ file[MAXPATHLEN-1] = '\0';
+ int filelen = strlen(file);
+ if ((filelen + strlen(filename)) > (MAXPATHLEN-1)) {
+ log_debug(os, container)("File path too long %s, %s", file, filename);
+ return OSCONTAINER_ERROR;
+ }
+ strncat(file, filename, MAXPATHLEN-filelen);
+ log_trace(os, container)("Path to %s is %s", filename, file);
+ fp = fopen(file, "r");
+ if (fp != NULL) {
+ int err = 0;
+ while ((p = fgets(buf, MAXPATHLEN, fp)) != NULL) {
+ if (strstr(p, matchline) != NULL) {
+ // discard matchline string prefix
+ int matched = sscanf(p, scan_fmt, discard, returnval);
+ if (matched == 2) {
+ fclose(fp);
+ return 0;
+ } else {
+ err = 1;
+ log_debug(os, container)("Type %s not found in file %s", scan_fmt, file);
+ }
+ }
+ }
+ if (err == 0) {
+ log_debug(os, container)("Empty file %s, or no match found for %s", file, matchline);
+ }
+ } else {
+ log_debug(os, container)("Open of file %s failed, %s", file, os::strerror(errno));
+ }
+ if (fp != NULL)
+ fclose(fp);
+ return OSCONTAINER_ERROR;
+ }
+ PRAGMA_DIAG_POP
+
#define GET_CONTAINER_INFO(return_type, subsystem, filename, \
logstring, scan_fmt, variable) \
return_type variable; \
{ \
int err; \
*** 209,218 ****
--- 286,311 ----
return (return_type) NULL; \
\
log_trace(os, container)(logstring, variable); \
}
+ #define GET_CONTAINER_INFO_LINE(return_type, subsystem, filename, \
+ matchline, logstring, scan_fmt, variable) \
+ return_type variable; \
+ { \
+ int err; \
+ err = subsystem_file_line_contents(subsystem, \
+ filename, \
+ matchline, \
+ scan_fmt, \
+ &variable); \
+ if (err != 0) \
+ return (return_type) OSCONTAINER_ERROR; \
+ \
+ log_trace(os, container)(logstring, variable); \
+ }
+
/* init
*
* Initialize the container support and determine if
* we are running under cgroup control.
*/
*** 264,274 ****
if (sscanf(p, "%*d %*d %*d:%*d %s %s %*[^-]- cgroup %*s %s", tmproot, tmpmount, tmpcgroups) != 3) {
continue;
}
while ((token = strsep(&cptr, ",")) != NULL) {
if (strcmp(token, "memory") == 0) {
! memory = new CgroupSubsystem(tmproot, tmpmount);
} else if (strcmp(token, "cpuset") == 0) {
cpuset = new CgroupSubsystem(tmproot, tmpmount);
} else if (strcmp(token, "cpu") == 0) {
cpu = new CgroupSubsystem(tmproot, tmpmount);
} else if (strcmp(token, "cpuacct") == 0) {
--- 357,367 ----
if (sscanf(p, "%*d %*d %*d:%*d %s %s %*[^-]- cgroup %*s %s", tmproot, tmpmount, tmpcgroups) != 3) {
continue;
}
while ((token = strsep(&cptr, ",")) != NULL) {
if (strcmp(token, "memory") == 0) {
! memory = new CgroupMemorySubsystem(tmproot, tmpmount);
} else if (strcmp(token, "cpuset") == 0) {
cpuset = new CgroupSubsystem(tmproot, tmpmount);
} else if (strcmp(token, "cpu") == 0) {
cpu = new CgroupSubsystem(tmproot, tmpmount);
} else if (strcmp(token, "cpuacct") == 0) {
*** 342,351 ****
--- 435,448 ----
}
while ((token = strsep(&controllers, ",")) != NULL) {
if (strcmp(token, "memory") == 0) {
memory->set_subsystem_path(base);
+ jlong hierarchy = uses_mem_hierarchy();
+ if (hierarchy > 0) {
+ memory->set_hierarchical(true);
+ }
} else if (strcmp(token, "cpuset") == 0) {
cpuset->set_subsystem_path(base);
} else if (strcmp(token, "cpu") == 0) {
cpu->set_subsystem_path(base);
} else if (strcmp(token, "cpuacct") == 0) {
*** 358,367 ****
--- 455,465 ----
// We need to update the amount of physical memory now that
// command line arguments have been processed.
if ((mem_limit = memory_limit_in_bytes()) > 0) {
os::Linux::set_physical_memory(mem_limit);
+ log_info(os, container)("Memory Limit is: " JLONG_FORMAT, mem_limit);
}
_is_containerized = true;
}
*** 372,381 ****
--- 470,494 ----
} else {
return NULL;
}
}
+ /* uses_mem_hierarchy
+ *
+ * Return whether or not hierarchical cgroup accounting is being
+ * done.
+ *
+ * return:
+ * A number > 0 if true, or
+ * OSCONTAINER_ERROR for not supported
+ */
+ jlong OSContainer::uses_mem_hierarchy() {
+ GET_CONTAINER_INFO(jlong, memory, "/memory.use_hierarchy",
+ "Use Hierarchy is: " JLONG_FORMAT, JLONG_FORMAT, use_hierarchy);
+ return use_hierarchy;
+ }
+
/* memory_limit_in_bytes
*
* Return the limit of available memory for this process.
*
*** 387,397 ****
jlong OSContainer::memory_limit_in_bytes() {
GET_CONTAINER_INFO(julong, memory, "/memory.limit_in_bytes",
"Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit);
if (memlimit >= _unlimited_memory) {
! log_trace(os, container)("Memory Limit is: Unlimited");
return (jlong)-1;
}
else {
return (jlong)memlimit;
}
--- 500,521 ----
jlong OSContainer::memory_limit_in_bytes() {
GET_CONTAINER_INFO(julong, memory, "/memory.limit_in_bytes",
"Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit);
if (memlimit >= _unlimited_memory) {
! log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited");
! if (memory->is_hierarchical()) {
! const char* matchline = "hierarchical_memory_limit";
! char* format = "%s " JULONG_FORMAT;
! GET_CONTAINER_INFO_LINE(julong, memory, "/memory.stat", matchline,
! "Hierarchical Memory Limit is: " JULONG_FORMAT, format, hier_memlimit)
! if (hier_memlimit >= _unlimited_memory) {
! log_trace(os, container)("Hierarchical Memory Limit is: Unlimited");
! } else {
! return (jlong)hier_memlimit;
! }
! }
return (jlong)-1;
}
else {
return (jlong)memlimit;
}
*** 399,409 ****
jlong OSContainer::memory_and_swap_limit_in_bytes() {
GET_CONTAINER_INFO(julong, memory, "/memory.memsw.limit_in_bytes",
"Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit);
if (memswlimit >= _unlimited_memory) {
! log_trace(os, container)("Memory and Swap Limit is: Unlimited");
return (jlong)-1;
} else {
return (jlong)memswlimit;
}
}
--- 523,544 ----
jlong OSContainer::memory_and_swap_limit_in_bytes() {
GET_CONTAINER_INFO(julong, memory, "/memory.memsw.limit_in_bytes",
"Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit);
if (memswlimit >= _unlimited_memory) {
! log_trace(os, container)("Non-Hierarchical Memory and Swap Limit is: Unlimited");
! if (memory->is_hierarchical()) {
! const char* matchline = "hierarchical_memsw_limit";
! char* format = "%s " JULONG_FORMAT;
! GET_CONTAINER_INFO_LINE(julong, memory, "/memory.stat", matchline,
! "Hierarchical Memory and Swap Limit is : " JULONG_FORMAT, format, hier_memlimit)
! if (hier_memlimit >= _unlimited_memory) {
! log_trace(os, container)("Hierarchical Memory and Swap Limit is: Unlimited");
! } else {
! return (jlong)hier_memlimit;
! }
! }
return (jlong)-1;
} else {
return (jlong)memswlimit;
}
}
< prev index next >