2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 05:28:00 +00:00

282 Commits

Author SHA1 Message Date
Ondřej Surý
091d738c72 Convert all categories and modules into static lists
Remove the complicated mechanism that could be (in theory) used by
external libraries to register new categories and modules with
statically defined lists in <isc/log.h>.  This is similar to what we
have done for <isc/result.h> result codes.  All the libraries are now
internal to BIND 9, so we don't need to provide a mechanism to register
extra categories and modules.
2024-08-20 12:50:39 +00:00
Aydın Mercan
5dbb560747 remove the crc64 implementation
CRC-64 has been added for map files. Now that the map file format has
been removed, there isn't a reason to keep the implementation.
2024-08-05 11:21:25 +00:00
Ondřej Surý
eed17611d8
Reduce lock contention during RBTDB tree pruning
The log message for commit 24381cc36d8528f5a4046fb2614451aeac4cdfc1
explained:

    In some older BIND 9 branches, the extra queuing overhead eliminated by
    this change could be remotely exploited to cause excessive memory use.
    Due to architectural shift, this branch is not vulnerable to that issue,
    but applying the fix to the latter is nevertheless deemed prudent for
    consistency and to make the code future-proof.

However, it turned out that having a single queue for the nodes to be
pruned increased lock contention to a level where cleaning up nodes from
the RBTDB took too long, causing the amount of memory used by the cache
to grow indefinitely over time.

This commit reverts the change to the pruning mechanism introduced by
commit 24381cc36d8528f5a4046fb2614451aeac4cdfc1 as BIND branches newer
than 9.16 were not affected by the excessive event queueing overhead
issue mentioned in the log message for the above commit.
2024-02-29 11:23:03 +01:00
Michał Kępień
8610799317 BIND 9.19.21
-----BEGIN SSH SIGNATURE-----
 U1NIU0lHAAAAAQAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBANamVSTMToLcHCXRu1f52e
 tTJWV3T1GSVrPYXwAGe6EVC7m9CTl06FZ9ZG/ymn1S1++dk4ByVZXf6dODe2Mu0RuqGmyf
 MUEMKXVdj3cEQhgRaMjBXvIZoYAsQlbHO2BEttomq8PhrpLRizDBq4Bv2aThM0XN2QqSGS
 ozwYMcPiGUoMVNcVrC4ZQ+Cptb5C4liqAcpRqrSo8l1vcNg5b1Hk6r7NFPdx542gsGMLae
 wZrnKn3LWz3ZXTGeK2cRmBxm/bydiVSCsc9XjB+tWtIGUpQsfaXqZ7Hs6t+1f1vsnu88oJ
 oi1dRBo3YNRl49UiCukXWayQrPJa8wwxURS9W28JMAAAADZ2l0AAAAAAAAAAZzaGE1MTIA
 AAEUAAAADHJzYS1zaGEyLTUxMgAAAQBSREyaosd+mY8kovqAvGYR8pOui/7gOi6pBprPGw
 RlOB5z6YOx5FOjbVL/YvBhKk2gbox++o8jCMEmdNNbWeO3U3uBvxCa+8QGARbuMV6vdoR4
 qjnOgOfryXyaRw7PQX0ZH0gPw1B1036y5bnW7WPkqrTvGgxW34O1q6j0EumE0vh90E24/l
 PAWKDCTqDR/+slGDuWgtPcCZuClljw1Mh0dAliKkGhp0l80qMQSr6O/p66A44UxzKwtnnt
 lagtO0j4nZ+BxC/hyaFc/FlCzeoc48qFQRIt0ZjYKU+XK0CUr2RTpYFdi/n7y3BNd7bDkD
 nIkEDddn/lXP5rkAdkmDCa
 -----END SSH SIGNATURE-----
gpgsig -----BEGIN SSH SIGNATURE-----
 U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAg25GGAuUyFX1gxo7QocNm8V6J/8
 frHSduYX7Aqk4iJLwAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
 AAAAQEGqBHXwCtEJxRzHbTp6CfBNjqwIAjRD9G+HC4M7q77KBEBgc6dRf15ZRRgiWJCk5P
 iHMZkEMyWCnELMzhiTzgE=
 -----END SSH SIGNATURE-----

Merge tag 'v9.19.21'

