This is an automated email from the git hooks/post-receive script.
firstyear pushed a change to branch master in repository 389-ds-base.
from bdbf4ef Issue 48085 - Expand the repl acceptance test suite new a96f833 Ticket 48864 - Add cgroup memory limit detection to 389-ds
The 1 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference.
Summary of changes: ldap/servers/slapd/slapi_pal.c | 77 +++++++++++++++++++++++++++++++++++++----- ldap/servers/slapd/util.c | 27 +-------------- 2 files changed, 70 insertions(+), 34 deletions(-)
This is an automated email from the git hooks/post-receive script.
firstyear pushed a commit to branch master in repository 389-ds-base.
commit a96f83331a8b3f1010645cddac8ba624b09c7eb3 Author: William Brown firstyear@redhat.com Date: Tue Apr 4 14:13:00 2017 +1000
Ticket 48864 - Add cgroup memory limit detection to 389-ds
Bug Description: Previously our memory limits only check hardware limits and shell resource limits. However, we may be in a container like docker or lxc, and unable to detect these limits. This can lead to crash conditions or worse, especially with autosizing on import we may have conditions where the server may not even be able to install.
Fix Description: Add support for cgroup memory limit detection so that we can properly determine our resource availability regardless of lxc, docker, systemd or others.
https://pagure.io/389-ds-base/issue/48864
Author: wibrown
Review by: mreynolds (Thanks!) --- ldap/servers/slapd/slapi_pal.c | 77 +++++++++++++++++++++++++++++++++++++----- ldap/servers/slapd/util.c | 27 +-------------- 2 files changed, 70 insertions(+), 34 deletions(-)
diff --git a/ldap/servers/slapd/slapi_pal.c b/ldap/servers/slapd/slapi_pal.c index 4bafd4b..91576ca 100644 --- a/ldap/servers/slapd/slapi_pal.c +++ b/ldap/servers/slapd/slapi_pal.c @@ -63,7 +63,11 @@ static int_fast32_t _spal_uint64_t_file_get(char *name, char *prefix, uint64_t *dest) { FILE *f; char s[40] = {0}; - size_t prefix_len = strlen(prefix); + size_t prefix_len = 0; + + if (prefix != NULL) { + prefix_len = strlen(prefix); + }
/* Make sure we can fit into our buffer */ assert((prefix_len + 20) < 39); @@ -85,9 +89,12 @@ _spal_uint64_t_file_get(char *name, char *prefix, uint64_t *dest) { retval = 1; break; } - if (strncmp(s, prefix, prefix_len) == 0) { + if (prefix_len > 0 && strncmp(s, prefix, prefix_len) == 0) { sscanf(s + prefix_len, "%"SCNu64, dest); break; + } else if (prefix_len == 0) { + sscanf(s, "%"SCNu64, dest); + break; } } fclose(f); @@ -127,7 +134,7 @@ spal_meminfo_get() { slapi_log_err(SLAPI_LOG_ERR, "spal_meminfo_get", "Unable to retrieve memory rlimit\n"); }
- if (rl_mem_soft != 0 && rl_mem_soft > vmrss) { + if (rl_mem_soft != 0 && vmrss != 0 && rl_mem_soft > vmrss) { rl_mem_soft_avail = rl_mem_soft - vmrss; }
@@ -150,6 +157,43 @@ spal_meminfo_get() { memtotal = memtotal * 1024; memavail = memavail * 1024;
+ /* If it's possible, get our cgroup info */ + uint64_t cg_mem_soft = 0; + uint64_t cg_mem_hard = 0; + uint64_t cg_mem_usage = 0; + uint64_t cg_mem_soft_avail = 0; + + char *f_cg_soft = "/sys/fs/cgroup/memory/memory.soft_limit_in_bytes"; + char *f_cg_hard = "/sys/fs/cgroup/memory/memory.limit_in_bytes"; + char *f_cg_usage = "/sys/fs/cgroup/memory/memory.usage_in_bytes"; + + if (_spal_uint64_t_file_get(f_cg_soft, NULL, &cg_mem_soft)) { + slapi_log_err(SLAPI_LOG_WARNING, "spal_meminfo_get", "Unable to retrieve %s. There may be no cgroup support on this platform\n", f_cg_soft); + } + + if (_spal_uint64_t_file_get(f_cg_hard, NULL, &cg_mem_hard)) { + slapi_log_err(SLAPI_LOG_WARNING, "spal_meminfo_get", "Unable to retrieve %s. There may be no cgroup support on this platform\n", f_cg_hard); + } + + if (_spal_uint64_t_file_get(f_cg_usage, NULL, &cg_mem_usage)) { + slapi_log_err(SLAPI_LOG_WARNING, "spal_meminfo_get", "Unable to retrieve %s. There may be no cgroup support on this platform\n", f_cg_hard); + } + + /* + * In some conditions, like docker, we only have a *hard* limit set. + * This obviously breaks our logic, so we need to make sure we correct this + */ + + if (cg_mem_hard != 0 && cg_mem_soft != 0 && cg_mem_hard < cg_mem_soft) { + /* Right, we only have a hard limit. Impose a 10% watermark. */ + cg_mem_soft = cg_mem_hard * 0.9; + } + + if (cg_mem_soft != 0 && cg_mem_usage != 0 && cg_mem_soft > cg_mem_usage) { + cg_mem_soft_avail = cg_mem_soft - cg_mem_usage; + } + + /* Now, compare the values and make a choice to which is provided */
/* Process consumed memory */ @@ -158,10 +202,20 @@ spal_meminfo_get() {
/* System Total memory */ /* If we have a memtotal, OR if no memtotal but rlimit */ - if (rl_mem_hard != 0 && ((memtotal != 0 && rl_mem_hard < memtotal) || memtotal == 0)) { + if (rl_mem_hard != 0 && + ((memtotal != 0 && rl_mem_hard < memtotal) || memtotal == 0) && + ((cg_mem_hard != 0 && rl_mem_hard < cg_mem_hard) || cg_mem_hard == 0) + ) + { + slapi_log_err(SLAPI_LOG_TRACE, "spal_meminfo_get", "system_total_bytes - using rlimit\n"); mi->system_total_bytes = rl_mem_hard; mi->system_total_pages = rl_mem_hard / mi->pagesize_bytes; + } else if (cg_mem_hard != 0 && ((memtotal != 0 && cg_mem_hard < memtotal) || memtotal == 0)) { + slapi_log_err(SLAPI_LOG_TRACE, "spal_meminfo_get", "system_total_bytes - using cgroup\n"); + mi->system_total_bytes = cg_mem_hard; + mi->system_total_pages = cg_mem_hard / mi->pagesize_bytes; } else if (memtotal != 0) { + slapi_log_err(SLAPI_LOG_TRACE, "spal_meminfo_get", "system_total_bytes - using memtotal\n"); mi->system_total_bytes = memtotal; mi->system_total_pages = memtotal / mi->pagesize_bytes; } else { @@ -172,13 +226,20 @@ spal_meminfo_get() {
/* System Available memory */
- if (rl_mem_soft_avail != 0 && ((memavail != 0 && (rl_mem_soft_avail) < memavail) || memavail == 0)) { + if (rl_mem_soft_avail != 0 && + ((memavail != 0 && (rl_mem_soft_avail) < memavail) || memavail == 0) && + ((cg_mem_soft_avail != 0 && rl_mem_soft_avail < cg_mem_soft_avail) || cg_mem_soft_avail == 0) + ) + { + slapi_log_err(SLAPI_LOG_TRACE, "spal_meminfo_get", "system_available_bytes - using rlimit\n"); mi->system_available_bytes = rl_mem_soft_avail; mi->system_available_pages = rl_mem_soft_avail / mi->pagesize_bytes; - } else if (rl_mem_soft != 0 && ((memavail != 0 && (rl_mem_soft) < memavail) || memavail == 0)) { - mi->system_available_bytes = rl_mem_soft; - mi->system_available_pages = rl_mem_soft / mi->pagesize_bytes; + } else if (cg_mem_soft_avail != 0 && ((memavail != 0 && (cg_mem_soft_avail) < memavail) || memavail == 0)) { + slapi_log_err(SLAPI_LOG_TRACE, "spal_meminfo_get", "system_available_bytes - using cgroup\n"); + mi->system_available_bytes = cg_mem_soft_avail; + mi->system_available_pages = cg_mem_soft_avail / mi->pagesize_bytes; } else if (memavail != 0) { + slapi_log_err(SLAPI_LOG_TRACE, "spal_meminfo_get", "system_available_bytes - using memavail\n"); mi->system_available_bytes = memavail; mi->system_available_pages = memavail / mi->pagesize_bytes; } else { diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c index a0753c0..012e83d 100644 --- a/ldap/servers/slapd/util.c +++ b/ldap/servers/slapd/util.c @@ -1459,37 +1459,12 @@ slapi_uniqueIDRdnSize(void) return util_uniqueidlen; }
- -/** - * Get the virtual memory size as defined by system rlimits. - * - * \return size_t bytes available - */ -static size_t util_getvirtualmemsize(void) -{ - struct rlimit rl; - /* the maximum size of a process's total available memory, in bytes */ - if (getrlimit(RLIMIT_AS, &rl) != 0) { - /* We received an error condition. There are a number of possible - * reasons we have have gotten here, but most likely is EINVAL, where - * rlim->rlim_cur was greater than rlim->rlim_max. - * As a result, we should return a 0, to tell the system we can't alloc - * memory. - */ - int errsrv = errno; - slapi_log_err(SLAPI_LOG_ERR,"util_getvirtualmemsize", - "getrlimit returned non-zero. errno=%u\n", errsrv); - return 0; - } - return rl.rlim_cur; -} - util_cachesize_result util_is_cachesize_sane(slapi_pal_meminfo *mi, uint64_t *cachesize) { /* Check we have a valid meminfo struct */ if (mi->system_available_bytes == 0) { - slapi_log_err(SLAPI_LOG_CRIT, "util_is_cachesize_sane", ""); + slapi_log_err(SLAPI_LOG_CRIT, "util_is_cachesize_sane", "Invalid system memory info, can not proceed."); return UTIL_CACHESIZE_ERROR; }
389-commits@lists.fedoraproject.org