diff --git a/SOURCES/slapi-0100-deadlok-between-write-and-search-operation.patch b/SOURCES/slapi-0100-deadlok-between-write-and-search-operation.patch
new file mode 100644
index 0000000..b441a46
--- /dev/null
+++ b/SOURCES/slapi-0100-deadlok-between-write-and-search-operation.patch
@@ -0,0 +1,2242 @@
+From 8b10ea485f7964ea53fb9ab1bd71105a2da96f84 Mon Sep 17 00:00:00 2001
+From: Thierry Bordaz <tbordaz@redhat.com>
+Date: Wed, 13 Sep 2017 12:39:08 +0200
+Subject: [PATCH 01/13] Bug 1435663: deadlock between write and search
+ operation in schema-compat plugin
+
+Problem description:
+    Schema compat is a betxn pre/post op plugin managing maps.
+    The maps are protected by a RW lock.
+    A typical deadlock scenario is when a read thread (SRCH) holding
+    the map lock needs a ressource (DB page) acquired by an
+    write thread (MOD/ADD/DEL..) and that write thread needs to update
+    the map and so acquire the map lock.
+
+    So far we have been able to reduce the frequency of those scenarios
+    (but not eliminate them) by restricting the scope of operations
+    that need to acquire the lock.
+
+    But scoping is not systematically possible like described in
+    https://bugzilla.redhat.com/show_bug.cgi?id=1435663#c16
+
+Fix description:
+    The fix implements a plugin RW reentrant lock 'plugin_lock'.
+    To do this it uses a thread private variables (thread_plugin_lock_status and
+    thread_plugin_lock_count to remember the current status of the lock
+    (free, read_acquired, write_acquired).
+
+    Then for write operations (even if it is out of the scope of SC), the lock is acquired in write
+    in the BE_preop operation (note not in BETXN_preop) and only released
+    in the BE_postop (postop/bepostop).
+    So a write operation acquires (exclusive) the maps lock before acquiring DB pages.
+    So read and write operation will acquire locks in the same order.
+
+    Design is https://www.freeipa.org/page/V4_slapi_nis_locking
+
+Signed-off-by: Thierry Bordaz <tbordaz@redhat.com>
+---
+ src/back-sch.c | 221 ++++++++++++++++++++++++++++++++++++++++
+ src/back-shr.c |  94 +++++++++++++++++
+ src/back-shr.h |  16 +++
+ src/map.c      | 271 +++++++++++++++++++++++++++++++++++++++++++++++--
+ src/map.h      |   3 +
+ src/plug-sch.c |  52 ++++++++++
+ 6 files changed, 651 insertions(+), 6 deletions(-)
+
+diff --git a/src/back-sch.c b/src/back-sch.c
+index 4612051..9313cd5 100644
+--- a/src/back-sch.c
++++ b/src/back-sch.c
+@@ -2304,6 +2304,157 @@ backend_betxn_pre_write_cb(Slapi_PBlock *pb)
+ 	return state->use_be_txns ? backend_write_cb(pb, state) : 0;
+ }
+ 
++static int
++backend_be_pre_write_cb(Slapi_PBlock *pb) {
++    int ret;
++    int lock_status;
++    int lock_count;
++    struct plugin_state *state;
++
++    slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
++
++    if (wrap_get_call_level() > 0) {
++        return 0;
++    }
++    if (state->ready_to_serve == 0) {
++        /* No data to serve yet */
++        return 0;
++    }
++    if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
++        return 0;
++    }
++
++
++    wrap_inc_call_level();
++
++    lock_status = get_plugin_monitor_status();
++    lock_count = get_plugin_monitor_count();
++    if (lock_status == MAP_RWLOCK_UNINIT) {
++        return 0;
++    }
++
++    if (lock_status == MAP_RWLOCK_FREE) {
++        set_plugin_monitor_count(1);
++
++        if (plugin_wrlock() == 0) {
++            ret = 0;
++        } else {
++            slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++                    "backend_be_pre_write_cb: unable to acquire write lock\n");
++            ret = -1;
++        }
++#if DEBUG_MAP_LOCK
++        slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++                "backend_be_pre_write_cb: (%p) MAP_RWLOCK_FREE -> MAP_WLOCK_HELD  : count=%d\n", PR_GetCurrentThread(), 1);
++#endif
++    } else {
++        set_plugin_monitor_count(lock_count + 1);
++#if DEBUG_MAP_LOCK
++        slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                        "backend_be_pre_write_cb: (%p)  %s --> MAP_WLOCK_HELD  : count=%d\n",
++                PR_GetCurrentThread(),
++                (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD",
++                lock_count + 1);
++#endif
++        ret = 0;
++        if (lock_status == MAP_RLOCK_HELD) {
++            /* lock is already acquired in read */
++
++#if DEBUG_MAP_LOCK
++            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map backend_be_pre_write_cb: weird situation map lock is held in read and now required in write mode\n");
++#endif
++            /* First free the lock held in read */
++            ret = plugin_unlock();
++            if (ret) {
++                    slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                            "backend_be_pre_write_cb: fail to unlock plugin lock (%d)\n", ret);
++            }
++
++            /* Second acquire it in write */
++            ret = plugin_wrlock();
++            if (ret) {
++                    slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                            "backend_be_pre_write_cb: fail to write lock plugin lock (%d)\n", ret);
++            }
++        }
++    }
++
++    set_plugin_monitor_status(MAP_WLOCK_HELD);
++    wrap_dec_call_level();
++
++    return ret;
++}
++
++static int
++backend_be_post_write_cb(Slapi_PBlock *pb)
++{
++        int ret;
++        int lock_status;
++        int lock_count;
++        struct plugin_state *state;
++
++        slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
++
++	if (wrap_get_call_level() > 0) {
++		return 0;
++	}
++	if (state->ready_to_serve == 0) {
++		/* No data to serve yet */
++		return 0;
++	}
++        if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
++            return 0;
++        }
++
++	wrap_inc_call_level();
++
++        lock_status = get_plugin_monitor_status();
++        lock_count = get_plugin_monitor_count();
++        if (lock_status == MAP_RWLOCK_UNINIT) {
++            return 0;
++        }
++
++        if (lock_count == 1) {
++            set_plugin_monitor_status(MAP_RWLOCK_FREE);
++            if (plugin_unlock() == 0) {
++                ret = 0;
++            } else {
++                slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++                                "backend_be_post_write_cb: unable to release write lock\n");
++                ret = -1;
++            }
++#if DEBUG_MAP_LOCK
++            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"backend_be_post_write_cb: (%p)  %s --> MAP_RWLOCK_FREE  : count=%d\n",
++                        PR_GetCurrentThread(),
++                        (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
++                        0);
++#endif
++        }
++        if (lock_count >= 1) {
++           set_plugin_monitor_count(lock_count - 1);
++#if DEBUG_MAP_LOCK
++            if (lock_count > 1) {
++                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                                    "backend_be_post_write_cb: (%p)  keep %s : count=%d\n",
++                            PR_GetCurrentThread(),
++                            (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
++                            lock_count - 1);
++            } else {
++                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                                    "backend_be_post_write_cb: (%p)  is now %s : count=%d\n",
++                            PR_GetCurrentThread(),
++                            "MAP_RWLOCK_FREE",
++                            lock_count - 1);
++            }
++#endif
++        }
++	wrap_dec_call_level();
++
++	return ret;
++}
++
+ #ifdef USE_PAM
+ static int
+ backend_bind_cb_pam(Slapi_PBlock *pb, const char *username, char *ndn)
+@@ -2814,6 +2965,42 @@ backend_init_betxn_preop(Slapi_PBlock *pb, struct plugin_state *state)
+ 	return 0;
+ }
+ 
++int
++backend_init_be_preop(Slapi_PBlock *pb, struct plugin_state *state)
++{
++	slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++	                "hooking up bet preoperation callbacks\n");
++	/* Intercept write requests and return an insufficient-access error for
++	 * attempts to write to anything we're managing. */
++	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN,
++			     backend_be_pre_write_cb) != 0) {
++		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++				"error hooking up betxn pre add callback\n");
++		return -1;
++	}
++	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN,
++			     backend_be_pre_write_cb) != 0) {
++		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++				"error hooking up betxn pre modify callback\n");
++		return -1;
++	}
++	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_MODRDN_FN,
++			     backend_be_pre_write_cb) != 0) {
++		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++				"error hooking up betxn pre modrdn callback\n");
++		return -1;
++	}
++	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN,
++			     backend_be_pre_write_cb) != 0) {
++		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++				"error hooking up betxn pre delete callback\n");
++		return -1;
++	}
++	/* We don't hook abandonment requests. */
++	/* We don't hook unbind requests. */
++	return 0;
++}
++
+ int
+ backend_init_betxn_postop(Slapi_PBlock *pb, struct plugin_state *state)
+ {
+@@ -2821,6 +3008,40 @@ backend_init_betxn_postop(Slapi_PBlock *pb, struct plugin_state *state)
+ 			"hooking up betxn postoperation callbacks\n");
+ 	return backend_shr_betxn_postop_init(pb, state);
+ }
++
++
++int
++backend_init_be_postop(Slapi_PBlock *pb, struct plugin_state *state)
++{
++	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_ADD_FN,
++			     backend_be_post_write_cb) != 0) {
++		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++				"error hooking up betxn post add callback\n");
++		return -1;
++	}
++	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODIFY_FN,
++			     backend_be_post_write_cb) != 0) {
++		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++				"error hooking up betxn post modify "
++				"callback\n");
++		return -1;
++	}
++	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODRDN_FN,
++			     backend_be_post_write_cb) != 0) {
++		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++				"error hooking up betxn post modrdn "
++				"callback\n");
++		return -1;
++	}
++	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_DELETE_FN,
++			     backend_be_post_write_cb) != 0) {
++		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++				"error hooking up betxn post delete "
++				"callback\n");
++		return -1;
++	}
++	return 0;
++}
+ #endif
+ 
+ int
+diff --git a/src/back-shr.c b/src/back-shr.c
+index a7ea92f..a227b0a 100644
+--- a/src/back-shr.c
++++ b/src/back-shr.c
+@@ -2866,3 +2866,97 @@ backend_shr_internal_postop_init(Slapi_PBlock *pb, struct plugin_state *state)
+ 	}
+ 	return 0;
+ }
++
++static unsigned int thread_dummy;
++static unsigned int thread_plugin_lock_status;
++static int thread_plugin_lock_count;
++
++void
++init_map_lock(void)
++{
++    /* The plugin lock is initialized as free */
++    slapi_log_error(SLAPI_LOG_FATAL, "init_plugin_lock",
++            "thread_id = %p\n", PR_GetCurrentThread());
++
++    PR_NewThreadPrivateIndex (&thread_dummy, NULL);
++    PR_NewThreadPrivateIndex(&thread_plugin_lock_status, NULL);
++    PR_NewThreadPrivateIndex(&thread_plugin_lock_count, NULL);
++
++    slapi_log_error(SLAPI_LOG_FATAL, "init_plugin_lock",
++            "thread_plugin_lock_status = %d\n", thread_plugin_lock_status);
++    slapi_log_error(SLAPI_LOG_FATAL, "init_map_lock",
++            "thread_plugin_lock_count = %d\n", thread_plugin_lock_count);
++}
++
++int
++rw_monitor_enabled(void)
++{
++    if (thread_plugin_lock_status)
++        return (int) MAP_MONITOR_ENABLED;
++    else
++        return (int) MAP_MONITOR_DISABLED;
++}
++
++int
++get_plugin_monitor_status(void)
++{
++    int ret;
++
++    if (thread_plugin_lock_status)
++        ret = (int) PR_GetThreadPrivate(thread_plugin_lock_status);
++    else
++        ret = (int) MAP_RWLOCK_UNINIT;
++#if DEBUG_MAP_LOCK
++    slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_status",
++            "lock_status = %d (%p)\n", ret, PR_GetCurrentThread());
++#endif
++    return ret;
++}
++
++void
++set_plugin_monitor_status(int lock_status)
++{
++#if DEBUG_MAP_LOCK
++    slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_status",
++            "lock_status = %d --> %d (%p)\n", get_plugin_monitor_status(), (int) lock_status, PR_GetCurrentThread());
++#endif
++
++    if (thread_plugin_lock_status)
++        PR_SetThreadPrivate(thread_plugin_lock_status, (void *) lock_status);
++    else
++        PR_SetThreadPrivate(thread_plugin_lock_status, (void *) MAP_RWLOCK_UNINIT);
++
++
++}
++
++int
++get_plugin_monitor_count(void)
++{
++    int ret;
++
++    if (thread_plugin_lock_count)
++        ret = (int) PR_GetThreadPrivate(thread_plugin_lock_count);
++    else
++        ret = (int) MAP_RWLOCK_UNINIT;
++#if DEBUG_MAP_LOCK
++    slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_count",
++            "lock_count = %d (%p)\n", ret, PR_GetCurrentThread());
++#endif
++    return ret;
++}
++
++void
++set_plugin_monitor_count(int lock_count)
++{
++#if DEBUG_MAP_LOCK
++    slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_count",
++            "lock_count = %d --> %d (%p)\n", get_plugin_monitor_count(), (int) lock_count, PR_GetCurrentThread());
++#endif
++
++    if (thread_plugin_lock_count)
++        PR_SetThreadPrivate(thread_plugin_lock_count, (void *) lock_count);
++    else
++        PR_SetThreadPrivate(thread_plugin_lock_count, (void *) MAP_RWLOCK_UNINIT);
++
++
++}
+diff --git a/src/back-shr.h b/src/back-shr.h
+index 2caea5d..8c68b4f 100644
+--- a/src/back-shr.h
++++ b/src/back-shr.h
+@@ -22,6 +22,22 @@
+ #ifndef back_shr_h
+ #define back_shr_h
+ 
++#define DEBUG_MAP_LOCK 0
++#define MAP_MONITOR_DISABLED 0
++#define MAP_MONITOR_ENABLED 1
++
++#define MAP_RWLOCK_UNINIT 3
++#define MAP_WLOCK_HELD    2
++#define MAP_RLOCK_HELD    1
++#define MAP_RWLOCK_FREE   0
++int  rw_monitor_enabled(void);
++int  get_plugin_monitor_status(void);
++void set_plugin_monitor_status(int lock_status);
++int  get_plugin_monitor_count(void);
++void set_plugin_monitor_count(int lock_count);
++void init_map_lock(void);
++
++
+ struct plugin_state;
+ 
+ void backend_shr_free_server_name(struct plugin_state *state, char *master);
+diff --git a/src/map.c b/src/map.c
+index ff18fcf..db9e093 100644
+--- a/src/map.c
++++ b/src/map.c
+@@ -45,6 +45,7 @@
+ #include "map.h"
+ #include "portmap.h"
+ #include "wrap.h"
++#include "back-shr.h"
+ 
+ /* The singleton for the cache. */
+ static struct {
+@@ -91,6 +92,7 @@ static struct {
+ 	} *domains;
+ 	int n_domains;
+ 	struct wrapped_rwlock *lock;
++        struct wrapped_rwlock *plugin_lock;
+ } map_data;
+ 
+ static void *
+@@ -1155,6 +1157,10 @@ map_init(struct slapi_pblock *pb, struct plugin_state *state)
+ 	if (map_data.lock == NULL) {
+ 		return -1;
+ 	}
++        map_data.plugin_lock = wrap_new_rwlock();
++	if (map_data.plugin_lock == NULL) {
++		return -1;
++	}
+ 	return 0;
+ }
+ 
+@@ -1193,6 +1199,8 @@ map_done(struct plugin_state *state)
+ 	}
+ 	wrap_free_rwlock(map_data.lock);
+ 	map_data.lock = NULL;
++        wrap_free_rwlock(map_data.plugin_lock);
++        map_data.plugin_lock = NULL;
+ }
+ 
+ int
+@@ -1219,19 +1227,270 @@ map_data_get_map_size(struct plugin_state *state,
+ }
+ 
+ int
+-map_rdlock(void)
++plugin_rdlock(void)
+ {
+-	return wrap_rwlock_rdlock(map_data.lock);
++	return wrap_rwlock_rdlock(map_data.plugin_lock);
+ }
+ 
+ int
+-map_wrlock(void)
++plugin_wrlock(void)
+ {
+-	return wrap_rwlock_wrlock(map_data.lock);
++	return wrap_rwlock_wrlock(map_data.plugin_lock);
+ }
+ 
+ int
+-map_unlock(void)
++plugin_unlock(void)
+ {
+-	return wrap_rwlock_unlock(map_data.lock);
++	return wrap_rwlock_unlock(map_data.plugin_lock);
+ }
++
++int
++map_rdlock(void)
++{
++	int lock_status;
++        int lock_count;
++	int rc = 0;
++
++	if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
++		/* This is not initialized used the old way */
++		slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++				"map rdlock: old way MAP_MONITOR_DISABLED\n");
++		return wrap_rwlock_rdlock(map_data.lock);
++	}
++
++
++	lock_status = get_plugin_monitor_status();
++        lock_count = get_plugin_monitor_count();
++
++#if DEBUG_MAP_LOCK
++	slapi_log_error(SLAPI_LOG_FATAL, "map_rdlock",
++				"thread_id = %p (call level = %d)\n", PR_GetCurrentThread(), wrap_get_call_level());
++#endif
++	if (lock_status == MAP_RWLOCK_UNINIT) {
++		/* This is not initialized used the old way */
++		slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++				"map rdlock: old way lock_status == MAP_RWLOCK_UNINIT\n");
++		return wrap_rwlock_rdlock(map_data.lock);
++	}
++
++	if (lock_status == MAP_RWLOCK_FREE) {
++		/* The plugin lock is free, acquire it */
++#if DEBUG_MAP_LOCK
++		slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++				"map rdlock: current lock_status == MAP_RWLOCK_FREE\n");
++#endif
++                set_plugin_monitor_status(MAP_RLOCK_HELD);
++                set_plugin_monitor_count(1);
++#if DEBUG_MAP_LOCK
++                if (lock_count != 0) {
++                    slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++				"map rdlock: (%p) ALERT !!!   count was %d -> 1\n", PR_GetCurrentThread(), lock_count);
++                }
++#endif
++
++                /* Acquire the slapi plugin in read */
++                rc = plugin_rdlock();
++                if (rc) {
++			slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++				"map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc);
++			return rc;
++		}
++#if DEBUG_MAP_LOCK
++		slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++				"map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD  : count=%d\n", PR_GetCurrentThread(), 1);
++#endif
++		rc = wrap_rwlock_rdlock(map_data.lock);
++		if (rc) {
++			slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++				"Fail to acquire map lock in read (%d)\n", rc);
++                        plugin_unlock();
++			return rc;
++		}
++		return 0;
++	}
++
++#if DEBUG_MAP_LOCK
++        slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++                            "map rdlock: (%p) was already hold %s : count=%d > %d!!!\n",
++                            PR_GetCurrentThread(),
++                            (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD",
++                            lock_count, lock_count + 1);
++#endif
++        set_plugin_monitor_count(lock_count + 1);
++	return 0;
++ }
++
++int
++map_wrlock(void)
++{
++	int lock_status;
++        int lock_count;
++	int rc = 0;
++
++	if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
++		/* This is not initialized used the old way */
++		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map wrlock: old way MAP_MONITOR_DISABLED\n");
++		return wrap_rwlock_wrlock(map_data.lock);
++	}
++
++	lock_status = get_plugin_monitor_status();
++        lock_count = get_plugin_monitor_count();
++
++#if DEBUG_MAP_LOCK
++	slapi_log_error(SLAPI_LOG_FATAL, "map wrlock",
++				"thread_id = %p (call level = %d)\n", PR_GetCurrentThread(), wrap_get_call_level());
++#endif
++	if (lock_status == MAP_RWLOCK_UNINIT) {
++		/* This is not initialized used the old way */
++		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map wrlock: old way lock_status == MAP_LOCK_UNINIT\n");
++
++		return wrap_rwlock_wrlock(map_data.lock);
++	}
++
++	if (lock_status == MAP_RWLOCK_FREE) {
++		/* The lock is free, acquire it */
++#if DEBUG_MAP_LOCK
++		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map wrlock: current lock_status == MAP_LOCK_FREE\n");
++#endif
++
++                set_plugin_monitor_count(1);
++#if DEBUG_MAP_LOCK
++                if (lock_count != 0) {
++                    slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map wrlock: (%p) ALERT !!!   count was %d --> 1\n", PR_GetCurrentThread(), lock_count);
++                }
++#endif
++                /* Acquire the slapi plugin in write */
++                rc = plugin_wrlock();
++                if (rc) {
++			slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++				"map wrlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc);
++			return rc;
++		}
++#if DEBUG_MAP_LOCK
++                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                        "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD  : count=%d\n", PR_GetCurrentThread(), 1);
++#endif
++
++		rc = wrap_rwlock_wrlock(map_data.lock);
++		if (rc) {
++			slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", PR_GetCurrentThread(), rc);
++                        plugin_unlock();
++			goto common;
++		}
++	} else {
++            set_plugin_monitor_count(lock_count + 1);
++#if DEBUG_MAP_LOCK
++		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map wrlock: (%p)  %s --> MAP_WLOCK_HELD  : count=%d\n",
++                        PR_GetCurrentThread(),
++                        (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD",
++                        lock_count + 1);
++#endif
++
++            if (lock_status == MAP_RLOCK_HELD) {
++                /* lock is already acquired in read */
++#if DEBUG_MAP_LOCK
++		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map wrlock: weird situation map lock is held in read and now required in write mode\n");
++#endif
++		/* First free the lock held in read */
++		rc = plugin_unlock();
++		if (rc) {
++			slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map wrlock: fail to unlock plugin lock (%d)\n", rc);
++			goto common;
++		}
++
++		/* Second acquire it in write */
++		rc = plugin_wrlock();
++		if (rc) {
++			slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map wrlock: fail to write lock plugin lock (%d)\n", rc);
++			goto common;
++		}
++            }
++        }
++
++common:
++    set_plugin_monitor_status(MAP_WLOCK_HELD);
++    return rc;
++ }
++
++int
++map_unlock(void)
++ {
++	int lock_status;
++        int lock_count;
++	int rc = 0;
++
++	if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
++		/* This is not initialized used the old way */
++		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map_unlock: old way MAP_MONITOR_DISABLED\n");
++		return wrap_rwlock_unlock(map_data.lock);
++	}
++
++	lock_status = get_plugin_monitor_status();
++        lock_count = get_plugin_monitor_count();
++
++#if DEBUG_MAP_LOCK
++	slapi_log_error(SLAPI_LOG_FATAL, "map_unlock",
++				"thread_id = %p (call level = %d)\n", PR_GetCurrentThread(), wrap_get_call_level());
++#endif
++	if (lock_status == MAP_RWLOCK_UNINIT) {
++		/* This is not initialized used the old way */
++		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map_unlock: old way lock_status == MAP_RWLOCK_UNINIT\n");
++
++		return wrap_rwlock_unlock(map_data.lock);
++	}
++
++        if (lock_count == 1) {
++            set_plugin_monitor_status(MAP_RWLOCK_FREE);
++            rc = plugin_unlock();
++            if (rc) {
++			slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map unlock: fail to unlock plugin lock (%d)\n", rc);
++			goto common;
++            }
++#if DEBUG_MAP_LOCK
++            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++				"map_unlock: (%p)  %s --> MAP_RWLOCK_FREE  : count=%d\n",
++                        PR_GetCurrentThread(),
++                        (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
++                        0);
++#endif
++            rc = wrap_rwlock_unlock(map_data.lock);
++            if (rc) {
++                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                    "map_unlock: fail to unlock map lock (%d)\n", rc);
++                goto common;
++            }
++        }
++        if (lock_count >= 1) {
++            set_plugin_monitor_count(lock_count - 1);
++#if DEBUG_MAP_LOCK
++            if (lock_count > 1) {
++                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                                    "map_unlock: (%p)  keep %s : count=%d\n",
++                            PR_GetCurrentThread(),
++                            (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
++                            lock_count - 1);
++            } else {
++                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                                    "map_unlock: (%p)  is now %s : count=%d\n",
++                            PR_GetCurrentThread(),
++                            "MAP_RWLOCK_FREE",
++                            lock_count - 1);
++            }
++#endif
++        }
++
++common:
++       return rc;
++ }
+diff --git a/src/map.h b/src/map.h
+index f5b0405..4d7cb8c 100644
+--- a/src/map.h
++++ b/src/map.h
+@@ -115,6 +115,9 @@ int map_data_get_domain_size(struct plugin_state *state,
+ 			     const char *domain_name);
+ int map_data_get_map_size(struct plugin_state *state,
+ 			  const char *domain_name, const char *map_name);
++int plugin_rdlock(void);
++int plugin_wrlock(void);
++int plugin_unlock(void);
+ int map_rdlock(void);
+ int map_wrlock(void);
+ int map_unlock(void);
+diff --git a/src/plug-sch.c b/src/plug-sch.c
+index 0c20a07..2d9c75b 100644
+--- a/src/plug-sch.c
++++ b/src/plug-sch.c
+@@ -62,6 +62,8 @@
+ #define PLUGIN_ID "schema-compat-plugin"
+ #define PLUGIN_PREOP_ID PLUGIN_ID "-preop"
+ #define PLUGIN_BETXN_PREOP_ID PLUGIN_ID "-betxn_preop"
++#define PLUGIN_BE_POSTOP_ID PLUGIN_ID "-be_postop"
++#define PLUGIN_BE_PREOP_ID PLUGIN_ID "-be_preop"
+ #define PLUGIN_BETXN_POSTOP_ID PLUGIN_ID "-betxn_postop"
+ #define PLUGIN_POSTOP_ID PLUGIN_ID "-postop"
+ #define PLUGIN_INTERNAL_POSTOP_ID PLUGIN_ID "-internal-postop"
+@@ -258,6 +260,35 @@ schema_compat_plugin_init_betxn_postop(Slapi_PBlock *pb)
+ 	}
+ 	return 0;
+ }
++static int
++schema_compat_plugin_init_bepreop(Slapi_PBlock *pb)
++{
++	slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03);
++	slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, &plugin_description);
++	slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, global_plugin_state);
++	if (backend_init_be_preop(pb, global_plugin_state) == -1) {
++		slapi_log_error(SLAPI_LOG_PLUGIN,
++				global_plugin_state->plugin_desc->spd_id,
++				"error registering be preoperation hooks\n");
++		return -1;
++	}
++	return 0;
++}
++static int
++schema_compat_plugin_init_bepostop(Slapi_PBlock *pb)
++{
++	slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03);
++	slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, &plugin_description);
++	slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, global_plugin_state);
++	if (backend_init_be_postop(pb, global_plugin_state) == -1) {
++		slapi_log_error(SLAPI_LOG_PLUGIN,
++				global_plugin_state->plugin_desc->spd_id,
++				"error registering be postoperation "
++				"hooks\n");
++		return -1;
++	}
++	return 0;
++}
+ #endif
+ static int
+ schema_compat_plugin_init_postop(Slapi_PBlock *pb)
+@@ -300,6 +331,9 @@ schema_compat_plugin_init(Slapi_PBlock *pb)
+ 				"error setting up plugin\n");
+ 		return -1;
+ 	}
++
++    init_map_lock();
++
+ 	/* Read global configuration. */
+ 	if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY,
+ 			      &plugin_entry) == 0) &&
+@@ -341,6 +375,15 @@ schema_compat_plugin_init(Slapi_PBlock *pb)
+ 				"error registering betxn preoperation plugin\n");
+ 		return -1;
+ 	}
++        if (slapi_register_plugin("bepreoperation", TRUE,
++				  "schema_compat_plugin_init_bepreop",
++				  schema_compat_plugin_init_bepreop,
++				  PLUGIN_BE_PREOP_ID, NULL,
++				  state->plugin_identity) != 0) {
++		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++				"error registering betxn preoperation plugin\n");
++		return -1;
++	}
+ #endif
+ 	if (slapi_register_plugin("postoperation", TRUE,
+ 				  "schema_compat_plugin_init_postop",
+@@ -370,6 +413,15 @@ schema_compat_plugin_init(Slapi_PBlock *pb)
+ 				"error registering betxn postoperation plugin\n");
+ 		return -1;
+ 	}
++        if (slapi_register_plugin("bepostoperation", TRUE,
++				  "schema_compat_plugin_init_bepostop",
++				  schema_compat_plugin_init_bepostop,
++				  PLUGIN_BE_POSTOP_ID, NULL,
++				  state->plugin_identity) != 0) {
++		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++				"error registering betxn postoperation plugin\n");
++		return -1;
++	}
+ #endif
+ 	if (slapi_register_plugin("preextendedop", TRUE,
+ 				  "schema_compat_plugin_init_extop",
+-- 
+2.21.0
+
+
+From 1ccbfe23576ac78f81d85bcce246e4d72cfc4db8 Mon Sep 17 00:00:00 2001
+From: Thierry Bordaz <tbordaz@redhat.com>
+Date: Wed, 3 Apr 2019 10:55:38 +0200
+Subject: [PATCH 07/13] Bug 1694263: Fix thread private variable initialization
+
+Fix description:
+	The initialization of the thread private variable was buggy.
+	The private variable required an allocated struct (per thread).
+	The struct is allocated on demand (during get/set) when the
+	retrieved (PR_GetThreadPrivate) struct is NULL.
+
+Signed-off-by: Thierry Bordaz <tbordaz@redhat.com>
+---
+ src/back-sch.c |  85 ++++++++---------
+ src/back-shr.c | 138 ++++++++++++++++++++++------
+ src/map.c      | 244 ++++++++++++++++++++++++-------------------------
+ 3 files changed, 274 insertions(+), 193 deletions(-)
+
+diff --git a/src/back-sch.c b/src/back-sch.c
+index 9313cd5..2d0bad0 100644
+--- a/src/back-sch.c
++++ b/src/back-sch.c
+@@ -2306,7 +2306,7 @@ backend_betxn_pre_write_cb(Slapi_PBlock *pb)
+ 
+ static int
+ backend_be_pre_write_cb(Slapi_PBlock *pb) {
+-    int ret;
++    int ret = 0;
+     int lock_status;
+     int lock_count;
+     struct plugin_state *state;
+@@ -2334,6 +2334,7 @@ backend_be_pre_write_cb(Slapi_PBlock *pb) {
+     }
+ 
+     if (lock_status == MAP_RWLOCK_FREE) {
++        /* This thread does not hold the map lock */
+         set_plugin_monitor_count(1);
+ 
+         if (plugin_wrlock() == 0) {
+@@ -2389,12 +2390,12 @@ backend_be_pre_write_cb(Slapi_PBlock *pb) {
+ static int
+ backend_be_post_write_cb(Slapi_PBlock *pb)
+ {
+-        int ret;
+-        int lock_status;
+-        int lock_count;
+-        struct plugin_state *state;
++    int ret = 0;
++    int lock_status;
++    int lock_count;
++    struct plugin_state *state;
+ 
+-        slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
++    slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
+ 
+ 	if (wrap_get_call_level() > 0) {
+ 		return 0;
+@@ -2409,47 +2410,47 @@ backend_be_post_write_cb(Slapi_PBlock *pb)
+ 
+ 	wrap_inc_call_level();
+ 
+-        lock_status = get_plugin_monitor_status();
+-        lock_count = get_plugin_monitor_count();
+-        if (lock_status == MAP_RWLOCK_UNINIT) {
+-            return 0;
+-        }
++    lock_status = get_plugin_monitor_status();
++    lock_count = get_plugin_monitor_count();
++    if (lock_status == MAP_RWLOCK_UNINIT) {
++        return 0;
++    }
+ 
+-        if (lock_count == 1) {
+-            set_plugin_monitor_status(MAP_RWLOCK_FREE);
+-            if (plugin_unlock() == 0) {
+-                ret = 0;
+-            } else {
+-                slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+-                                "backend_be_post_write_cb: unable to release write lock\n");
+-                ret = -1;
+-            }
+-#if DEBUG_MAP_LOCK
+-            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-				"backend_be_post_write_cb: (%p)  %s --> MAP_RWLOCK_FREE  : count=%d\n",
+-                        PR_GetCurrentThread(),
+-                        (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
+-                        0);
+-#endif
++    if (lock_count == 1) {
++        set_plugin_monitor_status(MAP_RWLOCK_FREE);
++        if (plugin_unlock() == 0) {
++            ret = 0;
++        } else {
++            slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
++                    "backend_be_post_write_cb: unable to release write lock\n");
++            ret = -1;
+         }
+-        if (lock_count >= 1) {
+-           set_plugin_monitor_count(lock_count - 1);
+ #if DEBUG_MAP_LOCK
+-            if (lock_count > 1) {
+-                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-                                    "backend_be_post_write_cb: (%p)  keep %s : count=%d\n",
+-                            PR_GetCurrentThread(),
+-                            (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
+-                            lock_count - 1);
+-            } else {
+-                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-                                    "backend_be_post_write_cb: (%p)  is now %s : count=%d\n",
+-                            PR_GetCurrentThread(),
+-                            "MAP_RWLOCK_FREE",
+-                            lock_count - 1);
+-            }
++        slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                "backend_be_post_write_cb: (%p)  %s --> MAP_RWLOCK_FREE  : count=%d\n",
++                PR_GetCurrentThread(),
++                (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
++                0);
+ #endif
++    }
++    if (lock_count >= 1) {
++        set_plugin_monitor_count(lock_count - 1);
++#if DEBUG_MAP_LOCK
++        if (lock_count > 1) {
++            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                    "backend_be_post_write_cb: (%p)  keep %s : count=%d\n",
++                    PR_GetCurrentThread(),
++                    (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
++                    lock_count - 1);
++        } else {
++            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                    "backend_be_post_write_cb: (%p)  is now %s : count=%d\n",
++                    PR_GetCurrentThread(),
++                    "MAP_RWLOCK_FREE",
++                    lock_count - 1);
+         }
++#endif
++    }
+ 	wrap_dec_call_level();
+ 
+ 	return ret;
+diff --git a/src/back-shr.c b/src/back-shr.c
+index a227b0a..920c135 100644
+--- a/src/back-shr.c
++++ b/src/back-shr.c
+@@ -37,6 +37,7 @@
+ #endif
+ 
+ #include <rpc/xdr.h>
++#include <nspr4/prtypes.h>
+ #include "../yp/yp.h"
+ 
+ #ifdef HAVE_TCPD_H
+@@ -2867,31 +2868,61 @@ backend_shr_internal_postop_init(Slapi_PBlock *pb, struct plugin_state *state)
+ 	return 0;
+ }
+ 
+-static unsigned int thread_dummy;
++PRBool use_lock_status = PR_FALSE;
+ static unsigned int thread_plugin_lock_status;
+-static int thread_plugin_lock_count;
++PRBool use_lock_count = PR_FALSE;
++static unsigned int thread_plugin_lock_count;
++/*
++ * https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/PR_NewThreadPrivateIndex
++ * It is called each time:
++ *  - PR_SetThreadPrivate is call with a not NULL private value
++ *  - on thread exit
++ */
++static void
++lock_status_free(void *ptr)
++{
++    int *lock_status = ptr;
++    if (lock_status) {
++        slapi_ch_free((void **)&lock_status);
++    }
++}
++static void
++lock_count_free(void *ptr)
++{
++    int *lock_count = ptr;
++    if (lock_count) {
++        slapi_ch_free((void **)&lock_count);
++    }
++}
+ 
+ void
+ init_map_lock(void)
+ {
++#if DEBUG_MAP_LOCK
+     /* The plugin lock is initialized as free */
+     slapi_log_error(SLAPI_LOG_FATAL, "init_plugin_lock",
+             "thread_id = %p\n", PR_GetCurrentThread());
++#endif
+ 
+-    PR_NewThreadPrivateIndex (&thread_dummy, NULL);
+-    PR_NewThreadPrivateIndex(&thread_plugin_lock_status, NULL);
+-    PR_NewThreadPrivateIndex(&thread_plugin_lock_count, NULL);
++    if (PR_NewThreadPrivateIndex(&thread_plugin_lock_status, lock_status_free) == PR_SUCCESS) {
++        use_lock_status = PR_TRUE;
++    }
++    if (PR_NewThreadPrivateIndex(&thread_plugin_lock_count, lock_count_free) == PR_SUCCESS) {
++        use_lock_count = PR_TRUE;
++    }
+ 
++#if DEBUG_MAP_LOCK
+     slapi_log_error(SLAPI_LOG_FATAL, "init_plugin_lock",
+             "thread_plugin_lock_status = %d\n", thread_plugin_lock_status);
+     slapi_log_error(SLAPI_LOG_FATAL, "init_map_lock",
+             "thread_plugin_lock_count = %d\n", thread_plugin_lock_count);
++#endif
+ }
+ 
+ int
+ rw_monitor_enabled(void)
+ {
+-    if (thread_plugin_lock_status)
++    if (use_lock_status)
+         return (int) MAP_MONITOR_ENABLED;
+     else
+         return (int) MAP_MONITOR_DISABLED;
+@@ -2902,13 +2933,27 @@ get_plugin_monitor_status(void)
+ {
+     int ret;
+ 
+-    if (thread_plugin_lock_status)
+-        ret = (int) PR_GetThreadPrivate(thread_plugin_lock_status);
+-    else
++    if (use_lock_status) {
++        int *lock_status_p;
++        lock_status_p = (int *) PR_GetThreadPrivate(thread_plugin_lock_status);
++        if (lock_status_p == NULL) {
++            /* if it was not initialized then allocates a structure
++             * that will be private to that thread.
++             * Later when the structure is retrieved (PR_GetThreadPrivate), the
++             * content of the structure can be read/write without allocating
++             * this private structure PR_SetThreadPrivate.
++             * So this branch is processed one time per each thread
++             */
++            lock_status_p = (int *) slapi_ch_calloc(1, sizeof (int));
++            PR_SetThreadPrivate(thread_plugin_lock_status, (void *) lock_status_p);
++            *lock_status_p = MAP_RWLOCK_FREE;
++        }
++        ret = *lock_status_p;
++    } else
+         ret = (int) MAP_RWLOCK_UNINIT;
+ #if DEBUG_MAP_LOCK
+     slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_status",
+-            "lock_status = %d (%p)\n", ret, PR_GetCurrentThread());
++            "(%s) lock_status = %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", ret, PR_GetCurrentThread());
+ #endif
+     return ret;
+ }
+@@ -2918,15 +2963,26 @@ set_plugin_monitor_status(int lock_status)
+ {
+ #if DEBUG_MAP_LOCK
+     slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_status",
+-            "lock_status = %d --> %d (%p)\n", get_plugin_monitor_status(), (int) lock_status, PR_GetCurrentThread());
++            "(%s) lock_status = %d --> %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", get_plugin_monitor_status(), (int) lock_status, PR_GetCurrentThread());
+ #endif
+ 
+-    if (thread_plugin_lock_status)
+-        PR_SetThreadPrivate(thread_plugin_lock_status, (void *) lock_status);
+-    else
+-        PR_SetThreadPrivate(thread_plugin_lock_status, (void *) MAP_RWLOCK_UNINIT);
+-
+-
++    if (use_lock_status) {
++        int *lock_status_p;
++
++        lock_status_p = (int *) PR_GetThreadPrivate(thread_plugin_lock_status);
++        if (lock_status_p == NULL) {
++            /* if it was not initialized then allocates a structure
++             * that will be private to that thread.
++             * Later when the structure is retrieved (PR_GetThreadPrivate), the
++             * content of the structure can be read/write without allocating
++             * this private structure PR_SetThreadPrivate.
++             * So this branch is processed one time per each thread
++             */
++            lock_status_p = (int *) slapi_ch_calloc(1, sizeof (int));
++            PR_SetThreadPrivate(thread_plugin_lock_status, (void *) lock_status_p);
++        }
++        *lock_status_p = lock_status;
++    }
+ }
+ 
+ int
+@@ -2934,13 +2990,27 @@ get_plugin_monitor_count(void)
+ {
+     int ret;
+ 
+-    if (thread_plugin_lock_count)
+-        ret = (int) PR_GetThreadPrivate(thread_plugin_lock_count);
+-    else
++    if (use_lock_count) {
++        int *lock_count;
++        lock_count = (int *) PR_GetThreadPrivate(thread_plugin_lock_count);
++        if (lock_count == NULL) {
++            /* if it was not initialized then allocates a structure
++             * that will be private to that thread.
++             * Later when the structure is retrieved (PR_GetThreadPrivate), the
++             * content of the structure can be read/write without allocating
++             * this private structure PR_SetThreadPrivate.
++             * So this branch is processed one time per each thread
++             */
++            lock_count = (int *) slapi_ch_calloc(1, sizeof (int));
++            PR_SetThreadPrivate(thread_plugin_lock_count, (void *) lock_count);
++            *lock_count = 0;
++        }
++        ret = *lock_count;
++    } else
+         ret = (int) MAP_RWLOCK_UNINIT;
+ #if DEBUG_MAP_LOCK
+     slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_count",
+-            "lock_count = %d (%p)\n", ret, PR_GetCurrentThread());
++            "(%s) lock_count = %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", ret, PR_GetCurrentThread());
+ #endif
+     return ret;
+ }
+@@ -2950,13 +3020,23 @@ set_plugin_monitor_count(int lock_count)
+ {
+ #if DEBUG_MAP_LOCK
+     slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_count",
+-            "lock_count = %d --> %d (%p)\n", get_plugin_monitor_count(), (int) lock_count, PR_GetCurrentThread());
++            "(%s) lock_count = %d --> %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", get_plugin_monitor_count(), (int) lock_count, PR_GetCurrentThread());
+ #endif
+-
+-    if (thread_plugin_lock_count)
+-        PR_SetThreadPrivate(thread_plugin_lock_count, (void *) lock_count);
+-    else
+-        PR_SetThreadPrivate(thread_plugin_lock_count, (void *) MAP_RWLOCK_UNINIT);
+-
+-
++    if (use_lock_count) {
++        int *lock_count_p;
++
++        lock_count_p = (int *) PR_GetThreadPrivate(thread_plugin_lock_count);
++        if (lock_count_p == NULL) {
++            /* if it was not initialized then allocates a structure
++             * that will be private to that thread.
++             * Later when the structure is retrieved (PR_GetThreadPrivate), the
++             * content of the structure can be read/write without allocating
++             * this private structure PR_SetThreadPrivate.
++             * So this branch is processed one time per each thread
++             */
++            lock_count_p = (int *) slapi_ch_calloc(1, sizeof (int));
++            PR_SetThreadPrivate(thread_plugin_lock_count, (void *) lock_count_p);
++        }
++        *lock_count_p = lock_count;
++    }
+ }
+diff --git a/src/map.c b/src/map.c
+index db9e093..e953925 100644
+--- a/src/map.c
++++ b/src/map.c
+@@ -1248,7 +1248,7 @@ int
+ map_rdlock(void)
+ {
+ 	int lock_status;
+-        int lock_count;
++    int lock_count;
+ 	int rc = 0;
+ 
+ 	if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
+@@ -1260,7 +1260,7 @@ map_rdlock(void)
+ 
+ 
+ 	lock_status = get_plugin_monitor_status();
+-        lock_count = get_plugin_monitor_count();
++    lock_count = get_plugin_monitor_count();
+ 
+ #if DEBUG_MAP_LOCK
+ 	slapi_log_error(SLAPI_LOG_FATAL, "map_rdlock",
+@@ -1271,52 +1271,52 @@ map_rdlock(void)
+ 		slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+ 				"map rdlock: old way lock_status == MAP_RWLOCK_UNINIT\n");
+ 		return wrap_rwlock_rdlock(map_data.lock);
+-	}
++    }
+ 
+-	if (lock_status == MAP_RWLOCK_FREE) {
+-		/* The plugin lock is free, acquire it */
++    if (lock_status == MAP_RWLOCK_FREE) {
++        /* The plugin lock is free, acquire it */
+ #if DEBUG_MAP_LOCK
+-		slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-				"map rdlock: current lock_status == MAP_RWLOCK_FREE\n");
++        slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++                "map rdlock: current lock_status == MAP_RWLOCK_FREE\n");
+ #endif
+-                set_plugin_monitor_status(MAP_RLOCK_HELD);
+-                set_plugin_monitor_count(1);
++        set_plugin_monitor_status(MAP_RLOCK_HELD);
++        set_plugin_monitor_count(1);
+ #if DEBUG_MAP_LOCK
+-                if (lock_count != 0) {
+-                    slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-				"map rdlock: (%p) ALERT !!!   count was %d -> 1\n", PR_GetCurrentThread(), lock_count);
+-                }
++        if (lock_count != 0) {
++            slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++                    "map rdlock: (%p) ALERT !!!   count was %d -> 1\n", PR_GetCurrentThread(), lock_count);
++        }
+ #endif
+ 
+-                /* Acquire the slapi plugin in read */
+-                rc = plugin_rdlock();
+-                if (rc) {
+-			slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-				"map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc);
+-			return rc;
+-		}
++        /* Acquire the slapi plugin in read */
++        rc = plugin_rdlock();
++        if (rc) {
++            slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++                    "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc);
++            return rc;
++        }
+ #if DEBUG_MAP_LOCK
+-		slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-				"map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD  : count=%d\n", PR_GetCurrentThread(), 1);
++        slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++                "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD  : count=%d\n", PR_GetCurrentThread(), 1);
+ #endif
+-		rc = wrap_rwlock_rdlock(map_data.lock);
+-		if (rc) {
+-			slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-				"Fail to acquire map lock in read (%d)\n", rc);
+-                        plugin_unlock();
+-			return rc;
+-		}
+-		return 0;
+-	}
++        rc = wrap_rwlock_rdlock(map_data.lock);
++        if (rc) {
++            slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++                    "Fail to acquire map lock in read (%d)\n", rc);
++            plugin_unlock();
++            return rc;
++        }
++        return 0;
++    }
+ 
+ #if DEBUG_MAP_LOCK
+-        slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-                            "map rdlock: (%p) was already hold %s : count=%d > %d!!!\n",
+-                            PR_GetCurrentThread(),
+-                            (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD",
+-                            lock_count, lock_count + 1);
++    slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++            "map rdlock: (%p) was already hold %s : count=%d > %d!!!\n",
++            PR_GetCurrentThread(),
++            (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD",
++            lock_count, lock_count + 1);
+ #endif
+-        set_plugin_monitor_count(lock_count + 1);
++    set_plugin_monitor_count(lock_count + 1);
+ 	return 0;
+  }
+ 
+@@ -1324,7 +1324,7 @@ int
+ map_wrlock(void)
+ {
+ 	int lock_status;
+-        int lock_count;
++    int lock_count;
+ 	int rc = 0;
+ 
+ 	if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
+@@ -1335,7 +1335,7 @@ map_wrlock(void)
+ 	}
+ 
+ 	lock_status = get_plugin_monitor_status();
+-        lock_count = get_plugin_monitor_count();
++    lock_count = get_plugin_monitor_count();
+ 
+ #if DEBUG_MAP_LOCK
+ 	slapi_log_error(SLAPI_LOG_FATAL, "map wrlock",
+@@ -1356,65 +1356,65 @@ map_wrlock(void)
+ 				"map wrlock: current lock_status == MAP_LOCK_FREE\n");
+ #endif
+ 
+-                set_plugin_monitor_count(1);
++        set_plugin_monitor_count(1);
+ #if DEBUG_MAP_LOCK
+-                if (lock_count != 0) {
+-                    slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-				"map wrlock: (%p) ALERT !!!   count was %d --> 1\n", PR_GetCurrentThread(), lock_count);
+-                }
++        if (lock_count != 0) {
++            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                    "map wrlock: (%p) ALERT !!!   count was %d --> 1\n", PR_GetCurrentThread(), lock_count);
++        }
+ #endif
+-                /* Acquire the slapi plugin in write */
+-                rc = plugin_wrlock();
+-                if (rc) {
+-			slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-				"map wrlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc);
+-			return rc;
+-		}
++        /* Acquire the slapi plugin in write */
++        rc = plugin_wrlock();
++        if (rc) {
++            slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++                    "map wrlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc);
++            return rc;
++        }
+ #if DEBUG_MAP_LOCK
+-                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-                        "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD  : count=%d\n", PR_GetCurrentThread(), 1);
++        slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD  : count=%d\n", PR_GetCurrentThread(), 1);
+ #endif
+ 
+-		rc = wrap_rwlock_wrlock(map_data.lock);
+-		if (rc) {
+-			slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-				"map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", PR_GetCurrentThread(), rc);
+-                        plugin_unlock();
+-			goto common;
+-		}
+-	} else {
+-            set_plugin_monitor_count(lock_count + 1);
++        rc = wrap_rwlock_wrlock(map_data.lock);
++        if (rc) {
++            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                    "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", PR_GetCurrentThread(), rc);
++            plugin_unlock();
++            goto common;
++        }
++    } else {
++        set_plugin_monitor_count(lock_count + 1);
+ #if DEBUG_MAP_LOCK
+-		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-				"map wrlock: (%p)  %s --> MAP_WLOCK_HELD  : count=%d\n",
+-                        PR_GetCurrentThread(),
+-                        (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD",
+-                        lock_count + 1);
++        slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                "map wrlock: (%p)  %s --> MAP_WLOCK_HELD  : count=%d\n",
++                PR_GetCurrentThread(),
++                (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD",
++                lock_count + 1);
+ #endif
+ 
+-            if (lock_status == MAP_RLOCK_HELD) {
+-                /* lock is already acquired in read */
++        if (lock_status == MAP_RLOCK_HELD) {
++            /* lock is already acquired in read */
+ #if DEBUG_MAP_LOCK
+-		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-				"map wrlock: weird situation map lock is held in read and now required in write mode\n");
++            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                    "map wrlock: weird situation map lock is held in read and now required in write mode\n");
+ #endif
+-		/* First free the lock held in read */
+-		rc = plugin_unlock();
+-		if (rc) {
+-			slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-				"map wrlock: fail to unlock plugin lock (%d)\n", rc);
+-			goto common;
+-		}
++            /* First free the lock held in read */
++            rc = plugin_unlock();
++            if (rc) {
++                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                        "map wrlock: fail to unlock plugin lock (%d)\n", rc);
++                goto common;
++            }
+ 
+-		/* Second acquire it in write */
+-		rc = plugin_wrlock();
+-		if (rc) {
+-			slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-				"map wrlock: fail to write lock plugin lock (%d)\n", rc);
+-			goto common;
+-		}
++            /* Second acquire it in write */
++            rc = plugin_wrlock();
++            if (rc) {
++                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                        "map wrlock: fail to write lock plugin lock (%d)\n", rc);
++                goto common;
+             }
+         }
++    }
+ 
+ common:
+     set_plugin_monitor_status(MAP_WLOCK_HELD);
+@@ -1425,7 +1425,7 @@ int
+ map_unlock(void)
+  {
+ 	int lock_status;
+-        int lock_count;
++    int lock_count;
+ 	int rc = 0;
+ 
+ 	if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
+@@ -1436,7 +1436,7 @@ map_unlock(void)
+ 	}
+ 
+ 	lock_status = get_plugin_monitor_status();
+-        lock_count = get_plugin_monitor_count();
++    lock_count = get_plugin_monitor_count();
+ 
+ #if DEBUG_MAP_LOCK
+ 	slapi_log_error(SLAPI_LOG_FATAL, "map_unlock",
+@@ -1448,48 +1448,48 @@ map_unlock(void)
+ 				"map_unlock: old way lock_status == MAP_RWLOCK_UNINIT\n");
+ 
+ 		return wrap_rwlock_unlock(map_data.lock);
+-	}
++    }
+ 
+-        if (lock_count == 1) {
+-            set_plugin_monitor_status(MAP_RWLOCK_FREE);
+-            rc = plugin_unlock();
+-            if (rc) {
+-			slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-				"map unlock: fail to unlock plugin lock (%d)\n", rc);
+-			goto common;
+-            }
+-#if DEBUG_MAP_LOCK
++    if (lock_count == 1) {
++        set_plugin_monitor_status(MAP_RWLOCK_FREE);
++        rc = plugin_unlock();
++        if (rc) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-				"map_unlock: (%p)  %s --> MAP_RWLOCK_FREE  : count=%d\n",
+-                        PR_GetCurrentThread(),
+-                        (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
+-                        0);
++                    "map unlock: fail to unlock plugin lock (%d)\n", rc);
++            goto common;
++        }
++#if DEBUG_MAP_LOCK
++        slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                "map_unlock: (%p)  %s --> MAP_RWLOCK_FREE  : count=%d\n",
++                PR_GetCurrentThread(),
++                (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
++                0);
+ #endif
+-            rc = wrap_rwlock_unlock(map_data.lock);
+-            if (rc) {
+-                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++        rc = wrap_rwlock_unlock(map_data.lock);
++        if (rc) {
++            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                     "map_unlock: fail to unlock map lock (%d)\n", rc);
+-                goto common;
+-            }
++            goto common;
+         }
+-        if (lock_count >= 1) {
+-            set_plugin_monitor_count(lock_count - 1);
++    }
++    if (lock_count >= 1) {
++        set_plugin_monitor_count(lock_count - 1);
+ #if DEBUG_MAP_LOCK
+-            if (lock_count > 1) {
+-                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-                                    "map_unlock: (%p)  keep %s : count=%d\n",
+-                            PR_GetCurrentThread(),
+-                            (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
+-                            lock_count - 1);
+-            } else {
+-                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-                                    "map_unlock: (%p)  is now %s : count=%d\n",
+-                            PR_GetCurrentThread(),
+-                            "MAP_RWLOCK_FREE",
+-                            lock_count - 1);
+-            }
+-#endif
++        if (lock_count > 1) {
++            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                    "map_unlock: (%p)  keep %s : count=%d\n",
++                    PR_GetCurrentThread(),
++                    (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
++                    lock_count - 1);
++        } else {
++            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
++                    "map_unlock: (%p)  is now %s : count=%d\n",
++                    PR_GetCurrentThread(),
++                    "MAP_RWLOCK_FREE",
++                    lock_count - 1);
+         }
++#endif
++    }
+ 
+ common:
+        return rc;
+-- 
+2.21.0
+
+
+From 5e6953c1d4e776f5e084ea69a4f6e6b485362b3d Mon Sep 17 00:00:00 2001
+From: Thierry Bordaz <tbordaz@redhat.com>
+Date: Wed, 10 Apr 2019 15:54:16 +0200
+Subject: [PATCH 08/13] Bug 1694263: improve debug msg to match pstack threadId
+
+Description:
+
+	A pstack is showing threadId that differs from the
+	the thread pointer. To match logs with pstack
+	better to display the threadId
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1694263
+Signed-off-by: Thierry Bordaz <tbordaz@redhat.com>
+---
+ src/back-sch.c | 10 +++++-----
+ src/back-shr.c | 15 +++++++++++----
+ src/back-shr.h |  1 +
+ src/map.c      | 30 +++++++++++++++---------------
+ 4 files changed, 32 insertions(+), 24 deletions(-)
+
+diff --git a/src/back-sch.c b/src/back-sch.c
+index 2d0bad0..4cacb28 100644
+--- a/src/back-sch.c
++++ b/src/back-sch.c
+@@ -2346,14 +2346,14 @@ backend_be_pre_write_cb(Slapi_PBlock *pb) {
+         }
+ #if DEBUG_MAP_LOCK
+         slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-                "backend_be_pre_write_cb: (%p) MAP_RWLOCK_FREE -> MAP_WLOCK_HELD  : count=%d\n", PR_GetCurrentThread(), 1);
++                "backend_be_pre_write_cb: (%p) MAP_RWLOCK_FREE -> MAP_WLOCK_HELD  : count=%d\n", (void *) PR_MyThreadId(), 1);
+ #endif
+     } else {
+         set_plugin_monitor_count(lock_count + 1);
+ #if DEBUG_MAP_LOCK
+         slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                         "backend_be_pre_write_cb: (%p)  %s --> MAP_WLOCK_HELD  : count=%d\n",
+-                PR_GetCurrentThread(),
++                (void *) PR_MyThreadId(),
+                 (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD",
+                 lock_count + 1);
+ #endif
+@@ -2428,7 +2428,7 @@ backend_be_post_write_cb(Slapi_PBlock *pb)
+ #if DEBUG_MAP_LOCK
+         slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                 "backend_be_post_write_cb: (%p)  %s --> MAP_RWLOCK_FREE  : count=%d\n",
+-                PR_GetCurrentThread(),
++                (void *) PR_MyThreadId(),
+                 (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
+                 0);
+ #endif
+@@ -2439,13 +2439,13 @@ backend_be_post_write_cb(Slapi_PBlock *pb)
+         if (lock_count > 1) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                     "backend_be_post_write_cb: (%p)  keep %s : count=%d\n",
+-                    PR_GetCurrentThread(),
++                    (void *) PR_MyThreadId(),
+                     (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
+                     lock_count - 1);
+         } else {
+             slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                     "backend_be_post_write_cb: (%p)  is now %s : count=%d\n",
+-                    PR_GetCurrentThread(),
++                    (void *) PR_MyThreadId(),
+                     "MAP_RWLOCK_FREE",
+                     lock_count - 1);
+         }
+diff --git a/src/back-shr.c b/src/back-shr.c
+index 920c135..2bfdf52 100644
+--- a/src/back-shr.c
++++ b/src/back-shr.c
+@@ -2868,6 +2868,13 @@ backend_shr_internal_postop_init(Slapi_PBlock *pb, struct plugin_state *state)
+ 	return 0;
+ }
+ 
++static int
++PR_MyThreadId(void)
++{
++    PRThread *thr = PR_GetCurrentThread();
++    PRUint32 myself = PR_GetThreadID(thr);
++    return myself;
++}
+ PRBool use_lock_status = PR_FALSE;
+ static unsigned int thread_plugin_lock_status;
+ PRBool use_lock_count = PR_FALSE;
+@@ -2953,7 +2960,7 @@ get_plugin_monitor_status(void)
+         ret = (int) MAP_RWLOCK_UNINIT;
+ #if DEBUG_MAP_LOCK
+     slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_status",
+-            "(%s) lock_status = %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", ret, PR_GetCurrentThread());
++            "(%s) lock_status = %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", ret, (void *) PR_MyThreadId());
+ #endif
+     return ret;
+ }
+@@ -2963,7 +2970,7 @@ set_plugin_monitor_status(int lock_status)
+ {
+ #if DEBUG_MAP_LOCK
+     slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_status",
+-            "(%s) lock_status = %d --> %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", get_plugin_monitor_status(), (int) lock_status, PR_GetCurrentThread());
++            "(%s) lock_status = %d --> %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", get_plugin_monitor_status(), (int) lock_status, (void *) PR_MyThreadId());
+ #endif
+ 
+     if (use_lock_status) {
+@@ -3010,7 +3017,7 @@ get_plugin_monitor_count(void)
+         ret = (int) MAP_RWLOCK_UNINIT;
+ #if DEBUG_MAP_LOCK
+     slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_count",
+-            "(%s) lock_count = %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", ret, PR_GetCurrentThread());
++            "(%s) lock_count = %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", ret, (void *) PR_MyThreadId());
+ #endif
+     return ret;
+ }
+@@ -3020,7 +3027,7 @@ set_plugin_monitor_count(int lock_count)
+ {
+ #if DEBUG_MAP_LOCK
+     slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_count",
+-            "(%s) lock_count = %d --> %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", get_plugin_monitor_count(), (int) lock_count, PR_GetCurrentThread());
++            "(%s) lock_count = %d --> %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", get_plugin_monitor_count(), (int) lock_count, (void *) PR_MyThreadId());
+ #endif
+     if (use_lock_count) {
+         int *lock_count_p;
+diff --git a/src/back-shr.h b/src/back-shr.h
+index 8c68b4f..5d72ad9 100644
+--- a/src/back-shr.h
++++ b/src/back-shr.h
+@@ -30,6 +30,7 @@
+ #define MAP_WLOCK_HELD    2
+ #define MAP_RLOCK_HELD    1
+ #define MAP_RWLOCK_FREE   0
++static int PR_MyThreadId(void);
+ int  rw_monitor_enabled(void);
+ int  get_plugin_monitor_status(void);
+ void set_plugin_monitor_status(int lock_status);
+diff --git a/src/map.c b/src/map.c
+index e953925..f80f465 100644
+--- a/src/map.c
++++ b/src/map.c
+@@ -1264,7 +1264,7 @@ map_rdlock(void)
+ 
+ #if DEBUG_MAP_LOCK
+ 	slapi_log_error(SLAPI_LOG_FATAL, "map_rdlock",
+-				"thread_id = %p (call level = %d)\n", PR_GetCurrentThread(), wrap_get_call_level());
++				"thread_id = %p (call level = %d)\n", (void *) PR_MyThreadId(), wrap_get_call_level());
+ #endif
+ 	if (lock_status == MAP_RWLOCK_UNINIT) {
+ 		/* This is not initialized used the old way */
+@@ -1284,7 +1284,7 @@ map_rdlock(void)
+ #if DEBUG_MAP_LOCK
+         if (lock_count != 0) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-                    "map rdlock: (%p) ALERT !!!   count was %d -> 1\n", PR_GetCurrentThread(), lock_count);
++                    "map rdlock: (%p) ALERT !!!   count was %d -> 1\n", (void *) PR_MyThreadId(), lock_count);
+         }
+ #endif
+ 
+@@ -1292,12 +1292,12 @@ map_rdlock(void)
+         rc = plugin_rdlock();
+         if (rc) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-                    "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc);
++                    "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", (void *) PR_MyThreadId(), rc);
+             return rc;
+         }
+ #if DEBUG_MAP_LOCK
+         slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-                "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD  : count=%d\n", PR_GetCurrentThread(), 1);
++                "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD  : count=%d\n", (void *) PR_MyThreadId(), 1);
+ #endif
+         rc = wrap_rwlock_rdlock(map_data.lock);
+         if (rc) {
+@@ -1312,7 +1312,7 @@ map_rdlock(void)
+ #if DEBUG_MAP_LOCK
+     slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+             "map rdlock: (%p) was already hold %s : count=%d > %d!!!\n",
+-            PR_GetCurrentThread(),
++            (void *) PR_MyThreadId(),
+             (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD",
+             lock_count, lock_count + 1);
+ #endif
+@@ -1339,7 +1339,7 @@ map_wrlock(void)
+ 
+ #if DEBUG_MAP_LOCK
+ 	slapi_log_error(SLAPI_LOG_FATAL, "map wrlock",
+-				"thread_id = %p (call level = %d)\n", PR_GetCurrentThread(), wrap_get_call_level());
++				"thread_id = %p (call level = %d)\n", (void *) PR_MyThreadId(), wrap_get_call_level());
+ #endif
+ 	if (lock_status == MAP_RWLOCK_UNINIT) {
+ 		/* This is not initialized used the old way */
+@@ -1360,25 +1360,25 @@ map_wrlock(void)
+ #if DEBUG_MAP_LOCK
+         if (lock_count != 0) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-                    "map wrlock: (%p) ALERT !!!   count was %d --> 1\n", PR_GetCurrentThread(), lock_count);
++                    "map wrlock: (%p) ALERT !!!   count was %d --> 1\n", (void *) PR_MyThreadId(), lock_count);
+         }
+ #endif
+         /* Acquire the slapi plugin in write */
+         rc = plugin_wrlock();
+         if (rc) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-                    "map wrlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_GetCurrentThread(), rc);
++                    "map wrlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", (void *) PR_MyThreadId(), rc);
+             return rc;
+         }
+ #if DEBUG_MAP_LOCK
+         slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-                "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD  : count=%d\n", PR_GetCurrentThread(), 1);
++                "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD  : count=%d\n", (void *) PR_MyThreadId(), 1);
+ #endif
+ 
+         rc = wrap_rwlock_wrlock(map_data.lock);
+         if (rc) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-                    "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", PR_GetCurrentThread(), rc);
++                    "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", (void *) PR_MyThreadId(), rc);
+             plugin_unlock();
+             goto common;
+         }
+@@ -1387,7 +1387,7 @@ map_wrlock(void)
+ #if DEBUG_MAP_LOCK
+         slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                 "map wrlock: (%p)  %s --> MAP_WLOCK_HELD  : count=%d\n",
+-                PR_GetCurrentThread(),
++                (void *) PR_MyThreadId(),
+                 (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD",
+                 lock_count + 1);
+ #endif
+@@ -1440,7 +1440,7 @@ map_unlock(void)
+ 
+ #if DEBUG_MAP_LOCK
+ 	slapi_log_error(SLAPI_LOG_FATAL, "map_unlock",
+-				"thread_id = %p (call level = %d)\n", PR_GetCurrentThread(), wrap_get_call_level());
++				"thread_id = %p (call level = %d)\n", (void *) PR_MyThreadId(), wrap_get_call_level());
+ #endif
+ 	if (lock_status == MAP_RWLOCK_UNINIT) {
+ 		/* This is not initialized used the old way */
+@@ -1461,7 +1461,7 @@ map_unlock(void)
+ #if DEBUG_MAP_LOCK
+         slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                 "map_unlock: (%p)  %s --> MAP_RWLOCK_FREE  : count=%d\n",
+-                PR_GetCurrentThread(),
++                (void *) PR_MyThreadId(),
+                 (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
+                 0);
+ #endif
+@@ -1478,13 +1478,13 @@ map_unlock(void)
+         if (lock_count > 1) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                     "map_unlock: (%p)  keep %s : count=%d\n",
+-                    PR_GetCurrentThread(),
++                    (void *) PR_MyThreadId(),
+                     (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
+                     lock_count - 1);
+         } else {
+             slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                     "map_unlock: (%p)  is now %s : count=%d\n",
+-                    PR_GetCurrentThread(),
++                    (void *) PR_MyThreadId(),
+                     "MAP_RWLOCK_FREE",
+                     lock_count - 1);
+         }
+-- 
+2.21.0
+
+
+From 52fd1595699ea9859c2f4c41ae7ff425d65ae3cf Mon Sep 17 00:00:00 2001
+From: Thierry Bordaz <tbordaz@redhat.com>
+Date: Wed, 10 Apr 2019 18:40:02 +0200
+Subject: [PATCH 09/13] Bug 1694263: On some 'cn=config' updates bepost_op are
+ not called that leads to lock leak
+
+Description:
+	The true cause of the hang was that some updates on 'cn=config'
+	can skip the BEPOST phase. (in this bug it was the maxbersize setting).
+	The consequence is that the slapi-nis map lock was acquired but not released.
+	The fix consist to ignore (not lock slapi-nis map) write operation done
+	on 'cn=config' and 'cn=schema'
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1694263
+Signed-off-by: Thierry Bordaz <tbordaz@redhat.com>
+---
+ src/back-sch.c | 48 +++++++++++++++++++++++++++++++++++++++++++++---
+ src/back-shr.c | 22 ++++++++++++++++++++--
+ src/back-shr.h |  3 ++-
+ src/plug-sch.c |  7 +++++++
+ 4 files changed, 74 insertions(+), 6 deletions(-)
+
+diff --git a/src/back-sch.c b/src/back-sch.c
+index 4cacb28..9201c2e 100644
+--- a/src/back-sch.c
++++ b/src/back-sch.c
+@@ -2303,6 +2303,33 @@ backend_betxn_pre_write_cb(Slapi_PBlock *pb)
+ 	slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
+ 	return state->use_be_txns ? backend_write_cb(pb, state) : 0;
+ }
++static PRBool
++backend_be_write_ignore(Slapi_PBlock *pb)
++{
++    char *dn = NULL;
++    Slapi_DN *target_sdn = NULL;
++    int check;
++    int i = 0;
++    PRBool ignore = PR_FALSE;
++
++    /* Check if the target DN is a subordinates of
++     * on of the ignored containers
++     */
++    slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET, &dn);
++    target_sdn = slapi_sdn_new_dn_byval(dn);
++
++    for (i = 0; ignored_containers_sdn[i]; i++) {
++        check  = slapi_sdn_issuffix(target_sdn, ignored_containers_sdn[i]);
++        if (check != 0) {
++            /* This entry is an ignored container */
++            ignore = PR_TRUE;
++            break;
++        }
++    }
++    slapi_sdn_free(&target_sdn);
++    return ignore;
++}
++
+ 
+ static int
+ backend_be_pre_write_cb(Slapi_PBlock *pb) {
+@@ -2323,6 +2350,14 @@ backend_be_pre_write_cb(Slapi_PBlock *pb) {
+     if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
+         return 0;
+     }
++    if (backend_be_write_ignore(pb)) {
++#if DEBUG_MAP_LOCK
++        slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++                "backend_be_pre_write_cb: (%p) operation is not impacting schema compat\n", PR_MyThreadId(), 1);
++#endif
++        return 0;
++    }
++
+ 
+ 
+     wrap_inc_call_level();
+@@ -2404,9 +2439,16 @@ backend_be_post_write_cb(Slapi_PBlock *pb)
+ 		/* No data to serve yet */
+ 		return 0;
+ 	}
+-        if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
+-            return 0;
+-        }
++    if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
++        return 0;
++    }
++    if (backend_be_write_ignore(pb)) {
++#if DEBUG_MAP_LOCK
++        slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
++                "backend_be_post_write_cb: (%p) operation was not impacting schema compat\n", PR_MyThreadId(), 1);
++#endif
++        return 0;
++    }
+ 
+ 	wrap_inc_call_level();
+ 
+diff --git a/src/back-shr.c b/src/back-shr.c
+index 2bfdf52..b348869 100644
+--- a/src/back-shr.c
++++ b/src/back-shr.c
+@@ -2868,7 +2868,7 @@ backend_shr_internal_postop_init(Slapi_PBlock *pb, struct plugin_state *state)
+ 	return 0;
+ }
+ 
+-static int
++int
+ PR_MyThreadId(void)
+ {
+     PRThread *thr = PR_GetCurrentThread();
+@@ -2902,14 +2902,32 @@ lock_count_free(void *ptr)
+     }
+ }
+ 
++/* This is used to ignore some write operations
++ * if they target subordinates entry of ignored containers
++ */
++Slapi_DN **ignored_containers_sdn = NULL;
+ void
+ init_map_lock(void)
+ {
+ #if DEBUG_MAP_LOCK
+     /* The plugin lock is initialized as free */
+     slapi_log_error(SLAPI_LOG_FATAL, "init_plugin_lock",
+-            "thread_id = %p\n", PR_GetCurrentThread());
++            "thread_id = %p\n", PR_MyThreadId());
+ #endif
++    if (ignored_containers_sdn == NULL) {
++        /* allocates ignored_containers_sdn of Slapi_DN* only once
++         * It will be used later in be_pre/post_write_cb
++         */
++        int cnt;
++        char *ignored_containers[3] = { "cn=config", "cn=schema", NULL};
++
++        for (cnt = 0; ignored_containers[cnt]; cnt++);
++        ignored_containers_sdn = (Slapi_DN **) slapi_ch_calloc(cnt + 1, sizeof(Slapi_DN *));
++
++        for (cnt = 0; ignored_containers[cnt]; cnt++) {
++            ignored_containers_sdn[cnt] = slapi_sdn_new_dn_byval(ignored_containers[cnt]);
++        }
++    }
+ 
+     if (PR_NewThreadPrivateIndex(&thread_plugin_lock_status, lock_status_free) == PR_SUCCESS) {
+         use_lock_status = PR_TRUE;
+diff --git a/src/back-shr.h b/src/back-shr.h
+index 5d72ad9..d01b999 100644
+--- a/src/back-shr.h
++++ b/src/back-shr.h
+@@ -30,13 +30,14 @@
+ #define MAP_WLOCK_HELD    2
+ #define MAP_RLOCK_HELD    1
+ #define MAP_RWLOCK_FREE   0
+-static int PR_MyThreadId(void);
++int PR_MyThreadId(void);
+ int  rw_monitor_enabled(void);
+ int  get_plugin_monitor_status(void);
+ void set_plugin_monitor_status(int lock_status);
+ int  get_plugin_monitor_count(void);
+ void set_plugin_monitor_count(int lock_count);
+ void init_map_lock(void);
++Slapi_DN **ignored_containers_sdn;
+ 
+ 
+ struct plugin_state;
+diff --git a/src/plug-sch.c b/src/plug-sch.c
+index 2d9c75b..913abe2 100644
+--- a/src/plug-sch.c
++++ b/src/plug-sch.c
+@@ -197,6 +197,13 @@ plugin_shutdown(Slapi_PBlock *pb)
+ 	if (state->plugin_base != NULL) {
+ 		slapi_ch_free((void **)&state->plugin_base);
+ 	}
++	if (ignored_containers_sdn) {
++		int i;
++		for (i = 0; ignored_containers_sdn[i]; i++) {
++			slapi_sdn_free(&ignored_containers_sdn[i]);
++		}
++		slapi_ch_free((void **)&ignored_containers_sdn);
++	}
+ 	slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ 			"plugin shutdown completed\n");
+ 	return 0;
+-- 
+2.21.0
+
+
+From c44f9ca81afa6cbf817159d37b0695d6462866eb Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Tue, 23 Apr 2019 09:39:08 +0300
+Subject: [PATCH 10/13] Cast callbacks passed to xdrrec_create to a right type
+
+With newer compilers there are stricter checks on callback type
+validation. As result, we need to cast the callback signatures even
+though it makes no practical difference in our test case.
+---
+ tests/clients/yp.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/tests/clients/yp.c b/tests/clients/yp.c
+index 200d591..bc2da1f 100644
+--- a/tests/clients/yp.c
++++ b/tests/clients/yp.c
+@@ -34,6 +34,8 @@
+ #include <rpc/rpc.h>
+ #include "../../yp/yp.h"
+ 
++typedef int (*xdrrec_proc_t)(void *, void *, int);
++
+ static struct sockaddr_in server;
+ static int connected;
+ 
+@@ -189,7 +191,7 @@ all(CLIENT *client, FILE *output, int argc, char **argv)
+ 	}
+ 
+ 	memset(&s, 0, sizeof(s));
+-	xdrrec_create(&s, 0, 0, (char *) &sock, &readjunk, &writejunk);
++	xdrrec_create(&s, 0, 0, (char *) &sock, (xdrrec_proc_t) &readjunk, (xdrrec_proc_t) &writejunk);
+ 	s.x_op = XDR_ENCODE;
+ 
+ 	memset(&req, 0, sizeof(req));
+@@ -218,7 +220,7 @@ all(CLIENT *client, FILE *output, int argc, char **argv)
+ 	xdr_destroy(&s);
+ 
+ 	memset(&s, 0, sizeof(s));
+-	xdrrec_create(&s, 0, 0, (char *) &sock, &readjunk, &writejunk);
++	xdrrec_create(&s, 0, 0, (char *) &sock, (xdrrec_proc_t) &readjunk, (xdrrec_proc_t) &writejunk);
+ 	s.x_op = XDR_DECODE;
+ 	xdrrec_skiprecord(&s);
+ 
+-- 
+2.21.0
+
+
+From a4f645e09d92a8b8f7a80f939091689075d53de1 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Tue, 23 Apr 2019 09:40:59 +0300
+Subject: [PATCH 11/13] Define send_ldap_result as an external function
+ prototype
+
+389-ds does not expose send_ldap_result() as a public API. However,
+we depend on it because slapi_send_ldap_result() is not usable for
+the specific use case of the schema compatibility plugin.
+---
+ src/back-sch.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/back-sch.c b/src/back-sch.c
+index 9201c2e..f6211bc 100644
+--- a/src/back-sch.c
++++ b/src/back-sch.c
+@@ -55,6 +55,12 @@
+ #include "map.h"
+ #include "back-sch.h"
+ 
++/*
++ * This is not a public function in 389-ds but we need to use it in backend_search_cb(),
++ * see a comment there on the difference between slapi_send_ldap_result() and send_ldap_result().
++ */
++extern void send_ldap_result(Slapi_PBlock *pb, int err, char *matched, char *text, int nentries, struct berval **urls);
++
+ static int backend_passwdmod_extop(Slapi_PBlock *pb);
+ backend_extop_handlers_t extop_handlers[] = {{EXTOP_PASSWD_OID, (IFP) backend_passwdmod_extop},
+ 					    {NULL, NULL}};
+-- 
+2.21.0
+
+
+From dc3c95cf5b5a2c2d5e7f81ed02f2d9bf3c9acb9f Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Tue, 23 Apr 2019 09:42:41 +0300
+Subject: [PATCH 12/13] Declare transaction-aware callbacks for schema compat
+ plugin
+
+Schema compatibility plugin provides two transaction-aware
+callbacks. The functions need to be declared as they are defined and
+used in different compilation units.
+---
+ src/backend.h | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/src/backend.h b/src/backend.h
+index f0a5bbb..4034704 100644
+--- a/src/backend.h
++++ b/src/backend.h
+@@ -68,6 +68,11 @@ int backend_init_postop(struct slapi_pblock *pb, struct plugin_state *state);
+ int backend_init_internal_postop(struct slapi_pblock *pb,
+ 				 struct plugin_state *state);
+ 
++/* Only used for schema compatibility plugin*/
++int backend_init_be_preop(Slapi_PBlock *pb, struct plugin_state *state);
++int backend_init_be_postop(Slapi_PBlock *pb, struct plugin_state *state);
++
++
+ /* Read the server's name. */
+ int backend_read_master_name(struct plugin_state *state,
+ 			     struct slapi_pblock *pb,
+-- 
+2.21.0
+
+
+From 1d9e79557df660f4556edb59bedead00eda9b757 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Tue, 23 Apr 2019 09:44:48 +0300
+Subject: [PATCH 13/13] Use portable definitions for printing PRUint32 values
+
+Also include proper headers for NSPR thread-local variable handling.
+Fixes covscan warnings.
+---
+ src/back-shr.c |  4 +++-
+ src/map.c      | 28 ++++++++++++++++------------
+ 2 files changed, 19 insertions(+), 13 deletions(-)
+
+diff --git a/src/back-shr.c b/src/back-shr.c
+index b348869..472846a 100644
+--- a/src/back-shr.c
++++ b/src/back-shr.c
+@@ -37,7 +37,9 @@
+ #endif
+ 
+ #include <rpc/xdr.h>
+-#include <nspr4/prtypes.h>
++#include <prtypes.h>
++/* NSPR private API for thread-local variables */
++#include <private/prpriv.h>
+ #include "../yp/yp.h"
+ 
+ #ifdef HAVE_TCPD_H
+diff --git a/src/map.c b/src/map.c
+index f80f465..3be60b4 100644
+--- a/src/map.c
++++ b/src/map.c
+@@ -23,6 +23,7 @@
+ #include "config.h"
+ #endif
+ 
++#include <inttypes.h>
+ #include <sys/types.h>
+ #include <search.h>
+ #include <stdlib.h>
+@@ -40,6 +41,9 @@
+ 
+ #include <rpc/rpc.h>
+ 
++/* NSPR private API for thread-local variables */
++#include <private/prpriv.h>
++
+ #include "backend.h"
+ #include "disp-nis.h"
+ #include "map.h"
+@@ -1264,7 +1268,7 @@ map_rdlock(void)
+ 
+ #if DEBUG_MAP_LOCK
+ 	slapi_log_error(SLAPI_LOG_FATAL, "map_rdlock",
+-				"thread_id = %p (call level = %d)\n", (void *) PR_MyThreadId(), wrap_get_call_level());
++				"thread_id = %"PRIx32" (call level = %d)\n", PR_MyThreadId(), wrap_get_call_level());
+ #endif
+ 	if (lock_status == MAP_RWLOCK_UNINIT) {
+ 		/* This is not initialized used the old way */
+@@ -1284,7 +1288,7 @@ map_rdlock(void)
+ #if DEBUG_MAP_LOCK
+         if (lock_count != 0) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-                    "map rdlock: (%p) ALERT !!!   count was %d -> 1\n", (void *) PR_MyThreadId(), lock_count);
++                    "map rdlock: (%"PRIx32") ALERT !!!   count was %d -> 1\n", PR_MyThreadId(), lock_count);
+         }
+ #endif
+ 
+@@ -1292,12 +1296,12 @@ map_rdlock(void)
+         rc = plugin_rdlock();
+         if (rc) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-                    "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", (void *) PR_MyThreadId(), rc);
++                    "map rdlock: (%"PRIx32") MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_MyThreadId(), rc);
+             return rc;
+         }
+ #if DEBUG_MAP_LOCK
+         slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-                "map rdlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD  : count=%d\n", (void *) PR_MyThreadId(), 1);
++                "map rdlock: (%"PRIx32") MAP_RWLOCK_FREE -> MAP_RLOCK_HELD  : count=%d\n", PR_MyThreadId(), 1);
+ #endif
+         rc = wrap_rwlock_rdlock(map_data.lock);
+         if (rc) {
+@@ -1311,8 +1315,8 @@ map_rdlock(void)
+ 
+ #if DEBUG_MAP_LOCK
+     slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-            "map rdlock: (%p) was already hold %s : count=%d > %d!!!\n",
+-            (void *) PR_MyThreadId(),
++            "map rdlock: (%x"PRIx32") was already hold %s : count=%d > %d!!!\n",
++            PR_MyThreadId(),
+             (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD",
+             lock_count, lock_count + 1);
+ #endif
+@@ -1360,25 +1364,25 @@ map_wrlock(void)
+ #if DEBUG_MAP_LOCK
+         if (lock_count != 0) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-                    "map wrlock: (%p) ALERT !!!   count was %d --> 1\n", (void *) PR_MyThreadId(), lock_count);
++                    "map wrlock: (%"PRIx32") ALERT !!!   count was %d --> 1\n", PR_MyThreadId(), lock_count);
+         }
+ #endif
+         /* Acquire the slapi plugin in write */
+         rc = plugin_wrlock();
+         if (rc) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+-                    "map wrlock: (%p) MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", (void *) PR_MyThreadId(), rc);
++                    "map wrlock: (%"PRIx32") MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_MyThreadId(), rc);
+             return rc;
+         }
+ #if DEBUG_MAP_LOCK
+         slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-                "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD  : count=%d\n", (void *) PR_MyThreadId(), 1);
++                "map wrlock: (%"PRIx32") MAP_RWLOCK_FREE --> MAP_WLOCK_HELD  : count=%d\n", PR_MyThreadId(), 1);
+ #endif
+ 
+         rc = wrap_rwlock_wrlock(map_data.lock);
+         if (rc) {
+             slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-                    "map wrlock: (%p) MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", (void *) PR_MyThreadId(), rc);
++                    "map wrlock: (%"PRIx32") MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", PR_MyThreadId(), rc);
+             plugin_unlock();
+             goto common;
+         }
+@@ -1386,8 +1390,8 @@ map_wrlock(void)
+         set_plugin_monitor_count(lock_count + 1);
+ #if DEBUG_MAP_LOCK
+         slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+-                "map wrlock: (%p)  %s --> MAP_WLOCK_HELD  : count=%d\n",
+-                (void *) PR_MyThreadId(),
++                "map wrlock: (%"PRIx32")  %s --> MAP_WLOCK_HELD  : count=%d\n",
++                PR_MyThreadId(),
+                 (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD",
+                 lock_count + 1);
+ #endif
+-- 
+2.21.0
+
diff --git a/SPECS/slapi-nis.spec b/SPECS/slapi-nis.spec
index ca86aee..0ea5184 100644
--- a/SPECS/slapi-nis.spec
+++ b/SPECS/slapi-nis.spec
@@ -11,13 +11,13 @@
 
 Name:		slapi-nis
 Version:	0.56.0
