diff options
author | Andrew Bartlett <abartlet@samba.org> | 2014-05-14 20:12:03 +1200 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2014-06-11 10:18:26 +0200 |
commit | 791c38282d681c60eaedb47803b9043991f5950d (patch) | |
tree | 55ad69a7a7f9f721eb42ef9f2e4789443bef2ce3 /source4/dsdb/schema/schema_set.c | |
parent | 8327321225251e312ccbd06bbefa5ebf98099f34 (diff) | |
download | samba-791c38282d681c60eaedb47803b9043991f5950d.tar.gz samba-791c38282d681c60eaedb47803b9043991f5950d.tar.xz samba-791c38282d681c60eaedb47803b9043991f5950d.zip |
dsdb: Do not refresh the schema using the wrong event context
What we now do is have the refresh function and module be on a
seperate object to the schema, only referring to the data and
not excuting on the original ldb and event loop.
That is, we never use another ldb context when calling the
refresh function, by binding the refresh handler to the
ldb and not the schema.
Andrew Bartlett
Change-Id: I5c323dda743cf5858badd01147fda6227599bc16
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'source4/dsdb/schema/schema_set.c')
-rw-r--r-- | source4/dsdb/schema/schema_set.c | 94 |
1 files changed, 69 insertions, 25 deletions
diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c index 78c6e56bb5..6029e46a7a 100644 --- a/source4/dsdb/schema/schema_set.c +++ b/source4/dsdb/schema/schema_set.c @@ -443,6 +443,26 @@ failed: * Attach the schema to an opaque pointer on the ldb, * so ldb modules can find it */ +int dsdb_set_schema_refresh_function(struct ldb_context *ldb, + dsdb_schema_refresh_fn refresh_fn, + struct ldb_module *module) +{ + int ret = ldb_set_opaque(ldb, "dsdb_schema_refresh_fn", refresh_fn); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_set_opaque(ldb, "dsdb_schema_refresh_fn_private_data", module); + if (ret != LDB_SUCCESS) { + return ret; + } + return LDB_SUCCESS; +} + +/** + * Attach the schema to an opaque pointer on the ldb, + * so ldb modules can find it + */ int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema) { struct dsdb_schema *old_schema; @@ -467,6 +487,8 @@ int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema) talloc_steal(ldb, schema); } + talloc_steal(ldb, schema); + ret = ldb_set_opaque(ldb, "dsdb_use_global_schema", NULL); if (ret != LDB_SUCCESS) { return ret; @@ -518,6 +540,16 @@ int dsdb_reference_schema(struct ldb_context *ldb, struct dsdb_schema *schema, return ret; } + ret = ldb_set_opaque(ldb, "dsdb_refresh_fn", NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_set_opaque(ldb, "dsdb_refresh_fn_private_data", NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = dsdb_schema_set_indices_and_attributes(ldb, schema, write_indices_and_attributes); if (ret != LDB_SUCCESS) { return ret; @@ -533,14 +565,15 @@ int dsdb_set_global_schema(struct ldb_context *ldb) { int ret; void *use_global_schema = (void *)1; - if (!global_schema) { - return LDB_SUCCESS; - } ret = ldb_set_opaque(ldb, "dsdb_use_global_schema", use_global_schema); if (ret != LDB_SUCCESS) { return ret; } + if (global_schema == NULL) { + return LDB_SUCCESS; + } + /* Set the new attributes based on the new schema */ ret = dsdb_schema_set_indices_and_attributes(ldb, global_schema, false /* Don't write indices and attributes, it's expensive */); if (ret == LDB_SUCCESS) { @@ -567,11 +600,13 @@ bool dsdb_uses_global_schema(struct ldb_context *ldb) struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb, TALLOC_CTX *reference_ctx) { const void *p; - struct dsdb_schema *schema_out; - struct dsdb_schema *schema_in; + struct dsdb_schema *schema_out = NULL; + struct dsdb_schema *schema_in = NULL; + dsdb_schema_refresh_fn refresh_fn; + struct ldb_module *loaded_from_module; bool use_global_schema; TALLOC_CTX *tmp_ctx = talloc_new(reference_ctx); - if (!tmp_ctx) { + if (tmp_ctx == NULL) { return NULL; } @@ -581,29 +616,38 @@ struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb, TALLOC_CTX *referen schema_in = global_schema; } else { p = ldb_get_opaque(ldb, "dsdb_schema"); - - schema_in = talloc_get_type(p, struct dsdb_schema); - if (!schema_in) { - talloc_free(tmp_ctx); - return NULL; + if (p != NULL) { + schema_in = talloc_get_type_abort(p, struct dsdb_schema); } } - if (schema_in->refresh_fn && !schema_in->refresh_in_progress) { - if (!talloc_reference(tmp_ctx, schema_in)) { - /* - * ensure that the schema_in->refresh_in_progress - * remains valid for the right amount of time - */ - talloc_free(tmp_ctx); - return NULL; + refresh_fn = ldb_get_opaque(ldb, "dsdb_schema_refresh_fn"); + if (refresh_fn) { + loaded_from_module = ldb_get_opaque(ldb, "dsdb_schema_refresh_fn_private_data"); + + SMB_ASSERT(loaded_from_module && (ldb_module_get_ctx(loaded_from_module) == ldb)); + } + + if (refresh_fn) { + /* We need to guard against recurisve calls here */ + if (ldb_set_opaque(ldb, "dsdb_schema_refresh_fn", NULL) != LDB_SUCCESS) { + ldb_debug_set(ldb, LDB_DEBUG_FATAL, + "dsdb_get_schema: clearing dsdb_schema_refresh_fn failed"); + } else { + schema_out = refresh_fn(loaded_from_module, + ldb_get_event_context(ldb), + schema_in, + use_global_schema); + } + if (ldb_set_opaque(ldb, "dsdb_schema_refresh_fn", refresh_fn) != LDB_SUCCESS) { + ldb_debug_set(ldb, LDB_DEBUG_FATAL, + "dsdb_get_schema: re-setting dsdb_schema_refresh_fn failed"); + } + if (!schema_out) { + schema_out = schema_in; + ldb_debug_set(ldb, LDB_DEBUG_FATAL, + "dsdb_get_schema: refresh_fn() failed"); } - schema_in->refresh_in_progress = true; - /* This may change schema, if it needs to reload it from disk */ - schema_out = schema_in->refresh_fn(schema_in->loaded_from_module, - schema_in, - use_global_schema); - schema_in->refresh_in_progress = false; } else { schema_out = schema_in; } |