ldap/servers/slapd/back-ldbm/back-ldbm.h | 22 +++++++++++-----------
ldap/servers/slapd/back-ldbm/backentry.c | 2 +-
ldap/servers/slapd/back-ldbm/cache.c | 19 ++++++++++++++-----
ldap/servers/slapd/back-ldbm/id2entry.c | 1 -
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 6 ++----
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 6 ++----
ldap/servers/slapd/modify.c | 4 ++++
7 files changed, 34 insertions(+), 26 deletions(-)
New commits:
commit 9a9f93c0b47a1755fd1bb637f35a730108119779
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Oct 28 11:37:53 2011 -0700
Bug 745259 - Incorrect entryUSN index under high load
in replicated environment
https://bugzilla.redhat.com/show_bug.cgi?id=745259
Description:
. Changed the backend entry lock from PRLock to PRMonitor to
allow re-entrant locking. In ldbm_back_delete and ldbm_
back_modify, backend entry lock was released before calling
be_preop plugins and re-acquired just after that to avoid
the deadlock by the be_preop plugins called from the same
thread. The short no-lock window was the cause of the entry-
usn corruption. By replacing PRLock with the re-entrant
PRMonitor, we could eliminate the no-lock window.
. Cleaned up compiler warnings.
diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h
b/ldap/servers/slapd/back-ldbm/back-ldbm.h
index f5668d2..db0c833 100644
--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h
@@ -350,19 +350,19 @@ struct backcommon {
/* From ep_type through ep_size MUST be identical to backcommon */
struct backentry {
- int ep_type; /* to distinguish backdn from backentry */
- struct backcommon *ep_lrunext; /* for the cache */
- struct backcommon *ep_lruprev; /* for the cache */
- ID ep_id; /* entry id */
- char ep_state; /* state in the cache */
- int ep_refcnt; /* entry reference cnt */
+ int ep_type; /* to distinguish backdn from backentry */
+ struct backcommon *ep_lrunext; /* for the cache */
+ struct backcommon *ep_lruprev; /* for the cache */
+ ID ep_id; /* entry id */
+ char ep_state; /* state in the cache */
+ int ep_refcnt; /* entry reference cnt */
size_t ep_size; /* for cache tracking */
- Slapi_Entry *ep_entry; /* real entry */
+ Slapi_Entry *ep_entry; /* real entry */
Slapi_Entry *ep_vlventry;
- void * ep_dn_link; /* linkage for the 3 hash */
- void * ep_id_link; /* tables used for */
- void * ep_uuid_link; /* looking up entries */
- PRLock *ep_mutexp; /* protection for mods */
+ void * ep_dn_link; /* linkage for the 3 hash */
+ void * ep_id_link; /* tables used for */
+ void * ep_uuid_link; /* looking up entries */
+ PRMonitor *ep_mutexp; /* protection for mods; make it reentrant */
};
/* From ep_type through ep_size MUST be identical to backcommon */
diff --git a/ldap/servers/slapd/back-ldbm/backentry.c
b/ldap/servers/slapd/back-ldbm/backentry.c
index c26f552..9fe6fb6 100644
--- a/ldap/servers/slapd/back-ldbm/backentry.c
+++ b/ldap/servers/slapd/back-ldbm/backentry.c
@@ -56,7 +56,7 @@ backentry_free( struct backentry **bep )
slapi_entry_free( ep->ep_entry );
}
if ( ep->ep_mutexp != NULL ) {
- PR_DestroyLock( ep->ep_mutexp );
+ PR_DestroyMonitor( ep->ep_mutexp );
}
slapi_ch_free( (void**)&ep );
*bep = NULL;
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
index 3d09bb3..e2f1768 100644
--- a/ldap/servers/slapd/back-ldbm/cache.c
+++ b/ldap/servers/slapd/back-ldbm/cache.c
@@ -1437,19 +1437,28 @@ int cache_lock_entry(struct cache *cache, struct backentry *e)
if (! e->ep_mutexp) {
/* make sure only one thread does this */
PR_Lock(cache->c_emutexalloc_mutex);
- if (! e->ep_mutexp)
- e->ep_mutexp = PR_NewLock();
+ if (! e->ep_mutexp) {
+ e->ep_mutexp = PR_NewMonitor();
+ if (!e->ep_mutexp) {
+ LOG("<= cache_lock_entry (DELETED)\n", 0, 0, 0);
+ LDAPDebug1Arg(LDAP_DEBUG_ANY,
+ "cache_lock_entry: failed to create a lock for %s\n",
+ backentry_get_ndn(e));
+ LOG("<= cache_lock_entry (FAILED)\n", 0, 0, 0);
+ return 1;
+ }
+ }
PR_Unlock(cache->c_emutexalloc_mutex);
}
/* wait on entry lock (done w/o holding the cache lock) */
- PR_Lock(e->ep_mutexp);
+ PR_EnterMonitor(e->ep_mutexp);
/* make sure entry hasn't been deleted now */
PR_Lock(cache->c_mutex);
if (e->ep_state & (ENTRY_STATE_DELETED|ENTRY_STATE_NOTINCACHE)) {
PR_Unlock(cache->c_mutex);
- PR_Unlock(e->ep_mutexp);
+ PR_ExitMonitor(e->ep_mutexp);
LOG("<= cache_lock_entry (DELETED)\n", 0, 0, 0);
return 1;
}
@@ -1463,7 +1472,7 @@ int cache_lock_entry(struct cache *cache, struct backentry *e)
void cache_unlock_entry(struct cache *cache, struct backentry *e)
{
LOG("=> cache_unlock_entry\n", 0, 0, 0);
- PR_Unlock(e->ep_mutexp);
+ PR_ExitMonitor(e->ep_mutexp);
}
/* DN cache */
diff --git a/ldap/servers/slapd/back-ldbm/id2entry.c
b/ldap/servers/slapd/back-ldbm/id2entry.c
index bd51a7f..91a4ff0 100644
--- a/ldap/servers/slapd/back-ldbm/id2entry.c
+++ b/ldap/servers/slapd/back-ldbm/id2entry.c
@@ -95,7 +95,6 @@ id2entry_add_ext( backend *be, struct backentry *e, back_txn *txn, int
encrypt
memset(&data, 0, sizeof(data));
if (entryrdn_get_switch())
{
- Slapi_Attr *eattr = NULL;
struct backdn *oldbdn = NULL;
Slapi_DN *sdn =
slapi_sdn_dup(slapi_entry_get_sdn_const(entry_to_use));
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index c1f1142..46bfcc3 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -210,11 +210,9 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
- /* have to unlock the entry here, in case the bepreop attempts
- to modify the same entry == deadlock */
- cache_unlock_entry( &inst->inst_cache, e );
+
rc = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN);
- cache_lock_entry( &inst->inst_cache, e );
+
if (rc == -1)
{
/*
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index 1a85e14..ba6527f 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -307,11 +307,9 @@ ldbm_back_modify( Slapi_PBlock *pb )
/* ec is the entry that our bepreop should get to mess with */
slapi_pblock_set( pb, SLAPI_MODIFY_EXISTING_ENTRY, ec->ep_entry );
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
- /* have to unlock the entry here, in case the bepreop attempts
- to modify the same entry == deadlock */
- cache_unlock_entry( &inst->inst_cache, e );
+
plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN);
- cache_lock_entry( &inst->inst_cache, e );
+
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
/* The Plugin may have messed about with some of the PBlock parameters... ie. mods */
slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
index 45e55b2..a0af006 100644
--- a/ldap/servers/slapd/modify.c
+++ b/ldap/servers/slapd/modify.c
@@ -75,7 +75,9 @@
/* Forward declarations */
static int modify_internal_pb (Slapi_PBlock *pb);
static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char *old_pw);
+#if 0 /* not used */
static void remove_mod (Slapi_Mods *smods, const char *type, Slapi_Mods *smod_unhashed);
+#endif
static int op_shared_allow_pw_change (Slapi_PBlock *pb, LDAPMod *mod, char **old_pw,
Slapi_Mods *smods);
static int hash_rootpw (LDAPMod **mods);
@@ -976,6 +978,7 @@ free_and_return:
}
}
+#if 0 /* not used */
static void remove_mod (Slapi_Mods *smods, const char *type, Slapi_Mods *smod_unhashed)
{
LDAPMod *mod;
@@ -991,6 +994,7 @@ static void remove_mod (Slapi_Mods *smods, const char *type,
Slapi_Mods *smod_un
}
}
}
+#endif
static int op_shared_allow_pw_change (Slapi_PBlock *pb, LDAPMod *mod, char **old_pw,
Slapi_Mods *smods)
{