BIND 9.19.21
2024-02-14 13:24:56 +01:00
Evan Hunt
ac9bd03a0d clean up dns_rbt
- create_node() in rbt.c cannot fail
- the dns_rbt_*name() functions, which are wrappers around
  dns_rbt_[add|find|delete]node(), were never used except in tests.

this change isn't really necessary since RBT is likely to go away
eventually anyway. but keeping the API as simple as possible while it
persists is a good thing, and may reduce confusion while QPDB is being
developed from RBTDB code.
2024-02-14 01:36:44 -08:00
Evan Hunt
78d173b548 move DNS_RBT_NSEC_* to db.h
these values pertain to whether a node is in the main, nsec, or nsec3
tree of an RBTDB. they need to be moved to a more generic location so
they can also be used by QPDB.

(this is in db.h rather than db_p.h because rbt.c needs access to it.
technically, that's a layer violation, but it's a long-existing one;
refactoring to get rid of it would be a large hassle, and eventually
we expect to remove rbt.c anyway.)
2024-02-14 01:13:44 -08:00
Michał Kępień
24381cc36d
Limit isc_async_run() overhead for tree pruning
Instead of issuing a separate isc_async_run() call for every RBTDB node
that triggers tree pruning, maintain a list of nodes from which tree
pruning can be started from and only issue an isc_async_run() call if
pruning has not yet been triggered by another RBTDB node.

In some older BIND 9 branches, the extra queuing overhead eliminated by
this change could be remotely exploited to cause excessive memory use.
Due to architectural shift, this branch is not vulnerable to that issue,
but applying the fix to the latter is nevertheless deemed prudent for
consistency and to make the code future-proof.
2024-01-05 12:33:14 +01:00
Michał Kępień
9cf1f39b54
Silence a scan-build warning in dns_rbt_addname()
Clang Static Analyzer is unable to grasp that when dns_rbt_addnode()
returns ISC_R_EXISTS, it always sets the pointer passed to it via its
'nodep' parameter to a non-NULL value.  Add an extra safety check in the
conditional expression used in dns_rbt_addname() to silence that
warning.
2023-12-22 19:27:37 +01:00
Mark Andrews
7e462c2b26 Also cleanup the space for the rbt nodes
As we are in overmem state we want to free more memory than we are
adding so we need to add in an allowance for the rbtnodes that may
have been added and the names stored with them.  There is the node
for the owner name and a possible ENT node if there was a node split.
2023-12-07 02:59:04 +00:00
Ondřej Surý
fd25be31f0
Cleanup the dns_name macros
1. Replace the "high-performance" macros that were only used if
   DNS_NAME_USEINLINE was defined before including <dns/name.h> with
   inline header functions with assertion checks and thus use them
   everywhere.

2. Replace the old struct initializers with C99 designated initializers
   for better understanding what is happening in these macros.
2023-09-12 16:14:10 +02:00
Ondřej Surý
d9048b3db1
Remove ISC_MEM_ZERO and isc_mem_*x() API
Use the new isc_mem_c*() calloc-like API for allocations that are
zeroed.

In turn, this also fixes couple of incorrect usage of the ISC_MEM_ZERO
for structures that need to be zeroed explicitly.

There are few places where isc_mem_cput() is used on structures with a
flexible member (or similar).
2023-08-31 22:08:35 +02:00
Ondřej Surý
55c29b8d83
Do extra manual isc_mem_cget() conversions
Some of the cases weren't caught by the coccinelle and there were some
places where cget+memmove() could get converted to simple creget().
2023-08-31 22:08:35 +02:00
Ondřej Surý
956155f613 Squash dns_name_fullhash() and dns_name_hash()
The only place where dns_name_hash() was being used is the old hash
table in the dns_badcache unit.  Squash the dns_name_fullhash() and
dns_name_hash() into single dns_name_hash() function that's always
case-insensitive as it doesn't make to do case-sensitive hashing of the
domain names and we were not using this anywhere.
2023-03-31 12:43:30 +00:00
Ondřej Surý
cd632ad31d
Implement dns_db node tracing
This implements node reference tracing that passes all the internal
layers from dns_db API (and friends) to increment_reference() and
decrement_reference().

It can be enabled by #defining DNS_DB_NODETRACE in <dns/trace.h> header.

