Remove db_nodelock_t in favor of reference counted qpdb

This removes the db_nodelock_t structure and changes the node_locks
array to be composed only of isc_rwlock_t pointers.  The .reference
member has been moved to qpdb->references in addition to
common.references that's external to dns_db API users.  The .exiting
members has been completely removed as it has no use when the reference
counting is used correctly.

(cherry picked from commit 431513d8b3)
This commit is contained in:
Ondřej Surý 2025-01-27 21:07:11 +01:00
parent 082a54cc5d
commit 7dab6cdfbc
No known key found for this signature in database
GPG key ID: 2820F37E873DEA41
3 changed files with 296 additions and 407 deletions

View file

@ -207,12 +207,12 @@ struct qpcache {
isc_rwlock_t tree_lock;
/* Locks for individual tree nodes */
unsigned int node_lock_count;
db_nodelock_t *node_locks;
dns_stats_t *rrsetstats; /* cache DB only */
isc_stats_t *cachestats; /* cache DB only */
isc_stats_t *gluecachestats; /* zone DB only */
/* Locked by lock. */
unsigned int active;
isc_refcount_t references;
isc_rwlock_t *node_locks;
uint32_t maxrrperset; /* Maximum RRs per RRset */
uint32_t maxtypepername; /* Maximum number of RR types per owner */
@ -262,6 +262,17 @@ struct qpcache {
dns_qp_t *nsec;
};
#ifdef DNS_DB_NODETRACE
#define qpcache_ref(ptr) qpcache__ref(ptr, __func__, __FILE__, __LINE__)
#define qpcache_unref(ptr) qpcache_unref(ptr, __func__, __FILE__, __LINE__)
#define qpcache_attach(ptr, ptrp) \
qpcache__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
#define qpcache_detach(ptrp) qpcache__detach(ptrp, __func__, __FILE__, __LINE__)
ISC_REFCOUNT_STATIC_TRACE_DECL(qpcache);
#else
ISC_REFCOUNT_STATIC_DECL(qpcache);
#endif
/*%
* Search Context
*/
@ -399,7 +410,7 @@ typedef struct qpc_dbit {
} qpc_dbit_t;
static void
free_qpdb(qpcache_t *qpdb, bool log);
qpcache__destroy(qpcache_t *qpdb);
static dns_dbmethods_t qpdb_cachemethods;
@ -640,17 +651,7 @@ qpcnode_newref(qpcache_t *qpdb, qpcnode_t *node, isc_rwlocktype_t nlocktype,
INSIST(nlocktype != isc_rwlocktype_none ||
tlocktype != isc_rwlocktype_none);
refs = isc_refcount_increment0(
&qpdb->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, &qpdb->node_locks[node->locknum],
refs + 1);
#else
UNUSED(refs);
#endif
qpcache_ref(qpdb);
}
static void
@ -675,17 +676,7 @@ qpcnode_decref(qpcache_t *qpdb, qpcnode_t *node DNS__DB_FLARG) {
return false;
}
refs = isc_refcount_decrement(
&qpdb->node_locks[node->locknum].references);
#if DNS_DB_NODETRACE
fprintf(stderr,
"decr:nodelock:%s:%s:%u:%p:%p->references = "
"%" PRIuFAST32 "\n",
func, file, line, node, &qpdb->node_locks[node->locknum],
refs - 1);
#else
UNUSED(refs);
#endif
qpcache_unref(qpdb);
return true;
}
@ -712,6 +703,7 @@ decref(qpcache_t *qpdb, qpcnode_t *node, isc_rwlocktype_t *nlocktypep,
isc_result_t result;
bool locked = *tlocktypep != isc_rwlocktype_none;
bool write_locked = false;
isc_rwlock_t *nlock = &qpdb->node_locks[node->locknum];
REQUIRE(*nlocktypep != isc_rwlocktype_none);
@ -733,8 +725,7 @@ decref(qpcache_t *qpdb, qpcnode_t *node, isc_rwlocktype_t *nlocktypep,
/* Upgrade the lock? */
if (*nlocktypep == isc_rwlocktype_read) {
NODE_FORCEUPGRADE(&qpdb->node_locks[node->locknum].lock,
nlocktypep);
NODE_FORCEUPGRADE(nlock, nlocktypep);
}
if (!qpcnode_decref(qpdb, node DNS__DB_FLARG_PASS)) {
@ -1114,8 +1105,8 @@ setup_delegation(qpc_search_t *search, dns_dbnode_t **nodep,
}
if (rdataset != NULL) {
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
NODE_RDLOCK(&(search->qpdb->node_locks[node->locknum].lock),
&nlocktype);
isc_rwlock_t *nlock = &search->qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
bindrdataset(search->qpdb, node, search->zonecut_header,
search->now, nlocktype, tlocktype,
rdataset DNS__DB_FLARG_PASS);
@ -1125,8 +1116,7 @@ setup_delegation(qpc_search_t *search, dns_dbnode_t **nodep,
nlocktype, tlocktype,
sigrdataset DNS__DB_FLARG_PASS);
}
NODE_UNLOCK(&(search->qpdb->node_locks[node->locknum].lock),
&nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
}
if (type == dns_rdatatype_dname) {
@ -1137,7 +1127,7 @@ setup_delegation(qpc_search_t *search, dns_dbnode_t **nodep,
static bool
check_stale_header(qpcnode_t *node, dns_slabheader_t *header,
isc_rwlocktype_t *nlocktypep, isc_rwlock_t *lock,
isc_rwlocktype_t *nlocktypep, isc_rwlock_t *nlock,
qpc_search_t *search, dns_slabheader_t **header_prev) {
if (!ACTIVE(header, search->now)) {
dns_ttl_t stale = header->ttl + STALE_TTL(header, search->qpdb);
@ -1201,7 +1191,7 @@ check_stale_header(qpcnode_t *node, dns_slabheader_t *header,
*/
if ((header->ttl < search->now - QPDB_VIRTUAL) &&
(*nlocktypep == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock, nlocktypep) == ISC_R_SUCCESS))
NODE_TRYUPGRADE(nlock, nlocktypep) == ISC_R_SUCCESS))
{
/*
* We update the node's status only when we can
@ -1248,20 +1238,20 @@ check_zonecut(qpcnode_t *node, void *arg DNS__DB_FLARG) {
dns_slabheader_t *header_prev = NULL, *header_next = NULL;
dns_slabheader_t *dname_header = NULL, *sigdname_header = NULL;
isc_result_t result;
isc_rwlock_t *lock = NULL;
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
REQUIRE(search->zonecut == NULL);
lock = &(search->qpdb->node_locks[node->locknum].lock);
NODE_RDLOCK(lock, &nlocktype);
nlock = &search->qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
/*
* Look for a DNAME or RRSIG DNAME rdataset.
*/
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
if (check_stale_header(node, header, &nlocktype, lock, search,
if (check_stale_header(node, header, &nlocktype, nlock, search,
&header_prev))
{
/* Do nothing. */
@ -1299,7 +1289,7 @@ check_zonecut(qpcnode_t *node, void *arg DNS__DB_FLARG) {
result = DNS_R_CONTINUE;
}
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
return result;
}
@ -1322,13 +1312,13 @@ find_deepest_zonecut(qpc_search_t *search, qpcnode_t *node,
dns_slabheader_t *header = NULL;
dns_slabheader_t *header_prev = NULL, *header_next = NULL;
dns_slabheader_t *found = NULL, *foundsig = NULL;
isc_rwlock_t *lock = NULL;
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
dns_qpchain_node(&search->chain, i, NULL, (void **)&node, NULL);
lock = &qpdb->node_locks[node->locknum].lock;
nlock = &qpdb->node_locks[node->locknum];
NODE_RDLOCK(lock, &nlocktype);
NODE_RDLOCK(nlock, &nlocktype);
/*
* Look for NS and RRSIG NS rdatasets.
@ -1336,7 +1326,7 @@ find_deepest_zonecut(qpc_search_t *search, qpcnode_t *node,
for (header = node->data; header != NULL; header = header_next)
{
header_next = header->next;
if (check_stale_header(node, header, &nlocktype, lock,
if (check_stale_header(node, header, &nlocktype, nlock,
search, &header_prev))
{
/* Do nothing. */
@ -1392,7 +1382,7 @@ find_deepest_zonecut(qpc_search_t *search, qpcnode_t *node,
need_headerupdate(foundsig, search->now)))
{
if (nlocktype != isc_rwlocktype_write) {
NODE_FORCEUPGRADE(lock, &nlocktype);
NODE_FORCEUPGRADE(nlock, &nlocktype);
POST(nlocktype);
}
if (need_headerupdate(found, search->now)) {
@ -1408,7 +1398,7 @@ find_deepest_zonecut(qpc_search_t *search, qpcnode_t *node,
}
}
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
if (found != NULL) {
break;
@ -1436,7 +1426,7 @@ find_coveringnsec(qpc_search_t *search, const dns_name_t *name,
dns_qpiter_t iter;
isc_result_t result;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *lock = NULL;
isc_rwlock_t *nlock = NULL;
dns_typepair_t matchtype, sigmatchtype;
dns_slabheader_t *found = NULL, *foundsig = NULL;
dns_slabheader_t *header = NULL;
@ -1475,11 +1465,11 @@ find_coveringnsec(qpc_search_t *search, const dns_name_t *name,
}
dns_name_copy(&node->name, fname);
lock = &(search->qpdb->node_locks[node->locknum].lock);
NODE_RDLOCK(lock, &nlocktype);
nlock = &search->qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
if (check_stale_header(node, header, &nlocktype, lock, search,
if (check_stale_header(node, header, &nlocktype, nlock, search,
&header_prev))
{
continue;
@ -1520,7 +1510,7 @@ find_coveringnsec(qpc_search_t *search, const dns_name_t *name,
} else {
result = ISC_R_NOTFOUND;
}
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
return result;
}
@ -1536,7 +1526,7 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
bool found_noqname = false;
bool all_negative = true;
bool empty_node;
isc_rwlock_t *lock = NULL;
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
dns_slabheader_t *header = NULL;
@ -1652,8 +1642,8 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
* We now go looking for rdata...
*/
lock = &(search.qpdb->node_locks[node->locknum].lock);
NODE_RDLOCK(lock, &nlocktype);
nlock = &search.qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
/*
* These pointers need to be reset here in case we did
@ -1672,7 +1662,7 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
header_prev = NULL;
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
if (check_stale_header(node, header, &nlocktype, lock, &search,
if (check_stale_header(node, header, &nlocktype, nlock, &search,
&header_prev))
{
/* Do nothing. */
@ -1774,7 +1764,7 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
* extant rdatasets. That means that this node doesn't
* meaningfully exist, and that we really have a partial match.
*/
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
if ((search.options & DNS_DBFIND_COVERINGNSEC) != 0) {
result = find_coveringnsec(
&search, name, nodep, now, foundname, rdataset,
@ -1832,7 +1822,7 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
if (found == NULL && (found_noqname || all_negative) &&
(search.options & DNS_DBFIND_COVERINGNSEC) != 0)
{
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
result = find_coveringnsec(
&search, name, nodep, now, foundname, rdataset,
sigrdataset DNS__DB_FLARG_PASS);
@ -1873,7 +1863,7 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
/*
* Go find the deepest zone cut.
*/
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
goto find_ns;
}
@ -1934,7 +1924,7 @@ node_exit:
if ((update != NULL || updatesig != NULL) &&
nlocktype != isc_rwlocktype_write)
{
NODE_FORCEUPGRADE(lock, &nlocktype);
NODE_FORCEUPGRADE(nlock, &nlocktype);
POST(nlocktype);
}
if (update != NULL && need_headerupdate(update, search.now)) {
@ -1944,7 +1934,7 @@ node_exit:
update_header(search.qpdb, updatesig, search.now);
}
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
tree_exit:
TREE_UNLOCK(&search.qpdb->tree_lock, &tlocktype);
@ -1956,12 +1946,12 @@ tree_exit:
if (search.need_cleanup) {
node = search.zonecut;
INSIST(node != NULL);
lock = &(search.qpdb->node_locks[node->locknum].lock);
nlock = &search.qpdb->node_locks[node->locknum];
NODE_RDLOCK(lock, &nlocktype);
NODE_RDLOCK(nlock, &nlocktype);
decref(search.qpdb, node, &nlocktype, &tlocktype,
true DNS__DB_FLARG_PASS);
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
INSIST(tlocktype == isc_rwlocktype_none);
}
@ -1975,7 +1965,7 @@ findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
dns_name_t *dcname, dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
qpcnode_t *node = NULL;
isc_rwlock_t *lock = NULL;
isc_rwlock_t *nlock = NULL;
isc_result_t result;
qpc_search_t search;
dns_slabheader_t *header = NULL;
@ -2039,12 +2029,12 @@ findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
* We now go looking for an NS rdataset at the node.
*/
lock = &(search.qpdb->node_locks[node->locknum].lock);
NODE_RDLOCK(lock, &nlocktype);
nlock = &search.qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
if (check_stale_header(node, header, &nlocktype, lock, &search,
if (check_stale_header(node, header, &nlocktype, nlock, &search,
&header_prev))
{
/*
@ -2057,7 +2047,7 @@ findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
* zonecut we know about. If so, find the deepest
* zonecut from this node up and return that instead.
*/
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
result = find_deepest_zonecut(
&search, node, nodep, foundname, rdataset,
sigrdataset DNS__DB_FLARG_PASS);
@ -2094,7 +2084,7 @@ findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
/*
* No NS records here.
*/
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
result = find_deepest_zonecut(&search, node, nodep, foundname,
rdataset,
sigrdataset DNS__DB_FLARG_PASS);
@ -2118,7 +2108,7 @@ findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
(foundsig != NULL && need_headerupdate(foundsig, search.now)))
{
if (nlocktype != isc_rwlocktype_write) {
NODE_FORCEUPGRADE(lock, &nlocktype);
NODE_FORCEUPGRADE(nlock, &nlocktype);
POST(nlocktype);
}
if (need_headerupdate(found, search.now)) {
@ -2130,7 +2120,7 @@ findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
}
}
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
tree_exit:
TREE_UNLOCK(&search.qpdb->tree_lock, &tlocktype);
@ -2155,7 +2145,7 @@ findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
dns_slabheader_t *found = NULL, *foundsig = NULL;
dns_typepair_t matchtype, sigmatchtype, negtype;
isc_result_t result;
isc_rwlock_t *lock = NULL;
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
REQUIRE(VALID_QPDB(qpdb));
@ -2169,8 +2159,8 @@ findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
now = isc_stdtime_now();
}
lock = &qpdb->node_locks[qpnode->locknum].lock;
NODE_RDLOCK(lock, &nlocktype);
nlock = &qpdb->node_locks[qpnode->locknum];
NODE_RDLOCK(nlock, &nlocktype);
matchtype = DNS_TYPEPAIR_VALUE(type, covers);
negtype = DNS_TYPEPAIR_VALUE(0, type);
@ -2186,7 +2176,7 @@ findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
if ((header->ttl + STALE_TTL(header, qpdb) <
now - QPDB_VIRTUAL) &&
(nlocktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock, &nlocktype) ==
NODE_TRYUPGRADE(nlock, &nlocktype) ==
ISC_R_SUCCESS))
{
/*
@ -2224,7 +2214,7 @@ findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
}
}
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
if (found == NULL) {
return ISC_R_NOTFOUND;
@ -2315,11 +2305,12 @@ expiredata(dns_db_t *db, dns_dbnode_t *node, void *data) {
dns_slabheader_t *header = data;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &qpdb->node_locks[qpnode->locknum];
NODE_WRLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
NODE_WRLOCK(nlock, &nlocktype);
expireheader(header, &nlocktype, &tlocktype,
dns_expire_flush DNS__DB_FILELINE);
NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
INSIST(tlocktype == isc_rwlocktype_none);
}
@ -2396,7 +2387,8 @@ overmem(qpcache_t *qpdb, dns_slabheader_t *newheader,
again:
do {
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
NODE_WRLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
isc_rwlock_t *nlock = &qpdb->node_locks[locknum];
NODE_WRLOCK(nlock, &nlocktype);
purged += expire_lru_headers(
qpdb, locknum, &nlocktype, tlocktypep,
@ -2412,7 +2404,7 @@ again:
{
min_last_used = header->last_used;
}
NODE_UNLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
locknum = (locknum + 1) % qpdb->node_lock_count;
} while (locknum != locknum_start && purged <= purgesize);
@ -2453,7 +2445,7 @@ set_index(void *what, unsigned int idx) {
}
static void
free_qpdb(qpcache_t *qpdb, bool log) {
qpcache__destroy(qpcache_t *qpdb) {
unsigned int i;
char buf[DNS_NAME_FORMATSIZE];
dns_qp_t **treep = NULL;
@ -2474,22 +2466,19 @@ free_qpdb(qpcache_t *qpdb, bool log) {
INSIST(*treep == NULL);
}
if (log) {
if (dns_name_dynamic(&qpdb->common.origin)) {
dns_name_format(&qpdb->common.origin, buf, sizeof(buf));
} else {
strlcpy(buf, "<UNKNOWN>", sizeof(buf));
}
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
"done free_qpdb(%s)", buf);
if (dns_name_dynamic(&qpdb->common.origin)) {
dns_name_format(&qpdb->common.origin, buf, sizeof(buf));
} else {
strlcpy(buf, "<UNKNOWN>", sizeof(buf));
}
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
ISC_LOG_DEBUG(1), "done %s(%s)", __func__, buf);
if (dns_name_dynamic(&qpdb->common.origin)) {
dns_name_free(&qpdb->common.origin, qpdb->common.mctx);
}
for (i = 0; i < qpdb->node_lock_count; i++) {
isc_refcount_destroy(&qpdb->node_locks[i].references);
NODE_DESTROYLOCK(&qpdb->node_locks[i].lock);
NODE_DESTROYLOCK(&qpdb->node_locks[i]);
}
/*
@ -2535,8 +2524,9 @@ free_qpdb(qpcache_t *qpdb, bool log) {
}
isc_mem_cput(qpdb->common.mctx, qpdb->node_locks, qpdb->node_lock_count,
sizeof(db_nodelock_t));
sizeof(qpdb->node_locks[0]));
TREE_DESTROYLOCK(&qpdb->tree_lock);
isc_refcount_destroy(&qpdb->references);
isc_refcount_destroy(&qpdb->common.references);
isc_rwlock_destroy(&qpdb->lock);
@ -2550,46 +2540,8 @@ free_qpdb(qpcache_t *qpdb, bool log) {
static void
qpdb_destroy(dns_db_t *arg) {
qpcache_t *qpdb = (qpcache_t *)arg;
bool want_free = false;
unsigned int i;
unsigned int inactive = 0;
/*
* Even though there are no external direct references, there still
* may be nodes in use.
*/
for (i = 0; i < qpdb->node_lock_count; i++) {
isc_rwlocktype_t nodelock = isc_rwlocktype_none;
NODE_WRLOCK(&qpdb->node_locks[i].lock, &nodelock);
qpdb->node_locks[i].exiting = true;
if (isc_refcount_current(&qpdb->node_locks[i].references) == 0)
{
inactive++;
}
NODE_UNLOCK(&qpdb->node_locks[i].lock, &nodelock);
}
if (inactive != 0) {
RWLOCK(&qpdb->lock, isc_rwlocktype_write);
qpdb->active -= inactive;
if (qpdb->active == 0) {
want_free = true;
}
RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
if (want_free) {
char buf[DNS_NAME_FORMATSIZE];
if (dns_name_dynamic(&qpdb->common.origin)) {
dns_name_format(&qpdb->common.origin, buf,
sizeof(buf));
} else {
strlcpy(buf, "<UNKNOWN>", sizeof(buf));
}
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
"calling free_qpdb(%s)", buf);
free_qpdb(qpdb, true);
}
}
qpcache_detach(&qpdb);
}
static void
@ -2611,6 +2563,7 @@ cleanup_deadnodes(void *arg) {
uint16_t locknum = isc_tid();
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &qpdb->node_locks[locknum];
qpcnode_t *qpnode = NULL, *qpnext = NULL;
isc_queue_t deadnodes;
@ -2619,14 +2572,14 @@ cleanup_deadnodes(void *arg) {
isc_queue_init(&deadnodes);
TREE_WRLOCK(&qpdb->tree_lock, &tlocktype);
NODE_WRLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
NODE_WRLOCK(nlock, &nlocktype);
RUNTIME_CHECK(isc_queue_splice(&deadnodes, &qpdb->deadnodes[locknum]));
isc_queue_for_each_entry_safe(&deadnodes, qpnode, qpnext, deadlink) {
decref(qpdb, qpnode, &nlocktype, &tlocktype, false);
}
NODE_UNLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
TREE_UNLOCK(&qpdb->tree_lock, &tlocktype);
}
@ -2643,11 +2596,11 @@ static void
reactivate_node(qpcache_t *qpdb, qpcnode_t *node,
isc_rwlocktype_t tlocktype ISC_ATTR_UNUSED DNS__DB_FLARG) {
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nodelock = &qpdb->node_locks[node->locknum].lock;
isc_rwlock_t *nlock = &qpdb->node_locks[node->locknum];
NODE_RDLOCK(nodelock, &nlocktype);
NODE_RDLOCK(nlock, &nlocktype);
newref(qpdb, node, nlocktype, tlocktype DNS__DB_FLARG_PASS);
NODE_UNLOCK(nodelock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
}
static qpcnode_t *
@ -2723,56 +2676,31 @@ attachnode(dns_db_t *db, dns_dbnode_t *source,
}
static void
detachnode(dns_db_t *db, dns_dbnode_t **targetp DNS__DB_FLARG) {
detachnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) {
qpcache_t *qpdb = (qpcache_t *)db;
qpcnode_t *node = NULL;
bool want_free = false;
bool inactive = false;
db_nodelock_t *nodelock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
REQUIRE(VALID_QPDB(qpdb));
REQUIRE(targetp != NULL && *targetp != NULL);
REQUIRE(nodep != NULL && *nodep != NULL);
node = (qpcnode_t *)(*targetp);
nodelock = &qpdb->node_locks[node->locknum];
node = (qpcnode_t *)(*nodep);
*nodep = NULL;
nlock = &qpdb->node_locks[node->locknum];
NODE_RDLOCK(&nodelock->lock, &nlocktype);
/*
* We can't destroy qpcache under nodelock, so we need
* to reference it before acquiring the lock.
*/
qpcache_ref(qpdb);
NODE_RDLOCK(nlock, &nlocktype);
decref(qpdb, node, &nlocktype, &tlocktype, true DNS__DB_FLARG_PASS);
if (isc_refcount_current(&nodelock->references) == 0 &&
nodelock->exiting)
{
inactive = true;
}
NODE_UNLOCK(nlock, &nlocktype);
NODE_UNLOCK(&nodelock->lock, &nlocktype);
INSIST(tlocktype == isc_rwlocktype_none);
*targetp = NULL;
if (inactive) {
RWLOCK(&qpdb->lock, isc_rwlocktype_write);
qpdb->active--;
if (qpdb->active == 0) {
want_free = true;
}
RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
if (want_free) {
char buf[DNS_NAME_FORMATSIZE];
if (dns_name_dynamic(&qpdb->common.origin)) {
dns_name_format(&qpdb->common.origin, buf,
sizeof(buf));
} else {
strlcpy(buf, "<UNKNOWN>", sizeof(buf));
}
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
"calling free_qpdb(%s)", buf);
free_qpdb(qpdb, true);
}
}
qpcache_detach(&qpdb);
}
static isc_result_t
@ -3388,6 +3316,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
bool newnsec;
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
bool cache_is_overmem = false;
dns_fixedname_t fixed;
dns_name_t *name = NULL;
@ -3499,7 +3428,9 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
overmem(qpdb, newheader, &tlocktype DNS__DB_FLARG_PASS);
}
NODE_WRLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
nlock = &qpdb->node_locks[qpnode->locknum];
NODE_WRLOCK(nlock, &nlocktype);
if (qpdb->rrsetstats != NULL) {
DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_STATCOUNT);
@ -3548,7 +3479,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
qpnode->delegating = 1;
}
NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
if (tlocktype != isc_rwlocktype_none) {
TREE_UNLOCK(&qpdb->tree_lock, &tlocktype);
@ -3566,6 +3497,7 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
isc_result_t result;
dns_slabheader_t *newheader = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
REQUIRE(VALID_QPDB(qpdb));
REQUIRE(version == NULL);
@ -3582,11 +3514,12 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
setttl(newheader, 0);
atomic_init(&newheader->attributes, DNS_SLABHEADERATTR_NONEXISTENT);
NODE_WRLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
nlock = &qpdb->node_locks[qpnode->locknum];
NODE_WRLOCK(nlock, &nlocktype);
result = add(qpdb, qpnode, NULL, newheader, DNS_DBADD_FORCE, false,
NULL, 0, nlocktype,
isc_rwlocktype_none DNS__DB_FLARG_PASS);
NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
return result;
}
@ -3620,7 +3553,7 @@ locknode(dns_db_t *db, dns_dbnode_t *node, isc_rwlocktype_t type) {
qpcache_t *qpdb = (qpcache_t *)db;
qpcnode_t *qpnode = (qpcnode_t *)node;
RWLOCK(&qpdb->node_locks[qpnode->locknum].lock, type);
RWLOCK(&qpdb->node_locks[qpnode->locknum], type);
}
static void
@ -3628,7 +3561,7 @@ unlocknode(dns_db_t *db, dns_dbnode_t *node, isc_rwlocktype_t type) {
qpcache_t *qpdb = (qpcache_t *)db;
qpcnode_t *qpnode = (qpcnode_t *)node;
RWUNLOCK(&qpdb->node_locks[qpnode->locknum].lock, type);
RWUNLOCK(&qpdb->node_locks[qpnode->locknum], type);
}
isc_result_t
@ -3651,11 +3584,11 @@ dns__qpcache_create(isc_mem_t *mctx, const dns_name_t *origin,
.common.origin = DNS_NAME_INITEMPTY,
.common.rdclass = rdclass,
.common.attributes = DNS_DBATTR_CACHE,
.common.references = 1,
.loopmgr = isc_loop_getloopmgr(loop),
.references = 1,
};
isc_refcount_init(&qpdb->common.references, 1);
/*
* If argv[0] exists, it points to a memory context to use for heap
*/
@ -3668,7 +3601,7 @@ dns__qpcache_create(isc_mem_t *mctx, const dns_name_t *origin,
qpdb->node_lock_count = isc_loopmgr_nloops(qpdb->loopmgr);
qpdb->node_locks = isc_mem_cget(mctx, qpdb->node_lock_count,
sizeof(db_nodelock_t));
sizeof(qpdb->node_locks[0]));
dns_rdatasetstats_create(mctx, &qpdb->rrsetstats);
qpdb->lru = isc_mem_cget(mctx, qpdb->node_lock_count,
@ -3696,12 +3629,8 @@ dns__qpcache_create(isc_mem_t *mctx, const dns_name_t *origin,
isc_queue_init(&qpdb->deadnodes[i]);
}
qpdb->active = qpdb->node_lock_count;
for (i = 0; i < (int)(qpdb->node_lock_count); i++) {
NODE_INITLOCK(&qpdb->node_locks[i].lock);
isc_refcount_init(&qpdb->node_locks[i].references, 0);
qpdb->node_locks[i].exiting = false;
NODE_INITLOCK(&qpdb->node_locks[i]);
}
/*
@ -3784,8 +3713,9 @@ rdatasetiter_first(dns_rdatasetiter_t *it DNS__DB_FLARG) {
qpcnode_t *qpnode = iterator->common.node;
dns_slabheader_t *header = NULL, *top_next = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &qpdb->node_locks[qpnode->locknum];
NODE_RDLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
NODE_RDLOCK(nlock, &nlocktype);
for (header = qpnode->data; header != NULL; header = top_next) {
top_next = header->next;
@ -3809,7 +3739,7 @@ rdatasetiter_first(dns_rdatasetiter_t *it DNS__DB_FLARG) {
}
}
NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
iterator->current = header;
@ -3829,6 +3759,7 @@ rdatasetiter_next(dns_rdatasetiter_t *it DNS__DB_FLARG) {
dns_typepair_t type, negtype;
dns_rdatatype_t rdtype, covers;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &qpdb->node_locks[qpnode->locknum];
bool expiredok = EXPIREDOK(iterator);
header = iterator->current;
@ -3836,7 +3767,7 @@ rdatasetiter_next(dns_rdatasetiter_t *it DNS__DB_FLARG) {
return ISC_R_NOMORE;
}
NODE_RDLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
NODE_RDLOCK(nlock, &nlocktype);
type = header->type;
rdtype = DNS_TYPEPAIR_TYPE(header->type);
@ -3897,7 +3828,7 @@ rdatasetiter_next(dns_rdatasetiter_t *it DNS__DB_FLARG) {
}
}
NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
iterator->current = header;
@ -3916,16 +3847,17 @@ rdatasetiter_current(dns_rdatasetiter_t *it,
qpcnode_t *qpnode = iterator->common.node;
dns_slabheader_t *header = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &qpdb->node_locks[qpnode->locknum];
header = iterator->current;
REQUIRE(header != NULL);
NODE_RDLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
NODE_RDLOCK(nlock, &nlocktype);
bindrdataset(qpdb, qpnode, header, iterator->common.now, nlocktype,
isc_rwlocktype_none, rdataset DNS__DB_FLARG_PASS);
NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
}
/*
@ -3949,7 +3881,7 @@ static void
dereference_iter_node(qpc_dbit_t *qpdbiter DNS__DB_FLARG) {
qpcache_t *qpdb = (qpcache_t *)qpdbiter->common.db;
qpcnode_t *node = qpdbiter->node;
isc_rwlock_t *lock = NULL;
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlocktype_t tlocktype = qpdbiter->tree_locked;
@ -3959,11 +3891,11 @@ dereference_iter_node(qpc_dbit_t *qpdbiter DNS__DB_FLARG) {
REQUIRE(tlocktype != isc_rwlocktype_write);
lock = &qpdb->node_locks[node->locknum].lock;
NODE_RDLOCK(lock, &nlocktype);
nlock = &qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
decref(qpdb, node, &nlocktype, &qpdbiter->tree_locked,
false DNS__DB_FLARG_PASS);
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
INSIST(qpdbiter->tree_locked == tlocktype);
@ -4398,3 +4330,9 @@ ISC_REFCOUNT_STATIC_TRACE_IMPL(qpcnode, qpcnode_destroy);
#else
ISC_REFCOUNT_STATIC_IMPL(qpcnode, qpcnode_destroy);
#endif
#ifdef DNS_DB_NODETRACE
ISC_REFCOUNT_STATIC_TRACE_IMPL(qpcache, qpcache__destroy);
#else
ISC_REFCOUNT_STATIC_IMPL(qpcache, qpcache__destroy);
#endif

View file

@ -168,7 +168,9 @@ struct qpzonedb {
isc_rwlock_t lock;
/* Locks for tree nodes */
int node_lock_count;
db_nodelock_t *node_locks;
isc_rwlock_t *node_locks;
isc_refcount_t references;
qpznode_t *origin;
qpznode_t *nsec3_origin;
isc_stats_t *gluecachestats;
@ -193,6 +195,18 @@ struct qpzonedb {
dns_qpmulti_t *nsec3; /* NSEC3 nodes only */
};
#ifdef DNS_DB_NODETRACE
#define qpzonedb_ref(ptr) qpzonedb__ref(ptr, __func__, __FILE__, __LINE__)
#define qpzonedb_unref(ptr) qpzonedb_unref(ptr, __func__, __FILE__, __LINE__)
#define qpzonedb_attach(ptr, ptrp) \
qpzonedb__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
#define qpzonedb_detach(ptrp) \
qpzonedb__detach(ptrp, __func__, __FILE__, __LINE__)
ISC_REFCOUNT_STATIC_TRACE_DECL(qpzonedb);
#else
ISC_REFCOUNT_STATIC_DECL(qpzonedb);
#endif
/*%
* Search Context
*/
@ -377,8 +391,7 @@ free_db_rcu(struct rcu_head *rcu_head) {
dns_name_free(&qpdb->common.origin, qpdb->common.mctx);
}
for (int i = 0; i < qpdb->node_lock_count; i++) {
isc_refcount_destroy(&qpdb->node_locks[i].references);
NODE_DESTROYLOCK(&qpdb->node_locks[i].lock);
NODE_DESTROYLOCK(&qpdb->node_locks[i]);
}
isc_heap_destroy(&qpdb->heap);
@ -388,13 +401,15 @@ free_db_rcu(struct rcu_head *rcu_head) {
}
isc_mem_cput(qpdb->common.mctx, qpdb->node_locks, qpdb->node_lock_count,
sizeof(db_nodelock_t));
isc_refcount_destroy(&qpdb->common.references);
sizeof(qpdb->node_locks[0]));
if (qpdb->loop != NULL) {
isc_loop_detach(&qpdb->loop);
}
isc_rwlock_destroy(&qpdb->lock);
isc_refcount_destroy(&qpdb->references);
isc_refcount_destroy(&qpdb->common.references);
qpdb->common.magic = 0;
qpdb->common.impmagic = 0;
@ -406,7 +421,7 @@ free_db_rcu(struct rcu_head *rcu_head) {
}
static void
free_qpdb(qpzonedb_t *qpdb, bool log) {
qpzone_destroy(qpzonedb_t *qpdb) {
REQUIRE(qpdb->future_version == NULL);
isc_refcount_decrementz(&qpdb->current_version->references);
@ -422,17 +437,14 @@ free_qpdb(qpzonedb_t *qpdb, bool log) {
dns_qpmulti_destroy(&qpdb->nsec);
dns_qpmulti_destroy(&qpdb->nsec3);
if (log) {
char buf[DNS_NAME_FORMATSIZE];
if (dns_name_dynamic(&qpdb->common.origin)) {
dns_name_format(&qpdb->common.origin, buf, sizeof(buf));
} else {
strlcpy(buf, "<UNKNOWN>", sizeof(buf));
}
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DB, ISC_LOG_DEBUG(1),
"called free_qpdb(%s)", buf);
char buf[DNS_NAME_FORMATSIZE];
if (dns_name_dynamic(&qpdb->common.origin)) {
dns_name_format(&qpdb->common.origin, buf, sizeof(buf));
} else {
strlcpy(buf, "<UNKNOWN>", sizeof(buf));
}
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DB,
ISC_LOG_DEBUG(1), "called %s(%s)", __func__, buf);
call_rcu(&qpdb->rcu_head, free_db_rcu);
}
@ -440,7 +452,6 @@ free_qpdb(qpzonedb_t *qpdb, bool log) {
static void
qpdb_destroy(dns_db_t *arg) {
qpzonedb_t *qpdb = (qpzonedb_t *)arg;
unsigned int inactive = 0;
if (qpdb->origin != NULL) {
qpznode_detach(&qpdb->origin);
@ -458,45 +469,7 @@ qpdb_destroy(dns_db_t *arg) {
dns__db_cleanup_gluelists(&qpdb->current_version->glue_stack);
}
/*
* Even though there are no external direct references, there still
* may be nodes in use.
*/
for (int i = 0; i < qpdb->node_lock_count; i++) {
isc_rwlocktype_t nodelock = isc_rwlocktype_none;
NODE_WRLOCK(&qpdb->node_locks[i].lock, &nodelock);
qpdb->node_locks[i].exiting = true;
if (isc_refcount_current(&qpdb->node_locks[i].references) == 0)
{
inactive++;
}
NODE_UNLOCK(&qpdb->node_locks[i].lock, &nodelock);
}
if (inactive != 0) {
bool want_free = false;
RWLOCK(&qpdb->lock, isc_rwlocktype_write);
qpdb->active -= inactive;
if (qpdb->active == 0) {
want_free = true;
}
RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
if (want_free) {
char buf[DNS_NAME_FORMATSIZE];
if (dns_name_dynamic(&qpdb->common.origin)) {
dns_name_format(&qpdb->common.origin, buf,
sizeof(buf));
} else {
strlcpy(buf, "<UNKNOWN>", sizeof(buf));
}
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DB, ISC_LOG_DEBUG(1),
"calling free_qpdb(%s)", buf);
free_qpdb(qpdb, true);
}
}
qpzonedb_detach(&qpdb);
}
static qpznode_t *
@ -527,11 +500,11 @@ allocate_version(isc_mem_t *mctx, uint32_t serial, unsigned int references,
.changed_list = ISC_LIST_INITIALIZER,
.resigned_list = ISC_LIST_INITIALIZER,
.link = ISC_LINK_INITIALIZER,
.references = ISC_REFCOUNT_INITIALIZER(references),
};
cds_wfs_init(&version->glue_stack);
isc_rwlock_init(&version->rwlock);
isc_refcount_init(&version->references, references);
return version;
}
@ -549,15 +522,15 @@ dns__qpzone_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
*qpdb = (qpzonedb_t){
.common.origin = DNS_NAME_INITEMPTY,
.common.rdclass = rdclass,
.common.references = ISC_REFCOUNT_INITIALIZER(1),
.node_lock_count = DEFAULT_NODE_LOCK_COUNT,
.current_serial = 1,
.least_serial = 1,
.next_serial = 2,
.open_versions = ISC_LIST_INITIALIZER,
.references = ISC_REFCOUNT_INITIALIZER(1),
};
isc_refcount_init(&qpdb->common.references, 1);
qpdb->common.methods = &qpdb_zonemethods;
if (type == dns_dbtype_stub) {
qpdb->common.attributes |= DNS_DBATTR_STUB;
@ -566,7 +539,7 @@ dns__qpzone_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
isc_rwlock_init(&qpdb->lock);
qpdb->node_locks = isc_mem_cget(mctx, qpdb->node_lock_count,
sizeof(db_nodelock_t));
sizeof(qpdb->node_locks[0]));
qpdb->common.update_listeners = cds_lfht_new(16, 16, 0, 0, NULL);
@ -575,9 +548,7 @@ dns__qpzone_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
qpdb->active = qpdb->node_lock_count;
for (int i = 0; i < qpdb->node_lock_count; i++) {
NODE_INITLOCK(&qpdb->node_locks[i].lock);
isc_refcount_init(&qpdb->node_locks[i].references, 0);
qpdb->node_locks[i].exiting = false;
NODE_INITLOCK(&qpdb->node_locks[i]);
}
/*
@ -622,7 +593,7 @@ dns__qpzone_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
if (result != ISC_R_SUCCESS) {
INSIST(result != ISC_R_EXISTS);
free_qpdb(qpdb, false);
qpzonedb_detach(&qpdb);
return result;
}
@ -639,7 +610,7 @@ dns__qpzone_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
if (result != ISC_R_SUCCESS) {
INSIST(result != ISC_R_EXISTS);
free_qpdb(qpdb, false);
qpzonedb_detach(&qpdb);
return result;
}
@ -669,18 +640,7 @@ qpznode_newref(qpzonedb_t *qpdb, qpznode_t *node DNS__DB_FLARG) {
return;
}
/* this is the first reference to the node */
refs = isc_refcount_increment0(
&qpdb->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, &qpdb->node_locks[node->locknum],
refs + 1);
#else
UNUSED(refs);
#endif
qpzonedb_ref(qpdb);
}
static void
@ -818,17 +778,7 @@ qpznode_decref(qpzonedb_t *qpdb, qpznode_t *node DNS__DB_FLARG) {
return false;
}
refs = isc_refcount_decrement(
&qpdb->node_locks[node->locknum].references);
#if DNS_DB_NODETRACE
fprintf(stderr,
"decr:nodelock:%s:%s:%u:%p:%p->references = "
"%" PRIuFAST32 "\n",
func, file, line, node, &qpdb->node_locks[node->locknum],
refs - 1);
#else
UNUSED(refs);
#endif
qpzonedb_unref(qpdb);
return true;
}
@ -873,8 +823,8 @@ decref(qpzonedb_t *qpdb, qpznode_t *node, uint32_t least_serial,
/* Upgrade the lock? */
if (*nlocktypep == isc_rwlocktype_read) {
NODE_FORCEUPGRADE(&qpdb->node_locks[node->locknum].lock,
nlocktypep);
isc_rwlock_t *nlock = &qpdb->node_locks[node->locknum];
NODE_FORCEUPGRADE(nlock, nlocktypep);
}
if (!qpznode_decref(qpdb, node DNS__DB_FLARG_PASS)) {
@ -963,10 +913,12 @@ setnsec3parameters(dns_db_t *db, qpz_version_t *version) {
unsigned int count, length;
qpzonedb_t *qpdb = (qpzonedb_t *)db;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
version->havensec3 = false;
node = qpdb->origin;
NODE_RDLOCK(&(qpdb->node_locks[node->locknum].lock), &nlocktype);
nlock = &qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
do {
@ -1033,7 +985,7 @@ setnsec3parameters(dns_db_t *db, qpz_version_t *version) {
}
}
unlock:
NODE_UNLOCK(&(qpdb->node_locks[node->locknum].lock), &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
}
static void
@ -1434,19 +1386,19 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
for (header = HEAD(resigned_list); header != NULL;
header = HEAD(resigned_list))
{
isc_rwlock_t *lock = NULL;
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
ISC_LIST_UNLINK(resigned_list, header, link);
lock = &qpdb->node_locks[HEADERNODE(header)->locknum].lock;
NODE_WRLOCK(lock, &nlocktype);
nlock = &qpdb->node_locks[HEADERNODE(header)->locknum];
NODE_WRLOCK(nlock, &nlocktype);
if (rollback && !IGNORE(header)) {
resigninsert(qpdb, header);
}
decref(qpdb, HEADERNODE(header), least_serial,
&nlocktype DNS__DB_FLARG_PASS);
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
}
if (EMPTY(cleanup_list)) {
@ -1457,20 +1409,20 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
for (changed = HEAD(cleanup_list); changed != NULL;
changed = next_changed)
{
isc_rwlock_t *lock = NULL;
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
next_changed = NEXT(changed, link);
node = changed->node;
lock = &qpdb->node_locks[node->locknum].lock;
nlock = &qpdb->node_locks[node->locknum];
NODE_WRLOCK(lock, &nlocktype);
NODE_WRLOCK(nlock, &nlocktype);
if (rollback) {
rollback_node(node, serial);
}
decref(qpdb, node, least_serial, &nlocktype DNS__DB_FILELINE);
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
isc_mem_put(qpdb->common.mctx, changed, sizeof(*changed));
}
@ -1492,6 +1444,7 @@ findrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
bool close_version = false;
dns_typepair_t matchtype, sigmatchtype;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
REQUIRE(VALID_QPZONE(qpdb));
REQUIRE(type != dns_rdatatype_any);
@ -1503,7 +1456,8 @@ findrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
}
serial = version->serial;
NODE_RDLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
nlock = &qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
matchtype = DNS_TYPEPAIR_VALUE(type, covers);
if (covers == 0) {
@ -1550,7 +1504,7 @@ findrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
}
}
NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
if (close_version) {
closeversion(db, (dns_dbversion_t **)&version,
@ -2049,6 +2003,7 @@ loading_addrdataset(void *arg, const dns_name_t *name,
isc_region_t region;
dns_slabheader_t *newheader = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
REQUIRE(rdataset->rdclass == qpdb->common.rdclass);
@ -2119,10 +2074,11 @@ loading_addrdataset(void *arg, const dns_name_t *name,
newheader->resign_lsb = rdataset->resign & 0x1;
}
NODE_WRLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
nlock = &qpdb->node_locks[node->locknum];
NODE_WRLOCK(nlock, &nlocktype);
result = add(qpdb, node, name, qpdb->current_version, newheader,
DNS_DBADD_MERGE, true, NULL, 0 DNS__DB_FLARG_PASS);
NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
if (result == ISC_R_SUCCESS &&
delegating_type(qpdb, node, rdataset->type))
@ -2319,6 +2275,7 @@ setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) {
qpzonedb_t *qpdb = (qpzonedb_t *)db;
dns_slabheader_t *header = NULL, oldheader;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
REQUIRE(VALID_QPZONE(qpdb));
REQUIRE(rdataset != NULL);
@ -2326,8 +2283,8 @@ setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) {
header = dns_slabheader_fromrdataset(rdataset);
NODE_WRLOCK(&qpdb->node_locks[HEADERNODE(header)->locknum].lock,
&nlocktype);
nlock = &qpdb->node_locks[HEADERNODE(header)->locknum];
NODE_WRLOCK(nlock, &nlocktype);
oldheader = *header;
@ -2358,8 +2315,7 @@ setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) {
DNS_SLABHEADER_SETATTR(header, DNS_SLABHEADERATTR_RESIGN);
resigninsert(qpdb, header);
}
NODE_UNLOCK(&qpdb->node_locks[HEADERNODE(header)->locknum].lock,
&nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
return ISC_R_SUCCESS;
}
@ -2369,6 +2325,7 @@ getsigningtime(dns_db_t *db, isc_stdtime_t *resign, dns_name_t *foundname,
qpzonedb_t *qpdb = (qpzonedb_t *)db;
dns_slabheader_t *header = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
uint16_t locknum;
isc_result_t result = ISC_R_NOTFOUND;
@ -2387,13 +2344,15 @@ getsigningtime(dns_db_t *db, isc_stdtime_t *resign, dns_name_t *foundname,
RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
again:
NODE_RDLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
nlock = &qpdb->node_locks[locknum];
NODE_RDLOCK(nlock, &nlocktype);
RWLOCK(&qpdb->lock, isc_rwlocktype_read);
header = isc_heap_element(qpdb->heap, 1);
if (header != NULL && HEADERNODE(header)->locknum != locknum) {
RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
NODE_UNLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
locknum = HEADERNODE(header)->locknum;
goto again;
}
@ -2407,7 +2366,7 @@ again:
result = ISC_R_SUCCESS;
}
RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
NODE_UNLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
return result;
}
@ -2580,8 +2539,8 @@ setup_delegation(qpz_search_t *search, dns_dbnode_t **nodep,
}
if (rdataset != NULL) {
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
NODE_RDLOCK(&(search->qpdb->node_locks[node->locknum].lock),
&nlocktype);
isc_rwlock_t *nlock = &search->qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
bindrdataset(search->qpdb, node, search->zonecut_header,
search->now, rdataset DNS__DB_FLARG_PASS);
if (sigrdataset != NULL && search->zonecut_sigheader != NULL) {
@ -2589,8 +2548,7 @@ setup_delegation(qpz_search_t *search, dns_dbnode_t **nodep,
search->zonecut_sigheader, search->now,
sigrdataset DNS__DB_FLARG_PASS);
}
NODE_UNLOCK(&(search->qpdb->node_locks[node->locknum].lock),
&nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
}
if (type == dns_rdatatype_dname) {
@ -2621,10 +2579,10 @@ step(qpz_search_t *search, dns_qpiter_t *it, direction_t direction,
result = dns_qpiter_current(it, nodename, (void **)&node, NULL);
while (result == ISC_R_SUCCESS) {
isc_rwlock_t *nodelock = &qpdb->node_locks[node->locknum].lock;
isc_rwlock_t *nlock = &qpdb->node_locks[node->locknum];
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
NODE_RDLOCK(nodelock, &nlocktype);
NODE_RDLOCK(nlock, &nlocktype);
for (header = node->data; header != NULL; header = header->next)
{
if (header->serial <= search->serial &&
@ -2633,7 +2591,7 @@ step(qpz_search_t *search, dns_qpiter_t *it, direction_t direction,
break;
}
}
NODE_UNLOCK(nodelock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
if (header != NULL) {
break;
}
@ -2768,14 +2726,14 @@ find_wildcard(qpz_search_t *search, qpznode_t **nodep,
*/
for (int i = dns_qpchain_length(&search->chain) - 1; i >= 0; i--) {
qpznode_t *node = NULL;
isc_rwlock_t *lock = NULL;
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
bool wild, active;
dns_qpchain_node(&search->chain, i, NULL, (void **)&node, NULL);
lock = &qpdb->node_locks[node->locknum].lock;
NODE_RDLOCK(lock, &nlocktype);
nlock = &qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
/*
* First we try to figure out if this node is active in
* the search's version. We do this now, even though we
@ -2793,7 +2751,7 @@ find_wildcard(qpz_search_t *search, qpznode_t **nodep,
active = (header != NULL);
wild = node->wild;
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
if (wild) {
qpznode_t *wnode = NULL;
@ -2818,8 +2776,8 @@ find_wildcard(qpz_search_t *search, qpznode_t **nodep,
* is active in the search's version, we're
* done.
*/
lock = &qpdb->node_locks[wnode->locknum].lock;
NODE_RDLOCK(lock, &nlocktype);
nlock = &qpdb->node_locks[wnode->locknum];
NODE_RDLOCK(nlock, &nlocktype);
for (header = wnode->data; header != NULL;
header = header->next)
{
@ -2830,7 +2788,7 @@ find_wildcard(qpz_search_t *search, qpznode_t **nodep,
break;
}
}
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
if (header != NULL ||
activeempty(search, &wit, wname))
{
@ -3001,8 +2959,8 @@ again:
do {
dns_slabheader_t *found = NULL, *foundsig = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
NODE_RDLOCK(&(search->qpdb->node_locks[node->locknum].lock),
&nlocktype);
isc_rwlock_t *nlock = &search->qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
empty_node = true;
for (header = node->data; header != NULL; header = header_next)
{
@ -3108,8 +3066,7 @@ again:
&prevnode, &nseciter,
&first);
}
NODE_UNLOCK(&(search->qpdb->node_locks[node->locknum].lock),
&nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
node = prevnode;
prevnode = NULL;
} while (empty_node && result == ISC_R_SUCCESS);
@ -3144,9 +3101,9 @@ check_zonecut(qpznode_t *node, void *arg DNS__DB_FLARG) {
dns_slabheader_t *found = NULL;
isc_result_t result = DNS_R_CONTINUE;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &search->qpdb->node_locks[node->locknum];
NODE_RDLOCK(&(search->qpdb->node_locks[node->locknum].lock),
&nlocktype);
NODE_RDLOCK(nlock, &nlocktype);
/*
* Look for an NS or DNAME rdataset active in our version.
@ -3256,8 +3213,7 @@ check_zonecut(qpznode_t *node, void *arg DNS__DB_FLARG) {
}
}
NODE_UNLOCK(&(search->qpdb->node_locks[node->locknum].lock),
&nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
return result;
}
@ -3281,7 +3237,7 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
dns_slabheader_t *foundsig = NULL, *cnamesig = NULL, *nsecsig = NULL;
dns_typepair_t sigtype;
bool active;
isc_rwlock_t *lock = NULL;
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
REQUIRE(VALID_QPZONE((qpzonedb_t *)db));
@ -3413,8 +3369,8 @@ found:
* have matched a wildcard.
*/
lock = &search.qpdb->node_locks[node->locknum].lock;
NODE_RDLOCK(lock, &nlocktype);
nlock = &search.qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
if (search.zonecut != NULL) {
/*
@ -3527,7 +3483,7 @@ found:
if (header->type == dns_rdatatype_nsec3 &&
!matchparams(header, &search))
{
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
goto partial_match;
}
/*
@ -3616,7 +3572,7 @@ found:
* we really have a partial match.
*/
if (!wild) {
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
goto partial_match;
}
}
@ -3632,7 +3588,7 @@ found:
*
* Return the delegation.
*/
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
result = setup_delegation(
&search, nodep, foundname, rdataset,
sigrdataset DNS__DB_FLARG_PASS);
@ -3654,7 +3610,7 @@ found:
goto node_exit;
}
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
result = find_closest_nsec(
&search, nodep, foundname, rdataset,
sigrdataset, false,
@ -3750,7 +3706,7 @@ found:
}
node_exit:
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
tree_exit:
if (nsec3) {
@ -3766,11 +3722,11 @@ tree_exit:
if (search.need_cleanup) {
node = search.zonecut;
INSIST(node != NULL);
lock = &(search.qpdb->node_locks[node->locknum].lock);
nlock = &search.qpdb->node_locks[node->locknum];
NODE_RDLOCK(lock, &nlocktype);
NODE_RDLOCK(nlock, &nlocktype);
decref(search.qpdb, node, 0, &nlocktype DNS__DB_FLARG_PASS);
NODE_UNLOCK(lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
}
if (close_version) {
@ -3829,52 +3785,26 @@ attachnode(dns_db_t *db, dns_dbnode_t *source,
}
static void
detachnode(dns_db_t *db, dns_dbnode_t **targetp DNS__DB_FLARG) {
detachnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) {
qpzonedb_t *qpdb = (qpzonedb_t *)db;
qpznode_t *node = NULL;
bool want_free = false;
bool inactive = false;
db_nodelock_t *nodelock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
REQUIRE(VALID_QPZONE(qpdb));
REQUIRE(targetp != NULL && *targetp != NULL);
REQUIRE(nodep != NULL && *nodep != NULL);
node = (qpznode_t *)(*targetp);
nodelock = &qpdb->node_locks[node->locknum];
node = (qpznode_t *)(*nodep);
*nodep = NULL;
nlock = &qpdb->node_locks[node->locknum];
NODE_RDLOCK(&nodelock->lock, &nlocktype);
qpzonedb_ref(qpdb);
NODE_RDLOCK(nlock, &nlocktype);
decref(qpdb, node, 0, &nlocktype DNS__DB_FLARG_PASS);
if (isc_refcount_current(&nodelock->references) == 0 &&
nodelock->exiting)
{
inactive = true;
}
NODE_UNLOCK(&nodelock->lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
*targetp = NULL;
if (inactive) {
RWLOCK(&qpdb->lock, isc_rwlocktype_write);
qpdb->active--;
if (qpdb->active == 0) {
want_free = true;
}
RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
if (want_free) {
char buf[DNS_NAME_FORMATSIZE];
if (dns_name_dynamic(&qpdb->common.origin)) {
dns_name_format(&qpdb->common.origin, buf,
sizeof(buf));
} else {
strlcpy(buf, "<UNKNOWN>", sizeof(buf));
}
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DB, ISC_LOG_DEBUG(1),
"calling free_qpdb(%s)", buf);
free_qpdb(qpdb, true);
}
}
qpzonedb_detach(&qpdb);
}
static unsigned int
@ -3943,7 +3873,7 @@ locknode(dns_db_t *db, dns_dbnode_t *dbnode, isc_rwlocktype_t type) {
qpzonedb_t *qpdb = (qpzonedb_t *)db;
qpznode_t *node = (qpznode_t *)dbnode;
RWLOCK(&qpdb->node_locks[node->locknum].lock, type);
RWLOCK(&qpdb->node_locks[node->locknum], type);
}
static void
@ -3951,7 +3881,7 @@ unlocknode(dns_db_t *db, dns_dbnode_t *dbnode, isc_rwlocktype_t type) {
qpzonedb_t *qpdb = (qpzonedb_t *)db;
qpznode_t *node = (qpznode_t *)dbnode;
RWUNLOCK(&qpdb->node_locks[node->locknum].lock, type);
RWUNLOCK(&qpdb->node_locks[node->locknum], type);
}
static void
@ -3997,8 +3927,9 @@ rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
qpz_version_t *version = qrditer->common.version;
dns_slabheader_t *header = NULL, *top_next = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &qpdb->node_locks[node->locknum];
NODE_RDLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
NODE_RDLOCK(nlock, &nlocktype);
for (header = node->data; header != NULL; header = top_next) {
top_next = header->next;
@ -4019,7 +3950,7 @@ rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
}
}
NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
qrditer->current = header;
@ -4040,13 +3971,14 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
dns_typepair_t type, negtype;
dns_rdatatype_t rdtype;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &qpdb->node_locks[node->locknum];
header = qrditer->current;
if (header == NULL) {
return ISC_R_NOMORE;
}
NODE_RDLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
NODE_RDLOCK(nlock, &nlocktype);
type = header->type;
rdtype = DNS_TYPEPAIR_TYPE(header->type);
@ -4090,7 +4022,7 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
}
}
NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
qrditer->current = header;
@ -4109,16 +4041,17 @@ rdatasetiter_current(dns_rdatasetiter_t *iterator,
qpznode_t *node = qrditer->common.node;
dns_slabheader_t *header = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &qpdb->node_locks[node->locknum];
header = qrditer->current;
REQUIRE(header != NULL);
NODE_RDLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
NODE_RDLOCK(nlock, &nlocktype);
bindrdataset(qpdb, node, header, qrditer->common.now,
rdataset DNS__DB_FLARG_PASS);
NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
}
/*
@ -4140,18 +4073,19 @@ static void
dereference_iter_node(qpdb_dbiterator_t *iter DNS__DB_FLARG) {
qpzonedb_t *qpdb = (qpzonedb_t *)iter->common.db;
qpznode_t *node = iter->node;
isc_rwlock_t *lock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
if (node == NULL) {
return;
}
lock = &qpdb->node_locks[node->locknum].lock;
NODE_RDLOCK(lock, &nlocktype);
decref(qpdb, node, 0, &nlocktype DNS__DB_FLARG_PASS);
NODE_UNLOCK(lock, &nlocktype);
iter->node = NULL;
nlock = &qpdb->node_locks[node->locknum];
NODE_RDLOCK(nlock, &nlocktype);
decref(qpdb, node, 0, &nlocktype DNS__DB_FLARG_PASS);
NODE_UNLOCK(nlock, &nlocktype);
}
static void
@ -4568,6 +4502,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
isc_region_t region;
dns_slabheader_t *newheader = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
dns_fixedname_t fn;
dns_name_t *name = dns_fixedname_initname(&fn);
dns_qp_t *nsec = NULL;
@ -4646,7 +4581,9 @@ addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
* (Note: node lock must be acquired after starting
* the QPDB transaction and released before committing.)
*/
NODE_WRLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
nlock = &qpdb->node_locks[node->locknum];
NODE_WRLOCK(nlock, &nlocktype);
result = ISC_R_SUCCESS;
if (nsec != NULL) {
@ -4677,7 +4614,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
node->delegating = true;
}
NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
if (nsec != NULL) {
dns_qpmulti_commit(qpdb->nsec, &nsec);
@ -4702,6 +4639,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
isc_result_t result;
qpz_changed_t *changed = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock;
REQUIRE(VALID_QPZONE(qpdb));
REQUIRE(version != NULL && version->qpdb == qpdb);
@ -4746,7 +4684,8 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
newheader->resign_lsb = 0;
}
NODE_WRLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
nlock = &qpdb->node_locks[node->locknum];
NODE_WRLOCK(nlock, &nlocktype);
changed = add_changed(newheader, version DNS__DB_FLARG_PASS);
for (topheader = node->data; topheader != NULL;
@ -4872,7 +4811,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
}
unlock:
NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
return result;
}
@ -4887,6 +4826,7 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
isc_result_t result;
dns_slabheader_t *newheader = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
REQUIRE(VALID_QPZONE(qpdb));
REQUIRE(version != NULL && version->qpdb == qpdb);
@ -4906,10 +4846,11 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
dns_name_copy(&node->name, nodename);
NODE_WRLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
nlock = &qpdb->node_locks[node->locknum];
NODE_WRLOCK(nlock, &nlocktype);
result = add(qpdb, node, nodename, version, newheader, DNS_DBADD_FORCE,
false, NULL, 0 DNS__DB_FLARG_PASS);
NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
return result;
}
@ -4918,14 +4859,18 @@ nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name) {
qpzonedb_t *qpdb = (qpzonedb_t *)db;
qpznode_t *qpnode = (qpznode_t *)node;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
REQUIRE(VALID_QPZONE(qpdb));
REQUIRE(node != NULL);
REQUIRE(name != NULL);
NODE_RDLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
nlock = &qpdb->node_locks[qpnode->locknum];
NODE_RDLOCK(nlock, &nlocktype);
dns_name_copy(&qpnode->name, name);
NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
NODE_UNLOCK(nlock, &nlocktype);
return ISC_R_SUCCESS;
}
@ -5165,6 +5110,12 @@ ISC_REFCOUNT_STATIC_TRACE_IMPL(qpznode, destroy_qpznode);
ISC_REFCOUNT_STATIC_IMPL(qpznode, destroy_qpznode);
#endif
#ifdef DNS_DB_NODETRACE
ISC_REFCOUNT_STATIC_TRACE_IMPL(qpzonedb, qpzone_destroy);
#else
ISC_REFCOUNT_STATIC_IMPL(qpzonedb, qpzone_destroy);
#endif
static void
qp_attach(void *uctx ISC_ATTR_UNUSED, void *pval,
uint32_t ival ISC_ATTR_UNUSED) {

View file

@ -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));
}