Blame SOURCES/0029-Ticket-49204-Fix-lower-bounds-on-import-autosize-On-.patch

b69e47
From 9be74e83539e204e9a56721da5c22bd9abf38195 Mon Sep 17 00:00:00 2001
b69e47
From: Mark Reynolds <mreynolds@redhat.com>
b69e47
Date: Wed, 19 Apr 2017 13:41:22 -0400
b69e47
Subject: [PATCH] Ticket 49204 - Fix lower bounds on import autosize + On small
b69e47
 VM, autotune breaks the access of the suffixes
b69e47
b69e47
    Bug Description:
b69e47
        ldif2db in some cases may set a cache of 0, which may y break imports.
b69e47
b69e47
        Under memory pressure, the amount of available memory at startup
b69e47
        can be so low that the configured cachememsize will be rejected
b69e47
        (unwilling to perform).
b69e47
        This should leave the cachememsize being "0" (default)
b69e47
        This conduct to be unable to access the suffix pages.
b69e47
b69e47
    Fix Description:
b69e47
b69e47
     * autosize set an incorrect percentage which was too high.
b69e47
     * we did not check the lower bound of the allocation
b69e47
       so we now set that we must have a minimum allocation.
b69e47
     * Set entrycache to a minimal value, even if it looks insane
b69e47
     * add a cap on reduction of caches, so we always allocate a few pages
b69e47
       at least, and prevent returning 0 to the caller.
b69e47
b69e47
    https://pagure.io/389-ds-base/issue/49204
b69e47
b69e47
    Author: wibrown, tbordaz
b69e47
b69e47
    Review by: tbordaz (Thanks mate, great work with this :) )
b69e47
---
b69e47
 ldap/servers/slapd/back-ldbm/cache.c               |  4 +--
b69e47
 ldap/servers/slapd/back-ldbm/dblayer.c             | 33 +++++++++++++---------
b69e47
 ldap/servers/slapd/back-ldbm/dblayer.h             | 12 ++++----
b69e47
 ldap/servers/slapd/back-ldbm/ldbm_config.c         |  4 +--
b69e47
 .../servers/slapd/back-ldbm/ldbm_instance_config.c | 23 +++++++++++++--
b69e47
 ldap/servers/slapd/slapi-private.h                 |  2 +-
b69e47
 ldap/servers/slapd/util.c                          | 20 +++++++++----
b69e47
 7 files changed, 65 insertions(+), 33 deletions(-)
b69e47
b69e47
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
b69e47
index 0f0cf3b..c6638a2 100644
b69e47
--- a/ldap/servers/slapd/back-ldbm/cache.c
b69e47
+++ b/ldap/servers/slapd/back-ldbm/cache.c
b69e47
@@ -65,7 +65,7 @@
b69e47
 
b69e47
 /* static functions */
b69e47
 static void entrycache_clear_int(struct cache *cache);
b69e47
-static void entrycache_set_max_size(struct cache *cache, size_t bytes);
b69e47
+static void entrycache_set_max_size(struct cache *cache, uint64_t bytes);
b69e47
 static int entrycache_remove_int(struct cache *cache, struct backentry *e);
b69e47
 static void entrycache_return(struct cache *cache, struct backentry **bep);
b69e47
 static int entrycache_replace(struct cache *cache, struct backentry *olde, struct backentry *newe);
b69e47
@@ -77,7 +77,7 @@ static void entry_lru_verify(struct cache *cache, struct backentry *e, int in);
b69e47
 
b69e47
 static int dn_same_id(const void *bdn, const void *k);
b69e47
 static void dncache_clear_int(struct cache *cache);
b69e47
-static void dncache_set_max_size(struct cache *cache, size_t bytes);
b69e47
+static void dncache_set_max_size(struct cache *cache, uint64_t bytes);
b69e47
 static int dncache_remove_int(struct cache *cache, struct backdn *dn);
b69e47
 static void dncache_return(struct cache *cache, struct backdn **bdn);
b69e47
 static int dncache_replace(struct cache *cache, struct backdn *olddn, struct backdn *newdn);
b69e47
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
b69e47
index 3c1fbb0..f834322 100644
b69e47
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
b69e47
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
b69e47
@@ -1237,8 +1237,8 @@ no_diskspace(struct ldbminfo *li, int dbenv_flags)
b69e47
     struct statvfs db_buf;
