static int new_partition_from_dn(struct ldb_context *ldb, struct partition_private_data *data, 
				 TALLOC_CTX *mem_ctx, 
				 struct ldb_dn *dn, const char *filename,
				 const char *backend_db_store,
				 struct dsdb_partition **partition) {
	struct dsdb_control_current_partition *ctrl;
	struct ldb_module *backend_module;
	char *backend_path;
	struct ldb_module *module_chain;
	const char **modules;
	const char **options = NULL;
	int ret;

	(*partition) = talloc_zero(mem_ctx, struct dsdb_partition);
	if (!*partition) {
		return ldb_oom(ldb);
	}

	(*partition)->ctrl = ctrl = talloc((*partition), struct dsdb_control_current_partition);
	if (!ctrl) {
		talloc_free(*partition);
		return ldb_oom(ldb);
	}

	/* the backend LDB is the DN (base64 encoded if not 'plain') followed by .ldb */
	backend_path = ldb_relative_path(ldb,
					 *partition,
					 filename);
	if (!backend_path) {
		ldb_asprintf_errstring(ldb,
				       "partition_init: unable to determine an relative path for partition: %s",
				       filename);
		talloc_free(*partition);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	(*partition)->backend_url = talloc_asprintf(*partition, "%s://%s",
						    backend_db_store,
						    backend_path);

	if (!(ldb_module_flags(ldb) & LDB_FLG_RDONLY)) {
		char *p;
		char *backend_dir;

		p = strrchr(backend_path, '/');
		if (p) {
			p[0] = '\0';
		}
		backend_dir = backend_path;

		/* Failure is quite reasonable, it might alredy exist */
		mkdir(backend_dir, 0700);
	}

	ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
	ctrl->dn = talloc_steal(ctrl, dn);
	
	options = ldb_options_get(ldb);
	ret = ldb_module_connect_backend(
	    ldb, (*partition)->backend_url, options, &backend_module);
	if (ret != LDB_SUCCESS) {
		return ret;
	}
	talloc_steal((*partition), backend_module);

	modules = find_modules_for_dn(data, dn);

	if (!modules) {
		DEBUG(0, ("Unable to load partition modules for new DN %s, perhaps you need to reprovision?  See partition-upgrade.txt for instructions\n", ldb_dn_get_linearized(dn)));
		talloc_free(*partition);
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}
	ret = ldb_module_load_list(ldb, modules, backend_module, &module_chain);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, 
				       "partition_init: "
				       "loading backend for %s failed: %s", 
				       ldb_dn_get_linearized(dn), ldb_errstring(ldb));
		talloc_free(*partition);
		return ret;
	}
	ret = ldb_module_init_chain(ldb, module_chain);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb,
				       "partition_init: "
				       "initialising backend for %s failed: %s", 
				       ldb_dn_get_linearized(dn), ldb_errstring(ldb));
		talloc_free(*partition);
		return ret;
	}

	/* This weirdness allows us to use ldb_next_request() in partition.c */
	(*partition)->module = ldb_module_new(*partition, ldb, "partition_next", NULL);
	if (!(*partition)->module) {
		talloc_free(*partition);
		return ldb_oom(ldb);
	}
	ldb_module_set_next((*partition)->module, talloc_steal((*partition)->module, module_chain));

	/* if we were in a transaction then we need to start a
	   transaction on this new partition, otherwise we'll get a
	   transaction mismatch when we end the transaction */
	if (data->in_transaction) {
		if (ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING) {
			ldb_debug(ldb, LDB_DEBUG_TRACE, "partition_start_trans() -> %s (new partition)", 
				  ldb_dn_get_linearized((*partition)->ctrl->dn));
		}
		ret = ldb_next_start_trans((*partition)->module);
	}

	return ret;
}
static int new_partition_from_dn(struct ldb_context *ldb, struct partition_private_data *data, 
				 TALLOC_CTX *mem_ctx, 
				 struct ldb_dn *dn, const char *filename,
				 const char *backend_db_store,
				 struct dsdb_partition **partition) {
	struct dsdb_control_current_partition *ctrl;
	struct ldb_module *backend_module;
	char *backend_path;
	struct ldb_module *module_chain;
	const char **modules;
	const char **options = NULL;
	int ret;

	(*partition) = talloc_zero(mem_ctx, struct dsdb_partition);
	if (!*partition) {
		return ldb_oom(ldb);
	}

	(*partition)->ctrl = ctrl = talloc((*partition), struct dsdb_control_current_partition);
	if (!ctrl) {
		talloc_free(*partition);
		return ldb_oom(ldb);
	}

	 
	backend_path = ldb_relative_path(ldb,
					 *partition,
					 filename);
	if (!backend_path) {
		ldb_asprintf_errstring(ldb,
				       "partition_init: unable to determine an relative path for partition: %s",
				       filename);
		talloc_free(*partition);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	(*partition)->backend_url = talloc_asprintf(*partition, "%s://%s",
						    backend_db_store,
						    backend_path);

	if (!(ldb_module_flags(ldb) & LDB_FLG_RDONLY)) {
		char *p;
		char *backend_dir;

		p = strrchr(backend_path, '/');
		if (p) {
			p[0] = '\0';
		}
		backend_dir = backend_path;

		 
		mkdir(backend_dir, 0700);
	}

	ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
	ctrl->dn = talloc_steal(ctrl, dn);
	
	options = ldb_options_get(ldb);
	ret = ldb_module_connect_backend(
	    ldb, (*partition)->backend_url, options, &backend_module);
	if (ret != LDB_SUCCESS) {
		return ret;
	}
	talloc_steal((*partition), backend_module);

	modules = find_modules_for_dn(data, dn);

	if (!modules) {
		DEBUG(0, ("Unable to load partition modules for new DN %s, perhaps you need to reprovision?  See partition-upgrade.txt for instructions\n", ldb_dn_get_linearized(dn)));
		talloc_free(*partition);
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}
	ret = ldb_module_load_list(ldb, modules, backend_module, &module_chain);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, 
				       "partition_init: "
				       "loading backend for %s failed: %s", 
				       ldb_dn_get_linearized(dn), ldb_errstring(ldb));
		talloc_free(*partition);
		return ret;
	}
	ret = ldb_module_init_chain(ldb, module_chain);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb,
				       "partition_init: "
				       "initialising backend for %s failed: %s", 
				       ldb_dn_get_linearized(dn), ldb_errstring(ldb));
		talloc_free(*partition);
		return ret;
	}

	 
	(*partition)->module = ldb_module_new(*partition, ldb, "partition_next", NULL);
	if (!(*partition)->module) {
		talloc_free(*partition);
		return ldb_oom(ldb);
	}
	ldb_module_set_next((*partition)->module, talloc_steal((*partition)->module, module_chain));

	 
	if (data->in_transaction) {
		if (ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING) {
			ldb_debug(ldb, LDB_DEBUG_TRACE, "partition_start_trans() -> %s (new partition)", 
				  ldb_dn_get_linearized((*partition)->ctrl->dn));
		}
		ret = ldb_next_start_trans((*partition)->module);
	}

	return ret;
}