-Release:	8%{?dist}
+Release:	12%{?dist}
 Summary:	NIS Server and Schema Compatibility plugins for Directory Server
 Group:		System Environment/Daemons
 License:	GPLv2
-URL:		http://slapi-nis.fedorahosted.org/
-Source0:	https://fedorahosted.org/releases/s/l/slapi-nis/slapi-nis-%{version}.tar.gz
-Source1:	https://fedorahosted.org/releases/s/l/slapi-nis/slapi-nis-%{version}.tar.gz.sig
+URL:		http://pagure.io/slapi-nis/
+Source0:	https://releases.pagure.org/slapi-nis/slapi-nis-%{version}.tar.gz
+Source1:	https://releases.pagure.org/slapi-nis/slapi-nis-%{version}.tar.gz.sig
 Patch1:		slapi-0001-Move-advance-definition-of-backend_passwdmod_extop-b.patch
 Patch2:		slapi-0002-Initialize-ret-before-use.patch
 Patch3:		slapi-0003-slapi-nis-resolve-IPA-groups-with-fully-qualified-su.patch
@@ -35,6 +35,7 @@ Patch18:	slapi-0017-Fix-nss_sss-callers.patch
 Patch19:	slapi-0018-Clean-up-unused-code.patch
 Patch20:	slapi-0019-Synchronize-nsswitch-backend-code-with-freeIPA.patch
 Patch21:	slapi-0020-Use-extended-SSSD-API-to-signal-that-an-entry-should.patch
