Blob Blame Raw
From 0cf9e38234476a0f3680ea388351f9bf90735818 Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@redhat.com>
Date: Fri, 14 Aug 2015 11:19:24 -0700
Subject: [PATCH 45/45] Ticket #48250 - Slapd crashes reported from latest
 build

Bug Description: There was a conflict between an import task and
deleting the instance.  While the import task was still running,
the backend instance was removed, which should have been rejected.

Fix Description: Backend tasks keeps instance refcnt positive and
disable the backend in the mapping tree.  This patch adds the
check for the mapping tree in the backend deletion callback.  If
the instance refcnt is positive or the mapping tree is disabled,
the deletion is backed off.

For the backend deletion, the referral info is not needed.  To
reduce unnecessary allocation and free, adding the code which
checks if the given referral variable is NULL or not to mtn_get_be.
If it is NULL, no allocation for the referral entry occurs.

https://fedorahosted.org/389/ticket/48250

Reviewed by rmeggins@redhat.com (Thank you, Rich!!)

(cherry picked from commit 01fea1f89a680358245677f72a67e9ccf196f66d)
(cherry picked from commit 7a4b0a705ec7376e704f6ae591beabf6c8f890af)
---
 ldap/servers/slapd/back-ldbm/ldbm_index_config.c | 11 +++--
 ldap/servers/slapd/mapping_tree.c                | 52 ++++++++++++++----------
 2 files changed, 39 insertions(+), 24 deletions(-)

diff --git a/ldap/servers/slapd/back-ldbm/ldbm_index_config.c b/ldap/servers/slapd/back-ldbm/ldbm_index_config.c
index 895d846..42c8ffe 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_index_config.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_index_config.c
@@ -128,7 +128,7 @@ ldbm_instance_index_config_add_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_
 
 /*
  * Config DSE callback for index deletes.
- */	
+ */
 int 
 ldbm_instance_index_config_delete_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg) 
 { 
@@ -138,15 +138,19 @@ ldbm_instance_index_config_delete_callback(Slapi_PBlock *pb, Slapi_Entry* e, Sla
   const struct berval *attrValue;
   int rc = SLAPI_DSE_CALLBACK_OK;
   struct attrinfo *ainfo = NULL;
+  Slapi_Backend *be = NULL;
   
   returntext[0] = '\0';
   *returncode = LDAP_SUCCESS;
 
-  if (slapi_counter_get_value(inst->inst_ref_count) > 0) {
+  if ((slapi_counter_get_value(inst->inst_ref_count) > 0) ||
+      /* check if the backend is ON or not. 
+       * If offline or being deleted, non SUCCESS is returned. */
+      (slapi_mapping_tree_select(pb, &be, NULL, returntext) != LDAP_SUCCESS)) {
     *returncode = LDAP_UNAVAILABLE;
     rc = SLAPI_DSE_CALLBACK_ERROR;
+    goto bail;
   }
-
   *returncode = LDAP_SUCCESS;
   
   slapi_entry_attr_find(e, "cn", &attr);
@@ -165,6 +169,7 @@ ldbm_instance_index_config_delete_callback(Slapi_PBlock *pb, Slapi_Entry* e, Sla
       rc = SLAPI_DSE_CALLBACK_ERROR;
     }
   }
+bail:
   return rc;
 }
 
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
index ca8d6af..165eba1 100644
--- a/ldap/servers/slapd/mapping_tree.c
+++ b/ldap/servers/slapd/mapping_tree.c
@@ -2171,7 +2171,9 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
     } 
 
     be[0] = NULL;
-    referral[0] = NULL;
+    if (referral) {
+        referral[0] = NULL;
+    }
 
     mtn_lock();
 
@@ -2658,7 +2660,9 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
          ((SLAPI_OPERATION_SEARCH == op_type)||(SLAPI_OPERATION_BIND == op_type) || 
          (SLAPI_OPERATION_UNBIND == op_type) || (SLAPI_OPERATION_COMPARE == op_type))) ||
         override_referral) {
-        *referral = NULL;
+        if (referral) {
+            *referral = NULL;
+        }
         if ((target_node == mapping_tree_root) ){
             /* If we got here, then we couldn't find a matching node 
              * for the target. We'll use the default backend.  Once
@@ -2679,22 +2683,25 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
                     /* there is only one backend no choice possible */
                     *index = 0;
                 } else {
-                    *index = mtn_get_be_distributed(pb, target_node,
-                         target_sdn, &flag_stop);
-			if (*index == SLAPI_BE_NO_BACKEND) 
-				result = LDAP_UNWILLING_TO_PERFORM;
-            	}
-           }
-	   if (*index == SLAPI_BE_REMOTE_BACKEND) {
-           	*be = NULL;
-               	*referral = (target_node->mtn_referral_entry ?
-                       		slapi_entry_dup(target_node->mtn_referral_entry) :
-                       		NULL);
+                    *index = mtn_get_be_distributed(pb, target_node, target_sdn, &flag_stop);
+                    if (*index == SLAPI_BE_NO_BACKEND) {
+                        result = LDAP_UNWILLING_TO_PERFORM;
+                    }
+                }
+            }
+            if (*index == SLAPI_BE_REMOTE_BACKEND) {
+                *be = NULL;
+                if (referral) {
+                    *referral = (target_node->mtn_referral_entry ?
+                                slapi_entry_dup(target_node->mtn_referral_entry) : NULL);
+                }
                 (*index)++;
             }else if ((*index == SLAPI_BE_NO_BACKEND) || (*index >= target_node->mtn_be_count)) {
-        	/* we have already returned all backends -> return NULL */
+                /* we have already returned all backends -> return NULL */
                 *be = NULL;
-                *referral = NULL;
+                if (referral) {
+                    *referral = NULL;
+                }
             } else {
                 /* return next backend, increment index */
                 *be = target_node->mtn_be[*index];
@@ -2749,7 +2756,9 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
              * send back NULL to jump to next node 
              */
             *be = NULL;
-            *referral = NULL;
+            if (referral) {
+                *referral = NULL;
+            }
             result = LDAP_SUCCESS;
         } else {
             /* first time we hit this referral -> return it
@@ -2758,11 +2767,12 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
              * returned this referral
              */
             *be = NULL;
-            *referral = (target_node->mtn_referral_entry ?
-                         slapi_entry_dup(target_node->mtn_referral_entry) :
-                         NULL);
+            if (referral) {
+                *referral = (target_node->mtn_referral_entry ?
+                             slapi_entry_dup(target_node->mtn_referral_entry) : NULL);
+            }
             (*index)++;
-            if (NULL == *referral) {
+            if (NULL == target_node->mtn_referral_entry) {
                 if (errorbuf) {
                     PR_snprintf(errorbuf, BUFSIZ,
                     "Mapping tree node for %s is set to return a referral,"
@@ -2782,7 +2792,7 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
                 "mapping tree selected backend : %s\n",
                 slapi_be_get_name(*be));
             slapi_be_Rlock(*be);
-        } else if (*referral) {
+        } else if (referral && *referral) {
             slapi_log_error(SLAPI_LOG_ARGS, NULL,
                 "mapping tree selected referral at node : %s\n",
                 slapi_sdn_get_dn(target_node->mtn_subtree));
-- 
1.9.3