The output then looks like this:

    incr:node:check_address_records:rootns.c:409:0x7f67f5a55a40->references = 1
    decr:node:check_address_records:rootns.c:449:0x7f67f5a55a40->references = 0

    incr:nodelock:check_address_records:rootns.c:409:0x7f67f5a55a40:0x7f68304d7040->references = 1
    decr:nodelock:check_address_records:rootns.c:449:0x7f67f5a55a40:0x7f68304d7040->references = 0

There's associated python script to find the missing detach located at:
https://gitlab.isc.org/isc-projects/bind9/-/snippets/1038
2023-02-28 11:44:15 +01:00
Tony Finch
6927a30926 Remove do-nothing header <isc/print.h>
This one really truly did nothing. No lines added!
2023-02-15 16:44:47 +00:00
Tony Finch
c70bb3deb5 Remove some remnants of bitstring labels
* rbt node chains were sized to allow for bitstring labels, so they
  had 256 levels; but in the absence of bistrings, 128 is enough.

* dns_byaddr_createptrname() had a redundant options argument,
  and a very outdated doc comment.

* A number of comments referred to bitstring labels in a way that is
  no longer helpful. (A few informative comments remain.)
2023-02-06 13:22:30 +00:00
Michal Nowak
afdb41a5aa
Update sources to Clang 15 formatting 2022-11-29 08:54:34 +01:00
Petr Špaček
53b3ceacd4
Replace #define DNS_NAMEATTR_ with struct of bools
sizeof(dns_name_t) did not change but the boolean attributes are now
separated as one-bit structure members. This allows debuggers to
pretty-print dns_name_t attributes without any special hacks, plus we
got rid of manual bit manipulation code.
2022-10-13 17:04:02 +02:00
Petr Špaček
8a3aa8bda4
Fix latent bug in RBT node attributes handling
Originally RBT node stored three lowest bits from dns_name_t attributes.
This had a curious side-effect noticed by Tony Finch:

If you create an rbt node from a DYNAMIC name then the flag will be
propagated through dns_rbt_namefromnode() ... if you subsequently call
dns_name_free() it will try to isc_mem_put() a piece of an rbt node ...
but dns_name_free() REQUIRE()s that the name is dynamic so in the usual
case where rbt nodes are created from non-dynamic names, this kind of
code will fail an assertion.

This is a bug it dates back to june 1999 when NAMEATTR_DYNAMIC was
invented.

Apparently it does not happen often :-)
I'm planning to get rid of DNS_NAMEATTR_ definitions and bit operations,
so removal of this "three-bit-subset" assignment is a first step.

We can keep only the ABSOLUTE flag in RBT node and nothing else because
names attached to rbt nodes are always readonly: The internal node_name()
function always sets the NAMEATTR_READONLY when making a dns_name that
refers to the node's name, so the READONLY flag will be set in the name
returned by dns_rbt_namefromnode().

Co-authored-by: Tony Finch <fanf@isc.org>
2022-10-13 13:08:28 +02:00
Ondřej Surý
c1d26b53eb
Add and use semantic patch to replace isc_mem_get/allocate+memset
Add new semantic patch to replace the straightfoward uses of:

  ptr = isc_mem_{get,allocate}(..., size);
  memset(ptr, 0, size);

with the new API call:

  ptr = isc_mem_{get,allocate}x(..., size, ISC_MEM_ZERO);
2022-10-05 16:44:05 +02:00
Tony Finch
cdd3d54bce Remove unused rbtnode->rpz flag
The rbtnode->rpz flag was left behind when rbt and rpz were disentangled
by CHANGES #4576. Removing it makes the comment above correct again.

This reduces the flags so they fit in a 32 bit word again. On 64
bit systems there is still padding so it doesn't change the size
of an rbtnode. On 32 bit systems it reduces an rbtnode by 4 bytes.
2022-05-02 19:47:58 +01:00
Tony Finch
72b23aafd2 Apply clang-format to rbt.c
Giving the code a proper spring cleaning
2022-04-27 11:05:05 +01:00
Tony Finch
b0bf49726e Clean up a few rbt comments
Avoid HTML entities, and describe what a function does
instead of explaining why it used to be a macro.
2022-04-27 11:05:05 +01:00
Tony Finch
084f146946 Fix style of a function name in rbt.c
Mechanically generated with:

:; spatch --no-show-diff --in-place --sp-file <<END lib/dns/rbt.c
@@ expression node, name; @@
- NODENAME(node, name)
+ node_name(node, name)
@@ parameter list params; @@
  static void
- NODENAME(params)
+ node_name(params)
  { ... }
END
2022-04-27 11:05:05 +01:00
Tony Finch
8adae2d813 Remove redundant rbt macro definitions
After the previous commit, these macros are no longer used.
2022-04-27 11:05:05 +01:00
Tony Finch
bee1c91b0a Remove do-nothing rbt macro calls
Pointer chasing reads better like left->right instead of RIGHT(left)

Mechanically generated with:

:; spatch --no-show-diff --in-place --sp-file <<END lib/dns/rbt.c
@@ expression node; @@
- PARENT(node)
+ node->parent
@@ expression node; @@
- LEFT(node)
+ node->left
@@ expression node; @@
- RIGHT(node)
+ node->right
@@ expression node; @@
- DOWN(node)
+ node->down
@@ expression node; @@
- UPPERNODE(node)
+ node->uppernode
@@ expression node; @@
- DATA(node)
+ node->data
@@ expression node; @@
- IS_EMPTY(node)
+ node->data == NULL
@@ expression node; @@
- HASHNEXT(node)
+ node->hashnext
@@ expression node; @@
- HASHVAL(node)
+ node->hashval
@@ expression node; @@
- COLOR(node)
+ node->color
@@ expression node; @@
- NAMELEN(node)
+ node->namelen
@@ expression node; @@
- OLDNAMELEN(node)
+ node->oldnamelen
@@ expression node; @@
- OFFSETLEN(node)
+ node->offsetlen
@@ expression node; @@
- ATTRS(node)
+ node->attributes
@@ expression node; @@
- IS_ROOT(node)
+ node->is_root
@@ expression node; @@
- FINDCALLBACK(node)
+ node->find_callback
@@ expression node; @@
- DIRTY(node)
+ node->dirty
@@ expression node; @@
- WILD(node)
+ node->wild
@@ expression node; @@
- LOCKNUM(node)
+ node->locknum
@@ expression node; @@
- MAKE_RED(node)
+ node->color = RED
@@ expression node; @@
- MAKE_BLACK(node)
+ node->color = BLACK
END
2022-04-27 11:05:05 +01:00
Evan Hunt
e9ef3defa4 consolidate fibonacci hashing in one place
Fibonacci hashing was implemented in four separate places (rbt.c,
rbtdb.c, resolver.c, zone.c). This commit combines them into a single
implementation. The hash_32() function is now replaced with
isc_hash_bits32().
2022-03-28 14:44:21 -07:00
Ondřej Surý
20f0936cf2 Remove use of the inline keyword used as suggestion to compiler
Historically, the inline keyword was a strong suggestion to the compiler
that it should inline the function marked inline.  As compilers became
better at optimising, this functionality has receded, and using inline
as a suggestion to inline a function is obsolete.  The compiler will
happily ignore it and inline something else entirely if it finds that's
a better optimisation.

Therefore, remove all the occurences of the inline keyword with static
functions inside single compilation unit and leave the decision whether
to inline a function or not entirely on the compiler

NOTE: We keep the usage the inline keyword when the purpose is to change
the linkage behaviour.
2022-03-25 08:33:43 +01:00
Ondřej Surý
584f0d7a7e Simplify way we tag unreachable code with only ISC_UNREACHABLE()
Previously, the unreachable code paths would have to be tagged with:

    INSIST(0);
    ISC_UNREACHABLE();

There was also older parts of the code that used comment annotation:

    /* NOTREACHED */

Unify the handling of unreachable code paths to just use:

    UNREACHABLE();

The UNREACHABLE() macro now asserts when reached and also uses
__builtin_unreachable(); when such builtin is available in the compiler.
2022-03-25 08:33:43 +01:00
Ondřej Surý
58bd26b6cf Update the copyright information in all files in the repository
This commit converts the license handling to adhere to the REUSE
specification.  It specifically:

1. Adds used licnses to LICENSES/ directory

2. Add "isc" template for adding the copyright boilerplate

3. Changes all source files to include copyright and SPDX license
   header, this includes all the C sources, documentation, zone files,
   configuration files.  There are notes in the doc/dev/copyrights file
   on how to add correct headers to the new files.

