From 518320ae33ae6d77d67ec216cd4cd68d69036be1 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 15 Feb 2019 10:27:14 +1300 Subject: [PATCH] dsdb: linked_attributes module knows about sorted links Until now the linked attrbutes module has allocated its private data on a per transaction basis, but we prefer to check the sorted links feature less often than that. So the private data struct is given module life time and a transaction member to carry out the old role. In coming patches, the sorted links flag will be used. Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett --- .../samdb/ldb_modules/linked_attributes.c | 81 +++++++++++++------ 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index 4fd1209a46b..41c8afbbac0 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -53,10 +53,17 @@ #include "librpc/gen_ndr/ndr_misc.h" #include "dsdb/samdb/ldb_modules/util.h" -struct la_private { + +struct la_private_transaction { struct la_context *la_list; }; + +struct la_private { + struct la_private_transaction *transaction; + bool sorted_links; +}; + struct la_op_store { struct la_op_store *next; struct la_op_store *prev; @@ -936,15 +943,18 @@ static int linked_attributes_rename(struct ldb_module *module, struct ldb_reques static int la_queue_mod_request(struct la_context *ac) { struct la_private *la_private = - talloc_get_type(ldb_module_get_private(ac->module), struct la_private); + talloc_get_type(ldb_module_get_private(ac->module), + struct la_private); - if (la_private == NULL) { - ldb_debug(ldb_module_get_ctx(ac->module), LDB_DEBUG_ERROR, __location__ ": No la_private transaction setup\n"); + if (la_private == NULL || la_private->transaction == NULL) { + ldb_debug(ldb_module_get_ctx(ac->module), + LDB_DEBUG_ERROR, + __location__ ": No la_private transaction setup\n"); return ldb_operr(ldb_module_get_ctx(ac->module)); } - talloc_steal(la_private, ac); - DLIST_ADD(la_private->la_list, ac); + talloc_steal(la_private->transaction, ac); + DLIST_ADD(la_private->transaction->la_list, ac); return ldb_module_done(ac->req, ac->op_controls, ac->op_response, LDB_SUCCESS); @@ -1209,15 +1219,19 @@ static int la_do_mod_request(struct ldb_module *module, struct la_context *ac) static int linked_attributes_start_transaction(struct ldb_module *module) { /* create our private structure for this transaction */ - struct la_private *la_private = talloc_get_type(ldb_module_get_private(module), - struct la_private); - talloc_free(la_private); - la_private = talloc(module, struct la_private); + struct la_private *la_private = + talloc_get_type(ldb_module_get_private(module), + struct la_private); + if (la_private == NULL) { return ldb_oom(ldb_module_get_ctx(module)); } - la_private->la_list = NULL; - ldb_module_set_private(module, la_private); + talloc_free(la_private->transaction); + la_private->transaction = talloc(module, struct la_private_transaction); + if (la_private->transaction == NULL) { + return ldb_oom(ldb_module_get_ctx(module)); + } + la_private->transaction->la_list = NULL; return ldb_next_start_trans(module); } @@ -1227,12 +1241,14 @@ static int linked_attributes_start_transaction(struct ldb_module *module) */ static int linked_attributes_prepare_commit(struct ldb_module *module) { - struct la_private *la_private = - talloc_get_type(ldb_module_get_private(module), struct la_private); struct la_context *ac; - - if (!la_private) { - /* prepare commit without begin_transaction - let someone else return the error, just don't segfault */ + struct la_private *la_private = + talloc_get_type(ldb_module_get_private(module), + struct la_private); + if (la_private == NULL || la_private->transaction == NULL) { + DBG_ERR("prepare_commit without begin_transaction\n"); + /* prepare commit without begin_transaction - let someone else + * return the error, just don't segfault */ return ldb_next_prepare_commit(module); } /* walk the list backwards, to do the first entry first, as we @@ -1242,7 +1258,7 @@ static int linked_attributes_prepare_commit(struct ldb_module *module) /* Start at the end of the list - so we can start * there, but ensure we don't create a loop by NULLing * it out in the first element */ - ac = DLIST_TAIL(la_private->la_list); + ac = DLIST_TAIL(la_private->transaction->la_list); for (; ac; ac=DLIST_PREV(ac)) { int ret; @@ -1250,14 +1266,12 @@ static int linked_attributes_prepare_commit(struct ldb_module *module) ret = la_do_mod_request(module, ac); if (ret != LDB_SUCCESS) { DEBUG(0,(__location__ ": Failed mod request ret=%d\n", ret)); - talloc_free(la_private); - ldb_module_set_private(module, NULL); + TALLOC_FREE(la_private->transaction); return ret; } } - talloc_free(la_private); - ldb_module_set_private(module, NULL); + TALLOC_FREE(la_private->transaction); return ldb_next_prepare_commit(module); } @@ -1265,15 +1279,17 @@ static int linked_attributes_prepare_commit(struct ldb_module *module) static int linked_attributes_del_transaction(struct ldb_module *module) { struct la_private *la_private = - talloc_get_type(ldb_module_get_private(module), struct la_private); - talloc_free(la_private); - ldb_module_set_private(module, NULL); + talloc_get_type(ldb_module_get_private(module), + struct la_private); + TALLOC_FREE(la_private->transaction); return ldb_next_del_trans(module); } static int linked_attributes_ldb_init(struct ldb_module *module) { int ret; + struct la_private *la_private = NULL; + struct ldb_context *ldb = ldb_module_get_ctx(module); ret = ldb_mod_register_control(module, LDB_CONTROL_VERIFY_NAME_OID); if (ret != LDB_SUCCESS) { @@ -1282,6 +1298,21 @@ static int linked_attributes_ldb_init(struct ldb_module *module) return ldb_operr(ldb_module_get_ctx(module)); } + la_private = talloc_zero(module, struct la_private); + if (la_private == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = dsdb_check_samba_compatible_feature(module, + SAMBA_SORTED_LINKS_FEATURE, + &la_private->sorted_links); + if (ret != LDB_SUCCESS) { + talloc_free(la_private); + return ret; + } + + ldb_module_set_private(module, la_private); return ldb_next_init(module); } -- 2.34.1