From ce24e054e604331a5b8623f725bba6a81750982f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 5 Apr 2019 10:46:50 +1300 Subject: [PATCH] ldb_kv: Skip @ records early in a search full scan @ records like @IDXLIST are only available via a base search on the specific name but the method by which they were excluded was expensive, after the unpack the DN is exploded and ldb_match_msg_error() would reject it for failing to match the scope. This uses the fact that @ records have the DN=@ prefix on their TDB/LMDB key to quickly exclude them from consideration. Based on analysis by Garming Sam. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13893 Signed-off-by: Andrew Bartlett Reviewed-by: Garming Sam Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Wed Apr 10 06:23:39 UTC 2019 on sn-devel-144 (cherry picked from commit 49b77d8df2d7113ac7ddb75e78de6628933ff852) --- lib/ldb/ldb_key_value/ldb_kv.c | 12 +++++++++++- lib/ldb/ldb_key_value/ldb_kv.h | 7 ++++--- lib/ldb/ldb_key_value/ldb_kv_index.c | 14 ++------------ lib/ldb/ldb_key_value/ldb_kv_search.c | 19 ++++++++++++++++++- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/lib/ldb/ldb_key_value/ldb_kv.c b/lib/ldb/ldb_key_value/ldb_kv.c index d4f896736a2..31bdfb532f2 100644 --- a/lib/ldb/ldb_key_value/ldb_kv.c +++ b/lib/ldb/ldb_key_value/ldb_kv.c @@ -63,12 +63,22 @@ struct ldb_kv_req_spy { * Determine if this key could hold a record. We allow the new GUID * index, the old DN index and a possible future ID= */ -bool ldb_kv_key_is_record(struct ldb_val key) +bool ldb_kv_key_is_normal_record(struct ldb_val key) { if (key.length < 4) { return false; } + /* + * @ records are not normal records, we don't want to index + * them nor search on them + */ + if (key.length > 4 && + memcmp(key.data, "DN=@", 4) == 0) { + return false; + } + + /* All other DN= records are however */ if (memcmp(key.data, "DN=", 3) == 0) { return true; } diff --git a/lib/ldb/ldb_key_value/ldb_kv.h b/lib/ldb/ldb_key_value/ldb_kv.h index 5070a588c00..cbc5213c765 100644 --- a/lib/ldb/ldb_key_value/ldb_kv.h +++ b/lib/ldb/ldb_key_value/ldb_kv.h @@ -231,10 +231,11 @@ int ldb_kv_search(struct ldb_kv_context *ctx); /* * The following definitions come from lib/ldb/ldb_key_value/ldb_kv.c */ /* - * Determine if this key could hold a record. We allow the new GUID - * index, the old DN index and a possible future ID= + * Determine if this key could hold a normal record. We allow the new + * GUID index, the old DN index and a possible future ID= but not + * DN=@. */ -bool ldb_kv_key_is_record(struct ldb_val key); +bool ldb_kv_key_is_normal_record(struct ldb_val key); struct ldb_val ldb_kv_key_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *dn); diff --git a/lib/ldb/ldb_key_value/ldb_kv_index.c b/lib/ldb/ldb_key_value/ldb_kv_index.c index 6d02c91a597..af02107b5d2 100644 --- a/lib/ldb/ldb_key_value/ldb_kv_index.c +++ b/lib/ldb/ldb_key_value/ldb_kv_index.c @@ -2925,12 +2925,7 @@ static int re_key(struct ldb_kv_private *ldb_kv, ldb = ldb_module_get_ctx(module); - if (key.length > 4 && - memcmp(key.data, "DN=@", 4) == 0) { - return 0; - } - - is_record = ldb_kv_key_is_record(key); + is_record = ldb_kv_key_is_normal_record(key); if (is_record == false) { return 0; } @@ -3012,12 +3007,7 @@ static int re_index(struct ldb_kv_private *ldb_kv, ldb = ldb_module_get_ctx(module); - if (key.length > 4 && - memcmp(key.data, "DN=@", 4) == 0) { - return 0; - } - - is_record = ldb_kv_key_is_record(key); + is_record = ldb_kv_key_is_normal_record(key); if (is_record == false) { return 0; } diff --git a/lib/ldb/ldb_key_value/ldb_kv_search.c b/lib/ldb/ldb_key_value/ldb_kv_search.c index a384ee92367..a54f6149b60 100644 --- a/lib/ldb/ldb_key_value/ldb_kv_search.c +++ b/lib/ldb/ldb_key_value/ldb_kv_search.c @@ -512,7 +512,24 @@ static int search_func(struct ldb_kv_private *ldb_kv, ac = talloc_get_type(state, struct ldb_kv_context); ldb = ldb_module_get_ctx(ac->module); - if (ldb_kv_key_is_record(key) == false) { + /* + * We want to skip @ records early in a search full scan + * + * @ records like @IDXLIST are only available via a base + * search on the specific name but the method by which they + * were excluded was expensive, after the unpack the DN is + * exploded and ldb_match_msg_error() would reject it for + * failing to match the scope. + * + * ldb_kv_key_is_normal_record() uses the fact that @ records + * have the DN=@ prefix on their TDB/LMDB key to quickly + * exclude them from consideration. + * + * (any other non-records are also excluded by the same key + * match) + */ + + if (ldb_kv_key_is_normal_record(key) == false) { return 0; } -- 2.17.1