Browse Source

Bug 711679 - unresponsive LDAP service when deleting vlv on replica

https://bugzilla.redhat.com/show_bug.cgi?id=711679

Bug Description:
When a vlv index is created, a newly generated vlv index object
is linked in the vlv search list.  If the server is under stress,
there could be some contention among threads and each thread
could add an identical vlv index object to the list, which leads
to open the vlv index db more than once - count of the objects.
Opening a db file locks it with a READ lock.  Deleting the vlv
index first closes the db which is supposed to release the READ
lock.  But since the db is opened more than once, still some READ
lock remains.  And the deleter's attempt to lock the db with WRITE
lock is kept waiting for the READ lock released, that never happens.

Fix Description:
Check the vlv index object before adding it to the vlv search list.
If the identical object is found in the list, adding is skipped.
Noriko Hosoi 14 years ago
parent
commit
25687041f1
2 changed files with 23 additions and 13 deletions
  1. 19 12
      ldap/servers/slapd/back-ldbm/vlv.c
  2. 4 1
      ldap/servers/slapd/back-ldbm/vlv_srch.c

+ 19 - 12
ldap/servers/slapd/back-ldbm/vlv.c

@@ -92,25 +92,32 @@ int vlv_AddSearchEntry(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
 
 int vlv_AddIndexEntry(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
 { 
-	struct vlvSearch *parent;
-	backend *be= ((ldbm_instance*)arg)->inst_be;
-	Slapi_DN parentdn;
-	
-	slapi_sdn_init(&parentdn);
-	slapi_sdn_get_parent(slapi_entry_get_sdn(entryBefore),&parentdn);
+    struct vlvSearch *parent;
+    backend *be= ((ldbm_instance*)arg)->inst_be;
+    Slapi_DN parentdn;
+
+    slapi_sdn_init(&parentdn);
+    slapi_sdn_get_parent(slapi_entry_get_sdn(entryBefore),&parentdn);
+
+    /* vlvIndex list is modified; need Wlock */
+    PR_RWLock_Wlock(be->vlvSearchList_lock);
+    parent= vlvSearch_finddn((struct vlvSearch *)be->vlvSearchList, &parentdn);
+    if(parent!=NULL)
     {
-        /* vlvIndex list is modified; need Wlock */
-        PR_RWLock_Wlock(be->vlvSearchList_lock);
-        parent= vlvSearch_finddn((struct vlvSearch *)be->vlvSearchList, &parentdn);
-        if(parent!=NULL)
-        {
+        char *name = slapi_entry_attr_get_charptr(entryBefore, type_vlvName);
+        if (vlvSearch_findname(parent, name)) {
+            /* The vlvindex is already in the vlvSearchList. Skip adding it. */
+            LDAPDebug1Arg(LDAP_DEBUG_BACKLDBM,
+                          "vlv_AddIndexEntry: %s is already in vlvSearchList\n",
+                          slapi_entry_get_dn_const(entryBefore));
+        } else {
             struct vlvIndex* newVlvIndex= vlvIndex_new();
             newVlvIndex->vlv_be=be;
             vlvIndex_init(newVlvIndex, be, parent, entryBefore);
             vlvSearch_addIndex(parent, newVlvIndex);
         }
-        PR_RWLock_Unlock(be->vlvSearchList_lock);
     }
+    PR_RWLock_Unlock(be->vlvSearchList_lock);
     slapi_sdn_done(&parentdn);
     return SLAPI_DSE_CALLBACK_OK;
 }

+ 4 - 1
ldap/servers/slapd/back-ldbm/vlv_srch.c

@@ -373,6 +373,9 @@ struct vlvIndex*
 vlvSearch_findindexname(const struct vlvSearch* plist, const char *name)
 {
     const struct vlvSearch* t= plist;
+    if (NULL == name) {
+        return NULL;
+    }
     for(; t!=NULL ; t= t->vlv_next)
     {
         struct vlvIndex *pi= t->vlv_index;
@@ -781,7 +784,7 @@ void vlvIndex_go_offline(struct vlvIndex *p, backend *be)
         return;
     p->vlv_online = 0;
     p->vlv_enabled = 0;
-	p->vlv_indexlength = 0;
+    p->vlv_indexlength = 0;
     p->vlv_attrinfo->ai_indexmask |= INDEX_OFFLINE;
     dblayer_erase_index_file_nolock(be, p->vlv_attrinfo, 1 /* chkpt if not busy */);
 }