Explorar o código

Trac Ticket #391 - Slapd crashes when deleting backends
while operations are still in progress

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

Bug Description: Deleting backend code ldbm_instance_delete_instance_
entry_callback had no checking for the ordinary operations accessing
the backend instance. Even if some operations are still in progress,
the backend instance could be deleted and it crashes the server.

Fix Description: Backend struct ldbm_instance had a member inst_ref_
count, which was not used. This patch converts the type PRInt32 to
Slapi_Counter and increments it when the backend instance is in use.
The delete code checks the counter and if it is greater than 0, it
returns SLAPI_DSE_CALLBACK_ERROR.

Noriko Hosoi %!s(int64=13) %!d(string=hai) anos
pai
achega
7f81635990

+ 1 - 3
ldap/servers/slapd/back-ldbm/back-ldbm.h

@@ -735,10 +735,8 @@ typedef struct ldbm_instance {
     int inst_flags;                   /* see above */
 
     PRLock *inst_config_mutex;
-
-    PRInt32 *inst_ref_count;          /* Keeps track of how many operations 
+    Slapi_Counter *inst_ref_count;    /* Keeps track of how many operations 
                                        * are currently using this instance */
-
     char *inst_dir_name;              /* The name of the directory in the db
                                        * directory that holds the index files
                                        * for this instance. Relative to the

+ 15 - 7
ldap/servers/slapd/back-ldbm/dblayer.c

@@ -3103,14 +3103,20 @@ out:
     slapi_ch_free((void**)&rel_path);
     /* close the database handle to avoid handle leak */
     if (dbp && (return_value != 0)) {
-        dblayer_close_file(dbp);
+        dblayer_close_file(&dbp);
     }
     return return_value;
 }
 
-int dblayer_close_file(DB *db)
+int 
+dblayer_close_file(DB **db)
 {
-    return db->close(db,0);
+    if (db) {
+        DB *dbp = *db;
+        *db = NULL; /* To avoid to leave stale DB, set NULL before closing. */
+        return dbp->close(dbp, 0);
+    }
+    return 1;
 }
 
 /*
@@ -3163,7 +3169,7 @@ int dblayer_get_index_file(backend *be, struct attrinfo *a, DB** ppDB, int open_
    */
   PR_AtomicIncrement(&a->ai_dblayer_count);
   