b69e47
     int using_region_files = !(dbenv_flags & ( DB_PRIVATE | DB_SYSTEM_MEM));
b69e47
     /* value of 10 == 10% == little more than the average overhead calculated for very large files on 64-bit system for bdb 4.7 */
b69e47
-    PRUint64 expected_siz = li->li_dbcachesize + li->li_dbcachesize/10; /* dbcache + region files */
b69e47
-    PRUint64 fsiz;
b69e47
+    uint64_t expected_siz = li->li_dbcachesize + li->li_dbcachesize/10; /* dbcache + region files */
b69e47
+    uint64_t fsiz;
b69e47
     char *region_dir;
b69e47
 
b69e47
     if (statvfs(li->li_directory, &db_buf) < 0){
b69e47
@@ -1263,7 +1263,7 @@ no_diskspace(struct ldbminfo *li, int dbenv_flags)
b69e47
                         li->li_dblayer_private->dblayer_dbhome_directory);
b69e47
                     return 1;
b69e47
                 }
b69e47
-                fsiz = ((PRUint64)dbhome_buf.f_bavail) * ((PRUint64)dbhome_buf.f_bsize);
b69e47
+                fsiz = ((uint64_t)dbhome_buf.f_bavail) * ((uint64_t)dbhome_buf.f_bsize);
b69e47
                 region_dir = li->li_dblayer_private->dblayer_dbhome_directory;