4. Handle the rest that can't be modified via .reuse/dep5 file.  The
   binary (or otherwise unmodifiable) files could have license places
   next to them in <foo>.license file, but this would lead to cluttered
   repository and most of the files handled in the .reuse/dep5 file are
   system test files.
2022-01-11 09:05:02 +01:00
Michal Nowak
9c013f37d0
Drop cppcheck workarounds
As cppcheck was removed from the CI, associated workarounds and
suppressions are not required anymore.
2021-12-14 15:03:56 +01:00
Evan Hunt
18cc459e05 Incidental cleanup
- there are several allocation functions in adb.c that can no
  longer return NULL.
- a macro in rbt.c was never used.
2021-10-18 14:35:50 -07:00
Evan Hunt
a55589f881 remove all references to isc_socket and related types
Removed socket.c, socket.h, and all references to isc_socket_t,
isc_socketmgr_t, isc_sockevent_t, etc.
2021-10-15 01:01:25 -07:00
Ondřej Surý
e603983ec9 Stop providing branch prediction information
The __builtin_expect() can be used to provide the compiler with branch
prediction information.  The Gcc manual says[1] on the subject:

    In general, you should prefer to use actual profile feedback for
    this (-fprofile-arcs), as programmers are notoriously bad at
    predicting how their programs actually perform.

Stop using __builtin_expect() and ISC_LIKELY() and ISC_UNLIKELY() macros
to provide the branch prediction information as the performance testing
shows that named performs better when the __builtin_expect() is not
being used.

1. https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fexpect
2021-10-14 10:33:24 +02:00
Ondřej Surý
8c819ec366 dns/rbt.c: Implement incremental hash table resizing
Originally, the hash table used in RBT database would be resized when it
reached certain number of elements (defined by overcommit).  This was
causing resolution brownouts for busy resolvers, because the rehashing
could take several seconds to complete.  This was mitigated by
pre-allocating the hash table in the RBT database used for caching to be
large-enough as determined by max-cache-size.  The downside of this
solution was that the pre-allocated hash table could take a significant
chunk of the memory even when the resolver cache would be otherwise
empty because the default value for max-cache-size is 90% of available
memory.

Implement incremental resizing[1] to perform the rehashing gradually:

 1. During the resize, allocate the new hash table, but keep the old
    table unchanged.
 2. In each lookup or delete operation, check both tables.
 3. Perform insertion operations only in the new table.
 4. At each insertion also move r elements from the old table to the new
    table.
 5. When all elements are removed from the old table, deallocate it.

To ensure that the old table is completely copied over before the new
table itself needs to be enlarged, it is necessary to increase the
size of the table by a factor of at least (r + 1)/r during resizing.

In our implementation r is equal to 1.

The downside of this approach is that the old table and the new table
could stay in memory for longer when there are no new insertions into
the hash table for prolonged periods of time as the incremental
rehashing happens only during the insertions.

The upside of this approach is that it's no longer necessary to
pre-allocate large hash table, because the RBT hash table rehashing
doesn't cause resolution brownouts anymore and thus we can use the
memory as needed.

1. https://en.m.wikipedia.org/wiki/Hash_table#Dynamic_resizing
2021-10-12 15:01:53 +02:00
Ondřej Surý
2e3a2eecfe Make isc_result a static enum
Remove the dynamic registration of result codes.  Convert isc_result_t
from unsigned + #defines into 32-bit enum type in grand unified
<isc/result.h> header.  Keep the existing values of the result codes
even at the expense of the description and identifier tables being
unnecessary large.

Additionally, add couple of:

    switch (result) {
    [...]
    default:
        break;
    }

statements where compiler now complains about missing enum values in the
switch statement.
2021-10-06 11:22:20 +02:00
Ondřej Surý
edee9440d0 Remove the mastefile-format map option
As previously announced, this commit removes the masterfile-format
format 'map' from named, all the tools, the documentation and the
system tests.
2021-09-17 07:09:50 +02:00
Evan Hunt
3b544d28bf map files over 2GB could not be loaded
- fixed a size comparison using "signed int" that failed if the file
  size was more than 2GB, since that was treated as a negative number.
- incidentally renamed deserialize32() to just deserialize(). we no
  longer have separate 32 and 64 bit rbtdb implementations.