-  if (NULL != a->ai_dblayer) {
+  if (a->ai_dblayer && ((dblayer_handle*)(a->ai_dblayer))->dblayer_dbp) {
     /* This means that the pointer is valid, so we should return it. */
     *ppDB = ((dblayer_handle*)(a->ai_dblayer))->dblayer_dbp;
     return 0;
@@ -3173,7 +3179,7 @@ int dblayer_get_index_file(backend *be, struct attrinfo *a, DB** ppDB, int open_
    * again.
    */
   PR_Lock(inst->inst_handle_list_mutex);
-  if (NULL != a->ai_dblayer) {
+  if (a->ai_dblayer && ((dblayer_handle*)(a->ai_dblayer))->dblayer_dbp) {
     /* another thread set the handle while we were waiting on the lock */
     *ppDB = ((dblayer_handle*)(a->ai_dblayer))->dblayer_dbp;
     PR_Unlock(inst->inst_handle_list_mutex);
@@ -3316,6 +3322,7 @@ int dblayer_erase_index_file_ex(backend *be, struct attrinfo *a,
 
   if (0 == dblayer_get_index_file(be, a, &db, 0 /* Don't create an index file
                                                    if it does not exist. */)) {
+    if(use_lock) slapi_rwlock_wrlock(pEnv->dblayer_env_lock); /* We will be causing logging activity */
     /* first, remove the file handle for this index, if we have it open */
     PR_Lock(inst->inst_handle_list_mutex);
     if (a->ai_dblayer) {
@@ -3340,7 +3347,7 @@ int dblayer_erase_index_file_ex(backend *be, struct attrinfo *a,
         DS_Sleep(DBLAYER_CACHE_DELAY);
         PR_Lock(inst->inst_handle_list_mutex);
       }
-      dblayer_close_file(handle->dblayer_dbp);
+      dblayer_close_file(&(handle->dblayer_dbp));
       
       /* remove handle from handle-list */
       if (inst->inst_handle_head == handle) {
@@ -3372,7 +3379,7 @@ int dblayer_erase_index_file_ex(backend *be, struct attrinfo *a,
         p = dbNamep + dbbasenamelen;
         sprintf(p, "%c%s%s",
                    get_sep(dbNamep), a->ai_type, LDBM_FILENAME_SUFFIX);
-        rc = dblayer_db_remove_ex(pEnv, dbNamep, 0, use_lock);
+        rc = dblayer_db_remove_ex(pEnv, dbNamep, 0, 0);
         a->ai_dblayer = NULL;
         if (dbNamep != dbName)
           slapi_ch_free_string(&dbNamep);
@@ -3386,6 +3393,7 @@ int dblayer_erase_index_file_ex(backend *be, struct attrinfo *a,
       /* no handle to close */
     }
     PR_Unlock(inst->inst_handle_list_mutex);
+    if(use_lock) slapi_rwlock_unlock(pEnv->dblayer_env_lock);
 
   }
   

+ 6 - 0
ldap/servers/slapd/back-ldbm/id2entry.c

@@ -382,6 +382,12 @@ id2entry( backend *be, ID id, back_txn *txn, int *err  )
                                     "(rdn=%s, ID=%d)\n", rdn, id);
                     /* Try rdn as dn. Could be RUV. */
                     normdn = slapi_ch_strdup(rdn);
+                } else if (NULL == normdn) {
+                    slapi_log_error(SLAPI_LOG_FATAL, ID2ENTRY, 
+                        "<= id2entry( %lu ) entryrdn_lookup_dn returned NULL. "
+                        "Index file may be deleted or corrupted.\n",
+                        (u_long)id);
+                    goto bail;
                 }
                 sdn = slapi_sdn_new_normdn_byval((const char *)normdn);
                 bdn = backdn_init(sdn, id, 0);

+ 2 - 2
ldap/servers/slapd/back-ldbm/import-merge.c

@@ -593,7 +593,7 @@ static int import_merge_one_file(ImportWorkerInfo *worker, int passes,
 	}
 	preclose_ret = ret;
 	/* Now close the files */
-	dblayer_close_file(output_file);
+	dblayer_close_file(&output_file);
 	/* Close the cursors */
 	/* Close and delete the files */
 	for (i = 0; i < passes; i++) {
@@ -605,7 +605,7 @@ static int import_merge_one_file(ImportWorkerInfo *worker, int passes,
 		if (0 != ret) {
 		    import_log_notice(worker->job, "MERGE FAIL 4");
 		} 
-		ret = dblayer_close_file(db);
+		ret = dblayer_close_file(&db);
 		if (0 != ret) {
 		    import_log_notice(worker->job, "MERGE FAIL 5");
 		}

+ 4 - 0
ldap/servers/slapd/back-ldbm/instance.c

@@ -123,6 +123,9 @@ int ldbm_instance_create(backend *be, char *name)
         goto error;
     }
 
+    /* Keeps track of how many operations are currently using this instance */
+    inst->inst_ref_count = slapi_counter_new();
+
     inst->inst_be = be;
     inst->inst_li = li;
     be->be_instance_info = inst;
@@ -411,6 +414,7 @@ ldbm_instance_destructor(void **arg)
     LDAPDebug(LDAP_DEBUG_ANY, "Destructor for instance %s called\n", 
               inst->inst_name, 0, 0);
 
+    slapi_counter_destroy(&(inst->inst_ref_count));
     slapi_ch_free_string(&inst->inst_name);
     PR_DestroyLock(inst->inst_config_mutex);
     slapi_ch_free_string(&inst->inst_dir_name);

+ 15 - 3
ldap/servers/slapd/back-ldbm/ldbm_add.c

@@ -132,7 +132,15 @@ ldbm_back_add( Slapi_PBlock *pb )
 	is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
 
 	inst = (ldbm_instance *) be->be_instance_info;
-		
+	if (inst->inst_ref_count) {
+		slapi_counter_increment(inst->inst_ref_count);
+	} else {
+		LDAPDebug1Arg(LDAP_DEBUG_ANY,
+		              "ldbm_add: instance %s does not exist.\n",
+		              inst->inst_name);
+		goto error_return;
+	}
+
 	/* sdn & parentsdn need to be initialized before "goto *_return" */
 	slapi_sdn_init(&parentsdn);
 	
@@ -878,8 +886,9 @@ ldbm_back_add( Slapi_PBlock *pb )
 			continue;
 		}
 		if (retval != 0) {
-			LDAPDebug( LDAP_DEBUG_ANY, "add: attempt to index %lu failed\n",
-								   (u_long)addingentry->ep_id, 0, 0 );
+			LDAPDebug2Args(LDAP_DEBUG_ANY,
+			               "add: attempt to index %lu failed (rc=%d)\n",
+			               (u_long)addingentry->ep_id, retval);
 			ADD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
 			if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
 				disk_full = 1;
@@ -1137,6 +1146,9 @@ common_return:
         }
         CACHE_RETURN( &inst->inst_cache, &addingentry );
     }
+	if (inst->inst_ref_count) {
+		slapi_counter_decrement(inst->inst_ref_count);
+	}
 	/* bepost op needs to know this result */
 	slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
 	/* JCMREPL - The bepostop is called even if the operation fails. */

+ 25 - 8
ldap/servers/slapd/back-ldbm/ldbm_bind.c

@@ -50,7 +50,7 @@ typedef enum LDAPWAEnum {
 	LDAPWA_NoDomainAttr = -3,
 	LDAPWA_InvalidCredentials = -2,
 	LDAPWA_Failure = -1,
-    LDAPWA_Success= 0
+	LDAPWA_Success= 0
 } LDAPWAStatus;
 
 int
@@ -211,6 +211,7 @@ ldbm_back_bind( Slapi_PBlock *pb )
 	Slapi_Value **bvals;
 	entry_address *addr;
 	back_txn txn = {NULL};
+	int rc = SLAPI_BIND_SUCCESS;
 
 	/* get parameters */
 	slapi_pblock_get( pb, SLAPI_BACKEND, &be );
@@ -226,10 +227,19 @@ ldbm_back_bind( Slapi_PBlock *pb )
 	}
 	
 	inst = (ldbm_instance *) be->be_instance_info;
+	if (inst->inst_ref_count) {
+		slapi_counter_increment(inst->inst_ref_count);
+	} else {
+		LDAPDebug1Arg(LDAP_DEBUG_ANY,
+		              "ldbm_bind: instance %s does not exist.\n",
+		              inst->inst_name);
+		return( SLAPI_BIND_FAIL );
+	}
 
 	/* always allow noauth simple binds (front end will send the result) */
 	if ( method == LDAP_AUTH_SIMPLE && cred->bv_len == 0 ) {
-		return( SLAPI_BIND_ANONYMOUS );
+		rc = SLAPI_BIND_ANONYMOUS;
+		goto bail;
 	}
 
 	/*
@@ -237,7 +247,8 @@ ldbm_back_bind( Slapi_PBlock *pb )
 	 *   and sending errors if the entry does not exist.
 	 */
 	if (( e = find_entry( pb, be, addr, &txn )) == NULL ) {
-		return( SLAPI_BIND_FAIL );
+		rc = SLAPI_BIND_FAIL;
+		goto bail;
 	}
 
 	switch ( method ) {
@@ -253,7 +264,8 @@ ldbm_back_bind( Slapi_PBlock *pb )
 			slapi_send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL,
 			    NULL, 0, NULL );
 			CACHE_RETURN( &inst->inst_cache, &e );
-			return( SLAPI_BIND_FAIL );
+			rc = SLAPI_BIND_FAIL;
+			goto bail;
 		}
 		bvals= attr_get_present_values(attr);
 		slapi_value_init_berval(&cv,cred);
@@ -269,7 +281,8 @@ ldbm_back_bind( Slapi_PBlock *pb )
 			    NULL, 0, NULL );
 			CACHE_RETURN( &inst->inst_cache, &e );
 			value_done(&cv);
-			return( SLAPI_BIND_FAIL );
+			rc = SLAPI_BIND_FAIL;
+			goto bail;
 		}
 		value_done(&cv);
 		}
@@ -279,11 +292,15 @@ ldbm_back_bind( Slapi_PBlock *pb )
 		slapi_send_ldap_result( pb, LDAP_STRONG_AUTH_NOT_SUPPORTED, NULL,
 		    "auth method not supported", 0, NULL );
 		CACHE_RETURN( &inst->inst_cache, &e );
-		return( SLAPI_BIND_FAIL );
+		rc = SLAPI_BIND_FAIL;
+		goto bail;
 	}
 
 	CACHE_RETURN( &inst->inst_cache, &e );
