< prev index next >

src/hotspot/os/linux/osContainer_linux.cpp

Print this page
@  rev 54246 : 8217338: [Containers] Improve systemd slice memory limit support
|  Summary: Use hierachical memory limit in addition to memory_limits_in_bytes
~  Reviewed-by: duke

*** 120,153 **** } char *subsystem_path() { return _path; } }; ! CgroupSubsystem* memory = NULL; CgroupSubsystem* cpuset = NULL; CgroupSubsystem* cpu = NULL; CgroupSubsystem* cpuacct = NULL; typedef char * cptr; PRAGMA_DIAG_PUSH PRAGMA_FORMAT_NONLITERAL_IGNORED ! template <typename T> int subsystem_file_contents(CgroupSubsystem* c, const char *filename, const char *scan_fmt, T returnval) { FILE *fp = NULL; char *p; char file[MAXPATHLEN+1]; char buf[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'; --- 120,174 ---- } 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; 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]; + bool found_match = false; if (c == NULL) { ! log_debug(os, container)("subsystem_file_line_contents: CgroupSubsytem* is NULL"); return OSCONTAINER_ERROR; } if (c->subsystem_path() == NULL) { ! log_debug(os, container)("subsystem_file_line_contents: subsystem path is NULL"); return OSCONTAINER_ERROR; } strncpy(file, c->subsystem_path(), MAXPATHLEN); file[MAXPATHLEN-1] = '\0';
*** 158,177 **** } strncat(file, filename, MAXPATHLEN-filelen); log_trace(os, container)("Path to %s is %s", filename, file); fp = fopen(file, "r"); if (fp != NULL) { ! p = fgets(buf, MAXPATHLEN, fp); ! if (p != NULL) { int matched = sscanf(p, scan_fmt, returnval); ! if (matched == 1) { fclose(fp); return 0; } else { log_debug(os, container)("Type %s not found in file %s", scan_fmt, file); } ! } else { log_debug(os, container)("Empty file %s", file); } } else { log_debug(os, container)("Open of file %s failed, %s", file, os::strerror(errno)); } --- 179,214 ---- } 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) { ! found_match = false; ! if (matchline == NULL) { ! // single-line file case int matched = sscanf(p, scan_fmt, returnval); ! found_match = (matched == 1); ! } else { ! // multi-line file case ! if (strstr(p, matchline) != NULL) { ! // discard matchline string prefix ! int matched = sscanf(p, scan_fmt, discard, returnval); ! found_match = (matched == 2); ! } else { ! continue; // substring not found ! } ! } ! if (found_match) { 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", file); } } else { log_debug(os, container)("Open of file %s failed, %s", file, os::strerror(errno)); }
*** 184,195 **** #define GET_CONTAINER_INFO(return_type, subsystem, filename, \ logstring, scan_fmt, variable) \ return_type variable; \ { \ int err; \ ! err = subsystem_file_contents(subsystem, \ filename, \ scan_fmt, \ &variable); \ if (err != 0) \ return (return_type) OSCONTAINER_ERROR; \ \ --- 221,233 ---- #define GET_CONTAINER_INFO(return_type, subsystem, filename, \ logstring, scan_fmt, variable) \ return_type variable; \ { \ int err; \ ! err = subsystem_file_line_contents(subsystem, \ filename, \ + NULL, \ scan_fmt, \ &variable); \ if (err != 0) \ return (return_type) OSCONTAINER_ERROR; \ \
*** 199,218 **** #define GET_CONTAINER_INFO_CPTR(return_type, subsystem, filename, \ logstring, scan_fmt, variable, bufsize) \ char variable[bufsize]; \ { \ int err; \ ! err = subsystem_file_contents(subsystem, \ filename, \ scan_fmt, \ variable); \ if (err != 0) \ return (return_type) NULL; \ \ log_trace(os, container)(logstring, variable); \ } /* init * * Initialize the container support and determine if * we are running under cgroup control. */ --- 237,273 ---- #define GET_CONTAINER_INFO_CPTR(return_type, subsystem, filename, \ logstring, scan_fmt, variable, bufsize) \ char variable[bufsize]; \ { \ int err; \ ! err = subsystem_file_line_contents(subsystem, \ filename, \ + NULL, \ scan_fmt, \ variable); \ if (err != 0) \ 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) { --- 319,329 ---- 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 **** --- 397,410 ---- } 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 **** --- 417,427 ---- // 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 **** --- 432,456 ---- } 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; } --- 462,483 ---- 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; } } --- 485,506 ---- 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 >