2021-09-01 08:01:27 -07:00
Ondřej Surý
29c2e52484 The isc/platform.h header has been completely removed
The isc/platform.h header was left empty which things either already
moved to config.h or to appropriate headers.  This is just the final
cleanup commit.
2021-07-06 05:33:48 +00:00
Michał Kępień
6b77583f54 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.
2021-06-17 17:09:37 +02:00
Michał Kępień
c096f91451 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.
2021-06-17 17:09:37 +02:00
Evan Hunt
b0aadaac8e rename dns_name_copynf() to dns_name_copy()
dns_name_copy() is now the standard name-copying function.
2021-05-22 00:37:27 -07:00
Ondřej Surý
7ba18870dc Reformat sources using clang-format-11 2020-12-08 18:36:23 +01:00
Artem Boldariev
a236151608 Fix build with DEBUG defined (-DDEBUG)
The problem was introduced by commit 98b55eb4.
2020-11-06 12:20:41 +02:00
Mark Andrews
48d54368d5 Remove the memmove call on dns_rbtnode_t structure that contains atomics
Calling the plain memmove on the structure that contains atomic members
triggers following TSAN warning (even when we don't really use the
atomic members in the code):

    WARNING: ThreadSanitizer: data race
      Read of size 8 at 0x000000000001 by thread T1 (mutexes: write M1, write M2):
	#0 memmove <null>
	#1 memmove /usr/include/x86_64-linux-gnu/bits/string_fortified.h:40:10
	#2 deletefromlevel lib/dns/rbt.c:2675:3
	#3 dns_rbt_deletenode lib/dns/rbt.c:2143:2
	#4 delete_node lib/dns/rbtdb.c
	#5 decrement_reference lib/dns/rbtdb.c:2202:4
	#6 prune_tree lib/dns/rbtdb.c:2259:3
	#7 dispatch lib/isc/task.c:1152:7
	#8 run lib/isc/task.c:1344:2

      Previous atomic write of size 8 at 0x000000000001 by thread T2 (mutexes: read M3):
	#0 __tsan_atomic64_fetch_sub <null>
	#1 decrement_reference lib/dns/rbtdb.c:2103:7
	#2 detachnode lib/dns/rbtdb.c:5440:6
	#3 dns_db_detachnode lib/dns/db.c:588:2
	#4 qctx_clean lib/ns/query.c:5104:3
	#5 ns_query_done lib/ns/query.c:10868:2
	#6 query_sign_nodata lib/ns/query.c
	#7 query_nodata lib/ns/query.c:8438:11
	#8 query_gotanswer lib/ns/query.c
	#9 query_lookup lib/ns/query.c:5624:10
	#10 ns__query_start lib/ns/query.c:5500:10
	#11 query_setup lib/ns/query.c:5224:11
	#12 ns_query_start lib/ns/query.c:11357:8
	#13 ns__client_request lib/ns/client.c:2166:3
	#14 udp_recv_cb lib/isc/netmgr/udp.c:414:2
	#15 uv__udp_recvmsg /home/ondrej/Projects/tsan/libuv/src/unix/udp.c
	#16 uv__udp_io /home/ondrej/Projects/tsan/libuv/src/unix/udp.c:180:5
	#17 uv__io_poll /home/ondrej/Projects/tsan/libuv/src/unix/linux-core.c:461:11
	#18 uv_run /home/ondrej/Projects/tsan/libuv/src/unix/core.c:385:5
	#19 nm_thread lib/isc/netmgr/netmgr.c:500:11

      Location is heap block of size 132 at 0x000000000030 allocated by thread T3:
	#0 malloc <null>
	#1 default_memalloc lib/isc/mem.c:713:8
	#2 mem_get lib/isc/mem.c:622:8
	#3 mem_allocateunlocked lib/isc/mem.c:1268:8
	#4 isc___mem_allocate lib/isc/mem.c:1288:7
	#5 isc__mem_allocate lib/isc/mem.c:2453:10
	#6 isc___mem_get lib/isc/mem.c:1037:11
	#7 isc__mem_get lib/isc/mem.c:2432:10
	#8 create_node lib/dns/rbt.c:2239:9
	#9 dns_rbt_addnode lib/dns/rbt.c:1435:12
	#10 findnodeintree lib/dns/rbtdb.c:2895:12
	#11 findnode lib/dns/rbtdb.c:2941:10
	#12 dns_db_findnode lib/dns/db.c:439:11
	#13 diff_apply lib/dns/diff.c:306:5
	#14 dns_diff_apply lib/dns/diff.c:459:10
	#15 do_one_tuple lib/ns/update.c:444:11
	#16 update_one_rr lib/ns/update.c:495:10
	#17 update_action lib/ns/update.c:3123:6
	#18 dispatch lib/isc/task.c:1152:7
	#19 run lib/isc/task.c:1344:2

      Mutex M1 is already destroyed.

      Mutex M2 is already destroyed.

      Mutex M3 is already destroyed.

      Thread T1 (running) created by main thread at:
	#0 pthread_create <null>
	#1 isc_thread_create lib/isc/pthreads/thread.c:73:8
	#2 isc_taskmgr_create lib/isc/task.c:1434:3
	#3 create_managers bin/named/main.c:915:11
	#4 setup bin/named/main.c:1223:11
	#5 main bin/named/main.c:1523:2

      Thread T2 (running) created by main thread at:
	#0 pthread_create <null>
	#1 isc_thread_create lib/isc/pthreads/thread.c:73:8
	#2 isc_nm_start lib/isc/netmgr/netmgr.c:223:3
	#3 create_managers bin/named/main.c:909:15
	#4 setup bin/named/main.c:1223:11
	#5 main bin/named/main.c:1523:2

      Thread T3 (running) created by main thread at:
	#0 pthread_create <null>
	#1 isc_thread_create lib/isc/pthreads/thread.c:73:8
	#2 isc_taskmgr_create lib/isc/task.c:1434:3
	#3 create_managers bin/named/main.c:915:11
	#4 setup bin/named/main.c:1223:11
	#5 main bin/named/main.c:1523:2

    SUMMARY: ThreadSanitizer: data race in memmove
