< 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 >