< prev index next >

src/hotspot/os/linux/osContainer_linux.cpp

Print this page
@  rev 53302 : [Containers] Also consider hierarchical memory limits.
|
~

*** 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. */
*** 276,286 **** &major, &minor, tmproot, tmpmount); if (matched == 6) { ! memory = new CgroupSubsystem(tmproot, tmpmount); } else log_debug(os, container)("Incompatible str containing cgroup and memory: %s", p); } else if (strstr(p, "cpuset") != NULL) { int matched = sscanf(p, "%d %d %d:%d %s %s", --- 369,379 ---- &major, &minor, tmproot, tmpmount); if (matched == 6) { ! memory = new CgroupMemorySubsystem(tmproot, tmpmount); } else log_debug(os, container)("Incompatible str containing cgroup and memory: %s", p); } else if (strstr(p, "cpuset") != NULL) { int matched = sscanf(p, "%d %d %d:%d %s %s",
*** 405,414 **** --- 498,511 ---- base = strsep(&p, "\n"); if (controller != NULL) { if (strstr(controller, "memory") != NULL) { memory->set_subsystem_path(base); + jlong hierarchy = uses_mem_hierarchy(); + if (hierarchy > 0) { + memory->set_hierarchical(true); + } } else if (strstr(controller, "cpuset") != NULL) { cpuset->set_subsystem_path(base); } else if (strstr(controller, "cpu,cpuacct") != NULL || strstr(controller, "cpuacct,cpu") != NULL) { cpu->set_subsystem_path(base); cpuacct->set_subsystem_path(base);
*** 424,433 **** --- 521,531 ---- // 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; }
*** 438,447 **** --- 536,560 ---- } 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. *
*** 453,463 **** 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; } --- 566,587 ---- 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; }
*** 465,475 **** 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; } } --- 589,610 ---- 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 >