summaryrefslogtreecommitdiffstats
path: root/source4/dsdb/schema/schema_set.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2014-05-14 20:12:03 +1200
committerAndrew Bartlett <abartlet@samba.org>2014-06-11 10:18:26 +0200
commit791c38282d681c60eaedb47803b9043991f5950d (patch)
tree55ad69a7a7f9f721eb42ef9f2e4789443bef2ce3 /source4/dsdb/schema/schema_set.c
parent8327321225251e312ccbd06bbefa5ebf98099f34 (diff)
downloadsamba-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.c94
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;
}