b69e47
             } else {
b69e47
                 /* Shared/private memory.  No need to check disk space, return success */
b69e47
@@ -1387,12 +1387,17 @@ dblayer_start(struct ldbminfo *li, int dbmode)
b69e47
     /* Sanity check on cache size on platforms which allow us to figure out
b69e47
      * the available phys mem */
b69e47
     slapi_pal_meminfo *mi = spal_meminfo_get();
b69e47
-    if (!util_is_cachesize_sane(mi, &(priv->dblayer_cachesize))) {
b69e47
+    util_cachesize_result result = util_is_cachesize_sane(mi, &(priv->dblayer_cachesize));
b69e47
+    if (result == UTIL_CACHESIZE_ERROR) {
b69e47
+        slapi_log_err(SLAPI_LOG_CRIT, "dblayer_start", "Unable to determine if cachesize was valid!!!");
b69e47
+    } else if (result == UTIL_CACHESIZE_REDUCED) {
b69e47
+        /* In some cases we saw this go to 0, prevent this. */
b69e47
+        if (priv->dblayer_cachesize < MINCACHESIZE) {
b69e47
+            priv->dblayer_cachesize = MINCACHESIZE;
b69e47
+        }
b69e47
         /* Oops---looks like the admin misconfigured, let's warn them */
b69e47
-        slapi_log_err(SLAPI_LOG_WARNING,"dblayer_start", "Likely CONFIGURATION ERROR -"
b69e47
-                  "dbcachesize is configured to use more than the available "
b69e47
-                  "physical memory, decreased to the largest available size (%"PRIu64" bytes).\n",
b69e47
-                  priv->dblayer_cachesize);
b69e47
+        slapi_log_err(SLAPI_LOG_WARNING, "dblayer_start", "Likely CONFIGURATION ERROR - dbcachesize is configured to use more than the available "
b69e47
+                  "memory, decreased to (%"PRIu64" bytes).\n", priv->dblayer_cachesize);
b69e47
         li->li_dbcachesize = priv->dblayer_cachesize;
b69e47
     }
b69e47
     spal_meminfo_destroy(mi);
b69e47
@@ -3816,7 +3821,7 @@ static const u_int32_t default_flags = DB_NEXT;
b69e47
 typedef struct txn_test_iter {
b69e47
     DB *db;
b69e47
     DBC *cur;
b69e47
-    size_t cnt;
b69e47
+    uint64_t cnt;
b69e47
     const char *attr;
b69e47
     u_int32_t flags;
b69e47
     backend *be;
b69e47
@@ -3938,10 +3943,10 @@ static int txn_test_threadmain(void *param)
b69e47
     Object *inst_obj;
b69e47
     int rc = 0;
b69e47
     txn_test_iter **ttilist = NULL;
b69e47
-    size_t tticnt = 0;
b69e47
+    uint64_t tticnt = 0;
b69e47
     DB_TXN *txn = NULL;
b69e47
     txn_test_cfg cfg = {0};
b69e47
-    size_t counter = 0;
b69e47
+    uint64_t counter = 0;
b69e47
     char keybuf[8192];
b69e47
     char databuf[8192];
b69e47
     int dbattempts = 0;
b69e47
@@ -4062,9 +4067,9 @@ retry_txn:
b69e47
         if (!rc) {
b69e47
             DBT key;
b69e47
             DBT data;
b69e47
-            size_t ii;
b69e47
-            size_t donecnt = 0;
b69e47
-            size_t cnt = 0;
b69e47
+            uint64_t ii;
b69e47
+            uint64_t donecnt = 0;
b69e47
+            uint64_t cnt = 0;
b69e47
 
b69e47
             /* phase 1 - open a cursor to each db */
b69e47
             if (cfg.verbose) {
b69e47
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.h b/ldap/servers/slapd/back-ldbm/dblayer.h
b69e47
index 816c943..77b04fa 100644
b69e47
--- a/ldap/servers/slapd/back-ldbm/dblayer.h
b69e47
+++ b/ldap/servers/slapd/back-ldbm/dblayer.h
b69e47
@@ -90,8 +90,8 @@ struct dblayer_private
b69e47
     int dblayer_ncache;
b69e47
     int dblayer_previous_ncache;
b69e47
     int dblayer_tx_max;
b69e47
-    size_t dblayer_cachesize;
b69e47
-    size_t dblayer_previous_cachesize; /* Cache size when we last shut down--
b69e47
+    uint64_t dblayer_cachesize;
b69e47
+    uint64_t dblayer_previous_cachesize; /* Cache size when we last shut down--
b69e47
                                         * used to determine if we delete 
b69e47
                                         * the mpool */
b69e47
     int dblayer_recovery_required;
b69e47
@@ -102,15 +102,15 @@ struct dblayer_private
b69e47
     int dblayer_durable_transactions;
b69e47
     int dblayer_checkpoint_interval;
b69e47
     int dblayer_circular_logging;
b69e47
-    size_t dblayer_page_size;       /* db page size if configured,
b69e47
+    uint64_t dblayer_page_size;       /* db page size if configured,
b69e47
                                      * otherwise default to DBLAYER_PAGESIZE */
b69e47
-    size_t dblayer_index_page_size; /* db index page size if configured,
b69e47
+    uint64_t dblayer_index_page_size; /* db index page size if configured,
b69e47
                                      * otherwise default to 
b69e47
                                      * DBLAYER_INDEX_PAGESIZE */
b69e47
     int dblayer_idl_divisor;        /* divide page size by this to get IDL 
b69e47
                                      * size */
b69e47
-    size_t dblayer_logfile_size;    /* How large can one logfile be ? */
b69e47
-    size_t dblayer_logbuf_size;     /* how large log buffer can be */
b69e47
+    uint64_t dblayer_logfile_size;    /* How large can one logfile be ? */
b69e47
+    uint64_t dblayer_logbuf_size;     /* how large log buffer can be */
b69e47
     int dblayer_file_mode;          /* pmode for files we create */
b69e47
     int dblayer_verbose;            /* Get libdb to exhale debugging info */
b69e47
     int dblayer_debug;              /* Will libdb emit debugging info into 
b69e47
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c
b69e47
index d5120d3..401cd60 100644
b69e47
--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c
b69e47
+++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c
b69e47
@@ -1582,9 +1582,9 @@ static config_info ldbm_config[] = {
b69e47
     {CONFIG_DB_DEBUG_CHECKPOINTING, CONFIG_TYPE_ONOFF, "off", &ldbm_config_db_debug_checkpointing_get, &ldbm_config_db_debug_checkpointing_set, 0},
b69e47
     {CONFIG_DB_HOME_DIRECTORY, CONFIG_TYPE_STRING, "", &ldbm_config_db_home_directory_get, &ldbm_config_db_home_directory_set, 0},
b69e47
     {CONFIG_IMPORT_CACHE_AUTOSIZE, CONFIG_TYPE_INT, "-1", &ldbm_config_import_cache_autosize_get, &ldbm_config_import_cache_autosize_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE},
b69e47
-    {CONFIG_CACHE_AUTOSIZE, CONFIG_TYPE_INT, "0", &ldbm_config_cache_autosize_get, &ldbm_config_cache_autosize_set, 0},
b69e47
+    {CONFIG_CACHE_AUTOSIZE, CONFIG_TYPE_INT, "10", &ldbm_config_cache_autosize_get, &ldbm_config_cache_autosize_set, 0},
b69e47
     {CONFIG_CACHE_AUTOSIZE_SPLIT, CONFIG_TYPE_INT, "40", &ldbm_config_cache_autosize_split_get, &ldbm_config_cache_autosize_split_set, 0},
b69e47
-    {CONFIG_IMPORT_CACHESIZE, CONFIG_TYPE_SIZE_T, "20000000", &ldbm_config_import_cachesize_get, &ldbm_config_import_cachesize_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE},
b69e47
+    {CONFIG_IMPORT_CACHESIZE, CONFIG_TYPE_SIZE_T, "16777216", &ldbm_config_import_cachesize_get, &ldbm_config_import_cachesize_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE},
b69e47
     {CONFIG_IDL_SWITCH, CONFIG_TYPE_STRING, "new", &ldbm_config_idl_get_idl_new, &ldbm_config_idl_set_tune, CONFIG_FLAG_ALWAYS_SHOW},
b69e47
     {CONFIG_IDL_UPDATE, CONFIG_TYPE_ONOFF, "on", &ldbm_config_idl_get_update, &ldbm_config_idl_set_update, 0},
b69e47
     {CONFIG_BYPASS_FILTER_TEST, CONFIG_TYPE_STRING, "on", &ldbm_config_get_bypass_filter_test, &ldbm_config_set_bypass_filter_test, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE},
b69e47
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c b/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c
b69e47
index 62cdbc3..36d830d 100644
b69e47
--- a/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c
b69e47
+++ b/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c
b69e47
@@ -93,6 +93,7 @@ ldbm_instance_config_cachememsize_set(void *arg, void *value, char *errorbuf, in
b69e47
     int retval = LDAP_SUCCESS;
b69e47
     size_t val = (size_t) value;
b69e47
     uint64_t delta = 0;
b69e47
+    uint64_t delta_original = 0;
b69e47
 
b69e47
     /* Do whatever we can to make sure the data is ok. */
b69e47
     /* There is an error here. We check the new val against our current mem-alloc 
b69e47
@@ -108,18 +109,34 @@ ldbm_instance_config_cachememsize_set(void *arg, void *value, char *errorbuf, in
b69e47
     if (apply) {
b69e47
         if (val > inst->inst_cache.c_maxsize) {
b69e47
             delta = val - inst->inst_cache.c_maxsize;
b69e47
+            delta_original = delta;
b69e47
 
b69e47
             util_cachesize_result sane;
b69e47
             slapi_pal_meminfo *mi = spal_meminfo_get();
b69e47
             sane = util_is_cachesize_sane(mi, &delta);
b69e47
             spal_meminfo_destroy(mi);
b69e47
 
b69e47
-            if (sane != UTIL_CACHESIZE_VALID){
b69e47
-                slapi_create_errormsg(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "Error: cachememsize value is too large.");
b69e47
-                slapi_log_err(SLAPI_LOG_ERR, "ldbm_instance_config_cachememsize_set", "cachememsize value is too large.\n");
b69e47
+            if (sane == UTIL_CACHESIZE_ERROR){
b69e47
+                slapi_create_errormsg(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "Error: unable to determine system memory limits.");
b69e47
+                slapi_log_err(SLAPI_LOG_ERR, "ldbm_instance_config_cachememsize_set", "Enable to determine system memory limits.\n");
b69e47
                 return LDAP_UNWILLING_TO_PERFORM;
b69e47
+            } else if (sane == UTIL_CACHESIZE_REDUCED) {
b69e47
+                slapi_log_err(SLAPI_LOG_WARNING, "ldbm_instance_config_cachememsize_set", "delta +%"PRIu64" of request %"PRIu64" reduced to %"PRIu64"\n", delta_original, val, delta);
b69e47
+                /*
b69e47
+                 * This works as: value = 100
b69e47
+                 * delta_original to inst, 20;
b69e47
+                 * delta reduced to 5:
b69e47
+                 * 100 - (20 - 5) == 85;
b69e47
+                 * so if you recalculated delta now (val - inst), it would be 5.
b69e47
+                 */
b69e47
+                val = val - (delta_original - delta);
b69e47
             }
b69e47
         }
b69e47
+        if (inst->inst_cache.c_maxsize < MINCACHESIZE || val < MINCACHESIZE) {
b69e47
+            slapi_log_err(SLAPI_LOG_ERR, "ldbm_instance_config_cachememsize_set", "force a minimal value %"PRIu64"\n", MINCACHESIZE);
b69e47
+            /* This value will trigger an autotune next start up, but it should increase only */
b69e47
+            val = MINCACHESIZE;
b69e47
+        }
b69e47
         cache_set_max_size(&(inst->inst_cache), val, CACHE_TYPE_ENTRY);
b69e47
     }
b69e47
 
b69e47
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
b69e47
index 0c76580..d9547d8 100644
b69e47
--- a/ldap/servers/slapd/slapi-private.h
b69e47
+++ b/ldap/servers/slapd/slapi-private.h
b69e47
@@ -1392,7 +1392,7 @@ typedef enum _util_cachesize_result {
b69e47
  * \return util_cachesize_result.
b69e47
  * \sa util_cachesize_result, spal_meminfo_get
b69e47
  */
b69e47
-util_cachesize_result util_is_cachesize_sane(slapi_pal_meminfo *mi, size_t *cachesize);
b69e47
+util_cachesize_result util_is_cachesize_sane(slapi_pal_meminfo *mi, uint64_t *cachesize);
b69e47
 
b69e47
 /**
b69e47
  * Retrieve the number of threads the server should run with based on this hardware.
b69e47
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
b69e47
index 012e83d..4ff6d41 100644
b69e47
--- a/ldap/servers/slapd/util.c
b69e47
+++ b/ldap/servers/slapd/util.c
b69e47
@@ -1468,16 +1468,26 @@ util_is_cachesize_sane(slapi_pal_meminfo *mi, uint64_t *cachesize)
b69e47
         return UTIL_CACHESIZE_ERROR;
b69e47
     }
b69e47
 
b69e47
+    util_cachesize_result result = UTIL_CACHESIZE_VALID;
b69e47
     slapi_log_err(SLAPI_LOG_TRACE, "util_is_cachesize_sane", "Available bytes %"PRIu64", requested bytes %"PRIu64"\n", mi->system_available_bytes, *cachesize);
b69e47
     if (*cachesize > mi->system_available_bytes) {
b69e47
-        /* Since we are ask for more than what's available, we give 3/4 of the remaining.
b69e47
+        /* Since we are ask for more than what's available, we give 1/2 of the remaining.
b69e47
          * the remaining system mem to the cachesize instead, and log a warning
b69e47
          */
b69e47
-        *cachesize = (mi->system_available_bytes * 0.75);
b69e47
-        slapi_log_err(SLAPI_LOG_TRACE, "util_is_cachesize_sane", "Adjusted cachesize to %"PRIu64"\n", *cachesize);
b69e47
-        return UTIL_CACHESIZE_REDUCED;
b69e47
+        uint64_t adjust_cachesize = (mi->system_available_bytes * 0.5);
b69e47
+        if (adjust_cachesize > *cachesize) {
b69e47
+            slapi_log_err(SLAPI_LOG_CRIT, "util_is_cachesize_sane", "Invalid adjusted cachesize is greater than request %"PRIu64, adjust_cachesize);
b69e47
+            return UTIL_CACHESIZE_ERROR;
b69e47
+        }
b69e47
+        if (adjust_cachesize < (16 * mi->pagesize_bytes)) {
b69e47
+            /* At minimum respond with 16 pages - that's 64k on x86_64 */
b69e47
+            adjust_cachesize = 16 * mi->pagesize_bytes;
b69e47
+        }
b69e47
+        *cachesize = adjust_cachesize;
b69e47
+        slapi_log_err(SLAPI_LOG_TRACE, "util_is_cachesize_sane", "Adjusted cachesize down to %"PRIu64"\n", *cachesize);
b69e47
+        result = UTIL_CACHESIZE_REDUCED;
b69e47
     }
b69e47
-    return UTIL_CACHESIZE_VALID;
b69e47
+    return result;
b69e47
 }
b69e47
 
b69e47
 long
b69e47
-- 
b69e47
2.9.3
b69e47