From c096f9145122e3cf1fc6068b6c76c24abd3d3cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Thu, 17 Jun 2021 17:09:37 +0200 Subject: [PATCH 1/3] Allow hash tables for cache RBTs to be grown Upon creation, each dns_rbt_t structure has its "maxhashbits" field initialized to the value of the RBT_HASH_MAX_BITS preprocessor macro, i.e. 32. When the dns_rbt_adjusthashsize() function is called for the first time for a given RBT (for cache RBTs, this happens when they are first created, i.e. upon named startup), it lowers the value of the "maxhashbits" field to the number of bits required to index the requested number of hash table slots. When a larger hash table size is subsequently requested, the value of the "maxhashbits" field should be increased accordingly, up to RBT_HASH_MAX_BITS. However, the loop in the rehash_bits() function currently ensures that the number of bits necessary to index the resized hash table will not be larger than rbt->maxhashbits instead of RBT_HASH_MAX_BITS, preventing the hash table from being grown once the "maxhashbits" field of a given dns_rbt_t structure is set to any value lower than RBT_HASH_MAX_BITS. Fix by tweaking the loop guard condition in the rehash_bits() function so that it compares the new number of bits used for indexing the hash table against RBT_HASH_MAX_BITS rather than rbt->maxhashbits. --- lib/dns/rbt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index 03ec0993ce..a42b7d08ff 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -2337,7 +2337,7 @@ static uint32_t rehash_bits(dns_rbt_t *rbt, size_t newcount) { uint32_t newbits = rbt->hashbits; - while (newcount >= HASHSIZE(newbits) && newbits < rbt->maxhashbits) { + while (newcount >= HASHSIZE(newbits) && newbits < RBT_HASH_MAX_BITS) { newbits += 1; } From 6b77583f54428b83dbb19d3fd9111afdd0fdc84e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Thu, 17 Jun 2021 17:09:37 +0200 Subject: [PATCH 2/3] Allow resetting hash table size limits for DNS DBs When "max-cache-size" is changed to "unlimited" (or "0") for a running named instance (using "rndc reconfig"), the hash table size limit for each affected cache DB is not reset to the maximum possible value, preventing those hash tables from being allowed to grow as a result of new nodes being added. Extend dns_rbt_adjusthashsize() to interpret "size" set to 0 as a signal to remove any previously imposed limits on the hash table size. Adjust API documentation for dns_db_adjusthashsize() accordingly. Move the call to dns_db_adjusthashsize() from dns_cache_setcachesize() so that it also happens when "size" is set to 0. --- lib/dns/cache.c | 3 ++- lib/dns/include/dns/db.h | 9 +++++---- lib/dns/rbt.c | 27 ++++++++++++++++++++++----- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/dns/cache.c b/lib/dns/cache.c index 633fc5d122..9935275d8f 100644 --- a/lib/dns/cache.c +++ b/lib/dns/cache.c @@ -957,8 +957,9 @@ dns_cache_setcachesize(dns_cache_t *cache, size_t size) { * time, or replacing other limits). */ isc_mem_setwater(cache->mctx, water, cache, hiwater, lowater); - dns_db_adjusthashsize(cache->db, size); } + + dns_db_adjusthashsize(cache->db, size); } size_t diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index 8664cf1458..fe36759a2c 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -1400,14 +1400,15 @@ dns_db_hashsize(dns_db_t *db); isc_result_t dns_db_adjusthashsize(dns_db_t *db, size_t size); /*%< - * For database implementations using a hash table, adjust - * the size of the hash table to store objects with size - * memory footprint. + * For database implementations using a hash table, adjust the size of + * the hash table to store objects with a maximum total memory footprint + * of 'size' bytes. If 'size' is set to 0, it means no finite limit is + * requested. * * Requires: * * \li 'db' is a valid database. - * \li 'size' is maximum memory footprint of the database + * \li 'size' is maximum memory footprint of the database in bytes * * Returns: * \li #ISC_R_SUCCESS The registration succeeded diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index a42b7d08ff..a05fcd8609 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -1080,11 +1080,28 @@ isc_result_t dns_rbt_adjusthashsize(dns_rbt_t *rbt, size_t size) { REQUIRE(VALID_RBT(rbt)); - size_t newsize = size / RBT_HASH_BUCKETSIZE; - - rbt->maxhashbits = rehash_bits(rbt, newsize); - - maybe_rehash(rbt, newsize); + if (size > 0) { + /* + * Setting a new, finite size limit was requested for the RBT. + * Estimate how many hash table slots are needed for the + * requested size and how many bits would be needed to index + * those hash table slots, then rehash the RBT if necessary. + * Note that the hash table can only grow, it is not shrunk if + * the requested size limit is lower than the current one. + */ + size_t newsize = size / RBT_HASH_BUCKETSIZE; + rbt->maxhashbits = rehash_bits(rbt, newsize); + maybe_rehash(rbt, newsize); + } else { + /* + * Setting an infinite size limit was requested for the RBT. + * Increase the maximum allowed number of hash table slots to + * 2^32, which enables the hash table to grow as nodes are + * added to the RBT without immediately preallocating 2^32 hash + * table slots. + */ + rbt->maxhashbits = RBT_HASH_MAX_BITS; + } return (ISC_R_SUCCESS); } From 0c59f1362cd2685125631f0a901785bf7d64a5f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Thu, 17 Jun 2021 17:09:37 +0200 Subject: [PATCH 3/3] Add CHANGES entry --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index c671794708..0b83c6f118 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +5658. [bug] Increasing "max-cache-size" for a running named instance + (using "rndc reconfig") was not causing the hash tables + used by cache databases to be grown accordingly. This + has been fixed. [GL #2770] + 5657. [cleanup] Removed support for builtin atomics in old versions of clang (<< 3.6.0) and gcc (<< 4.7.0), and atomics emulated with mutex. [GL #2606]