2020-09-21 08:58:20 +00:00
Evan Hunt
dcee985b7f update all copyright headers to eliminate the typo 2020-09-14 16:20:40 -07:00
Mark Andrews
71ef3a8038 Only test node->data if we care about whether data is present or not.
WARNING: ThreadSanitizer: data race (pid=28788)
  Write of size 8 at 0x7b200002e060 by thread T1 (mutexes: write M2947):
    #0 add32 /builds/isc-projects/bind9/lib/dns/rbtdb.c:6638:18 (libdns.so.1110+0xe7843)
    #1 addrdataset /builds/isc-projects/bind9/lib/dns/rbtdb.c:6975:12 (libdns.so.1110+0xe4185)
    #2 dns_db_addrdataset /builds/isc-projects/bind9/lib/dns/db.c:783:10 (libdns.so.1110+0x650ee)
    #3 validated /builds/isc-projects/bind9/lib/dns/resolver.c:5140:11 (libdns.so.1110+0x1909f7)
    #4 dispatch /builds/isc-projects/bind9/lib/isc/task.c:1157:7 (libisc.so.1107+0x507f5)
    #5 run /builds/isc-projects/bind9/lib/isc/task.c:1331:2 (libisc.so.1107+0x4d749)

  Previous read of size 8 at 0x7b200002e060 by thread T5 (mutexes: write M521146194917735760):
    #0 dns_rbt_findnode /builds/isc-projects/bind9/lib/dns/rbt.c:1708:9 (libdns.so.1110+0xd910d)
    #1 cache_find /builds/isc-projects/bind9/lib/dns/rbtdb.c:5098:11 (libdns.so.1110+0xe188e)
    #2 dns_db_find /builds/isc-projects/bind9/lib/dns/db.c:554:11 (libdns.so.1110+0x642bb)
    #3 dns_view_find2 /builds/isc-projects/bind9/lib/dns/view.c:1068:11 (libdns.so.1110+0x1cc2c4)
    #4 dbfind_name /builds/isc-projects/bind9/lib/dns/adb.c:3714:11 (libdns.so.1110+0x46a4b)
    #5 dns_adb_createfind2 /builds/isc-projects/bind9/lib/dns/adb.c:3133:12 (libdns.so.1110+0x45278)
    #6 findname /builds/isc-projects/bind9/lib/dns/resolver.c:3166:11 (libdns.so.1110+0x1827f0)
    #7 fctx_getaddresses /builds/isc-projects/bind9/lib/dns/resolver.c:3462:3 (libdns.so.1110+0x18032d)
    #8 fctx_try /builds/isc-projects/bind9/lib/dns/resolver.c:3819:12 (libdns.so.1110+0x17e174)
    #9 fctx_start /builds/isc-projects/bind9/lib/dns/resolver.c:4219:4 (libdns.so.1110+0x1787a3)
    #10 dispatch /builds/isc-projects/bind9/lib/isc/task.c:1157:7 (libisc.so.1107+0x507f5)
    #11 run /builds/isc-projects/bind9/lib/isc/task.c:1331:2 (libisc.so.1107+0x4d749)
