From 7dab6cdfbc26bfa3aa37168c382563047d4dee95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Mon, 27 Jan 2025 21:07:11 +0100 Subject: [PATCH] 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 431513d8b3cc595a7612479fd7811e959501e6dd) --- lib/dns/qpcache.c | 336 ++++++++++++++++--------------------- lib/dns/qpzone.c | 355 +++++++++++++++++----------------------- tests/dns/qpzone_test.c | 12 +- 3 files changed, 296 insertions(+), 407 deletions(-) diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index 26e373aeb7..23b566bcd6 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -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, "", 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, "", 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, "", 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, "", 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 diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index 20f0efdf66..dc59100d61 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -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, "", 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, "", 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, "", 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, "", 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) { diff --git a/tests/dns/qpzone_test.c b/tests/dns/qpzone_test.c index a2d00814a3..eca1a70ed1 100644 --- a/tests/dns/qpzone_test.c +++ b/tests/dns/qpzone_test.c @@ -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)); }