[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Sun Jul 29 08:52:02 MDT 2012


The branch, master has been updated
       via  b567d3a s4-dsdb: Fill in lastKnownParent when moving to lostAndFound
       via  54b83ce s4-dsdb: Do not strip base components off DN before searching for NC root
       via  056b215 s4-dsdb: Change move to lostAndFound to use container in this partiion and add debugging
       via  03a75af s4-dsdb: Provide a way to force incoming renames to take priority
       via  26eb354 s4-dsdb: Provide a way to handle conflicts due to rename
      from  fc6d7bf s4-librpc: Fix private context for dcerpc_connect_timeout_handler

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit b567d3a607d7bb27c804c6450af4b9144282214d
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Sat Jul 28 15:27:26 2012 +1000

    s4-dsdb: Fill in lastKnownParent when moving to lostAndFound
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Sun Jul 29 16:51:34 CEST 2012 on sn-devel-104

commit 54b83ce9b7bb70e26f8c83bc0ed7fcf5b8985399
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Sun Jul 29 15:03:21 2012 +1000

    s4-dsdb: Do not strip base components off DN before searching for NC root

commit 056b2151568979fa688654920d1d19b7b9c810d2
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Sat Jul 28 09:40:39 2012 +1000

    s4-dsdb: Change move to lostAndFound to use container in this partiion and add debugging
    
    The logic looking for LostAndFound failed for a user, so add extensive
    debugging to make this eaiser to trace down in future.
    
    Andrew Bartlett

commit 03a75afa79da19d9c7ac3b4c86b1a402a27e14e5
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Jun 8 12:26:32 2012 +1000

    s4-dsdb: Provide a way to force incoming renames to take priority
    
    This should mean that a samba-tool drs replicate --full-sync forces a
    replication of all objects, regardless of if we think the local name
    is newer and regards any local name as being in conflict.
    
    Andrew Bartlett

commit 26eb35409ca458086f679351f39dad972142ca1c
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Jun 8 12:25:29 2012 +1000

    s4-dsdb: Provide a way to handle conflicts due to rename
    
    This allows us to proceed with replication when the source DC is sending us an object
    which has a matching object in this NC (by name) but not by GUID.
    
    Andrew Bartlett

-----------------------------------------------------------------------

Summary of changes:
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c |  226 +++++++++++++++++++----
 source4/dsdb/samdb/samdb.h                      |    3 +
 2 files changed, 193 insertions(+), 36 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 6f26299..930696a 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -3326,6 +3326,8 @@ failed:
   callback for conflict DN handling where we have renamed the incoming
   record. After renaming it, we need to ensure the change of name and
   rDN for the incoming record is seen as an originating update by this DC.
+
+  This also handles updating lastKnownParent for entries sent to lostAndFound
  */
 static int replmd_op_name_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
 {
@@ -3345,15 +3347,43 @@ static int replmd_op_name_modify_callback(struct ldb_request *req, struct ldb_re
 		return replmd_op_callback(req, ares);
 	}
 
+	if (ar->objs->objects[ar->index_current].last_known_parent) {
+		struct ldb_message *msg = ldb_msg_new(req);
+		if (msg == NULL) {
+			ldb_module_oom(ar->module);
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
+
+		msg->dn = req->op.add.message->dn;
+
+		ret = ldb_msg_add_steal_string(msg, "lastKnownParent",
+					       ldb_dn_get_extended_linearized(msg, ar->objs->objects[ar->index_current].last_known_parent, 1));
+		if (ret != LDB_SUCCESS) {
+			DEBUG(0,(__location__ ": Failed to add lastKnownParent string to the msg\n"));
+			ldb_module_oom(ar->module);
+			return ret;
+		}
+		msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
+
+		ret = dsdb_module_modify(ar->module, msg, DSDB_FLAG_OWN_MODULE, req);
+		if (ret != LDB_SUCCESS) {
+			DEBUG(0,(__location__ ": Failed to modify lastKnownParent of lostAndFound DN '%s' - %s",
+				 ldb_dn_get_linearized(msg->dn),
+				 ldb_errstring(ldb_module_get_ctx(ar->module))));
+			return ret;
+		}
+		TALLOC_FREE(msg);
+	}
+
 	return replmd_op_callback(req, ares);
 }
 
 /*
-  callback for replmd_replicated_apply_add()
+  callback for replmd_replicated_apply_add() and replmd_replicated_handle_rename()
   This copes with the creation of conflict records in the case where
   the DN exists, but with a different objectGUID
  */
-static int replmd_op_add_callback(struct ldb_request *req, struct ldb_reply *ares)
+static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct ldb_reply *ares, int (*callback)(struct ldb_request *req, struct ldb_reply *ares))
 {
 	struct ldb_dn *conflict_dn;
 	struct replmd_replicated_request *ar =
@@ -3370,7 +3400,7 @@ static int replmd_op_add_callback(struct ldb_request *req, struct ldb_reply *are
 	if (ares->error != LDB_ERR_ENTRY_ALREADY_EXISTS) {
 		/* call the normal callback for everything except
 		   conflicts */
-		return replmd_op_callback(req, ares);
+		return callback(req, ares);
 	}
 
 	ret = samdb_rodc(ldb_module_get_ctx(ar->module), &rodc);
@@ -3381,7 +3411,17 @@ static int replmd_op_add_callback(struct ldb_request *req, struct ldb_reply *are
 	 * we have a conflict, and need to decide if we will keep the
 	 * new record or the old record
 	 */
-	conflict_dn = req->op.add.message->dn;
+
+	switch (req->operation) {
+	case LDB_ADD:
+		conflict_dn = req->op.add.message->dn;
+		break;
+	case LDB_RENAME:
+		conflict_dn = req->op.rename.newdn;
+		break;
+	default:
+		return ldb_module_operr(ar->module);
+	}
 
 	if (rodc) {
 		/*
@@ -3397,12 +3437,6 @@ static int replmd_op_add_callback(struct ldb_request *req, struct ldb_reply *are
 		goto failed;
 	}
 
- 	/*
-	 * we have a conflict, and need to decide if we will keep the
-	 * new record or the old record
-	 */
-	conflict_dn = req->op.add.message->dn;
-
 	/*
 	 * first we need the replPropertyMetaData attribute from the
 	 * old record
@@ -3462,13 +3496,21 @@ static int replmd_op_add_callback(struct ldb_request *req, struct ldb_reply *are
 		goto failed;
 	}
 
-	rename_incoming_record = !replmd_replPropertyMetaData1_is_newer(omd_name, rmd_name);
+	rename_incoming_record = !(ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING) &&
+		!replmd_replPropertyMetaData1_is_newer(omd_name, rmd_name);
 
 	if (rename_incoming_record) {
 		struct GUID guid;
 		struct ldb_dn *new_dn;
 		struct ldb_message *new_msg;
 
+		if (req->operation == LDB_RENAME) {
+			DEBUG(0,(__location__ ": Unable to handle incoming renames where this would "
+				 "create a conflict. Incoming record is %s\n",
+				 ldb_dn_get_extended_linearized(req, conflict_dn, 1)));
+			goto failed;
+		}
+
 		guid = samdb_result_guid(req->op.add.message, "objectGUID");
 		if (GUID_all_zero(&guid)) {
 			DEBUG(0,(__location__ ": Failed to find objectGUID for conflicting incoming record %s\n",
@@ -3485,17 +3527,27 @@ static int replmd_op_add_callback(struct ldb_request *req, struct ldb_reply *are
 		DEBUG(1,(__location__ ": Resolving conflict record via incoming rename '%s' -> '%s'\n",
 			 ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));
 
-		/* re-submit the request, but with a different
-		   callback, so we don't loop forever. */
-		new_msg = ldb_msg_copy_shallow(req, req->op.add.message);
-		if (!new_msg) {
-			goto failed;
-			DEBUG(0,(__location__ ": Failed to copy conflict DN message for %s\n",
-				 ldb_dn_get_linearized(conflict_dn)));
+		switch (req->operation) {
+		case LDB_ADD:
+			/* re-submit the request, but with a different
+			   callback, so we don't loop forever. */
+			new_msg = ldb_msg_copy_shallow(req, req->op.add.message);
+			if (!new_msg) {
+				goto failed;
+				DEBUG(0,(__location__ ": Failed to copy conflict DN message for %s\n",
+					 ldb_dn_get_linearized(conflict_dn)));
+			}
+			new_msg->dn = new_dn;
+			req->op.add.message = new_msg;
+			req->callback = replmd_op_name_modify_callback;
+			break;
+		case LDB_RENAME:
+			req->op.rename.newdn = new_dn;
+			req->callback = callback;
+			break;
+		default:
+			return ldb_module_operr(ar->module);
 		}
-		new_msg->dn = new_dn;
-		req->op.add.message = new_msg;
-		req->callback = replmd_op_name_modify_callback;
 
 		return ldb_next_request(ar->module, req);
 	} else {
@@ -3539,7 +3591,7 @@ static int replmd_op_add_callback(struct ldb_request *req, struct ldb_reply *are
 			goto failed;
 		}
 
-		req->callback = replmd_op_callback;
+		req->callback = callback;
 
 		return ldb_next_request(ar->module, req);
 	}
@@ -3549,7 +3601,36 @@ failed:
 	 * will stop with an error, but there is not much else we can
 	 * do
 	 */
-	return replmd_op_callback(req, ares);
+	return callback(req, ares);
+}
+
+/*
+  callback for replmd_replicated_apply_add()
+  This copes with the creation of conflict records in the case where
+  the DN exists, but with a different objectGUID
+ */
+static int replmd_op_add_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+	struct replmd_replicated_request *ar =
+		talloc_get_type_abort(req->context, struct replmd_replicated_request);
+
+	if (ar->objs->objects[ar->index_current].last_known_parent) {
+		/* This is like a conflict DN, where we put the object in LostAndFound
+		   see MS-DRSR 4.1.10.6.10 FindBestParentObject */
+		return replmd_op_possible_conflict_callback(req, ares, replmd_op_name_modify_callback);
+	}
+
+	return replmd_op_possible_conflict_callback(req, ares, replmd_op_callback);
+}
+
+/*
+  callback for replmd_replicated_handle_rename()
+  This copes with the creation of conflict records in the case where
+  the DN exists, but with a different objectGUID
+ */
+static int replmd_op_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+	return replmd_op_possible_conflict_callback(req, ares, ldb_modify_default_callback);
 }
 
 /*
@@ -3695,30 +3776,64 @@ static int replmd_replicated_apply_search_for_parent_callback(struct ldb_request
 		struct ldb_message *parent_msg = ares->message;
 		struct ldb_message *msg = ar->objs->objects[ar->index_current].msg;
 		struct ldb_dn *parent_dn;
-		int comp_num = ldb_dn_get_comp_num(msg->dn);
-		if (comp_num > 1) {
-			if (!ldb_dn_remove_base_components(msg->dn, comp_num - 1)) {
-				talloc_free(ares);
-				return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module));
-			}
-		}
+		int comp_num;
+
 		if (!ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE")
 		    && ldb_msg_check_string_attribute(parent_msg, "isDeleted", "TRUE")) {
 			/* Per MS-DRSR 4.1.10.6.10
 			 * FindBestParentObject we need to move this
 			 * new object under a deleted object to
 			 * lost-and-found */
+			struct ldb_dn *nc_root;
+
+			ret = dsdb_find_nc_root(ldb_module_get_ctx(ar->module), msg, msg->dn, &nc_root);
+			if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+				ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
+						       "No suitable NC root found for %s.  "
+						       "We need to move this object because parent object %s "
+						       "is deleted, but this object is not.",
+						       ldb_dn_get_linearized(msg->dn),
+						       ldb_dn_get_linearized(parent_msg->dn));
+				return ldb_module_done(ar->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
+			} else if (ret != LDB_SUCCESS) {
+				ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
+						       "Unable to find NC root for %s: %s. "
+						       "We need to move this object because parent object %s "
+						       "is deleted, but this object is not.",
+						       ldb_dn_get_linearized(msg->dn),
+						       ldb_errstring(ldb_module_get_ctx(ar->module)),
+						       ldb_dn_get_linearized(parent_msg->dn));
+				return ldb_module_done(ar->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
+			}
 			
 			ret = dsdb_wellknown_dn(ldb_module_get_ctx(ar->module), msg,
-						ldb_get_default_basedn(ldb_module_get_ctx(ar->module)),
+						nc_root,
 						DS_GUID_LOSTANDFOUND_CONTAINER,
 						&parent_dn);
 			if (ret != LDB_SUCCESS) {
-				return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module));
+				ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
+						       "Unable to find LostAndFound Container for %s "
+						       "in partition %s: %s. "
+						       "We need to move this object because parent object %s "
+						       "is deleted, but this object is not.",
+						       ldb_dn_get_linearized(msg->dn), ldb_dn_get_linearized(nc_root),
+						       ldb_errstring(ldb_module_get_ctx(ar->module)),
+						       ldb_dn_get_linearized(parent_msg->dn));
+				return ldb_module_done(ar->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
 			}