-
+bail:
+	if (inst->inst_ref_count) {
+		slapi_counter_decrement(inst->inst_ref_count);
+	}
 	/* success:  front end will send result */
-	return( SLAPI_BIND_SUCCESS );
+	return rc;
 }

+ 15 - 3
ldap/servers/slapd/back-ldbm/ldbm_compare.c

@@ -61,7 +61,6 @@ ldbm_back_compare( Slapi_PBlock *pb )
 	Slapi_DN *namespace_dn;
 	back_txn txn = {NULL};
 
-
 	slapi_pblock_get( pb, SLAPI_BACKEND, &be );
 	slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
 	slapi_pblock_get( pb, SLAPI_TARGET_ADDRESS, &addr);
@@ -75,16 +74,25 @@ ldbm_back_compare( Slapi_PBlock *pb )
 	}
 
 	inst = (ldbm_instance *) be->be_instance_info;
+	if (inst->inst_ref_count) {
+		slapi_counter_increment(inst->inst_ref_count);
+	} else {
+		LDAPDebug1Arg(LDAP_DEBUG_ANY,
+		              "ldbm_compare: instance %s does not exist.\n",
+		              inst->inst_name);
+		return -1;
+	}
 	/* get the namespace dn */
 	namespace_dn = (Slapi_DN*)slapi_be_getsuffix(be, 0);
 
 	if ( (e = find_entry( pb, be, addr, &txn )) == NULL ) {
-		return( -1 );	/* error result sent by find_entry() */
+		ret = -1;	/* error result sent by find_entry() */
+		goto bail;
 	}
 
 	err = slapi_access_allowed (pb, e->ep_entry, type, bval, SLAPI_ACL_COMPARE);
 	if ( err != LDAP_SUCCESS ) {
-		slapi_send_ldap_result( pb, err, NULL, NULL, 0, NULL );								
+		slapi_send_ldap_result( pb, err, NULL, NULL, 0, NULL );
 		ret = 1;
 	} else {
 
@@ -117,5 +125,9 @@ ldbm_back_compare( Slapi_PBlock *pb )
 	}
 
 	CACHE_RETURN( &inst->inst_cache, &e );
