The Samba-Bugzilla – Attachment 15077 Details for
Bug 12204
Samba fails to replicate schema 69
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Minimal fix for online replication
tmp410.diff.txt (text/plain), 10.11 KB, created by
Stefan Metzmacher
on 2019-04-17 20:42:59 UTC
(
hide
)
Description:
Minimal fix for online replication
Filename:
MIME Type:
Creator:
Stefan Metzmacher
Created:
2019-04-17 20:42:59 UTC
Size:
10.11 KB
patch
obsolete
>From 661dc4574110b0f13c127c8aa6ed0c385292b77c Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 Feb 2019 14:49:55 +0000 >Subject: [PATCH] dsdb/repl: we need to replicate the whole schema before we > can apply it > >Otherwise we may not be able to construct a working schema that's >required to apply the changes. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12204 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Garming Sam <garming@catalyst.net.nz> >--- > source4/dsdb/repl/drepl_out_helpers.c | 174 ++++++++++++++++++++++++-- > 1 file changed, 164 insertions(+), 10 deletions(-) > >diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c >index 8da49ac14290..3d0edf4ac29b 100644 >--- a/source4/dsdb/repl/drepl_out_helpers.c >+++ b/source4/dsdb/repl/drepl_out_helpers.c >@@ -240,6 +240,15 @@ NTSTATUS dreplsrv_out_drsuapi_recv(struct tevent_req *req) > return NT_STATUS_OK; > } > >+struct dreplsrv_op_pull_source_schema_cycle { >+ struct repsFromTo1 repsFrom1; >+ size_t object_count; >+ struct drsuapi_DsReplicaObjectListItemEx *first_object; >+ struct drsuapi_DsReplicaObjectListItemEx *last_object; >+ uint32_t linked_attributes_count; >+ struct drsuapi_DsReplicaLinkedAttribute *linked_attributes; >+}; >+ > struct dreplsrv_op_pull_source_state { > struct tevent_context *ev; > struct dreplsrv_out_operation *op; >@@ -251,6 +260,7 @@ struct dreplsrv_op_pull_source_state { > struct dreplsrv_partition_source_dsa *source_dsa_retry; > enum drsuapi_DsExtendedOperation extended_op_retry; > bool retry_started; >+ struct dreplsrv_op_pull_source_schema_cycle *schema_cycle; > }; > > static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq); >@@ -280,6 +290,38 @@ struct tevent_req *dreplsrv_op_pull_source_send(TALLOC_CTX *mem_ctx, > return req; > } > >+static bool dreplsrv_op_pull_source_detect_schema_cycle(struct tevent_req *req) >+{ >+ struct dreplsrv_op_pull_source_state *state = >+ tevent_req_data(req, >+ struct dreplsrv_op_pull_source_state); >+ bool is_schema = false; >+ >+ if (state->op->extended_op == DRSUAPI_EXOP_NONE) { >+ struct dreplsrv_out_operation *op = state->op; >+ struct dreplsrv_service *service = op->service; >+ struct ldb_dn *schema_dn = ldb_get_schema_basedn(service->samdb); >+ struct dreplsrv_partition *partition = op->source_dsa->partition; >+ >+ is_schema = ldb_dn_compare(partition->dn, schema_dn) == 0; >+ } >+ >+ if (is_schema) { >+ struct dreplsrv_op_pull_source_schema_cycle *sc; >+ >+ sc = talloc_zero(state, >+ struct dreplsrv_op_pull_source_schema_cycle); >+ if (tevent_req_nomem(sc, req)) { >+ return false; >+ } >+ sc->repsFrom1 = *state->op->source_dsa->repsFrom1; >+ >+ state->schema_cycle = sc; >+ } >+ >+ return true; >+} >+ > static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req); > > static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq) >@@ -287,6 +329,7 @@ static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq) > struct tevent_req *req = tevent_req_callback_data(subreq, > struct tevent_req); > NTSTATUS status; >+ bool ok; > > status = dreplsrv_out_drsuapi_recv(subreq); > TALLOC_FREE(subreq); >@@ -294,6 +337,11 @@ static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq) > return; > } > >+ ok = dreplsrv_op_pull_source_detect_schema_cycle(req); >+ if (!ok) { >+ return; >+ } >+ > dreplsrv_op_pull_source_get_changes_trigger(req); > } > >@@ -430,7 +478,7 @@ static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req) > { > struct dreplsrv_op_pull_source_state *state = tevent_req_data(req, > struct dreplsrv_op_pull_source_state); >- struct repsFromTo1 *rf1 = state->op->source_dsa->repsFrom1; >+ const struct repsFromTo1 *rf1 = state->op->source_dsa->repsFrom1; > struct dreplsrv_service *service = state->op->service; > struct dreplsrv_partition *partition = state->op->source_dsa->partition; > struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi; >@@ -441,8 +489,13 @@ static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req) > NTSTATUS status; > uint32_t replica_flags; > struct drsuapi_DsReplicaHighWaterMark highwatermark; >- struct ldb_dn *schema_dn = ldb_get_schema_basedn(service->samdb); > struct drsuapi_DsReplicaOIDMapping_Ctr *mappings = NULL; >+ bool is_schema = false; >+ >+ if (state->schema_cycle != NULL) { >+ is_schema = true; >+ rf1 = &state->schema_cycle->repsFrom1; >+ } > > r = talloc(state, struct drsuapi_DsGetNCChanges); > if (tevent_req_nomem(r, req)) { >@@ -502,14 +555,10 @@ static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req) > } > replica_flags &= ~DRSUAPI_DRS_WRIT_REP; > } else if (partition->rodc_replica || state->op->extended_op == DRSUAPI_EXOP_REPL_SECRET) { >- bool for_schema = false; >- if (ldb_dn_compare_base(schema_dn, partition->dn) == 0) { >- for_schema = true; >- } > status = dreplsrv_get_rodc_partial_attribute_set(service, r, > &pas, > &mappings, >- for_schema); >+ is_schema); > if (!NT_STATUS_IS_OK(status)) { > DEBUG(0,(__location__ ": Failed to construct RODC partial attribute set : %s\n", nt_errstr(status))); > tevent_req_nterror(req, status); >@@ -779,6 +828,7 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req > struct dreplsrv_partition *partition = state->op->source_dsa->partition; > struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi; > struct ldb_dn *schema_dn = ldb_get_schema_basedn(service->samdb); >+ struct dreplsrv_op_pull_source_schema_cycle *sc = NULL; > struct dsdb_schema *schema; > struct dsdb_schema *working_schema = NULL; > const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr; >@@ -793,6 +843,7 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req > NTSTATUS nt_status; > uint32_t dsdb_repl_flags = 0; > struct ldb_dn *nc_root = NULL; >+ bool was_schema = false; > int ret; > > switch (ctr_level) { >@@ -826,6 +877,89 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req > return; > } > >+ /* >+ * We need to cache the schema changes until we replicated >+ * everything before we can apply the new schema. >+ */ >+ if (state->schema_cycle != NULL) { >+ TALLOC_CTX *mem = NULL; >+ struct drsuapi_DsReplicaObjectListItemEx **ptr = NULL; >+ struct drsuapi_DsReplicaObjectListItemEx *l = NULL; >+ >+ was_schema = true; >+ sc = state->schema_cycle; >+ >+ sc->repsFrom1 = rf1; >+ >+ if (sc->first_object == NULL) { >+ mem = sc; >+ ptr = &sc->first_object; >+ } else { >+ mem = sc->last_object; >+ ptr = &sc->last_object->next_object; >+ } >+ *ptr = talloc_move(mem, &first_object); >+ for (l = *ptr; l != NULL; l = l->next_object) { >+ sc->object_count++; >+ if (l->next_object == NULL) { >+ sc->last_object = l; >+ break; >+ } >+ } >+ >+ if (sc->linked_attributes_count == 0) { >+ sc->linked_attributes = talloc_move(sc, &linked_attributes); >+ sc->linked_attributes_count = linked_attributes_count; >+ linked_attributes_count = 0; >+ } else if (linked_attributes_count > 0) { >+ struct drsuapi_DsReplicaLinkedAttribute *new_las = NULL; >+ struct drsuapi_DsReplicaLinkedAttribute *tmp_las = NULL; >+ uint64_t new_count; >+ uint64_t add_size; >+ uint32_t add_idx; >+ >+ new_count = sc->linked_attributes_count; >+ new_count += linked_attributes_count; >+ if (new_count > UINT32_MAX) { >+ nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP); >+ tevent_req_nterror(req, nt_status); >+ return; >+ } >+ add_size = linked_attributes_count; >+ add_size *= sizeof(linked_attributes[0]); >+ if (add_size > SIZE_MAX) { >+ nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP); >+ tevent_req_nterror(req, nt_status); >+ return; >+ } >+ add_idx = sc->linked_attributes_count; >+ >+ tmp_las = talloc_realloc(sc, >+ sc->linked_attributes, >+ struct drsuapi_DsReplicaLinkedAttribute, >+ new_count); >+ if (tevent_req_nomem(tmp_las, req)) { >+ return; >+ } >+ new_las = talloc_move(tmp_las, &linked_attributes); >+ memcpy(&tmp_las[add_idx], new_las, add_size); >+ sc->linked_attributes = tmp_las; >+ sc->linked_attributes_count = new_count; >+ linked_attributes_count = 0; >+ } >+ >+ if (more_data) { >+ /* we don't need this structure anymore */ >+ TALLOC_FREE(r); >+ >+ dreplsrv_op_pull_source_get_changes_trigger(req); >+ return; >+ } >+ >+ /* detach sc from state */ >+ state->schema_cycle = NULL; >+ } >+ > schema = dsdb_get_schema(service->samdb, state); > if (!schema) { > DEBUG(0,(__location__ ": Schema is not loaded yet!\n")); >@@ -837,9 +971,14 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req > * Decide what working schema to use for object conversion. > * We won't need a working schema for empty replicas sent. > */ >- if (first_object) { >- bool is_schema = ldb_dn_compare(partition->dn, schema_dn) == 0; >- if (is_schema) { >+ if (sc != NULL) { >+ first_object = talloc_move(r, &sc->first_object); >+ object_count = sc->object_count; >+ linked_attributes = talloc_move(r, &sc->linked_attributes); >+ linked_attributes_count = sc->linked_attributes_count; >+ TALLOC_FREE(sc); >+ >+ if (first_object != NULL) { > /* create working schema to convert objects with */ > status = dsdb_repl_make_working_schema(service->samdb, > schema, >@@ -904,6 +1043,15 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req > > if (W_ERROR_EQUAL(status, WERR_DS_DRA_SCHEMA_MISMATCH)) { > struct dreplsrv_partition *p; >+ bool ok; >+ >+ if (was_schema) { >+ nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP); >+ DBG_ERR("Got mismatch for schema partition: %s/%s\n", >+ win_errstr(status), nt_errstr(nt_status)); >+ tevent_req_nterror(req, nt_status); >+ return; >+ } > > if (state->retry_started) { > nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP); >@@ -992,6 +1140,12 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req > DEBUG(4,("Wrong schema when applying reply GetNCChanges, retrying\n")); > > state->retry_started = true; >+ >+ ok = dreplsrv_op_pull_source_detect_schema_cycle(req); >+ if (!ok) { >+ return; >+ } >+ > dreplsrv_op_pull_source_get_changes_trigger(req); > return; > >-- >2.17.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 12204
:
12426
|
12427
|
12428
|
12435
|
12436
|
12437
|
12438
|
12439
|
13224
|
14850
|
15077
|
15081
|
15082