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

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