diff --git a/SOURCES/0056-Ticket-49313-Change-the-retrochangelog-default-cache.patch b/SOURCES/0056-Ticket-49313-Change-the-retrochangelog-default-cache.patch
new file mode 100644
index 0000000..c1089ec
--- /dev/null
+++ b/SOURCES/0056-Ticket-49313-Change-the-retrochangelog-default-cache.patch
@@ -0,0 +1,47 @@
+From 0fc3c803c34311eb05c5c7a7e710c8591b592649 Mon Sep 17 00:00:00 2001
+From: Thierry Bordaz <tbordaz@redhat.com>
+Date: Thu, 27 Jul 2017 18:10:05 +0200
+Subject: [PATCH] Ticket 49313 - Change the retrochangelog default cache size
+
+Bug Description:
+    Default retroCL backend entry cache size is 2Mb.
+    It has been reported in many deployments that DB corruption could
+    be prevented by increasing entry cache to 200Mb.
+    There is no identified reproducible steps to debug this DB corruption.
+    So to prevent this problem we are increasing the entry cache
+
+Fix Description:
+    Set default cn=changelog cache to 200Mb (based on production cases)
+    An other option would be to set a maximum number of entries but
+    as we do not know if it works to prevent DB corruption, let's prefere
+    entry cache size
+
+https://pagure.io/389-ds-base/issue/49313
+
+Reviewed by: William Brown
+
+Platforms tested: F23
+
+Flag Day: no
+
+Doc impact: no
+---
+ ldap/servers/plugins/retrocl/retrocl.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ldap/servers/plugins/retrocl/retrocl.h b/ldap/servers/plugins/retrocl/retrocl.h
+index 6963d4b..eef1a17 100644
+--- a/ldap/servers/plugins/retrocl/retrocl.h
++++ b/ldap/servers/plugins/retrocl/retrocl.h
+@@ -58,7 +58,7 @@ typedef struct _cnumRet {
+ #else
+ #define RETROCL_DLL_DEFAULT_THREAD_STACKSIZE 131072L
+ #endif
+-#define RETROCL_BE_CACHEMEMSIZE  "2097152"
++#define RETROCL_BE_CACHEMEMSIZE  "209715200"
+ #define RETROCL_BE_CACHESIZE "-1"
+ #define RETROCL_PLUGIN_NAME "DSRetroclPlugin"
+ 
+-- 
+2.9.4
+
diff --git a/SOURCES/0057-Ticket-49287-v3-extend-csnpl-handling-to-multiple-ba.patch b/SOURCES/0057-Ticket-49287-v3-extend-csnpl-handling-to-multiple-ba.patch
new file mode 100644
index 0000000..8a71d55
--- /dev/null
+++ b/SOURCES/0057-Ticket-49287-v3-extend-csnpl-handling-to-multiple-ba.patch
@@ -0,0 +1,795 @@
+From 6b5aa0e288f1ea5553d4dd5d220d4e5daf50a247 Mon Sep 17 00:00:00 2001
+From: Mark Reynolds <mreynolds@redhat.com>
+Date: Mon, 31 Jul 2017 14:45:50 -0400
+Subject: [PATCH] Ticket 49287 - v3 extend csnpl handling to multiple backends
+
+        The csn pending list mechanism failed if internal operation affected multiple backends
+
+        This fix is an extension to the fix in ticket 49008, the thread local data now also contains
+        a list of all affected replicas.
+
+        http://www.port389.org/docs/389ds/design/csn-pending-lists-and-ruv-update.html
+
+        Reviewed by: William, Thierry - thanks
+---
+ ldap/servers/plugins/replication/csnpl.c         |  85 ++++++++--
+ ldap/servers/plugins/replication/csnpl.h         |   8 +-
+ ldap/servers/plugins/replication/repl5.h         |  22 ++-
+ ldap/servers/plugins/replication/repl5_init.c    |  48 +++++-
+ ldap/servers/plugins/replication/repl5_plugins.c |  16 +-
+ ldap/servers/plugins/replication/repl5_replica.c |  18 ++-
+ ldap/servers/plugins/replication/repl5_ruv.c     | 191 ++++++++++++++---------
+ ldap/servers/plugins/replication/repl5_ruv.h     |   6 +-
+ ldap/servers/slapd/slapi-private.h               |   2 +-
+ 9 files changed, 283 insertions(+), 113 deletions(-)
+
+diff --git a/ldap/servers/plugins/replication/csnpl.c b/ldap/servers/plugins/replication/csnpl.c
+index 4a0f5f5..12a0bb8 100644
+--- a/ldap/servers/plugins/replication/csnpl.c
++++ b/ldap/servers/plugins/replication/csnpl.c
+@@ -14,7 +14,6 @@
+ 
+ #include "csnpl.h"
+ #include "llist.h"
+-#include "repl_shared.h"
+ 
+ struct csnpl 
+ {
+@@ -22,13 +21,17 @@ struct csnpl
+ 	Slapi_RWLock*	csnLock;	/* lock to serialize access to PL */
+ };	
+ 
++
+ typedef struct _csnpldata
+ {
+ 	PRBool	committed;  /* True if CSN committed */
+ 	CSN	*csn;       /* The actual CSN */
++	Replica * prim_replica; /* The replica where the prom csn was generated */
+ 	const CSN *prim_csn;  /* The primary CSN of an operation consising of multiple sub ops*/
+ } csnpldata;
+ 
++static PRBool csn_primary_or_nested(csnpldata *csn_data,  const CSNPL_CTX *csn_ctx);
++
+ /* forward declarations */
+ #ifdef DEBUG
+ static void _csnplDumpContentNoLock(CSNPL *csnpl, const char *caller);
+@@ -104,7 +107,7 @@ void csnplFree (CSNPL **csnpl)
+  *          1 if the csn has already been seen
+  *         -1 for any other kind of errors
+  */
+-int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSN *prim_csn)
++int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSNPL_CTX *prim_csn)
+ {
+ 	int rc;
+ 	csnpldata *csnplnode;
+@@ -129,10 +132,13 @@ int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSN *prim_csn)
+         return 1;
+     }
+ 
+-	csnplnode = (csnpldata *)slapi_ch_malloc(sizeof(csnpldata));
++	csnplnode = (csnpldata *)slapi_ch_calloc(1, sizeof(csnpldata));
+ 	csnplnode->committed = PR_FALSE;
+ 	csnplnode->csn = csn_dup(csn);
+-	csnplnode->prim_csn = prim_csn;
++	if (prim_csn) {
++		csnplnode->prim_csn = prim_csn->prim_csn;
++		csnplnode->prim_replica =  prim_csn->prim_repl;
++	}
+ 	csn_as_string(csn, PR_FALSE, csn_str);
+ 	rc = llistInsertTail (csnpl->csnList, csn_str, csnplnode);
+ 
+@@ -187,8 +193,58 @@ int csnplRemove (CSNPL *csnpl, const CSN *csn)
+ 
+ 	return 0;
+ }
++PRBool csn_primary(Replica *replica, const CSN *csn,  const CSNPL_CTX *csn_ctx)
++{
++    if (csn_ctx == NULL)
++        return PR_FALSE;
++    
++    if (replica != csn_ctx->prim_repl) {
++        /* The CSNs are not from the same replication topology
++         * so even if the csn values are equal they are not related
++         * to the same operation
++         */
++        return PR_FALSE;
++    }
++    
++    /* Here the two CSNs belong to the same replication topology */
++    
++    /* check if the CSN identifies the primary update */
++    if (csn_is_equal(csn, csn_ctx->prim_csn)) {
++        return PR_TRUE;
++    }
++    
++    return PR_FALSE;
++}
++
++static PRBool csn_primary_or_nested(csnpldata *csn_data,  const CSNPL_CTX *csn_ctx)
++{
++    if ((csn_data == NULL) || (csn_ctx == NULL))
++        return PR_FALSE;
++    
++    if (csn_data->prim_replica != csn_ctx->prim_repl) {
++        /* The CSNs are not from the same replication topology
++         * so even if the csn values are equal they are not related
++         * to the same operation
++         */
++        return PR_FALSE;
++    }
++    
++    /* Here the two CSNs belong to the same replication topology */
++    
++    /* First check if the CSN identifies the primary update */
++    if (csn_is_equal(csn_data->csn, csn_ctx->prim_csn)) {
++        return PR_TRUE;
++    }
++    
++    /* Second check if the CSN identifies a nested update */
++    if (csn_is_equal(csn_data->prim_csn, csn_ctx->prim_csn)) {
++        return PR_TRUE;
++    }
++    
++    return PR_FALSE;
++}
+ 
+-int csnplRemoveAll (CSNPL *csnpl, const CSN *csn)
++int csnplRemoveAll (CSNPL *csnpl, const CSNPL_CTX *csn_ctx)
+ {
+ 	csnpldata *data;
+ 	void *iterator;
+@@ -197,8 +253,7 @@ int csnplRemoveAll (CSNPL *csnpl, const CSN *csn)
+ 	data = (csnpldata *)llistGetFirst(csnpl->csnList, &iterator);
+ 	while (NULL != data)
+ 	{
+-		if (csn_is_equal(data->csn, csn) ||
+-		    csn_is_equal(data->prim_csn, csn)) {
++		if (csn_primary_or_nested(data, csn_ctx)) {
+ 			csnpldata_free(&data);
+ 			data = (csnpldata *)llistRemoveCurrentAndGetNext(csnpl->csnList, &iterator);
+ 		} else {
+@@ -213,13 +268,13 @@ int csnplRemoveAll (CSNPL *csnpl, const CSN *csn)
+ }
+ 
+ 
+-int csnplCommitAll (CSNPL *csnpl, const CSN *csn)
++int csnplCommitAll (CSNPL *csnpl, const CSNPL_CTX *csn_ctx)
+ {
+ 	csnpldata *data;
+ 	void *iterator;
+ 	char csn_str[CSN_STRSIZE];
+ 
+-	csn_as_string(csn, PR_FALSE, csn_str);
++	csn_as_string(csn_ctx->prim_csn, PR_FALSE, csn_str);
+ 	slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
+ 		            "csnplCommitALL: committing all csns for csn %s\n", csn_str);
+ 	slapi_rwlock_wrlock (csnpl->csnLock);
+@@ -229,8 +284,7 @@ int csnplCommitAll (CSNPL *csnpl, const CSN *csn)
+ 		csn_as_string(data->csn, PR_FALSE, csn_str);
+ 		slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
+ 				"csnplCommitALL: processing data csn %s\n", csn_str);
+-		if (csn_is_equal(data->csn, csn) ||
+-		    csn_is_equal(data->prim_csn, csn)) {
++                if (csn_primary_or_nested(data, csn_ctx)) {
+ 			data->committed = PR_TRUE;
+ 		}
+ 		data = (csnpldata *)llistGetNext (csnpl->csnList, &iterator);
+@@ -395,7 +449,12 @@ static void _csnplDumpContentNoLock(CSNPL *csnpl, const char *caller)
+ 
+ /* wrapper around csn_free, to satisfy NSPR thread context API */
+ void
+-csnplFreeCSN (void *arg)
++csnplFreeCSNPL_CTX (void *arg)
+ {
+-	csn_free((CSN **)&arg);
++	CSNPL_CTX *csnpl_ctx = (CSNPL_CTX *)arg;
++	csn_free(&csnpl_ctx->prim_csn);
++	if (csnpl_ctx->sec_repl) {
++		slapi_ch_free((void **)&csnpl_ctx->sec_repl);
++	}
++	slapi_ch_free((void **)&csnpl_ctx);
+ }
+diff --git a/ldap/servers/plugins/replication/csnpl.h b/ldap/servers/plugins/replication/csnpl.h
+index 594c8f2..1036c62 100644
+--- a/ldap/servers/plugins/replication/csnpl.h
++++ b/ldap/servers/plugins/replication/csnpl.h
+@@ -17,15 +17,17 @@
+ #define CSNPL_H
+ 
+ #include "slapi-private.h"
++#include "repl5.h"
+ 
+ typedef struct csnpl CSNPL;
+ 
+ CSNPL* csnplNew(void);
+ void csnplFree (CSNPL **csnpl);
+-int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSN *prim_csn);
++int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSNPL_CTX *prim_csn);
+ int csnplRemove (CSNPL *csnpl, const CSN *csn);
+-int csnplRemoveAll (CSNPL *csnpl, const CSN *csn);
+-int csnplCommitAll (CSNPL *csnpl, const CSN *csn);
++int csnplRemoveAll (CSNPL *csnpl, const CSNPL_CTX *csn_ctx);
++int csnplCommitAll (CSNPL *csnpl, const CSNPL_CTX *csn_ctx);
++PRBool csn_primary(Replica *replica, const CSN *csn,  const CSNPL_CTX *csn_ctx);
+ CSN* csnplGetMinCSN (CSNPL *csnpl, PRBool *committed);
+ int csnplCommit (CSNPL *csnpl, const CSN *csn);
+ CSN *csnplRollUp(CSNPL *csnpl, CSN ** first);
+diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
+index 1d8989c..718f64e 100644
+--- a/ldap/servers/plugins/replication/repl5.h
++++ b/ldap/servers/plugins/replication/repl5.h
+@@ -228,12 +228,27 @@ int multimaster_be_betxnpostop_delete (Slapi_PBlock *pb);
+ int multimaster_be_betxnpostop_add (Slapi_PBlock *pb);
+ int multimaster_be_betxnpostop_modify (Slapi_PBlock *pb);
+ 
++/* In repl5_replica.c */
++typedef struct replica Replica;
++
++/* csn pending lists */
++#define CSNPL_CTX_REPLCNT 4
++typedef struct CSNPL_CTX
++{
++	CSN *prim_csn;
++	size_t repl_alloc; /* max number of replicas  */
++	size_t repl_cnt; /* number of replicas affected by operation */
++	Replica *prim_repl; /* pirmary replica */
++	Replica **sec_repl; /* additional replicas affected */
++} CSNPL_CTX;
++
+ /* In repl5_init.c */
+ extern int repl5_is_betxn;
+ char* get_thread_private_agmtname(void);
+ void  set_thread_private_agmtname (const char *agmtname);
+-void  set_thread_primary_csn (const CSN *prim_csn);
+-CSN*  get_thread_primary_csn(void);
++void  set_thread_primary_csn (const CSN *prim_csn, Replica *repl);
++void  add_replica_to_primcsn(CSNPL_CTX *prim_csn, Replica *repl);
++CSNPL_CTX*  get_thread_primary_csn(void);
+ void* get_thread_private_cache(void);
+ void  set_thread_private_cache (void *buf);
+ char* get_repl_session_id (Slapi_PBlock *pb, char *id, CSN **opcsn);
+@@ -302,7 +317,6 @@ typedef struct repl_bos Repl_Bos;
+ 
+ /* In repl5_agmt.c */
+ typedef struct repl5agmt Repl_Agmt;
+-typedef struct replica Replica;
+ 
+ #define TRANSPORT_FLAG_SSL 1
+ #define TRANSPORT_FLAG_TLS 2
+@@ -629,6 +643,8 @@ PRUint64 replica_get_precise_purging(Replica *r);
+ void replica_set_precise_purging(Replica *r, PRUint64 on_off);
+ PRBool ignore_error_and_keep_going(int error);
+ void replica_check_release_timeout(Replica *r, Slapi_PBlock *pb);
++void replica_lock_replica(Replica *r);
++void replica_unlock_replica(Replica *r);
+ 
+ /* The functions below handles the state flag */
+ /* Current internal state flags */
+diff --git a/ldap/servers/plugins/replication/repl5_init.c b/ldap/servers/plugins/replication/repl5_init.c
+index edffb84..b0bc515 100644
+--- a/ldap/servers/plugins/replication/repl5_init.c
++++ b/ldap/servers/plugins/replication/repl5_init.c
+@@ -154,26 +154,62 @@ set_thread_private_agmtname(const char *agmtname)
+ 		PR_SetThreadPrivate(thread_private_agmtname, (void *)agmtname);
+ }
+ 
+-CSN*
++CSNPL_CTX*
+ get_thread_primary_csn(void)
+ {
+-	CSN *prim_csn = NULL;
++	CSNPL_CTX *prim_csn = NULL;
+ 	if (thread_primary_csn)
+-		prim_csn = (CSN *)PR_GetThreadPrivate(thread_primary_csn);
++		prim_csn = (CSNPL_CTX *)PR_GetThreadPrivate(thread_primary_csn);
++
+ 	return prim_csn;
+ }
+ void
+-set_thread_primary_csn(const CSN *prim_csn)
++set_thread_primary_csn (const CSN *prim_csn, Replica *repl)
+ {
+ 	if (thread_primary_csn) {
+ 		if (prim_csn) {
+-			PR_SetThreadPrivate(thread_primary_csn, (void *)csn_dup(prim_csn));
++			CSNPL_CTX *csnpl_ctx = (CSNPL_CTX *)slapi_ch_calloc(1,sizeof(CSNPL_CTX));
++			csnpl_ctx->prim_csn = csn_dup(prim_csn);
++			/* repl_alloc, repl_cnt and sec_repl are 0 by calloc */
++			csnpl_ctx->prim_repl = repl;
++			PR_SetThreadPrivate(thread_primary_csn, (void *)csnpl_ctx);
+ 		} else {
+ 			PR_SetThreadPrivate(thread_primary_csn, NULL);
+ 		}
+ 	}
+ }
+ 
++void
++add_replica_to_primcsn(CSNPL_CTX *csnpl_ctx, Replica *repl)
++{
++	size_t found = 0;
++	size_t it = 0;
++
++	if (repl == csnpl_ctx->prim_repl) return;
++
++	while (it < csnpl_ctx->repl_cnt) {
++		if (csnpl_ctx->sec_repl[it] == repl) {
++			found = 1;
++			break;
++		}
++		it++;
++	}
++	if (found) return;
++
++	if (csnpl_ctx->repl_cnt < csnpl_ctx->repl_alloc) {
++		csnpl_ctx->sec_repl[csnpl_ctx->repl_cnt++] = repl;
++		return;
++	}
++	csnpl_ctx->repl_alloc += CSNPL_CTX_REPLCNT;
++	if (csnpl_ctx->repl_cnt == 0) {
++		csnpl_ctx->sec_repl = (Replica **)slapi_ch_calloc(csnpl_ctx->repl_alloc, sizeof(Replica *));
++	} else {
++		csnpl_ctx->sec_repl = (Replica **)slapi_ch_realloc((char *)csnpl_ctx->sec_repl, csnpl_ctx->repl_alloc * sizeof(Replica *));
++	}
++	csnpl_ctx->sec_repl[csnpl_ctx->repl_cnt++] = repl;
++	return;
++}
++
+ void*
+ get_thread_private_cache ()
+ {
+@@ -740,7 +776,7 @@ multimaster_start( Slapi_PBlock *pb )
+ 		/* Initialize thread private data for logging. Ignore if fails */
+ 		PR_NewThreadPrivateIndex (&thread_private_agmtname, NULL);
+ 		PR_NewThreadPrivateIndex (&thread_private_cache, NULL);
+-		PR_NewThreadPrivateIndex (&thread_primary_csn, csnplFreeCSN);
++		PR_NewThreadPrivateIndex (&thread_primary_csn, csnplFreeCSNPL_CTX);
+ 
+ 		/* Decode the command line args to see if we're dumping to LDIF */
+ 		is_ldif_dump = check_for_ldif_dump(pb);
+diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
+index 9ef06af..c31d9d5 100644
+--- a/ldap/servers/plugins/replication/repl5_plugins.c
++++ b/ldap/servers/plugins/replication/repl5_plugins.c
+@@ -45,6 +45,7 @@
+ #include "repl.h"
+ #include "cl5_api.h"
+ #include "urp.h"
++#include "csnpl.h"
+ 
+ static char *local_purl = NULL;
+ static char *purl_attrs[] = {"nsslapd-localhost", "nsslapd-port", "nsslapd-secureport", NULL};
+@@ -1034,7 +1035,7 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
+ {
+ 	Slapi_Operation *op = NULL;
+ 	CSN *opcsn;
+-	CSN *prim_csn;
++	CSNPL_CTX *prim_csn;
+ 	int rc;
+ 	slapi_operation_parameters *op_params = NULL;
+ 	Object *repl_obj = NULL;
+@@ -1070,14 +1071,15 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
+ 	if (repl_obj == NULL)
+ 		return return_value;
+ 
++	r = (Replica*)object_get_data (repl_obj);
++	PR_ASSERT (r);
++
+ 	slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
+ 	if (rc) { /* op failed - just return */
+ 		cancel_opcsn(pb);
+ 		goto common_return;
+ 	}
+ 
+-	r = (Replica*)object_get_data (repl_obj);
+-	PR_ASSERT (r);
+ 
+ 	replica_check_release_timeout(r, pb);
+ 
+@@ -1223,12 +1225,12 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
+ common_return:
+ 	opcsn = operation_get_csn(op);
+ 	prim_csn = get_thread_primary_csn();
+-	if (csn_is_equal(opcsn, prim_csn)) {
++	if (csn_primary(r, opcsn, prim_csn)) {
+ 		if (return_value == 0) {
+ 			/* the primary csn was succesfully committed
+ 			 * unset it in the thread local data
+ 			 */
+-			set_thread_primary_csn(NULL);
++			set_thread_primary_csn(NULL, NULL);
+ 		}
+ 	}
+ 	if (repl_obj) {
+@@ -1430,7 +1432,7 @@ cancel_opcsn (Slapi_PBlock *pb)
+ 
+             ruv_obj = replica_get_ruv (r);
+             PR_ASSERT (ruv_obj);
+-            ruv_cancel_csn_inprogress ((RUV*)object_get_data (ruv_obj), opcsn, replica_get_rid(r));
++            ruv_cancel_csn_inprogress (r, (RUV*)object_get_data (ruv_obj), opcsn, replica_get_rid(r));
+             object_release (ruv_obj);
+         }
+ 
+@@ -1491,7 +1493,7 @@ process_operation (Slapi_PBlock *pb, const CSN *csn)
+     ruv = (RUV*)object_get_data (ruv_obj);
+     PR_ASSERT (ruv);
+  
+-    rc = ruv_add_csn_inprogress (ruv, csn);
++    rc = ruv_add_csn_inprogress (r, ruv, csn);
+ 
+     object_release (ruv_obj);
+     object_release (r_obj);
+diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
+index 1bdc138..7927ac3 100644
+--- a/ldap/servers/plugins/replication/repl5_replica.c
++++ b/ldap/servers/plugins/replication/repl5_replica.c
+@@ -923,7 +923,7 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
+ 					}
+ 				}
+ 				/* Update max csn for local and remote replicas */
+-				rc = ruv_update_ruv (ruv, updated_csn, replica_purl, r->repl_rid);
++				rc = ruv_update_ruv (ruv, updated_csn, replica_purl, r, r->repl_rid);
+ 				if (RUV_COVERS_CSN == rc)
+ 				{
+ 					slapi_log_err(SLAPI_LOG_REPL,
+@@ -3663,7 +3663,7 @@ assign_csn_callback(const CSN *csn, void *data)
+         }
+     }
+ 
+-    ruv_add_csn_inprogress (ruv, csn);
++    ruv_add_csn_inprogress (r, ruv, csn);
+ 
+     replica_unlock(r->repl_lock);
+ 
+@@ -3692,13 +3692,13 @@ abort_csn_callback(const CSN *csn, void *data)
+     {
+         int rc = csnplRemove(r->min_csn_pl, csn);
+         if (rc) {
+-            slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "abort_csn_callback - csnplRemove failed");
++            slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "abort_csn_callback - csnplRemove failed\n");
+             replica_unlock(r->repl_lock);
+             return;
+         }
+     }
+ 
+-    ruv_cancel_csn_inprogress (ruv, csn, replica_get_rid(r));
++    ruv_cancel_csn_inprogress (r, ruv, csn, replica_get_rid(r));
+     replica_unlock(r->repl_lock);
+ 
+     object_release (ruv_obj);
+@@ -4489,3 +4489,13 @@ replica_check_release_timeout(Replica *r, Slapi_PBlock *pb)
+ 	}
+ 	replica_unlock(r->repl_lock);
+ }
++void
++replica_lock_replica(Replica *r)
++{
++	replica_lock(r->repl_lock);
++}
++void
++replica_unlock_replica(Replica *r)
++{
++	replica_unlock(r->repl_lock);
++}
+diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
+index d59e6d2..39449b6 100644
+--- a/ldap/servers/plugins/replication/repl5_ruv.c
++++ b/ldap/servers/plugins/replication/repl5_ruv.c
+@@ -77,7 +77,7 @@ static char *get_replgen_from_berval(const struct berval *bval);
+ static const char * const prefix_replicageneration = "{replicageneration}";
+ static const char * const prefix_ruvcsn = "{replica "; /* intentionally missing '}' */
+ 
+-static int ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSN *csn, const char *replica_purl, PRBool isLocal);
++static int ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSNPL_CTX *prim_csn, const char *replica_purl, PRBool isLocal);
+ 
+ /* API implementation */
+ 
+@@ -1599,13 +1599,13 @@ ruv_dump(const RUV *ruv, char *ruv_name, PRFileDesc *prFile)
+ 
+ /* this function notifies the ruv that there are operations in progress so that
+    they can be added to the pending list for the appropriate client. */
+-int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
++int ruv_add_csn_inprogress (void *repl, RUV *ruv, const CSN *csn)
+ {
+     RUVElement* replica;
+     char csn_str[CSN_STRSIZE];
+     int rc = RUV_SUCCESS;
+     int rid = csn_get_replicaid (csn);
+-    CSN *prim_csn;
++    CSNPL_CTX *prim_csn;
+ 
+     PR_ASSERT (ruv && csn);
+ 
+@@ -1645,8 +1645,13 @@ int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
+     }
+     prim_csn = get_thread_primary_csn();
+     if (prim_csn == NULL) {
+-        set_thread_primary_csn(csn);
++        set_thread_primary_csn(csn, (Replica *)repl);
+         prim_csn = get_thread_primary_csn();
++    } else {
++	/* the prim csn data already exist, need to check if
++	 * current replica is already present
++	 */
++	add_replica_to_primcsn(prim_csn, (Replica *)repl);
+     }
+     rc = csnplInsert (replica->csnpl, csn, prim_csn);
+     if (rc == 1)    /* we already seen this csn */
+@@ -1656,7 +1661,7 @@ int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
+                             "The csn %s has already be seen - ignoring\n",
+                             csn_as_string (csn, PR_FALSE, csn_str));
+         }
+-        set_thread_primary_csn(NULL);
++        set_thread_primary_csn(NULL, NULL);
+         rc = RUV_COVERS_CSN;    
+     }
+     else if(rc != 0)
+@@ -1681,11 +1686,13 @@ done:
+     return rc;
+ }
+ 
+-int ruv_cancel_csn_inprogress (RUV *ruv, const CSN *csn, ReplicaId local_rid)
++int ruv_cancel_csn_inprogress (void *repl, RUV *ruv, const CSN *csn, ReplicaId local_rid)
+ {
+-    RUVElement* replica;
++    RUVElement* repl_ruv;
+     int rc = RUV_SUCCESS;
+-    CSN *prim_csn = NULL;
++    CSNPL_CTX *prim_csn = NULL;
++    Replica *repl_it;
++    size_t it;
+ 
+ 
+     PR_ASSERT (ruv && csn);
+@@ -1693,29 +1700,53 @@ int ruv_cancel_csn_inprogress (RUV *ruv, const CSN *csn, ReplicaId local_rid)
+     prim_csn = get_thread_primary_csn();
+     /* locate ruvElement */
+     slapi_rwlock_wrlock (ruv->lock);
+-    replica = ruvGetReplica (ruv, csn_get_replicaid (csn));
+-    if (replica == NULL) {
++    repl_ruv = ruvGetReplica (ruv, csn_get_replicaid (csn));
++    if (repl_ruv == NULL) {
+         /* ONREPL - log error */
+ 	rc = RUV_NOTFOUND;
+ 	goto done;
+     }
+-    if (csn_is_equal(csn, prim_csn)) {
+-	/* the prim csn is cancelled, lets remove all dependent csns */
+-	ReplicaId prim_rid = csn_get_replicaid (csn);
+-	replica = ruvGetReplica (ruv, prim_rid);
+-	rc = csnplRemoveAll (replica->csnpl, prim_csn);
+-	if (prim_rid != local_rid) {
+-		if( local_rid != READ_ONLY_REPLICA_ID) {
+-			replica = ruvGetReplica (ruv, local_rid);
+-			if (replica) {
+-				rc = csnplRemoveAll (replica->csnpl, prim_csn);
+-			} else {
+-				rc = RUV_NOTFOUND;
+-			}
+-		}
+-	}
++    if (csn_primary(repl, csn, prim_csn)) {
++        /* the prim csn is cancelled, lets remove all dependent csns */
++        /* for the primary replica we can have modifications for two RIDS:
++         * - the local RID for direct or internal operations
++         * - a remote RID if the primary csn is for a replciated op.
++         */
++        ReplicaId prim_rid = csn_get_replicaid(csn);
++        repl_ruv = ruvGetReplica(ruv, prim_rid);
++        if (!repl_ruv) {
++            rc = RUV_NOTFOUND;
++            goto done;
++        }
++        rc = csnplRemoveAll(repl_ruv->csnpl, prim_csn);
++
++        if (prim_rid != local_rid && local_rid != READ_ONLY_REPLICA_ID) {
++            repl_ruv = ruvGetReplica(ruv, local_rid);
++            if (!repl_ruv) {
++                rc = RUV_NOTFOUND;
++                goto done;
++            }
++            rc = csnplRemoveAll(repl_ruv->csnpl, prim_csn);
++        }
++
++        for (it = 0; it < prim_csn->repl_cnt; it++) {
++            repl_it = prim_csn->sec_repl[it];
++            replica_lock_replica(repl_it);
++            local_rid = replica_get_rid(repl_it);
++            if (local_rid != READ_ONLY_REPLICA_ID) {
++                Object *ruv_obj = replica_get_ruv(repl_it);
++                RUV *ruv_it = object_get_data(ruv_obj);
++                repl_ruv = ruvGetReplica(ruv_it, local_rid);
++                if (repl_ruv) {
++                    rc = csnplRemoveAll(repl_ruv->csnpl, prim_csn);
++                } else {
++                    rc = RUV_NOTFOUND;
++                }
++            }
++            replica_unlock_replica(repl_it);
++        }
+     } else {
+-	rc = csnplRemove (replica->csnpl, csn);
++	rc = csnplRemove (repl_ruv->csnpl, csn);
+     }
+     if (rc != 0)
+         rc = RUV_NOTFOUND;
+@@ -1727,86 +1758,100 @@ done:
+     return rc;
+ }
+ 
+-int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, ReplicaId local_rid)
++int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, void *replica, ReplicaId local_rid)
+ {
+     int rc=RUV_SUCCESS;
+-    RUVElement *replica;
++    RUVElement *repl_ruv;
+     ReplicaId prim_rid;
++    Replica *repl_it = NULL;
++    size_t it = 0;
+ 
+-    CSN *prim_csn = get_thread_primary_csn();
++    CSNPL_CTX *prim_csn = get_thread_primary_csn();
+ 
+-    if (! csn_is_equal(csn, prim_csn)) {
++    if (! csn_primary(replica, csn, prim_csn)) {
+ 	/* not a primary csn, nothing to do */
+ 	return rc;
+     }
+-    slapi_rwlock_wrlock (ruv->lock);
++
++    /* first handle primary replica 
++     * there can be two ruv elements affected
++     */
+     prim_rid = csn_get_replicaid (csn);
+-    replica = ruvGetReplica (ruv, local_rid);
+-    rc = ruv_update_ruv_element(ruv, replica, csn, replica_purl, PR_TRUE);
+-    if ( rc || local_rid == prim_rid) goto done;
+-    replica = ruvGetReplica (ruv, prim_rid);
+-    rc = ruv_update_ruv_element(ruv, replica, csn, replica_purl, PR_FALSE);
+-done:
++    slapi_rwlock_wrlock (ruv->lock);
++    if ( local_rid != prim_rid) {
++	repl_ruv = ruvGetReplica (ruv, prim_rid);
++	rc = ruv_update_ruv_element(ruv, repl_ruv, prim_csn, replica_purl, PR_FALSE);
++    }
++    repl_ruv = ruvGetReplica (ruv, local_rid);
++    rc = ruv_update_ruv_element(ruv, repl_ruv, prim_csn, replica_purl, PR_TRUE);
+     slapi_rwlock_unlock (ruv->lock);
++    if (rc) return rc;
++
++    /* now handle secondary replicas */
++    for (it=0; it<prim_csn->repl_cnt; it++) {
++	repl_it = prim_csn->sec_repl[it];
++	replica_lock_replica(repl_it);
++	Object *ruv_obj = replica_get_ruv (repl_it);
++	RUV *ruv_it = object_get_data (ruv_obj);
++	slapi_rwlock_wrlock (ruv_it->lock);
++	repl_ruv = ruvGetReplica (ruv_it, replica_get_rid(repl_it));
++	rc = ruv_update_ruv_element(ruv_it, repl_ruv, prim_csn, replica_purl, PR_TRUE);
++	slapi_rwlock_unlock (ruv_it->lock);
++	replica_unlock_replica(repl_it);
++	if (rc) break;
++    }
+     return rc;
+ }
++
+ static int
+-ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSN *csn, const char *replica_purl, PRBool isLocal)
++ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSNPL_CTX *prim_csn, const char *replica_purl, PRBool isLocal)
+ {
+     int rc=RUV_SUCCESS;
+     char csn_str[CSN_STRSIZE];
+     CSN *max_csn;
+     CSN *first_csn = NULL;
+     
+-    if (replica == NULL)
+-    {
++    if (replica == NULL) {
+         /* we should have a ruv element at this point because it would have
+            been added by ruv_add_inprogress function */
+         slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "ruv_update_ruv - "
+-			            "Can't locate RUV element for replica %d\n", csn_get_replicaid (csn)); 
++                        "Can't locate RUV element for replica %d\n", csn_get_replicaid (prim_csn->prim_csn));
+         goto done;
+     } 
+ 
+-	if (csnplCommitAll(replica->csnpl, csn) != 0)
+-	{
+-		slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "ruv_update_ruv - Cannot commit csn %s\n",
+-			            csn_as_string(csn, PR_FALSE, csn_str));
++    if (csnplCommitAll(replica->csnpl, prim_csn) != 0) {
++        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "ruv_update_ruv - Cannot commit csn %s\n",
++                        csn_as_string(prim_csn->prim_csn, PR_FALSE, csn_str));
+         rc = RUV_CSNPL_ERROR;
+         goto done;
+-	}
+-    else
+-    {
++    } else {
+         if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
+             slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "ruv_update_ruv - "
+-                            "Successfully committed csn %s\n", csn_as_string(csn, PR_FALSE, csn_str));
++                            "Successfully committed csn %s\n", csn_as_string(prim_csn->prim_csn, PR_FALSE, csn_str));
+         }
+     }
+ 
+-	if ((max_csn = csnplRollUp(replica->csnpl, &first_csn)) != NULL)
+-	{
+-#ifdef DEBUG
+-		slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "ruv_update_ruv - Rolled up to csn %s\n",
+-			            csn_as_string(max_csn, PR_FALSE, csn_str)); /* XXXggood remove debugging */
+-#endif
++    if ((max_csn = csnplRollUp(replica->csnpl, &first_csn)) != NULL) {
++        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "ruv_update_ruv - Rolled up to csn %s\n",
++                        csn_as_string(max_csn, PR_FALSE, csn_str)); /* XXXggood remove debugging */
+         /* replica object sets min csn for local replica */
+-		if (!isLocal && replica->min_csn == NULL) {
+-		  /* bug 559223 - it seems that, under huge stress, a server might pass
+-		   * through this code when more than 1 change has already been sent and commited into
+-		   * the pending lists... Therefore, as we are trying to set the min_csn ever 
+-		   * generated by this replica, we need to set the first_csn as the min csn in the
+-		   * ruv */
+-		  set_min_csn_nolock(ruv, first_csn, replica_purl);
+-		}
+-		/* only update the max_csn in the RUV if it is greater than the existing one */
+-		rc = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, PR_TRUE /* must be greater */);
+-		/* It is possible that first_csn points to max_csn.
+-		   We need to free it once */
+-		if (max_csn != first_csn) {
+-			csn_free(&first_csn); 
+-		}
+-		csn_free(&max_csn);
+-	}
+-
++        if (!isLocal && replica->min_csn == NULL) {
++            /* bug 559223 - it seems that, under huge stress, a server might pass
++             * through this code when more than 1 change has already been sent and commited into
++             * the pending lists... Therefore, as we are trying to set the min_csn ever
++             * generated by this replica, we need to set the first_csn as the min csn in the
++             * ruv */
++        set_min_csn_nolock(ruv, first_csn, replica_purl);
++        }
++        /* only update the max_csn in the RUV if it is greater than the existing one */
++        rc = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, PR_TRUE /* must be greater */);
++        /* It is possible that first_csn points to max_csn.
++           We need to free it once */
++        if (max_csn != first_csn) {
++            csn_free(&first_csn);
++        }
++        csn_free(&max_csn);
++    }
+ done:
+ 
+     return rc;
+diff --git a/ldap/servers/plugins/replication/repl5_ruv.h b/ldap/servers/plugins/replication/repl5_ruv.h
+index c8960fd..f3cd38b 100644
+--- a/ldap/servers/plugins/replication/repl5_ruv.h
++++ b/ldap/servers/plugins/replication/repl5_ruv.h
+@@ -108,9 +108,9 @@ int ruv_to_bervals(const RUV *ruv, struct berval ***bvals);
+ PRInt32 ruv_replica_count (const RUV *ruv);
+ char **ruv_get_referrals(const RUV *ruv);
+ void ruv_dump(const RUV *ruv, char *ruv_name, PRFileDesc *prFile);
+-int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn);
+-int ruv_cancel_csn_inprogress (RUV *ruv, const CSN *csn, ReplicaId rid);
+-int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, ReplicaId local_rid);
++int ruv_add_csn_inprogress (void *repl, RUV *ruv, const CSN *csn);
++int ruv_cancel_csn_inprogress (void *repl, RUV *ruv, const CSN *csn, ReplicaId rid);
++int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, void *replica, ReplicaId local_rid);
+ int ruv_move_local_supplier_to_first(RUV *ruv, ReplicaId rid);
+ int ruv_get_first_id_and_purl(RUV *ruv, ReplicaId *rid, char **replica_purl );
+ int ruv_local_contains_supplier(RUV *ruv, ReplicaId rid);
+diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
+index 0836d66..3910dbe 100644
+--- a/ldap/servers/slapd/slapi-private.h
++++ b/ldap/servers/slapd/slapi-private.h
+@@ -193,7 +193,7 @@ const CSN *csn_max(const CSN *csn1,const CSN *csn2);
+    a csn from the set.*/
+ int csn_increment_subsequence (CSN *csn);
+ 
+-void csnplFreeCSN (void *arg);
++void csnplFreeCSNPL_CTX (void *arg);
+ /*
+  * csnset.c
+  */
+-- 
+2.9.4
+
diff --git a/SOURCES/0058-Ticket-49336-SECURITY-Locked-account-provides-differ.patch b/SOURCES/0058-Ticket-49336-SECURITY-Locked-account-provides-differ.patch
new file mode 100644
index 0000000..c110f0a
--- /dev/null
+++ b/SOURCES/0058-Ticket-49336-SECURITY-Locked-account-provides-differ.patch
@@ -0,0 +1,201 @@
+From 95b39e29361812a62f2e038c89a88d717c82794e Mon Sep 17 00:00:00 2001
+From: William Brown <firstyear@redhat.com>
+Date: Mon, 31 Jul 2017 14:13:49 +1000
+Subject: [PATCH] Ticket 49336 - SECURITY: Locked account provides different
+ return code
+
+Bug Description:  The directory server password lockout policy prevents binds
+ from operating once a threshold of failed passwords has been met. During
+ this lockout, if you bind with a successful password, a different error code
+ is returned. This means that an attacker has no ratelimit or penalty during
+ an account lock, and can continue to attempt passwords via bruteforce, using
+ the change in return code to ascertain a sucessful password auth.
+
+Fix Description:  Move the account lock check *before* the password bind
+check. If the account is locked, we do not mind disclosing this as the
+attacker will either ignore it (and will not bind anyway), or they will
+be forced to back off as the attack is not working preventing the
+bruteforce.
+
+https://pagure.io/389-ds-base/issue/49336
+
+Author: wibrown
+
+Review by: tbordaz (Thanks!)
+
+Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
+---
+ .../suites/password/pwd_lockout_bypass_test.py     | 55 ++++++++++++++++++++++
+ ldap/servers/slapd/bind.c                          | 29 ++++++++----
+ ldap/servers/slapd/pw_verify.c                     | 15 +++---
+ 3 files changed, 84 insertions(+), 15 deletions(-)
+ create mode 100644 dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py
+
+diff --git a/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py b/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py
+new file mode 100644
+index 0000000..e4add72
+--- /dev/null
++++ b/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py
+@@ -0,0 +1,55 @@
++# --- BEGIN COPYRIGHT BLOCK ---
++# Copyright (C) 2017 Red Hat, Inc.
++# All rights reserved.
++#
++# License: GPL (version 3 or any later version).
++# See LICENSE for details.
++# --- END COPYRIGHT BLOCK ---
++#
++import pytest
++from lib389.tasks import *
++from lib389.utils import *
++from lib389.topologies import topology_st
++from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES
++import ldap
++
++# The irony of these names is not lost on me.
++GOOD_PASSWORD = 'password'
++BAD_PASSWORD = 'aontseunao'
++
++logging.getLogger(__name__).setLevel(logging.INFO)
++log = logging.getLogger(__name__)
++
++def test_lockout_bypass(topology_st):
++    inst = topology_st.standalone
++
++    # Configure the lock policy
++    inst.config.set('passwordMaxFailure', '1')
++    inst.config.set('passwordLockoutDuration', '99999')
++    inst.config.set('passwordLockout', 'on')
++
++    # Create the account
++    users = UserAccounts(inst, DEFAULT_SUFFIX)
++    testuser = users.create(properties=TEST_USER_PROPERTIES)
++    testuser.set('userPassword', GOOD_PASSWORD)
++
++    conn = testuser.bind(GOOD_PASSWORD)
++    assert conn != None
++    conn.unbind_s()
++
++    # Bind with bad creds twice
++    # This is the failure.
++    with pytest.raises(ldap.INVALID_CREDENTIALS):
++        conn = testuser.bind(BAD_PASSWORD)
++    # Now we should not be able to ATTEMPT the bind. It doesn't matter that
++    # we disclose that we have hit the rate limit here, what matters is that
++    # it exists.
++    with pytest.raises(ldap.CONSTRAINT_VIOLATION):
++        conn = testuser.bind(BAD_PASSWORD)
++
++    # now bind with good creds
++    # Should be error 19 still.
++    with pytest.raises(ldap.CONSTRAINT_VIOLATION):
++        conn = testuser.bind(GOOD_PASSWORD)
++
++
+diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
+index 7f4414f..064ace1 100644
+--- a/ldap/servers/slapd/bind.c
++++ b/ldap/servers/slapd/bind.c
+@@ -662,12 +662,14 @@ do_bind( Slapi_PBlock *pb )
+         /* We could be serving multiple database backends.  Select the appropriate one */
+         /* pw_verify_be_dn will select the backend we need for us. */
+ 
+-        if (auto_bind) {
+-            /* We have no password material. We should just check who we are binding as. */
+-            rc = pw_validate_be_dn(pb, &referral);
+-        } else {
+-            rc = pw_verify_be_dn(pb, &referral);
+-        }
++        /*
++         * WARNING: We have to validate *all* other conditions *first* before
++         * we attempt the bind!
++         *
++         * this is because ldbm_bind.c will SEND THE FAILURE.
++         */
++
++        rc = pw_validate_be_dn(pb, &referral);
+ 
+         if (rc == SLAPI_BIND_NO_BACKEND) {
+             send_nobackend_ldap_result( pb );
+@@ -736,8 +738,18 @@ do_bind( Slapi_PBlock *pb )
+                     myrc = 0;
+                 }
+                 if (!auto_bind) {
+-                    /* 
+-                     * There could be a race that bind_target_entry was not added 
++                    /*
++                     * Okay, we've made it here. FINALLY check if the entry really
++                     * can bind or not. THIS IS THE PASSWORD CHECK.
++                     */
++                    rc = pw_verify_be_dn(pb, &referral);
++                    if (rc != SLAPI_BIND_SUCCESS) {
++                        /* Invalid pass - lets bail ... */
++                        goto bind_failed;
++                    }
++
++                    /*
++                     * There could be a race that bind_target_entry was not added
+                      * when bind_target_entry was retrieved before be_bind, but it
+                      * was in be_bind.  Since be_bind returned SLAPI_BIND_SUCCESS,
+                      * the entry is in the DS.  So, we need to retrieve it once more.
+@@ -786,6 +798,7 @@ do_bind( Slapi_PBlock *pb )
+                 }
+             }
+         } else { /* if auto_bind || rc == slapi_bind_success | slapi_bind_anonymous */
++        bind_failed:
+             if (rc == LDAP_OPERATIONS_ERROR) {
+                 send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Function not implemented", 0, NULL );
+                 goto free_and_return;
+diff --git a/ldap/servers/slapd/pw_verify.c b/ldap/servers/slapd/pw_verify.c
+index 852b027..cb182ed 100644
+--- a/ldap/servers/slapd/pw_verify.c
++++ b/ldap/servers/slapd/pw_verify.c
+@@ -55,7 +55,7 @@ pw_verify_root_dn(const char *dn, const Slapi_Value *cred)
+ int
+ pw_verify_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
+ {
+-    int rc = 0;
++    int rc = SLAPI_BIND_SUCCESS;
+     Slapi_Backend *be = NULL;
+ 
+     if (slapi_mapping_tree_select(pb, &be, referral, NULL, 0) != LDAP_SUCCESS) {
+@@ -109,14 +109,10 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
+     slapi_pblock_get(pb, SLAPI_BIND_CREDENTIALS, &cred);
+     slapi_pblock_get(pb, SLAPI_BIND_METHOD, &method);
+ 
+-    if (pb_sdn != NULL || cred != NULL) {
++    if (pb_sdn == NULL) {
+         return LDAP_OPERATIONS_ERROR;
+     }
+ 
+-    if (*referral) {
+-        return SLAPI_BIND_REFERRAL;
+-    }
+-
+     /* We need a slapi_sdn_isanon? */
+     if (method == LDAP_AUTH_SIMPLE && cred->bv_len == 0) {
+         return SLAPI_BIND_ANONYMOUS;
+@@ -130,7 +126,11 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
+     if (slapi_mapping_tree_select(pb, &be, referral, NULL, 0) != LDAP_SUCCESS) {
+         return SLAPI_BIND_NO_BACKEND;
+     }
+-    slapi_be_Unlock(be);
++
++    if (*referral) {
++        slapi_be_Unlock(be);
++        return SLAPI_BIND_REFERRAL;
++    }
+ 
+     slapi_pblock_set(pb, SLAPI_BACKEND, be);
+     slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
+@@ -138,6 +138,7 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
+     set_db_default_result_handlers(pb);
+ 
+     /* The backend associated with this identity is real. */
++    slapi_be_Unlock(be);
+ 
+     return SLAPI_BIND_SUCCESS;
+ }
+-- 
+2.9.4
+
diff --git a/SOURCES/0059-Ticket-49298-force-sync-on-shutdown.patch b/SOURCES/0059-Ticket-49298-force-sync-on-shutdown.patch
new file mode 100644
index 0000000..4d900fb
--- /dev/null
+++ b/SOURCES/0059-Ticket-49298-force-sync-on-shutdown.patch
@@ -0,0 +1,177 @@
+From ba30cc562f5ebd58955502a19edbf9720a45b655 Mon Sep 17 00:00:00 2001
+From: Mark Reynolds <mreynolds@redhat.com>
+Date: Tue, 8 Aug 2017 13:02:53 -0400
+Subject: [PATCH] Ticket 49298 - force sync() on shutdown
+
+        Bug Description:  During shutdown on xfs we would occasionally
+        see a broke dse.ldif (specifically, empty). This happens due to
+        a bug in xfs where the directory isn't synced on rename().
+
+        Fix Description:  As we shutdown call sync() to force all our
+        writes to disk - dse.ldif, logs, db, all of it.
+
+        https://pagure.io/389-ds-base/issue/49298
+---
+ ldap/servers/slapd/dse.c  | 59 +++++++++++++++++++++++++++++------------------
+ ldap/servers/slapd/main.c |  9 ++++----
+ 2 files changed, 42 insertions(+), 26 deletions(-)
+
+diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
+index 5715c83..fa1aacc 100644
+--- a/ldap/servers/slapd/dse.c
++++ b/ldap/servers/slapd/dse.c
+@@ -40,6 +40,8 @@
+ #include "slap.h"
+ #include <pwd.h>
+ 
++#include <unistd.h> /* provides fsync/close */
++
+ /* #define SLAPI_DSE_DEBUG */ 	/* define this to force trace log	*/
+ 								/* messages to always be logged		*/
+ 
+@@ -72,11 +74,11 @@
+ struct dse_callback
+ {
+     int operation;
+-	int flags;
+-	Slapi_DN *base;
+-	int scope;
+-	char *filter;				/* NULL means match all entries */
+-    Slapi_Filter *slapifilter;	/* NULL means match all entries */
++    int flags;
++    Slapi_DN *base;
++    int scope;
++    char *filter;               /* NULL means match all entries */
++    Slapi_Filter *slapifilter;  /* NULL means match all entries */
+     int (*fn)(Slapi_PBlock *,Slapi_Entry *,Slapi_Entry *,int*,char*,void *);
+     void *fn_arg;
+     struct slapdplugin *plugin;
+@@ -89,13 +91,14 @@ struct dse
+     char *dse_tmpfile; /* and written to when changes are made via LDAP */
+     char *dse_fileback; /* contain the latest info, just before a new change */
+     char *dse_filestartOK; /* contain the latest info with which the server has successfully started */
++    char *dse_configdir; /* The location of config files - allows us to fsync the dir post rename */
+     Avlnode *dse_tree;
+     struct dse_callback *dse_callback;
+     Slapi_RWLock *dse_rwlock; /* a read-write lock to protect the whole dse backend */
+-	char **dse_filelist; /* these are additional read only files used to */
+-						 /* initialize the dse */
+-	int  dse_is_updateable; /* if non-zero, this DSE can be written to */
+-	int  dse_readonly_error_reported; /* used to ensure that read-only errors are logged only once */
++    char **dse_filelist; /* these are additional read only files used to */
++                         /* initialize the dse */
++    int  dse_is_updateable; /* if non-zero, this DSE can be written to */
++    int  dse_readonly_error_reported; /* used to ensure that read-only errors are logged only once */
+ };
+ 
+ struct dse_node
+@@ -361,37 +364,39 @@ dse_new( char *filename, char *tmpfilename, char *backfilename, char *startokfil
+ 			if (!strstr(filename, realconfigdir))
+ 			{
+ 				pdse->dse_filename = slapi_ch_smprintf("%s/%s", realconfigdir, filename );
+-			}
+-			else
++			} else {
+ 				pdse->dse_filename = slapi_ch_strdup(filename);
++			}
+ 
+ 			if (!strstr(tmpfilename, realconfigdir)) {
+ 				pdse->dse_tmpfile = slapi_ch_smprintf("%s/%s", realconfigdir, tmpfilename );
+-			}
+-			else
++			} else {
+ 				pdse->dse_tmpfile = slapi_ch_strdup(tmpfilename);
++			}
++
++			pdse->dse_configdir = slapi_ch_strdup(realconfigdir);
+ 
+ 			if ( backfilename != NULL )
+ 			{
+ 				if (!strstr(backfilename, realconfigdir)) {
+ 					pdse->dse_fileback = slapi_ch_smprintf("%s/%s", realconfigdir, backfilename );
+-				}
+-				else
++				} else {
+ 					pdse->dse_fileback = slapi_ch_strdup(backfilename);
+-			}
+-			else
++				}
++			} else {
+ 				pdse->dse_fileback = NULL;
++            }
+ 
+ 			if ( startokfilename != NULL )
+ 			{
+ 				if (!strstr(startokfilename, realconfigdir)) {
+ 					pdse->dse_filestartOK = slapi_ch_smprintf("%s/%s", realconfigdir, startokfilename );
+-				}
+-				else
++				} else {
+ 					pdse->dse_filestartOK = slapi_ch_strdup(startokfilename);
+-			}
+-			else
++				}
++			} else {
+ 				pdse->dse_filestartOK = NULL;
++			}
+ 
+ 			pdse->dse_tree= NULL;
+ 			pdse->dse_callback= NULL;
+@@ -440,6 +445,7 @@ dse_destroy(struct dse *pdse)
+     slapi_ch_free((void **)&(pdse->dse_tmpfile));
+     slapi_ch_free((void **)&(pdse->dse_fileback));
+     slapi_ch_free((void **)&(pdse->dse_filestartOK));
++    slapi_ch_free((void **)&(pdse->dse_configdir));
+     dse_callback_deletelist(&pdse->dse_callback);
+     charray_free(pdse->dse_filelist);
+     nentries = avl_free(pdse->dse_tree, dse_internal_delete_entry);
+@@ -991,8 +997,9 @@ dse_write_file_nolock(struct dse* pdse)
+     FPWrapper	fpw;
+     int rc = 0;
+ 
+-	if (dont_ever_write_dse_files)
++	if (dont_ever_write_dse_files) {
+ 		return rc;
++	}
+ 
+     fpw.fpw_rc = 0;
+ 	fpw.fpw_prfd = NULL;
+@@ -1042,6 +1049,14 @@ dse_write_file_nolock(struct dse* pdse)
+ 							pdse->dse_tmpfile, pdse->dse_filename,
+ 							rc, slapd_system_strerror( rc ));
+                 }
++				/*
++				 * We have now written to the tmp location, and renamed it
++				 * we need to open and fsync the dir to make the rename stick.
++				 */
++				int fp_configdir = open(pdse->dse_configdir, O_PATH | O_DIRECTORY);
++				fsync(fp_configdir);
++				close(fp_configdir);
++
+             }
+         }
+ 		if (fpw.fpw_prfd)
+diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
+index ba1f5e8..3351464 100644
+--- a/ldap/servers/slapd/main.c
++++ b/ldap/servers/slapd/main.c
+@@ -1154,11 +1154,12 @@ cleanup:
+ 	ndn_cache_destroy();
+ 	NSS_Shutdown();
+ 	PR_Cleanup();
+-#if defined( hpux )
+-	exit( return_value );
+-#else
++	/*
++	 * Server has stopped, lets force everything to disk: logs
++	 * db, dse.ldif, all of it.
++	 */
++	sync();
+ 	return return_value;
+-#endif
+ }
+ 
+ 
+-- 
+2.9.4
+
diff --git a/SOURCES/0060-Ticket-49334-fix-backup-restore-if-changelog-exists.patch b/SOURCES/0060-Ticket-49334-fix-backup-restore-if-changelog-exists.patch
new file mode 100644
index 0000000..25d4010
--- /dev/null
+++ b/SOURCES/0060-Ticket-49334-fix-backup-restore-if-changelog-exists.patch
@@ -0,0 +1,37 @@
+From c903f66194f04e97fc684f5a9654cedb27530931 Mon Sep 17 00:00:00 2001
+From: Ludwig Krispenz <lkrispen@redhat.com>
+Date: Mon, 31 Jul 2017 10:51:08 +0200
+Subject: [PATCH 1/3] Ticket 49334 - fix backup restore if changelog exists
+
+The corrcect flag to copy a directory in backup/restore must be passed for the changelog directory
+
+Reviewed by: William, thanks
+---
+ ldap/servers/slapd/back-ldbm/dblayer.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
+index ff97aa4..3a97f2f 100644
+--- a/ldap/servers/slapd/back-ldbm/dblayer.c
++++ b/ldap/servers/slapd/back-ldbm/dblayer.c
+@@ -6143,7 +6143,7 @@ dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task)
+             return_value = dblayer_copy_directory(li, task, changelogdir,
+                                                   changelog_destdir,
+                                                   0 /* backup */,
+-                                                  &cnt, 1, 0, 0);
++                                                  &cnt, 0, 0, 1);
+             if (return_value) {
+                 slapi_log_err(SLAPI_LOG_ERR,
+                           "dblayer_backup", "Error in copying directory "
+@@ -6823,7 +6823,7 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char *
+                     *cldirname = '\0';
+                     return_value = dblayer_copy_directory(li, task, filename1,
+                                                           changelogdir, 1 /* restore */,
+-                                                          &cnt, 1, 0 ,0);
++                                                          &cnt, 0, 0 ,1);
+                     *cldirname = '/';
+                     if (return_value) {
+                         slapi_log_err(SLAPI_LOG_ERR,
+-- 
+2.9.4
+
diff --git a/SOURCES/0061-Ticket-49356-mapping-tree-crash-can-occur-during-tot.patch b/SOURCES/0061-Ticket-49356-mapping-tree-crash-can-occur-during-tot.patch
new file mode 100644
index 0000000..23540e5
--- /dev/null
+++ b/SOURCES/0061-Ticket-49356-mapping-tree-crash-can-occur-during-tot.patch
@@ -0,0 +1,502 @@
+From b0954a5df7841330732a5ab532c528a68cf380cf Mon Sep 17 00:00:00 2001
+From: William Brown <firstyear@redhat.com>
+Date: Fri, 18 Aug 2017 13:00:46 +1000
+Subject: [PATCH] Ticket 49356 - mapping tree crash can occur during tot init
+
+Bug Description:  Two faults were found in the handling of the mapping
+tree of 389 directory server. The first fault was that the tree-free
+check was not performed atomically and may cause an incorrect operations
+error to be returned. The second was that during a total init the referral
+would not lock the be, but the pw_verify code assumed a be was locked.
+This caused a segfault.
+
+Fix Description:  Fix the freed check to use atomics. Fix the pw_verify
+to assert be is NULL (which is correct, there is no backend).
+
+https://pagure.io/389-ds-base/issue/49356
+
+Author: wibrown
+
+Review by: mreynolds (THanks!)
+---
+ .../mapping_tree/referral_during_tot_init.py       |  57 ++++++++
+ ldap/servers/slapd/fedse.c                         |  10 ++
+ ldap/servers/slapd/main.c                          |  10 --
+ ldap/servers/slapd/mapping_tree.c                  | 150 +++++++++++----------
+ ldap/servers/slapd/pw_verify.c                     |   8 +-
+ 5 files changed, 150 insertions(+), 85 deletions(-)
+ create mode 100644 dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py
+
+diff --git a/dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py b/dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py
+new file mode 100644
+index 0000000..e5aee7d
+--- /dev/null
++++ b/dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py
+@@ -0,0 +1,57 @@
++# --- BEGIN COPYRIGHT BLOCK ---
++# Copyright (C) 2017 Red Hat, Inc.
++# All rights reserved.
++#
++# License: GPL (version 3 or any later version).
++# See LICENSE for details.
++# --- END COPYRIGHT BLOCK ---
++#
++import ldap
++import pytest
++from lib389.topologies import topology_m2
++from lib389._constants import (DEFAULT_SUFFIX, HOST_MASTER_2, PORT_MASTER_2, TASK_WAIT)
++
++from lib389.idm.user import (TEST_USER_PROPERTIES, UserAccounts)
++
++def test_referral_during_tot(topology_m2):
++
++    master1 = topology_m2.ms["master1"]
++    master2 = topology_m2.ms["master2"]
++
++    # Create a bunch of entries on master1
++    ldif_dir = master1.get_ldif_dir()
++    import_ldif = ldif_dir + '/ref_during_tot_import.ldif'
++    master1.buildLDIF(10000, import_ldif)
++
++    master1.stop()
++    try:
++        master1.ldif2db(bename=None, excludeSuffixes=None, encrypt=False, suffixes=[DEFAULT_SUFFIX], import_file=import_ldif)
++    except:
++        pass
++    # master1.tasks.importLDIF(suffix=DEFAULT_SUFFIX, input_file=import_ldif, args={TASK_WAIT: True})
++    master1.start()
++    users = UserAccounts(master1, DEFAULT_SUFFIX, rdn='ou=Accounting')
++
++    u = users.create(properties=TEST_USER_PROPERTIES)
++    u.set('userPassword', 'password')
++
++    binddn = u.dn
++    bindpw = 'password'
++
++    # Now export them to master2
++    master1.agreement.init(DEFAULT_SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
++
++    # While that's happening try to bind as a user to master 2
++    # This should trigger the referral code.
++    for i in range(0, 100):
++        conn = ldap.initialize(master2.toLDAPURL())
++        conn.set_option(ldap.OPT_REFERRALS, False)
++        try:
++            conn.simple_bind_s(binddn, bindpw)
++            conn.unbind_s()
++        except ldap.REFERRAL:
++            pass
++
++    # Done.
++
++
+diff --git a/ldap/servers/slapd/fedse.c b/ldap/servers/slapd/fedse.c
+index 13a3c74..c2a862b 100644
+--- a/ldap/servers/slapd/fedse.c
++++ b/ldap/servers/slapd/fedse.c
+@@ -1853,6 +1853,16 @@ setup_internal_backends(char *configdir)
+ 		be_addsuffix(be,&monitor);
+ 		be_addsuffix(be,&config);
+ 
++        /*
++         * Now that the be's are in place, we can
++         * setup the mapping tree.
++         */
++
++        if (mapping_tree_init()) {
++            slapi_log_err(SLAPI_LOG_EMERG, "setup_internal_backends", "Failed to init mapping tree\n");
++            exit(1);
++        }
++
+ 		add_internal_entries();
+ 
+ 		add_easter_egg_entry();
+diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
+index 552d54d..1d9afce 100644
+--- a/ldap/servers/slapd/main.c
++++ b/ldap/servers/slapd/main.c
+@@ -1034,16 +1034,6 @@ main( int argc, char **argv)
+ 
+ 		ps_init_psearch_system();   /* must come before plugin_startall() */
+ 
+-		/* Initailize the mapping tree */
+-
+-		if (mapping_tree_init())
+-		{
+-			slapi_log_err(SLAPI_LOG_EMERG, "main", "Failed to init mapping tree\n");
+-			return_value = 1;
+-			goto cleanup;
+-		}
+-
+-
+ 		/* initialize UniqueID generator - must be done once backends are started
+ 		   and event queue is initialized but before plugins are started */
+ 		/* Note: This DN is no need to be normalized. */
+diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
+index 1b8d2d9..dfb6584 100644
+--- a/ldap/servers/slapd/mapping_tree.c
++++ b/ldap/servers/slapd/mapping_tree.c
+@@ -88,13 +88,13 @@ struct mt_node
+  *      release backend lock 
+  *
+  */
+-static Slapi_RWLock    *myLock;    /* global lock on the mapping tree structures */
++static Slapi_RWLock *myLock = NULL; /* global lock on the mapping tree structures */
+ 
+ 
+ static mapping_tree_node *mapping_tree_root = NULL;
+-static int mapping_tree_inited = 0;
+-static int mapping_tree_freed = 0;
+-static int extension_type = -1;    /* type returned from the factory */
++static int32_t mapping_tree_inited = 0;
++static int32_t mapping_tree_freed = 0;
++static int extension_type = -1; /* type returned from the factory */
+ 
+ /* The different states a mapping tree node can be in. */
+ #define    MTN_DISABLED                 0    /* The server acts like the node isn't there. */
+@@ -1659,22 +1659,24 @@ add_internal_mapping_tree_node(const char *subtree, Slapi_Backend *be, mapping_t
+ {
+     Slapi_DN *dn;
+     mapping_tree_node *node;
+-    backend ** be_list = (backend **) slapi_ch_malloc(sizeof(backend *));
++    backend **be_list = (backend **)slapi_ch_malloc(sizeof(backend *));
++    int *be_states = (int *)slapi_ch_malloc(sizeof(int));
+ 
+     be_list[0] = be;
++    be_states[0] = SLAPI_BE_STATE_ON;
+ 
+     dn = slapi_sdn_new_dn_byval(subtree);
+-    node= mapping_tree_node_new(
+-            dn,
+-            be_list,
+-            NULL, /* backend_name */
+-            NULL,
+-            1,    /* number of backends at this node */
+-            1,    /* size of backend list structure */
+-            NULL, /* referral */
+-            parent,
+-            MTN_BACKEND,
+-            1, /* The config  node is a private node.
++    node = mapping_tree_node_new(
++        dn,
++        be_list,
++        NULL, /* backend_name */
++        be_states, /* be state */
++        1,    /* number of backends at this node */
++        1,    /* size of backend list structure */
++        NULL, /* referral */
++        parent,
++        MTN_BACKEND,
++        1,                    /* The config  node is a private node.
+                 *  People can't see or change it. */
+             NULL, NULL, NULL, 0); /* no distribution */
+     return node;
+@@ -1722,17 +1724,20 @@ mapping_tree_init()
+     
+     /* we call this function from a single thread, so it should be ok */
+ 
+-    if(mapping_tree_freed){
+-    /* shutdown has been detected */
+-      return 0;
+-    }
+-
+-    if (mapping_tree_inited)
++    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
++        /* shutdown has been detected */
+         return 0;
++    }
+ 
+-    /* ONREPL - I have moved this up because otherwise we can endup calling this 
++    /* ONREPL - I have moved this up because otherwise we can endup calling this
+      * function recursively */
++    if (myLock != NULL) {
++        return 0;
++    }
++    myLock = slapi_new_rwlock();
++    slapi_rwlock_wrlock(myLock);
+ 
++    /* Should be fenced by the rwlock. */
+     mapping_tree_inited = 1;
+ 
+     slapi_register_supported_control(MTN_CONTROL_USE_ONE_BACKEND_OID,
+@@ -1740,10 +1745,8 @@ mapping_tree_init()
+     slapi_register_supported_control(MTN_CONTROL_USE_ONE_BACKEND_EXT_OID,
+                      SLAPI_OPERATION_SEARCH);
+ 
+-    myLock = slapi_new_rwlock();
+-
+-    be= slapi_be_select_by_instance_name(DSE_BACKEND);
+-    mapping_tree_root= add_internal_mapping_tree_node("", be, NULL);
++    be = slapi_be_select_by_instance_name(DSE_BACKEND);
++    mapping_tree_root = add_internal_mapping_tree_node("", be, NULL);
+ 
+     /* We also need to add the config and schema backends to the mapping tree.
+      * They are special in that users will not know about it's node in the 
+@@ -1757,17 +1760,23 @@ mapping_tree_init()
+     node= add_internal_mapping_tree_node("cn=schema", be, mapping_tree_root);
+     mapping_tree_node_add_child(mapping_tree_root, node);
+ 
+-    /* 
++    slapi_rwlock_unlock(myLock);
++
++    /*
+      * Now we need to look under cn=mapping tree, cn=config to find the rest
+      * of the mapping tree entries.
+      * Builds the mapping tree from entries in the DIT.  This function just
+      * calls mapping_tree_node_get_children with the special case for the
+      * root node.
+      */
+-    if (mapping_tree_node_get_children(mapping_tree_root, 1))
++
++    if (mapping_tree_node_get_children(mapping_tree_root, 1)) {
+         return -1;
++    }
+ 
++    slapi_rwlock_wrlock(myLock);
+     mtn_create_extension(mapping_tree_root);
++    slapi_rwlock_unlock(myLock);
+ 
+     /* setup the dse callback functions for the ldbm instance config entry */
+     {
+@@ -1840,8 +1849,8 @@ mapping_tree_free ()
+      */ 
+     slapi_unregister_backend_state_change_all();
+     /* recursively free tree nodes */
+-    mtn_free_node (&mapping_tree_root);
+-    mapping_tree_freed = 1;
++    mtn_free_node(&mapping_tree_root);
++    __atomic_store_4(&mapping_tree_freed, 1, __ATOMIC_RELAXED);
+ }
+ 
+ /* This function returns the first node to parse when a search is done 
+@@ -2083,14 +2092,12 @@ int slapi_dn_write_needs_referral(Slapi_DN *target_sdn, Slapi_Entry **referral)
+     mapping_tree_node *target_node = NULL;
+     int ret = 0;
+ 
+-    if(mapping_tree_freed){
++    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
+         /* shutdown detected */
+         goto done;
+     }
+ 
+-    if(!mapping_tree_inited) {
+-        mapping_tree_init();
+-    }
++    PR_ASSERT(mapping_tree_inited == 1);
+ 
+     if (target_sdn) {
+         mtn_lock();
+@@ -2157,8 +2164,8 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
+     int fixup = 0;
+     
+ 
+-    if(mapping_tree_freed){
+-        /* shutdown detected */ 
++    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
++        /* shutdown detected */
+         return LDAP_OPERATIONS_ERROR;
+     }
+ 
+@@ -2175,9 +2182,7 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
+     target_sdn = operation_get_target_spec (op);
+     fixup = operation_is_flag_set(op, OP_FLAG_TOMBSTONE_FIXUP);
+ 
+-    if(!mapping_tree_inited) {
+-        mapping_tree_init();
+-    } 
++    PR_ASSERT(mapping_tree_inited == 1);
+ 
+     be[0] = NULL;
+     if (referral) {
+@@ -2188,8 +2193,9 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
+ 
+     /* Get the mapping tree node that is the best match for the target dn. */
+     target_node = slapi_get_mapping_tree_node_by_dn(target_sdn);
+-    if (target_node == NULL)
++    if (target_node == NULL) {
+         target_node = mapping_tree_root;
++    }
+ 
+     /* The processing of the base scope root DSE search and all other LDAP operations on "" 
+      *  will be transferred to the internal DSE backend 
+@@ -2266,8 +2272,8 @@ int slapi_mapping_tree_select_all(Slapi_PBlock *pb, Slapi_Backend **be_list,
+     Slapi_DN *sdn = NULL;
+     int flag_partial_result = 0;
+     int op_type;
+-    
+-    if(mapping_tree_freed){
++
++    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
+         return LDAP_OPERATIONS_ERROR;
+     }
+ 
+@@ -2287,9 +2293,7 @@ int slapi_mapping_tree_select_all(Slapi_PBlock *pb, Slapi_Backend **be_list,
+     slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &op_type);
+     slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &scope);
+ 
+-    if(!mapping_tree_inited){
+-        mapping_tree_init();
+-    } 
++    PR_ASSERT(mapping_tree_inited == 1);
+ 
+     mtn_lock();
+ 
+@@ -2448,8 +2452,8 @@ int slapi_mapping_tree_select_and_check(Slapi_PBlock *pb,char *newdn, Slapi_Back
+     Slapi_Operation *op;
+     int ret;
+     int need_unlock = 0;
+-    
+-    if(mapping_tree_freed){
++
++    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
+         return LDAP_OPERATIONS_ERROR;
+      }
+ 
+@@ -2635,7 +2639,7 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
+     int flag_stop = 0;
+     struct slapi_componentid *cid = NULL;
+ 
+-    if(mapping_tree_freed){
++    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
+         /* shut down detected */
+         return LDAP_OPERATIONS_ERROR; 
+     }
+@@ -2719,21 +2723,22 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
+                     } else {
+                         /* This MTN has not been linked to its backend
+                          * instance yet. */
+-                        target_node->mtn_be[*index] =
+-                            slapi_be_select_by_instance_name(
+-                                target_node->mtn_backend_names[*index]);
+-                        *be = target_node->mtn_be[*index];
+-                        if(*be==NULL) {
+-                            slapi_log_err(SLAPI_LOG_BACKLDBM, "mtn_get_be",
+-                                "Warning: Mapping tree node entry for %s "
+-                                "point to an unknown backend : %s\n",
+-                                slapi_sdn_get_dn(target_node->mtn_subtree),
+-                                target_node->mtn_backend_names[*index]);
+-                            /* Well there's still not backend instance for
+-                             * this MTN, so let's have the default backend
+-                             * deal with this.
+-                             */
+-                            *be = defbackend_get_backend();
++                        /* WARNING: internal memory dse backends don't provide NAMES */
++                        if (target_node->mtn_backend_names != NULL) {
++                            target_node->mtn_be[*index] = slapi_be_select_by_instance_name(target_node->mtn_backend_names[*index]);
++                            *be = target_node->mtn_be[*index];
++                            if (*be == NULL) {
++                                slapi_log_err(SLAPI_LOG_BACKLDBM, "mtn_get_be",
++                                              "Warning: Mapping tree node entry for %s "
++                                              "point to an unknown backend : %s\n",
++                                              slapi_sdn_get_dn(target_node->mtn_subtree),
++                                              target_node->mtn_backend_names[*index]);
++                                /* Well there's still not backend instance for
++                                 * this MTN, so let's have the default backend
++                                 * deal with this.
++                                 */
++                                *be = defbackend_get_backend();
++                            }
+                         }
+                     }
+                 }
+@@ -2745,10 +2750,11 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
+             result = LDAP_OPERATIONS_ERROR;
+                     *be = defbackend_get_backend();
+                 }
+-                if (flag_stop)
++                if (flag_stop) {
+                     *index = SLAPI_BE_NO_BACKEND;
+-                else
++                } else {
+                     (*index)++;
++                }
+             }
+         }        
+     } else {
+@@ -2822,7 +2828,7 @@ static mapping_tree_node *best_matching_child(mapping_tree_node *parent,
+     mapping_tree_node *highest_match_node = NULL;
+     mapping_tree_node *current;
+ 
+-    if(mapping_tree_freed){
++    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
+         /* shutdown detected */
+         return NULL;
+     }
+@@ -2849,7 +2855,7 @@ mtn_get_mapping_tree_node_by_entry(mapping_tree_node* node, const Slapi_DN *dn)
+ {
+     mapping_tree_node *found_node = NULL;
+ 
+-    if(mapping_tree_freed){
++    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
+         /* shutdown detected */
+         return NULL;
+     }
+@@ -2895,7 +2901,7 @@ slapi_get_mapping_tree_node_by_dn(const Slapi_DN *dn)
+     mapping_tree_node *current_best_match = mapping_tree_root;
+     mapping_tree_node *next_best_match = mapping_tree_root;
+ 
+-    if(mapping_tree_freed){
++    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
+         /* shutdown detected */
+         return NULL;
+     }
+@@ -2929,7 +2935,7 @@ get_mapping_tree_node_by_name(mapping_tree_node * node, char * be_name)
+     int i;
+     mapping_tree_node *found_node = NULL;
+ 
+-    if(mapping_tree_freed){
++    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
+         /* shutdown detected */
+         return NULL;
+     }
+@@ -2980,7 +2986,7 @@ slapi_get_mapping_tree_node_configdn (const Slapi_DN *root)
+ {
+     char *dn = NULL;
+ 
+-    if(mapping_tree_freed){
++    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
+         /* shutdown detected */
+         return NULL;
+     }
+@@ -3007,7 +3013,7 @@ slapi_get_mapping_tree_node_configsdn (const Slapi_DN *root)
+     char *dn = NULL;
+     Slapi_DN *sdn = NULL;
+ 
+-    if(mapping_tree_freed){
++    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
+         /* shutdown detected */
+         return NULL;
+     }
+diff --git a/ldap/servers/slapd/pw_verify.c b/ldap/servers/slapd/pw_verify.c
+index cb182ed..1f0c18a 100644
+--- a/ldap/servers/slapd/pw_verify.c
++++ b/ldap/servers/slapd/pw_verify.c
+@@ -58,12 +58,14 @@ pw_verify_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
+     int rc = SLAPI_BIND_SUCCESS;
+     Slapi_Backend *be = NULL;
+ 
+-    if (slapi_mapping_tree_select(pb, &be, referral, NULL, 0) != LDAP_SUCCESS) {
++    int mt_result = slapi_mapping_tree_select(pb, &be, referral, NULL, 0);
++    if (mt_result != LDAP_SUCCESS) {
+         return SLAPI_BIND_NO_BACKEND;
+     }
+ 
+     if (*referral) {
+-        slapi_be_Unlock(be);
++        /* If we have a referral, this is NULL */
++        PR_ASSERT(be == NULL);
+         return SLAPI_BIND_REFERRAL;
+     }
+ 
+@@ -128,7 +130,7 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
+     }
+ 
+     if (*referral) {
+-        slapi_be_Unlock(be);
++        PR_ASSERT(be == NULL);
+         return SLAPI_BIND_REFERRAL;
+     }
+ 
+-- 
+2.9.4
+
diff --git a/SPECS/389-ds-base.spec b/SPECS/389-ds-base.spec
index f8c6789..fd533d0 100644
--- a/SPECS/389-ds-base.spec
+++ b/SPECS/389-ds-base.spec
@@ -7,8 +7,6 @@
 # also need the relprefix field for a pre-release e.g. .0 - also comment out for official release
 #% global relprefix 0.
 
-%global use_openldap 1
-%global use_db4 0
 # If perl-Socket-2.000 or newer is available, set 0 to use_Socket6.
 %global use_Socket6 0
 %global use_nunc_stans 1
@@ -32,7 +30,7 @@
 Summary:          389 Directory Server (base)
 Name:             389-ds-base
 Version:          1.3.6.1
-Release:          %{?relprefix}16%{?prerel}%{?dist}
+Release:          %{?relprefix}19%{?prerel}%{?dist}
 License:          GPLv3+
 URL:              https://www.port389.org/
 Group:            System Environment/Daemons
@@ -43,17 +41,9 @@ Provides:         ldif2ldbm >= 0
 
 BuildRequires:    nspr-devel
 BuildRequires:    nss-devel
-BuildRequires:    svrcore-devel >= 4.1.2
-%if %{use_openldap}
+BuildRequires:    svrcore-devel >= 4.1.3
 BuildRequires:    openldap-devel
-%else
-BuildRequires:    mozldap-devel
-%endif
-%if %{use_db4}
-BuildRequires:    db4-devel
-%else
 BuildRequires:    libdb-devel
-%endif
 BuildRequires:    cyrus-sasl-devel
 BuildRequires:    icu
 BuildRequires:    libicu-devel
@@ -93,11 +83,7 @@ Requires:         libsemanage-python
 Requires:         selinux-policy >= 3.13.1-137
 
 # the following are needed for some of our scripts
-%if %{use_openldap}
 Requires:         openldap-clients
-%else
-Requires:         mozldap-tools
-%endif
 # use_openldap assumes perl-Mozilla-LDAP is built with openldap support
 Requires:         perl-Mozilla-LDAP
 
@@ -112,11 +98,7 @@ Requires:         cyrus-sasl-md5
 Requires:         cyrus-sasl-plain
 
 # this is needed for verify-db.pl
-%if %{use_db4}
-Requires:         db4-utils
-%else
 Requires:         libdb-utils
-%endif
 
 # This picks up libperl.so as a Requires, so we add this versioned one
 Requires:         perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
@@ -137,7 +119,7 @@ Requires:         perl-Socket
 %endif
 Requires:         perl-NetAddr-IP
 Requires:         systemd-libs
-Requires:         svrcore >= 4.1.2
+Requires:         svrcore >= 4.1.3
 
 # upgrade path from monolithic % {name} (including -libs & -devel) to % {name} + % {name}-snmp
 Obsoletes:        %{name} <= 1.3.5.4
@@ -207,6 +189,12 @@ Patch52:          0052-Ticket-49257-Reject-nsslapd-cachememsize-nsslapd-cac.patc
 Patch53:          0053-Ticket-49257-Reject-dbcachesize-updates-while-auto-c.patch
 Patch54:          0054-Ticket-49184-adjust-logging-level-in-MO-plugin.patch
 Patch55:          0055-Ticket-49241-add-symblic-link-location-to-db2bak.pl-.patch
+Patch56:          0056-Ticket-49313-Change-the-retrochangelog-default-cache.patch
+Patch57:          0057-Ticket-49287-v3-extend-csnpl-handling-to-multiple-ba.patch
+Patch58:          0058-Ticket-49336-SECURITY-Locked-account-provides-differ.patch
+Patch59:          0059-Ticket-49298-force-sync-on-shutdown.patch
+Patch60:          0060-Ticket-49334-fix-backup-restore-if-changelog-exists.patch
+Patch61:          0061-Ticket-49356-mapping-tree-crash-can-occur-during-tot.patch
 
 
 %description
@@ -218,17 +206,9 @@ Summary:          Core libraries for 389 Directory Server
 Group:            System Environment/Daemons
 BuildRequires:    nspr-devel
 BuildRequires:    nss-devel
-BuildRequires:    svrcore-devel >= 4.1.2
-%if %{use_openldap}
+BuildRequires:    svrcore-devel >= 4.1.3
 BuildRequires:    openldap-devel
-%else
-BuildRequires:    mozldap-devel
-%endif
-%if %{use_db4}
-BuildRequires:    db4-devel
-%else
 BuildRequires:    libdb-devel
-%endif
 BuildRequires:    cyrus-sasl-devel
 BuildRequires:    libicu-devel
 BuildRequires:    pcre-devel
@@ -251,12 +231,8 @@ Requires:         %{name}-libs = %{version}-%{release}
 Requires:         pkgconfig
 Requires:         nspr-devel
 Requires:         nss-devel
-Requires:         svrcore-devel >= 4.1.2
-%if %{use_openldap}
+Requires:         svrcore-devel >= 4.1.3
 Requires:         openldap-devel
-%else
-Requires:         mozldap-devel
-%endif
 %if %{use_nunc_stans}
 Requires:         libtalloc
 Requires:         libevent
@@ -345,12 +321,15 @@ cp %{SOURCE2} README.devel
 %patch53 -p1
 %patch54 -p1
 %patch55 -p1
-
+%patch56 -p1
+%patch57 -p1
+%patch58 -p1
+%patch59 -p1
+%patch60 -p1
+%patch61 -p1
 %build
 
-%if %{use_openldap}
 OPENLDAP_FLAG="--with-openldap"
-%endif
 %{?with_tmpfiles_d: TMPFILES_FLAG="--with-tmpfiles-d=%{with_tmpfiles_d}"}
 # hack hack hack https://bugzilla.redhat.com/show_bug.cgi?id=833529
 NSSARGS="--with-svrcore-inc=%{_includedir} --with-svrcore-lib=%{_libdir} --with-nss-lib=%{_libdir} --with-nss-inc=%{_includedir}/nss3"
@@ -442,11 +421,7 @@ HOMEDIR="/usr/share/dirsrv"
 
 getent group $GROUPNAME >/dev/null || /usr/sbin/groupadd -f -g $ALLOCATED_GID -r $GROUPNAME
 if ! getent passwd $USERNAME >/dev/null ; then
-    if ! getent passwd $ALLOCATED_UID >/dev/null ; then
-        /usr/sbin/useradd -r -u $ALLOCATED_UID -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME
-    else
-        /usr/sbin/useradd -r -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME
-    fi
+    /usr/sbin/useradd -r -u $ALLOCATED_UID -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME
 fi
 
 echo looking for instances in %{_sysconfdir}/%{pkgname} > $output 2>&1 || :
@@ -583,6 +558,23 @@ fi
 %{_sysconfdir}/%{pkgname}/dirsrvtests
 
 %changelog
+* Mon Aug 21 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.19-1
+- Bump version to 1.3.6.19-1
+- Remove old mozldap and db4 requirements
+- Resolves: Bug 1483865 - Crash while binding to a server during replication online init
+
+* Tue Aug 8 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-18
+- Bump version to 1.3.6.1-18
+- Require srvcore 4.1.3
+- Resolves: Bug 1479757 - dse.ldif and fsync
+- Resolves: Bug 1479755 - backup fails if changelog is enabled
+- Resolves: Bug 1479756 - Locked account provides different return code if password is correct 
+
+* Mon Jul 31 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-17
+- Bump version to 1.3.6.1-17
+- Resolves: Bug 1476161 - replication halt - pending list first CSN not committed, pending list increasing
+- Resolves: Bug 1476162 - Change the retrochangelog default cache size
+
 * Tue Jun 6 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-16
 - Bump version to 1.3.6.1-16
 - Resolves: Bug 1444938 - nsslapd-allowed-sasl-mechanisms doesn't reset to default values without a restart