+			ar->objs->objects[ar->index_current].last_known_parent
+				= talloc_steal(ar->objs->objects[ar->index_current].msg, parent_msg->dn);
 		} else {
 			parent_dn = parent_msg->dn;
 		}
+
+		comp_num = ldb_dn_get_comp_num(msg->dn);
+		if (comp_num > 1) {
+			if (!ldb_dn_remove_base_components(msg->dn, comp_num - 1)) {
+				talloc_free(ares);
+				return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module));
+			}
+		}
 		if (!ldb_dn_add_base(msg->dn, parent_dn)) {
 			talloc_free(ares);
 			return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module));
@@ -3814,16 +3929,53 @@ static int replmd_replicated_handle_rename(struct replmd_replicated_request *ar,
 	md_local  = replmd_replPropertyMetaData1_find_attid(omd, DRSUAPI_ATTID_name);
 	/* if there is no name attribute then we have to assume the
 	   object we've received is in fact newer */
-	if (!md_remote || !md_local ||
+	if (ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING ||
+	    !md_remote || !md_local ||
 	    replmd_replPropertyMetaData1_is_newer(md_local, md_remote)) {
+		struct ldb_request *req;
+		int ret;
+		TALLOC_CTX *tmp_ctx = talloc_new(msg);
+		struct ldb_result *res;
+
 		DEBUG(4,("replmd_replicated_request rename %s => %s\n",
 			 ldb_dn_get_linearized(ar->search_msg->dn),
 			 ldb_dn_get_linearized(msg->dn)));
+
+
+		res = talloc_zero(tmp_ctx, struct ldb_result);
+		if (!res) {
+			talloc_free(tmp_ctx);
+			return ldb_oom(ldb_module_get_ctx(ar->module));
+		}
+
 		/* pass rename to the next module
 		 * so it doesn't appear as an originating update */
-		return dsdb_module_rename(ar->module,
-					  ar->search_msg->dn, msg->dn,
-					  DSDB_FLAG_NEXT_MODULE | DSDB_MODIFY_RELAX, parent);
+		ret = ldb_build_rename_req(&req, ldb_module_get_ctx(ar->module), tmp_ctx,
+					   ar->search_msg->dn, msg->dn,
+					   NULL,
+					   ar,
+					   replmd_op_rename_callback,
+					   parent);
+		LDB_REQ_SET_LOCATION(req);
+		if (ret != LDB_SUCCESS) {
+			talloc_free(tmp_ctx);
+			return ret;
+		}
+
+		ret = dsdb_request_add_controls(req, DSDB_MODIFY_RELAX);
+		if (ret != LDB_SUCCESS) {
+			talloc_free(tmp_ctx);
+			return ret;
+		}
+
+		ret = ldb_next_request(ar->module, req);
+
+		if (ret == LDB_SUCCESS) {
+			ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+		}
+
+		talloc_free(tmp_ctx);
+		return ret;
 	}
 
 	/* we're going to keep our old object */
@@ -4078,6 +4230,8 @@ static int replmd_replicated_apply_search_callback(struct ldb_request *req,
 		break;
 
 	case LDB_REPLY_DONE:
+		ar->objs->objects[ar->index_current].last_known_parent = NULL;
+
 		if (ar->search_msg != NULL) {
 			ret = replmd_replicated_apply_merge(ar);
 		} else {
diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h
index c4cb3bd..6946782 100644
--- a/source4/dsdb/samdb/samdb.h
+++ b/source4/dsdb/samdb/samdb.h
@@ -135,6 +135,9 @@ struct dsdb_extended_replicated_object {
 	struct ldb_val parent_guid_value;
 	const char *when_changed;
 	struct replPropertyMetaDataBlob *meta_data;
+
+	/* Only used for internal processing in repl_meta_data */
+	struct ldb_dn *last_known_parent;
 };
 
 struct dsdb_extended_replicated_objects {


-- 
Samba Shared Repository


More information about the samba-cvs mailing list