+bail:
+	if (inst->inst_ref_count) {
+		slapi_counter_decrement(inst->inst_ref_count);
+	}
 	return( ret );
 }

+ 12 - 1
ldap/servers/slapd/back-ldbm/ldbm_delete.c

@@ -146,6 +146,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
 	delete_tombstone_entry = operation_is_flag_set(operation, OP_FLAG_TOMBSTONE_ENTRY);
 	
 	inst = (ldbm_instance *) be->be_instance_info;
+	if (inst->inst_ref_count) {
+		slapi_counter_increment(inst->inst_ref_count);
+	} else {
+		LDAPDebug1Arg(LDAP_DEBUG_ANY,
+		              "ldbm_delete: instance %s does not exist.\n",
+		              inst->inst_name);
+		goto error_return;
+	}
 
 	/* The dblock serializes writes to the database,
 	 * which reduces deadlocking in the db code,
@@ -1206,6 +1214,9 @@ common_return:
 			CACHE_RETURN( &inst->inst_cache, &e );
 		}
 	}
+	if (inst->inst_ref_count) {
+		slapi_counter_decrement(inst->inst_ref_count);
+	}
 	
 	if (ruv_c_init) {
 		modify_term(&ruv_c, be);
@@ -1214,7 +1225,7 @@ common_return:
 diskfull_return:
     if(ldap_result_code!=-1)
 	{
-    	slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL );
+		slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL );
 	}
 	modify_term(&parent_modify_c,be);
 	if (rc == 0 && opcsn && !is_fixup_operation && !delete_tombstone_entry)

+ 7 - 1
ldap/servers/slapd/back-ldbm/ldbm_index_config.c

@@ -167,6 +167,13 @@ ldbm_instance_index_config_delete_callback(Slapi_PBlock *pb, Slapi_Entry* e, Sla
   
   returntext[0] = '\0';
   *returncode = LDAP_SUCCESS;
+
+  if (slapi_counter_get_value(inst->inst_ref_count) > 0) {
+    *returncode = LDAP_UNAVAILABLE;
+    rc = SLAPI_DSE_CALLBACK_ERROR;
+  }
+
+  *returncode = LDAP_SUCCESS;
   
   slapi_entry_attr_find(e, "cn", &attr);
   slapi_attr_first_value(attr, &sval);
@@ -184,7 +191,6 @@ ldbm_instance_index_config_delete_callback(Slapi_PBlock *pb, Slapi_Entry* e, Sla
       rc = SLAPI_DSE_CALLBACK_ERROR;
     }
   }
-  
   return rc;
 }
 

+ 2 - 1
ldap/servers/slapd/back-ldbm/ldbm_instance_config.c

@@ -1194,7 +1194,8 @@ ldbm_instance_delete_instance_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entr
     }
 
     /* check if some online task is happening */
