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