+Patch22:	slapi-0100-deadlok-between-write-and-search-operation.patch
 
 BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
@@ -96,6 +97,7 @@ for attributes from multiple entries in the tree.
 %patch19 -p1
 %patch20 -p1
 %patch21 -p1
+%patch22 -p1
 
 %build
 libtoolize -f -c
@@ -131,6 +133,21 @@ rm -rf $RPM_BUILD_ROOT
 %{_sbindir}/nisserver-plugin-defs
 
 %changelog
+* Tue Apr 23 2019 Alexander Bokovoy <abokovoy@redhat.com> - 0.56.0-12
+- Related: #1435663
+  Covscan fixes
+
+* Wed Mar 27 2019 Alexander Bokovoy <abokovoy@redhat.com> - 0.56.0-11
+- Fixed: #1435663
+  Additional set of fixes for conflicts over cn=config updates
+
+* Wed Mar 27 2019 Alexander Bokovoy <abokovoy@redhat.com> - 0.56.0-10
+- Fixed: #1435663
+
+* Wed Dec 05 2018 Alexander Bokovoy <abokovoy@redhat.com> - 0.56.0-9
+- Fixed: #1502429
+- Update upstream reference to http://pagure.io/slapi-nis/
+
 * Fri Dec 08 2017 Alexander Bokovoy <abokovoy@redhat.com> - 0.56.0-8
 - Fixed: #1473572
 - Changes of ID overrides now force clearing of affected SSSD cache entries on IPA master