-    if (instance_set_busy(inst) != 0) {
+    if ((instance_set_busy(inst) != 0) ||
+        (slapi_counter_get_value(inst->inst_ref_count) > 0)) {
         LDAPDebug(LDAP_DEBUG_ANY, "ldbm: '%s' is in the middle of a task. "
                   "Cancel the task or wait for it to finish, "
                   "then try again.\n", instance_name, 0, 0);

+ 11 - 0
ldap/servers/slapd/back-ldbm/ldbm_modify.c

@@ -368,6 +368,14 @@ ldbm_back_modify( Slapi_PBlock *pb )
 	{
 		goto error_return;
 	}
+	if (inst->inst_ref_count) {
+		slapi_counter_increment(inst->inst_ref_count);
+	} else {
+		LDAPDebug1Arg(LDAP_DEBUG_ANY,
+		              "ldbm_modify: instance %s does not exist.\n",
+		              inst->inst_name);
+		goto error_return;
+	}
 
 	/* no need to check the dn syntax as this is a replicated op */
 	if(!repl_op){
@@ -813,6 +821,9 @@ common_return:
 		cache_unlock_entry( &inst->inst_cache, e);
 		CACHE_RETURN( &inst->inst_cache, &e);
 	}
+	if (inst->inst_ref_count) {
+		slapi_counter_decrement(inst->inst_ref_count);
+	}
 
 	/* result code could be used in the bepost plugin functions. */
 	slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);

+ 12 - 0
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c

@@ -191,6 +191,15 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
         return( -1 );
     } 
 
+    if (inst->inst_ref_count) {
+        slapi_counter_increment(inst->inst_ref_count);
+    } else {
+        LDAPDebug1Arg(LDAP_DEBUG_ANY,
+                      "ldbm_modrdn: instance %s does not exist.\n",
+                      inst->inst_name);
+        return( -1 );
+    }
+
     /* The dblock serializes writes to the database,
      * which reduces deadlocking in the db code,
      * which means that we run faster.
@@ -1292,6 +1301,9 @@ common_return:
             e_in_cache = 1;
         }
     }
+    if (inst->inst_ref_count) {
+        slapi_counter_decrement(inst->inst_ref_count);
+    }
 
     moddn_unlock_and_return_entry(be,&e);
 

+ 23 - 16
ldap/servers/slapd/back-ldbm/ldbm_search.c

@@ -169,6 +169,9 @@ ldbm_back_search_cleanup(Slapi_PBlock *pb,
     slapi_pblock_get( pb, SLAPI_BACKEND, &be );
     inst = (ldbm_instance *) be->be_instance_info;
     CACHE_RETURN(&inst->inst_cache, &e); /* NULL e is handled correctly */