2020-09-09 14:12:29 +10:00
Ondřej Surý
78543ad5a7 Fix off-by-one error when calculating new hashtable size
When calculating the new hashtable bitsize, there was an off-by-one
error that would allow the new bitsize to be larger than maximum allowed
causing assertion failure in the rehash() function.
2020-08-28 16:21:21 +02:00
Ondřej Surý
1e043a011b Reduce the default RBT hash table size to 16 entries (4 bits)
The hash table rework MRs (!3865, !3871) increased the default RBT hash
table size from 64 to 65,536 entries (for 64-bit architectures, that is
512 bytes before vs. 524,288 bytes after).  This works fine for RBTs
used for cache databases, but since three separate RBT databases are
created for every zone loaded (RRs, NSEC, NSEC3), memory usage would
skyrocket when BIND 9 is used as an authoritative DNS server with many
zones.

The default RBT hash table size before the rework was 64 entries, this
commit reduces it to 16 entries because our educated guess is that most
zones are just couple of entries (SOA, NS, A, AAAA, MX) and rehashing
small hash tables is actually cheap.  The rework we did in the previous
MRs tries to avoid growing the hash tables for big-to-huge caches where
growing the hash table comes at a price because the whole cache needs to
be locked.
2020-08-10 10:31:19 +02:00
Ondřej Surý
e24bc324b4 Fix the rbt hashtable and grow it when setting max-cache-size
There were several problems with rbt hashtable implementation:

1. Our internal hashing function returns uint64_t value, but it was
   silently truncated to unsigned int in dns_name_hash() and
   dns_name_fullhash() functions.  As the SipHash 2-4 higher bits are
   more random, we need to use the upper half of the return value.

2. The hashtable implementation in rbt.c was using modulo to pick the
   slot number for the hash table.  This has several problems because
   modulo is: a) slow, b) oblivious to patterns in the input data.  This
   could lead to very uneven distribution of the hashed data in the
   hashtable.  Combined with the single-linked lists we use, it could
   really hog-down the lookup and removal of the nodes from the rbt
   tree[a].  The Fibonacci Hashing is much better fit for the hashtable
   function here.  For longer description, read "Fibonacci Hashing: The
   Optimization that the World Forgot"[b] or just look at the Linux
   kernel.  Also this will make Diego very happy :).

3. The hashtable would rehash every time the number of nodes in the rbt
   tree would exceed 3 * (hashtable size).  The overcommit will make the
   uneven distribution in the hashtable even worse, but the main problem
   lies in the rehashing - every time the database grows beyond the
   limit, each subsequent rehashing will be much slower.  The mitigation
   here is letting the rbt know how big the cache can grown and
   pre-allocate the hashtable to be big enough to actually never need to
   rehash.  This will consume more memory at the start, but since the
   size of the hashtable is capped to `1 << 32` (e.g. 4 mio entries), it
   will only consume maximum of 32GB of memory for hashtable in the
   worst case (and max-cache-size would need to be set to more than
   4TB).  Calling the dns_db_adjusthashsize() will also cap the maximum
   size of the hashtable to the pre-computed number of bits, so it won't
   try to consume more gigabytes of memory than available for the
   database.

   FIXME: What is the average size of the rbt node that gets hashed?  I
   chose the pagesize (4k) as initial value to precompute the size of
   the hashtable, but the value is based on feeling and not any real
   data.

For future work, there are more places where we use result of the hash
value modulo some small number and that would benefit from Fibonacci
Hashing to get better distribution.

Notes:
a. A doubly linked list should be used here to speedup the removal of
   the entries from the hashtable.
b. https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/
2020-07-21 08:44:26 +02:00