[9.20] chg: dev: Refactor reference counting in both QPDB and RBTDB
Clean up the pattern in the newref() and decref() functions in QP and RBTDB databases. Replace the `db_nodelock_t` structure with plain reference counting for every active database node in QPDB. Related to #5134 Backport of MR !10006 Merge branch 'backport-5134-refactor-decref-functions-in-qpdb-9.20' into 'bind-9.20' See merge request isc-projects/bind9!10035
This commit is contained in:
+300
-348
File diff suppressed because it is too large
Load Diff
+279
-273
File diff suppressed because it is too large
Load Diff
+27
-23
@@ -404,7 +404,7 @@ check_stale_header(dns_rbtnode_t *node, dns_slabheader_t *header,
|
||||
/*
|
||||
* header->down can be non-NULL if the
|
||||
* refcount has just decremented to 0
|
||||
* but dns__rbtdb_decref() has not
|
||||
* but dns__rbtnode_release() has not
|
||||
* performed clean_cache_node(), in
|
||||
* which case we need to purge the stale
|
||||
* headers first.
|
||||
@@ -483,8 +483,8 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name,
|
||||
* We increment the reference count on node to ensure that
|
||||
* search->zonecut_header will still be valid later.
|
||||
*/
|
||||
dns__rbtdb_newref(search->rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(search->rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
search->zonecut = node;
|
||||
search->zonecut_header = dname_header;
|
||||
search->zonecut_sigheader = sigdname_header;
|
||||
@@ -591,8 +591,9 @@ find_deepest_zonecut(rbtdb_search_t *search, dns_rbtnode_t *node,
|
||||
}
|
||||
result = DNS_R_DELEGATION;
|
||||
if (nodep != NULL) {
|
||||
dns__rbtdb_newref(search->rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(
|
||||
search->rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
*nodep = node;
|
||||
}
|
||||
dns__rbtdb_bindrdataset(search->rbtdb, node, found,
|
||||
@@ -743,8 +744,8 @@ find_coveringnsec(rbtdb_search_t *search, const dns_name_t *name,
|
||||
now, nlocktype,
|
||||
sigrdataset DNS__DB_FLARG_PASS);
|
||||
}
|
||||
dns__rbtdb_newref(search->rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(search->rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
|
||||
dns_name_copy(fname, foundname);
|
||||
|
||||
@@ -1009,8 +1010,9 @@ cache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
|
||||
nsecheader != NULL)
|
||||
{
|
||||
if (nodep != NULL) {
|
||||
dns__rbtdb_newref(search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(
|
||||
search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
*nodep = node;
|
||||
}
|
||||
dns__rbtdb_bindrdataset(search.rbtdb, node, nsecheader,
|
||||
@@ -1054,8 +1056,9 @@ cache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
|
||||
*/
|
||||
if (nsheader != NULL) {
|
||||
if (nodep != NULL) {
|
||||
dns__rbtdb_newref(search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(
|
||||
search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
*nodep = node;
|
||||
}
|
||||
dns__rbtdb_bindrdataset(search.rbtdb, node, nsheader,
|
||||
@@ -1089,8 +1092,8 @@ cache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
|
||||
*/
|
||||
|
||||
if (nodep != NULL) {
|
||||
dns__rbtdb_newref(search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
*nodep = node;
|
||||
}
|
||||
|
||||
@@ -1166,8 +1169,9 @@ tree_exit:
|
||||
lock = &(search.rbtdb->node_locks[node->locknum].lock);
|
||||
|
||||
NODE_RDLOCK(lock, &nlocktype);
|
||||
dns__rbtdb_decref(search.rbtdb, node, 0, &nlocktype, &tlocktype,
|
||||
true, false DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_release(search.rbtdb, node, 0, &nlocktype,
|
||||
&tlocktype, true,
|
||||
false DNS__DB_FLARG_PASS);
|
||||
NODE_UNLOCK(lock, &nlocktype);
|
||||
INSIST(tlocktype == isc_rwlocktype_none);
|
||||
}
|
||||
@@ -1305,8 +1309,8 @@ cache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
|
||||
}
|
||||
|
||||
if (nodep != NULL) {
|
||||
dns__rbtdb_newref(search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
*nodep = node;
|
||||
}
|
||||
|
||||
@@ -1604,13 +1608,13 @@ dns__cacherbt_expireheader(dns_slabheader_t *header,
|
||||
/*
|
||||
* If no one else is using the node, we can clean it up now.
|
||||
* We first need to gain a new reference to the node to meet a
|
||||
* requirement of dns__rbtdb_decref().
|
||||
* requirement of dns__rbtnode_release().
|
||||
*/
|
||||
dns__rbtdb_newref(rbtdb, RBTDB_HEADERNODE(header),
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtdb_decref(rbtdb, RBTDB_HEADERNODE(header), 0,
|
||||
&nlocktype, tlocktypep, true,
|
||||
false DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(rbtdb, RBTDB_HEADERNODE(header),
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_release(rbtdb, RBTDB_HEADERNODE(header), 0,
|
||||
&nlocktype, tlocktypep, true,
|
||||
false DNS__DB_FLARG_PASS);
|
||||
|
||||
if (rbtdb->cachestats == NULL) {
|
||||
return;
|
||||
|
||||
+14
-12
@@ -199,8 +199,8 @@ zone_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name,
|
||||
* We increment the reference count on node to ensure that
|
||||
* search->zonecut_header will still be valid later.
|
||||
*/
|
||||
dns__rbtdb_newref(search->rbtdb, node,
|
||||
isc_rwlocktype_read DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(search->rbtdb, node,
|
||||
isc_rwlocktype_read DNS__DB_FLARG_PASS);
|
||||
search->zonecut = node;
|
||||
search->zonecut_header = found;
|
||||
search->need_cleanup = true;
|
||||
@@ -902,7 +902,7 @@ again:
|
||||
foundname, NULL);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
if (nodep != NULL) {
|
||||
dns__rbtdb_newref(
|
||||
dns__rbtnode_acquire(
|
||||
search->rbtdb, node,
|
||||
isc_rwlocktype_read
|
||||
DNS__DB_FLARG_PASS);
|
||||
@@ -1195,8 +1195,9 @@ found:
|
||||
* ensure that search->zonecut_header will
|
||||
* still be valid later.
|
||||
*/
|
||||
dns__rbtdb_newref(search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(
|
||||
search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
search.zonecut = node;
|
||||
search.zonecut_header = header;
|
||||
search.zonecut_sigheader = NULL;
|
||||
@@ -1372,8 +1373,8 @@ found:
|
||||
goto tree_exit;
|
||||
}
|
||||
if (nodep != NULL) {
|
||||
dns__rbtdb_newref(search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
*nodep = node;
|
||||
}
|
||||
if (search.rbtversion->secure && !search.rbtversion->havensec3)
|
||||
@@ -1442,8 +1443,8 @@ found:
|
||||
|
||||
if (nodep != NULL) {
|
||||
if (!at_zonecut) {
|
||||
dns__rbtdb_newref(search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(search.rbtdb, node,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
} else {
|
||||
search.need_cleanup = false;
|
||||
}
|
||||
@@ -1480,8 +1481,9 @@ tree_exit:
|
||||
lock = &(search.rbtdb->node_locks[node->locknum].lock);
|
||||
|
||||
NODE_RDLOCK(lock, &nlocktype);
|
||||
dns__rbtdb_decref(search.rbtdb, node, 0, &nlocktype, &tlocktype,
|
||||
true, false DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_release(search.rbtdb, node, 0, &nlocktype,
|
||||
&tlocktype, true,
|
||||
false DNS__DB_FLARG_PASS);
|
||||
NODE_UNLOCK(lock, &nlocktype);
|
||||
INSIST(tlocktype == isc_rwlocktype_none);
|
||||
}
|
||||
@@ -2311,7 +2313,7 @@ dns__zonerbt_resigndelete(dns_rbtdb_t *rbtdb, dns_rbtdb_version_t *version,
|
||||
header->heap_index);
|
||||
header->heap_index = 0;
|
||||
if (version != NULL) {
|
||||
dns__rbtdb_newref(
|
||||
dns__rbtnode_acquire(
|
||||
rbtdb, RBTDB_HEADERNODE(header),
|
||||
isc_rwlocktype_write DNS__DB_FLARG_PASS);
|
||||
ISC_LIST_APPEND(version->resigned_list, header, link);
|
||||
|
||||
+99
-103
@@ -1115,14 +1115,39 @@ delete_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rbtnode_erefs_increment(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node DNS__DB_FLARG) {
|
||||
uint_fast32_t refs = isc_refcount_increment0(&node->references);
|
||||
|
||||
#if DNS_DB_NODETRACE
|
||||
fprintf(stderr, "incr:node:%s:%s:%u:%p->references = %" PRIuFAST32 "\n",
|
||||
func, file, line, node, refs + 1);
|
||||
#endif
|
||||
|
||||
if (refs > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* this is the first reference to the node */
|
||||
refs = isc_refcount_increment0(
|
||||
&rbtdb->node_locks[node->locknum].references);
|
||||
#if DNS_DB_NODETRACE
|
||||
fprintf(stderr,
|
||||
"incr:nodelock:%s:%s:%u:%p:%p->references = "
|
||||
"%" PRIuFAST32 "\n",
|
||||
func, file, line, node, &rbtdb->node_locks[node->locknum],
|
||||
refs + 1);
|
||||
#else
|
||||
UNUSED(refs);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Caller must be holding the node lock.
|
||||
*/
|
||||
void
|
||||
dns__rbtdb_newref(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
isc_rwlocktype_t nlocktype DNS__DB_FLARG) {
|
||||
uint_fast32_t refs;
|
||||
|
||||
dns__rbtnode_acquire(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
isc_rwlocktype_t nlocktype DNS__DB_FLARG) {
|
||||
if (nlocktype == isc_rwlocktype_write &&
|
||||
ISC_LINK_LINKED(node, deadlink))
|
||||
{
|
||||
@@ -1130,28 +1155,7 @@ dns__rbtdb_newref(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
deadlink);
|
||||
}
|
||||
|
||||
refs = isc_refcount_increment0(&node->references);
|
||||
#if DNS_DB_NODETRACE
|
||||
fprintf(stderr, "incr:node:%s:%s:%u:%p->references = %" PRIuFAST32 "\n",
|
||||
func, file, line, node, refs + 1);
|
||||
#else
|
||||
UNUSED(refs);
|
||||
#endif
|
||||
|
||||
if (refs == 0) {
|
||||
/* this is the first reference to the node */
|
||||
refs = isc_refcount_increment0(
|
||||
&rbtdb->node_locks[node->locknum].references);
|
||||
#if DNS_DB_NODETRACE
|
||||
fprintf(stderr,
|
||||
"incr:nodelock:%s:%s:%u:%p:%p->references = "
|
||||
"%" PRIuFAST32 "\n",
|
||||
func, file, line, node,
|
||||
&rbtdb->node_locks[node->locknum], refs + 1);
|
||||
#else
|
||||
UNUSED(refs);
|
||||
#endif
|
||||
}
|
||||
rbtnode_erefs_increment(rbtdb, node);
|
||||
}
|
||||
|
||||
/*%
|
||||
@@ -1170,7 +1174,7 @@ send_to_prune_tree(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
*prune = (rbtdb_prune_t){ .node = node };
|
||||
|
||||
dns_db_attach((dns_db_t *)rbtdb, &prune->db);
|
||||
dns__rbtdb_newref(rbtdb, node, nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(rbtdb, node, nlocktype DNS__DB_FLARG_PASS);
|
||||
|
||||
isc_async_run(rbtdb->loop, prune_tree, prune);
|
||||
}
|
||||
@@ -1275,11 +1279,34 @@ reactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
}
|
||||
}
|
||||
|
||||
dns__rbtdb_newref(rbtdb, node, nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(rbtdb, node, nlocktype DNS__DB_FLARG_PASS);
|
||||
|
||||
NODE_UNLOCK(nodelock, &nlocktype);
|
||||
}
|
||||
|
||||
static bool
|
||||
rbtnode_erefs_decrement(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node DNS__DB_FLARG) {
|
||||
db_nodelock_t *nodelock = &rbtdb->node_locks[node->locknum];
|
||||
uint_fast32_t refs = isc_refcount_decrement(&node->references);
|
||||
#if DNS_DB_NODETRACE
|
||||
fprintf(stderr, "decr:node:%s:%s:%u:%p->references = %" PRIuFAST32 "\n",
|
||||
func, file, line, node, refs - 1);
|
||||
#endif
|
||||
if (refs > 1) {
|
||||
return false;
|
||||
}
|
||||
refs = isc_refcount_decrement(&nodelock->references);
|
||||
#if DNS_DB_NODETRACE
|
||||
fprintf(stderr,
|
||||
"decr:nodelock:%s:%s:%u:%p:%p->references = "
|
||||
"%" PRIuFAST32 "\n",
|
||||
func, file, line, node, nodelock, refs - 1);
|
||||
#else
|
||||
UNUSED(refs);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Caller must be holding the node lock; either the read or write lock.
|
||||
* Note that the lock must be held even when node references are
|
||||
@@ -1295,17 +1322,15 @@ reactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
* will be immediately freed.
|
||||
*/
|
||||
bool
|
||||
dns__rbtdb_decref(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
uint32_t least_serial, isc_rwlocktype_t *nlocktypep,
|
||||
isc_rwlocktype_t *tlocktypep, bool tryupgrade,
|
||||
bool pruning DNS__DB_FLARG) {
|
||||
dns__rbtnode_release(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
uint32_t least_serial, isc_rwlocktype_t *nlocktypep,
|
||||
isc_rwlocktype_t *tlocktypep, bool tryupgrade,
|
||||
bool pruning DNS__DB_FLARG) {
|
||||
isc_result_t result;
|
||||
bool locked = *tlocktypep != isc_rwlocktype_none;
|
||||
bool write_locked = false;
|
||||
int bucket = node->locknum;
|
||||
db_nodelock_t *nodelock = &rbtdb->node_locks[bucket];
|
||||
db_nodelock_t *nodelock = &rbtdb->node_locks[node->locknum];
|
||||
bool no_reference = true;
|
||||
uint_fast32_t refs;
|
||||
|
||||
REQUIRE(*nlocktypep != isc_rwlocktype_none);
|
||||
|
||||
@@ -1313,49 +1338,27 @@ dns__rbtdb_decref(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
((n)->data != NULL || ((l) && (n)->down != NULL) || \
|
||||
(n) == (r)->origin_node || (n) == (r)->nsec3_origin_node)
|
||||
|
||||
/* Handle easy and/or typical case first. */
|
||||
refs = isc_refcount_decrement(&node->references);
|
||||
#if DNS_DB_NODETRACE
|
||||
fprintf(stderr, "decr:node:%s:%s:%u:%p->references = %" PRIuFAST32 "\n",
|
||||
func, file, line, node, refs - 1);
|
||||
#endif
|
||||
if (refs > 1) {
|
||||
if (!rbtnode_erefs_decrement(rbtdb, node DNS__DB_FLARG_PASS)) {
|
||||
return false;
|
||||
}
|
||||
refs = isc_refcount_decrement(&nodelock->references);
|
||||
#if DNS_DB_NODETRACE
|
||||
fprintf(stderr,
|
||||
"decr:nodelock:%s:%s:%u:%p:%p->references = "
|
||||
"%" PRIuFAST32 "\n",
|
||||
func, file, line, node, nodelock, refs - 1);
|
||||
#else
|
||||
UNUSED(refs);
|
||||
#endif
|
||||
|
||||
if (!node->dirty && KEEP_NODE(node, rbtdb, locked)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Node lock ref has decremented to 0 and we may need to clean up the
|
||||
* node. To clean it up, the node ref needs to decrement to 0 under the
|
||||
* node write lock, so we regain the ref and try again.
|
||||
*/
|
||||
dns__rbtdb_newref(rbtdb, node, *nlocktypep DNS__DB_FLARG_PASS);
|
||||
|
||||
/* Upgrade the lock? */
|
||||
if (*nlocktypep == isc_rwlocktype_read) {
|
||||
/*
|
||||
* Node lock ref has decremented to 0 and we may need to clean
|
||||
* up the node. To clean it up, the node ref needs to decrement
|
||||
* to 0 under the node write lock, so we regain the ref and try
|
||||
* again.
|
||||
*/
|
||||
rbtnode_erefs_increment(rbtdb, node DNS__DB_FLARG_PASS);
|
||||
NODE_FORCEUPGRADE(&nodelock->lock, nlocktypep);
|
||||
}
|
||||
|
||||
refs = isc_refcount_decrement(&node->references);
|
||||
#if DNS_DB_NODETRACE
|
||||
fprintf(stderr, "decr:node:%s:%s:%u:%p->references = %" PRIuFAST32 "\n",
|
||||
func, file, line, node, refs - 1);
|
||||
#else
|
||||
UNUSED(refs);
|
||||
#endif
|
||||
if (refs > 1) {
|
||||
return false;
|
||||
if (!rbtnode_erefs_decrement(rbtdb, node DNS__DB_FLARG_PASS)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (node->dirty) {
|
||||
@@ -1407,15 +1410,6 @@ dns__rbtdb_decref(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
write_locked = true;
|
||||
}
|
||||
|
||||
refs = isc_refcount_decrement(&nodelock->references);
|
||||
#if DNS_DB_NODETRACE
|
||||
fprintf(stderr,
|
||||
"decr:nodelock:%s:%s:%u:%p:%p->references = %" PRIuFAST32 "\n",
|
||||
func, file, line, node, nodelock, refs - 1);
|
||||
#else
|
||||
UNUSED(refs);
|
||||
#endif
|
||||
|
||||
if (KEEP_NODE(node, rbtdb, locked || write_locked)) {
|
||||
goto restore_locks;
|
||||
}
|
||||
@@ -1433,9 +1427,9 @@ dns__rbtdb_decref(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
* different node buckets and we don't want to do juggle locks
|
||||
* right now.
|
||||
*
|
||||
* Since prune_tree() also calls dns__rbtdb_decref(), check the
|
||||
* value of the 'pruning' parameter (which is only set to
|
||||
* 'true' in the dns__rbtdb_decref() call present in
|
||||
* Since prune_tree() also calls dns__rbtnode_release(), check
|
||||
* the value of the 'pruning' parameter (which is only set to
|
||||
* 'true' in the dns__rbtnode_release() call present in
|
||||
* prune_tree()) to prevent an infinite loop and to allow a
|
||||
* node sent to prune_tree() to be deleted by the delete_node()
|
||||
* call in the code branch below.
|
||||
@@ -1455,7 +1449,7 @@ dns__rbtdb_decref(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
} else {
|
||||
INSIST(node->data == NULL);
|
||||
if (!ISC_LINK_LINKED(node, deadlink)) {
|
||||
ISC_LIST_APPEND(rbtdb->deadnodes[bucket], node,
|
||||
ISC_LIST_APPEND(rbtdb->deadnodes[node->locknum], node,
|
||||
deadlink);
|
||||
}
|
||||
}
|
||||
@@ -1474,7 +1468,7 @@ restore_locks:
|
||||
/*
|
||||
* Prune the RBTDB tree of trees. Start by attempting to delete a node that is
|
||||
* the only one left on its RBTDB level (see the send_to_prune_tree() call in
|
||||
* dns__rbtdb_decref()). Then, if the node has a parent (which can either
|
||||
* dns__rbtnode_release()). Then, if the node has a parent (which can either
|
||||
* exist on the same RBTDB level or on an upper RBTDB level), check whether the
|
||||
* latter is an interior node (i.e. a node with a non-NULL 'down' pointer). If
|
||||
* the parent node is not an interior node, attempt deleting the parent node as
|
||||
@@ -1510,12 +1504,12 @@ prune_tree(void *arg) {
|
||||
NODE_WRLOCK(&rbtdb->node_locks[locknum].lock, &nlocktype);
|
||||
do {
|
||||
parent = node->parent;
|
||||
dns__rbtdb_decref(rbtdb, node, 0, &nlocktype, &tlocktype, true,
|
||||
true DNS__DB_FILELINE);
|
||||
dns__rbtnode_release(rbtdb, node, 0, &nlocktype, &tlocktype,
|
||||
true, true DNS__DB_FILELINE);
|
||||
|
||||
/*
|
||||
* Check whether the parent is an interior node. Note that it
|
||||
* might have been one before the dns__rbtdb_decref() call on
|
||||
* might have been one before the dns__rbtnode_release() call on
|
||||
* the previous line, but decrementing the reference count for
|
||||
* 'node' could have caused 'node->parent->down' to become
|
||||
* NULL.
|
||||
@@ -1537,8 +1531,8 @@ prune_tree(void *arg) {
|
||||
* We need to gain a reference to the parent node
|
||||
* before decrementing it in the next iteration.
|
||||
*/
|
||||
dns__rbtdb_newref(rbtdb, parent,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(rbtdb, parent,
|
||||
nlocktype DNS__DB_FLARG_PASS);
|
||||
} else {
|
||||
parent = NULL;
|
||||
}
|
||||
@@ -1973,9 +1967,9 @@ dns__rbtdb_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
rbtdb, RBTDB_HEADERNODE(header)->locknum,
|
||||
header);
|
||||
}
|
||||
dns__rbtdb_decref(rbtdb, RBTDB_HEADERNODE(header), least_serial,
|
||||
&nlocktype, &tlocktype, true,
|
||||
false DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_release(rbtdb, RBTDB_HEADERNODE(header),
|
||||
least_serial, &nlocktype, &tlocktype, true,
|
||||
false DNS__DB_FLARG_PASS);
|
||||
NODE_UNLOCK(lock, &nlocktype);
|
||||
INSIST(tlocktype == isc_rwlocktype_none);
|
||||
}
|
||||
@@ -1987,7 +1981,7 @@ dns__rbtdb_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
/*
|
||||
* We acquire a tree write lock here in order to make
|
||||
* sure that stale nodes will be removed in
|
||||
* dns__rbtdb_decref(). If we didn't have the lock,
|
||||
* dns__rbtnode_release(). If we didn't have the lock,
|
||||
* those nodes could miss the chance to be removed
|
||||
* until the server stops. The write lock is
|
||||
* expensive, but this should be rare enough
|
||||
@@ -2020,9 +2014,9 @@ dns__rbtdb_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
if (rollback) {
|
||||
rollback_node(rbtnode, serial);
|
||||
}
|
||||
dns__rbtdb_decref(rbtdb, rbtnode, least_serial,
|
||||
&nlocktype, &tlocktype, true,
|
||||
false DNS__DB_FILELINE);
|
||||
dns__rbtnode_release(rbtdb, rbtnode, least_serial,
|
||||
&nlocktype, &tlocktype, true,
|
||||
false DNS__DB_FILELINE);
|
||||
|
||||
NODE_UNLOCK(lock, &nlocktype);
|
||||
|
||||
@@ -2140,7 +2134,7 @@ dns__rbtdb_bindrdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
return;
|
||||
}
|
||||
|
||||
dns__rbtdb_newref(rbtdb, node, locktype DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(rbtdb, node, locktype DNS__DB_FLARG_PASS);
|
||||
|
||||
INSIST(rdataset->methods == NULL); /* We must be disassociated. */
|
||||
|
||||
@@ -2271,8 +2265,8 @@ dns__rbtdb_detachnode(dns_db_t *db, dns_dbnode_t **targetp DNS__DB_FLARG) {
|
||||
|
||||
NODE_RDLOCK(&nodelock->lock, &nlocktype);
|
||||
|
||||
if (dns__rbtdb_decref(rbtdb, node, 0, &nlocktype, &tlocktype, true,
|
||||
false DNS__DB_FLARG_PASS))
|
||||
if (dns__rbtnode_release(rbtdb, node, 0, &nlocktype, &tlocktype, true,
|
||||
false DNS__DB_FLARG_PASS))
|
||||
{
|
||||
if (isc_refcount_current(&nodelock->references) == 0 &&
|
||||
nodelock->exiting)
|
||||
@@ -3841,8 +3835,8 @@ dns__rbtdb_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) {
|
||||
/* Note that the access to origin_node doesn't require a DB lock */
|
||||
onode = (dns_rbtnode_t *)rbtdb->origin_node;
|
||||
if (onode != NULL) {
|
||||
dns__rbtdb_newref(rbtdb, onode,
|
||||
isc_rwlocktype_none DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(rbtdb, onode,
|
||||
isc_rwlocktype_none DNS__DB_FLARG_PASS);
|
||||
*nodep = rbtdb->origin_node;
|
||||
} else {
|
||||
INSIST(IS_CACHE(rbtdb));
|
||||
@@ -4353,8 +4347,9 @@ dereference_iter_node(rbtdb_dbiterator_t *rbtdbiter DNS__DB_FLARG) {
|
||||
|
||||
lock = &rbtdb->node_locks[node->locknum].lock;
|
||||
NODE_RDLOCK(lock, &nlocktype);
|
||||
dns__rbtdb_decref(rbtdb, node, 0, &nlocktype, &rbtdbiter->tree_locked,
|
||||
false, false DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_release(rbtdb, node, 0, &nlocktype,
|
||||
&rbtdbiter->tree_locked, false,
|
||||
false DNS__DB_FLARG_PASS);
|
||||
NODE_UNLOCK(lock, &nlocktype);
|
||||
|
||||
INSIST(rbtdbiter->tree_locked == tlocktype);
|
||||
@@ -4825,7 +4820,8 @@ dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
dns__rbtdb_newref(rbtdb, node, isc_rwlocktype_none DNS__DB_FLARG_PASS);
|
||||
dns__rbtnode_acquire(rbtdb, node,
|
||||
isc_rwlocktype_none DNS__DB_FLARG_PASS);
|
||||
|
||||
*nodep = rbtdbiter->node;
|
||||
|
||||
|
||||
+6
-6
@@ -373,8 +373,8 @@ void
|
||||
dns__rbtdb_freeglue(dns_glue_t *glue_list);
|
||||
|
||||
void
|
||||
dns__rbtdb_newref(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
isc_rwlocktype_t locktype DNS__DB_FLARG);
|
||||
dns__rbtnode_acquire(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
isc_rwlocktype_t locktype DNS__DB_FLARG);
|
||||
/*%<
|
||||
* Increment the reference counter to a node in an RBT database.
|
||||
* If the caller holds a node lock then its lock type is specified
|
||||
@@ -384,10 +384,10 @@ dns__rbtdb_newref(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
*/
|
||||
|
||||
bool
|
||||
dns__rbtdb_decref(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
uint32_t least_serial, isc_rwlocktype_t *nlocktypep,
|
||||
isc_rwlocktype_t *tlocktypep, bool tryupgrade,
|
||||
bool pruning DNS__DB_FLARG);
|
||||
dns__rbtnode_release(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
uint32_t least_serial, isc_rwlocktype_t *nlocktypep,
|
||||
isc_rwlocktype_t *tlocktypep, bool tryupgrade,
|
||||
bool pruning DNS__DB_FLARG);
|
||||
/*%<
|
||||
* Decrement the reference counter to a node in an RBT database.
|
||||
* 'nlocktypep' and 'tlocktypep' are pointers to the current status
|
||||
|
||||
@@ -101,7 +101,7 @@ const char *ownercase_vectors[12][2] = {
|
||||
static bool
|
||||
ownercase_test_one(const char *str1, const char *str2) {
|
||||
isc_result_t result;
|
||||
db_nodelock_t node_locks[1];
|
||||
isc_rwlock_t node_locks[1];
|
||||
qpzonedb_t qpdb = {
|
||||
.common.methods = &qpdb_zonemethods,
|
||||
.common.mctx = mctx,
|
||||
@@ -125,7 +125,7 @@ ownercase_test_one(const char *str1, const char *str2) {
|
||||
|
||||
memset(node_locks, 0, sizeof(node_locks));
|
||||
/* Minimal initialization of the mock objects */
|
||||
NODE_INITLOCK(&qpdb.node_locks[0].lock);
|
||||
NODE_INITLOCK(&qpdb.node_locks[0]);
|
||||
|
||||
isc_buffer_constinit(&b, str1, strlen(str1));
|
||||
isc_buffer_add(&b, strlen(str1));
|
||||
@@ -145,7 +145,7 @@ ownercase_test_one(const char *str1, const char *str2) {
|
||||
/* Retrieve the case to name2 */
|
||||
dns_rdataset_getownercase(&rdataset, name2);
|
||||
|
||||
NODE_DESTROYLOCK(&qpdb.node_locks[0].lock);
|
||||
NODE_DESTROYLOCK(&qpdb.node_locks[0]);
|
||||
|
||||
return dns_name_caseequal(name1, name2);
|
||||
}
|
||||
@@ -166,7 +166,7 @@ ISC_RUN_TEST_IMPL(ownercase) {
|
||||
|
||||
ISC_RUN_TEST_IMPL(setownercase) {
|
||||
isc_result_t result;
|
||||
db_nodelock_t node_locks[1];
|
||||
isc_rwlock_t node_locks[1];
|
||||
qpzonedb_t qpdb = {
|
||||
.common.methods = &qpdb_zonemethods,
|
||||
.common.mctx = mctx,
|
||||
@@ -194,7 +194,7 @@ ISC_RUN_TEST_IMPL(setownercase) {
|
||||
|
||||
/* Minimal initialization of the mock objects */
|
||||
memset(node_locks, 0, sizeof(node_locks));
|
||||
NODE_INITLOCK(&qpdb.node_locks[0].lock);
|
||||
NODE_INITLOCK(&qpdb.node_locks[0]);
|
||||
|
||||
isc_buffer_constinit(&b, str1, strlen(str1));
|
||||
isc_buffer_add(&b, strlen(str1));
|
||||
@@ -211,7 +211,7 @@ ISC_RUN_TEST_IMPL(setownercase) {
|
||||
/* Retrieve the case to name2 */
|
||||
dns_rdataset_getownercase(&rdataset, name2);
|
||||
|
||||
NODE_DESTROYLOCK(&qpdb.node_locks[0].lock);
|
||||
NODE_DESTROYLOCK(&qpdb.node_locks[0]);
|
||||
|
||||
assert_true(dns_name_caseequal(name1, name2));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user