+    if (inst->inst_ref_count) {
+        slapi_counter_decrement(inst->inst_ref_count);
+    }
 
     if(sort_control!=NULL)
     {
@@ -343,6 +346,7 @@ ldbm_back_search( Slapi_PBlock *pb )
     int backend_count = 1;
     static int print_once = 1;
     back_txn txn = {NULL};
+    int rc = 0;
 
     slapi_pblock_get( pb, SLAPI_BACKEND, &be );
     slapi_pblock_get( pb, SLAPI_OPERATION, &operation);
@@ -366,6 +370,14 @@ ldbm_back_search( Slapi_PBlock *pb )
                                "Null target DN", 0, NULL );
         return( -1 );
     }
+    if (inst->inst_ref_count) {
+        slapi_counter_increment(inst->inst_ref_count);
+    } else {
+        LDAPDebug1Arg(LDAP_DEBUG_ANY,
+                      "ldbm_search: instance %s does not exist.\n",
+                      inst->inst_name);
+        return( -1 );
+    }
     base = slapi_sdn_get_dn(basesdn);
 
     /* Initialize the result set structure here because we need to use it during search processing */
@@ -383,9 +395,8 @@ ldbm_back_search( Slapi_PBlock *pb )
         sort = slapi_control_present( controls, LDAP_CONTROL_SORTREQUEST, &sort_spec, &is_sorting_critical_orig );
         if(sort)
         {
-            int r= parse_sort_spec(sort_spec, &sort_control);
-            if(r!=0)
-            {
+            rc = parse_sort_spec(sort_spec, &sort_control);
+            if (rc) {
                 /* Badly formed SORT control */
                 return ldbm_back_search_cleanup(pb, li, sort_control, 
                                 LDAP_PROTOCOL_ERROR, "Sort Control", 
@@ -401,12 +412,11 @@ ldbm_back_search( Slapi_PBlock *pb )
         {
             if(sort)
             {
-                int r = vlv_parse_request_control( be, vlv_spec, &vlv_request_control );
-                if(r!=LDAP_SUCCESS)
-                {
+                rc = vlv_parse_request_control( be, vlv_spec, &vlv_request_control );
+                if (rc != LDAP_SUCCESS) {
                     /* Badly formed VLV control */
                     return ldbm_back_search_cleanup(pb, li, sort_control,
-                                r, "VLV Control", SLAPI_FAIL_GENERAL, 
+                                rc, "VLV Control", SLAPI_FAIL_GENERAL, 
                                 &vlv_request_control, NULL);
                 }
                 {
@@ -421,13 +431,12 @@ ldbm_back_search( Slapi_PBlock *pb )
                     /* This dn is normalized. */
                     PR_snprintf(dn,sizeof(dn),"dn: oid=%s,cn=features,cn=config",LDAP_CONTROL_VLVREQUEST);
                     feature= slapi_str2entry(dn,0);
-                    r= plugin_call_acl_plugin (pb, feature, dummyAttrs, NULL, SLAPI_ACL_READ, ACLPLUGIN_ACCESS_DEFAULT, NULL);
+                    rc = plugin_call_acl_plugin (pb, feature, dummyAttrs, NULL, SLAPI_ACL_READ, ACLPLUGIN_ACCESS_DEFAULT, NULL);
                     slapi_entry_free(feature);
-                    if(r!=LDAP_SUCCESS)
-                    {
+                    if (rc != LDAP_SUCCESS) {
                         /* Client isn't allowed to do this. */
                         return ldbm_back_search_cleanup(pb, li, sort_control, 
-                                    r, "VLV Control", SLAPI_FAIL_GENERAL, 
+                                    rc, "VLV Control", SLAPI_FAIL_GENERAL, 
                                     &vlv_request_control, NULL);
                     }
                 }
@@ -650,22 +659,20 @@ ldbm_back_search( Slapi_PBlock *pb )
              */
             if (virtual_list_view && (NULL != candidates))
             {
-                int r = 0;
                 IDList *idl = NULL;
                 Slapi_Filter *filter = NULL;
                 slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter );
-                r = vlv_filter_candidates(be, pb, candidates, basesdn,
+                rc = vlv_filter_candidates(be, pb, candidates, basesdn,
                                           scope, filter, &idl,
                                           lookthrough_limit, time_up);
-                if(r == 0)
-                {
+                if (rc == 0) {
                     idl_free(candidates);
                     candidates= idl;
                 }
                 else
                 {
                     return ldbm_back_search_cleanup(pb, li, sort_control,
-                                                    r, NULL, -1, 
+                                                    rc, NULL, -1, 
                                                     &vlv_request_control, e);
                 }
             }

+ 2 - 1
ldap/servers/slapd/back-ldbm/ldif2ldbm.c

@@ -684,7 +684,8 @@ int ldbm_back_ldif2ldbm( Slapi_PBlock *pb )
     }
 
     /* check if an import/restore is already ongoing... */
-    if (instance_set_busy(inst) != 0) {
+    if ((instance_set_busy(inst) != 0) ||
+        (slapi_counter_get_value(inst->inst_ref_count) > 0)) {
         LDAPDebug(LDAP_DEBUG_ANY, "ldbm: '%s' is already in the middle of "
                   "another task and cannot be disturbed.\n",
                   inst->inst_name, 0, 0);

+ 8 - 2
ldap/servers/slapd/back-ldbm/misc.c

@@ -174,7 +174,7 @@ compute_entry_tombstone_rdn(const char *entryrdn, const char *uniqueid)
 int instance_set_busy(ldbm_instance *inst)
 {
     PR_Lock(inst->inst_config_mutex);
-    if (inst->inst_flags & INST_FLAG_BUSY) {
+    if (is_instance_busy(inst)) {
         PR_Unlock(inst->inst_config_mutex);
         return -1;
     }
@@ -187,7 +187,7 @@ int instance_set_busy(ldbm_instance *inst)
 int instance_set_busy_and_readonly(ldbm_instance *inst)
 {
     PR_Lock(inst->inst_config_mutex);
-    if (inst->inst_flags & INST_FLAG_BUSY) {
+    if (is_instance_busy(inst)) {
         PR_Unlock(inst->inst_config_mutex);
         return -1;
     }
@@ -280,6 +280,12 @@ is_anyinstance_busy(struct ldbminfo *li)
     return rval;
 }
 
+int
+is_instance_busy(ldbm_instance *inst)
+{
+    return inst->inst_flags & INST_FLAG_BUSY;
+}
+
 /*
  * delete the given file/directory and its sub files/directories
  */

+ 2 - 1
ldap/servers/slapd/back-ldbm/proto-back-ldbm.h

@@ -150,7 +150,7 @@ int dblayer_database_size(struct ldbminfo *li, unsigned int *size);
 int dblayer_terminate(struct ldbminfo *li);
 int dblayer_close_indexes(backend *be);
 int dblayer_open_file(backend *be, char* indexname, int create, struct attrinfo *ai, DB **ppDB);
-int dblayer_close_file(DB *db);
+int dblayer_close_file(DB **db);
 void dblayer_sys_pages(size_t *pagesize, size_t *pages, size_t *procpages, size_t *availpages);
 int dblayer_is_cachesize_sane(size_t *cachesize);
 void dblayer_remember_disk_filled(struct ldbminfo *li);
@@ -375,6 +375,7 @@ void instance_set_not_busy(ldbm_instance *inst);
 void allinstance_set_busy(struct ldbminfo *li);
 void allinstance_set_not_busy(struct ldbminfo *li);
 int is_anyinstance_busy(struct ldbminfo *li);
+int is_instance_busy(ldbm_instance *inst);
 int ldbm_delete_dirs(char *path);
 int mkdir_p(char *dir, unsigned int mode);
 int is_fullpath(char *path);

+ 1 - 1
ldap/servers/slapd/back-ldbm/vlv.c

@@ -159,7 +159,7 @@ int vlv_DeleteSearchEntry(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
 int vlv_DeleteIndexEntry(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
 {
     ldbm_instance *inst = (ldbm_instance*)arg;
-    if (inst && (inst->inst_flags & INST_FLAG_BUSY)) {
+    if (inst && is_instance_busy(inst)) {
         LDAPDebug( LDAP_DEBUG_ANY,
                        "Backend instance: '%s' is already in the middle of "
                        "another task and cannot be disturbed.\n",