Explorar o código

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 [email protected] (Thank you, Rich!!)
Noriko Hosoi %!s(int64=10) %!d(string=hai) anos
pai
achega
01fea1f89a

+ 8 - 3
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;
 }
 

+ 31 - 21
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));