From e517d68a8f2772b863a7c072bd95d224b4ab8bf4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 27 Jul 2016 00:20:27 +1200 Subject: [PATCH] ldb: Add flags to ltdb_search_dn1() to control memory allocation This is used in the index code in particular to avoid an allocation per value (as there may be one value per DB object at times Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Andrew Bartlett Signed-off-by: Stefan Metzmacher Reviewed-by: Douglas Bagnall --- lib/ldb/ldb_tdb/ldb_cache.c | 10 ++++---- lib/ldb/ldb_tdb/ldb_index.c | 6 +++-- lib/ldb/ldb_tdb/ldb_search.c | 58 ++++++++++++++++++++++++++++++++++++-------- lib/ldb/ldb_tdb/ldb_tdb.c | 7 +++--- lib/ldb/ldb_tdb/ldb_tdb.h | 3 ++- 5 files changed, 63 insertions(+), 21 deletions(-) diff --git a/lib/ldb/ldb_tdb/ldb_cache.c b/lib/ldb/ldb_tdb/ldb_cache.c index 6467af1d00c..2f19d276ece 100644 --- a/lib/ldb/ldb_tdb/ldb_cache.c +++ b/lib/ldb/ldb_tdb/ldb_cache.c @@ -126,7 +126,7 @@ static int ltdb_attributes_load(struct ldb_module *module) dn = ldb_dn_new(module, ldb, LTDB_ATTRIBUTES); if (dn == NULL) goto failed; - r = ltdb_search_dn1(module, dn, msg); + r = ltdb_search_dn1(module, dn, msg, 0); talloc_free(dn); if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) { goto failed; @@ -301,7 +301,7 @@ int ltdb_cache_load(struct ldb_module *module) baseinfo_dn = ldb_dn_new(baseinfo, ldb, LTDB_BASEINFO); if (baseinfo_dn == NULL) goto failed; - r= ltdb_search_dn1(module, baseinfo_dn, baseinfo); + r= ltdb_search_dn1(module, baseinfo_dn, baseinfo, 0); if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) { goto failed; } @@ -319,7 +319,7 @@ int ltdb_cache_load(struct ldb_module *module) tdb_transaction_commit(ltdb->tdb); - if (ltdb_search_dn1(module, baseinfo_dn, baseinfo) != LDB_SUCCESS) { + if (ltdb_search_dn1(module, baseinfo_dn, baseinfo, 0) != LDB_SUCCESS) { goto failed; } } @@ -341,7 +341,7 @@ int ltdb_cache_load(struct ldb_module *module) options_dn = ldb_dn_new(options, ldb, LTDB_OPTIONS); if (options_dn == NULL) goto failed; - r= ltdb_search_dn1(module, options_dn, options); + r= ltdb_search_dn1(module, options_dn, options, 0); if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) { goto failed; } @@ -374,7 +374,7 @@ int ltdb_cache_load(struct ldb_module *module) indexlist_dn = ldb_dn_new(module, ldb, LTDB_INDEXLIST); if (indexlist_dn == NULL) goto failed; - r = ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist); + r = ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist, 0); if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) { goto failed; } diff --git a/lib/ldb/ldb_tdb/ldb_index.c b/lib/ldb/ldb_tdb/ldb_index.c index e6bfb1b6239..800363a0a3d 100644 --- a/lib/ldb/ldb_tdb/ldb_index.c +++ b/lib/ldb/ldb_tdb/ldb_index.c @@ -178,7 +178,9 @@ normal_index: return LDB_ERR_OPERATIONS_ERROR; } - ret = ltdb_search_dn1(module, dn, msg); + ret = ltdb_search_dn1(module, dn, msg, + LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC + |LDB_UNPACK_DATA_FLAG_NO_DN); if (ret != LDB_SUCCESS) { talloc_free(msg); return ret; @@ -949,7 +951,7 @@ static int ltdb_index_filter(const struct dn_list *dn_list, return LDB_ERR_OPERATIONS_ERROR; } - ret = ltdb_search_dn1(ac->module, dn, msg); + ret = ltdb_search_dn1(ac->module, dn, msg, 0); talloc_free(dn); if (ret == LDB_ERR_NO_SUCH_OBJECT) { /* the record has disappeared? yes, this can happen */ diff --git a/lib/ldb/ldb_tdb/ldb_search.c b/lib/ldb/ldb_tdb/ldb_search.c index 62a36c7c252..979e7c83f97 100644 --- a/lib/ldb/ldb_tdb/ldb_search.c +++ b/lib/ldb/ldb_tdb/ldb_search.c @@ -238,16 +238,50 @@ static int ltdb_search_base(struct ldb_module *module, struct ldb_dn *dn) struct ltdb_parse_data_unpack_ctx { struct ldb_message *msg; struct ldb_module *module; + unsigned int unpack_flags; }; static int ltdb_parse_data_unpack(TDB_DATA key, TDB_DATA data, void *private_data) { struct ltdb_parse_data_unpack_ctx *ctx = private_data; - + unsigned int nb_elements_in_db; + int ret; struct ldb_context *ldb = ldb_module_get_ctx(ctx->module); - int ret = ldb_unpack_data(ldb, (struct ldb_val *)&data, ctx->msg); + struct ldb_val data_parse = { + .data = data.dptr, + .length = data.dsize + }; + + if (ctx->unpack_flags & LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC) { + /* + * If we got LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC + * we need at least do a memdup on the whole + * data buffer as that may change later + * and the caller needs a stable result. + */ + data_parse.data = talloc_memdup(ctx->msg, + data.dptr, + data.dsize); + if (data_parse.data == NULL) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "Unable to allocate data(%d) for %*.*s\n", + (int)data.dsize, + (int)key.dsize, (int)key.dsize, key.dptr); + return LDB_ERR_OPERATIONS_ERROR; + } + } + + ret = ldb_unpack_data_only_attr_list_flags(ldb, &data_parse, + ctx->msg, + NULL, 0, + ctx->unpack_flags, + &nb_elements_in_db); if (ret == -1) { + if (data_parse.data != data.dptr) { + talloc_free(data_parse.data); + } + ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %*.*s\n", (int)key.dsize, (int)key.dsize, key.dptr); return LDB_ERR_OPERATIONS_ERROR; @@ -262,7 +296,8 @@ static int ltdb_parse_data_unpack(TDB_DATA key, TDB_DATA data, return LDB_ERR_NO_SUCH_OBJECT on record-not-found and LDB_SUCCESS on success */ -int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg) +int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg, + unsigned int unpack_flags) { void *data = ldb_module_get_private(module); struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); @@ -270,7 +305,8 @@ int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_mes TDB_DATA tdb_key; struct ltdb_parse_data_unpack_ctx ctx = { .msg = msg, - .module = module + .module = module, + .unpack_flags = unpack_flags }; /* form the key */ @@ -296,12 +332,14 @@ int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_mes } else if (ret != LDB_SUCCESS) { return ret; } - - if (!msg->dn) { - msg->dn = ldb_dn_copy(msg, dn); - } - if (!msg->dn) { - return LDB_ERR_OPERATIONS_ERROR; + + if ((unpack_flags & LDB_UNPACK_DATA_FLAG_NO_DN) == 0) { + if (!msg->dn) { + msg->dn = ldb_dn_copy(msg, dn); + } + if (!msg->dn) { + return LDB_ERR_OPERATIONS_ERROR; + } } return LDB_SUCCESS; diff --git a/lib/ldb/ldb_tdb/ldb_tdb.c b/lib/ldb/ldb_tdb/ldb_tdb.c index 1a4f4cad4c4..7cc0a2e08d1 100644 --- a/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/lib/ldb/ldb_tdb/ldb_tdb.c @@ -449,7 +449,7 @@ static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn) /* in case any attribute of the message was indexed, we need to fetch the old record */ - ret = ltdb_search_dn1(module, dn, msg); + ret = ltdb_search_dn1(module, dn, msg, LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC); if (ret != LDB_SUCCESS) { /* not finding the old record is an error */ goto done; @@ -1033,7 +1033,8 @@ static int ltdb_rename(struct ltdb_context *ctx) } /* we need to fetch the old record to re-add under the new name */ - ret = ltdb_search_dn1(module, req->op.rename.olddn, msg); + ret = ltdb_search_dn1(module, req->op.rename.olddn, msg, + LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC); if (ret != LDB_SUCCESS) { /* not finding the old record is an error */ return ret; @@ -1232,7 +1233,7 @@ static int ltdb_sequence_number(struct ltdb_context *ctx, goto done; } - ret = ltdb_search_dn1(module, dn, msg); + ret = ltdb_search_dn1(module, dn, msg, 0); if (ret != LDB_SUCCESS) { goto done; } diff --git a/lib/ldb/ldb_tdb/ldb_tdb.h b/lib/ldb/ldb_tdb/ldb_tdb.h index caa98ebf8ef..7390a047b20 100644 --- a/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/lib/ldb/ldb_tdb/ldb_tdb.h @@ -101,7 +101,8 @@ int ltdb_index_transaction_cancel(struct ldb_module *module); int ltdb_has_wildcard(struct ldb_module *module, const char *attr_name, const struct ldb_val *val); void ltdb_search_dn1_free(struct ldb_module *module, struct ldb_message *msg); -int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg); +int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg, + unsigned int unpack_flags); int ltdb_add_attr_results(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_message *msg, -- 2.11.4.GIT