Wednesday, April 5, 2017

[389-commits] [389-ds-base] 01/01: Ticket 48864 - Add cgroup memory limit detection to 389-ds

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

--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
_______________________________________________
389-commits mailing list -- 389-commits@lists.fedoraproject.org
To unsubscribe send an email to 389-commits-leave@lists.fedoraproject.org

No comments:

Post a Comment