dns_glue_t *glue;
} dns_glue_additionaldata_ctx_t;
-typedef struct {
- isc_rwlock_t lock;
- /* Protected in the refcount routines. */
- isc_refcount_t references;
- /* Locked by lock. */
- bool exiting;
-} db_nodelock_t;
-
static inline bool
prio_type(dns_typepair_t type) {
switch (type) {
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 */
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
*/
} qpc_dbit_t;
static void
-free_qpdb(qpcache_t *qpdb, bool log);
+qpcache__destroy(qpcache_t *qpdb);
static dns_dbmethods_t qpdb_cachemethods;
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
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;
}
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);
/* 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)) {
}
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);
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) {
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);
*/
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
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. */
result = DNS_R_CONTINUE;
}
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
return result;
}
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.
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. */
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)) {
}
}
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
if (found != NULL) {
break;
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;
}
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;
} else {
result = ISC_R_NOTFOUND;
}
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
return result;
}
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;
* 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
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. */
* 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,
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);
/*
* Go find the deepest zone cut.
*/
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
goto find_ns;
}
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)) {
update_header(search.qpdb, updatesig, search.now);
}
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
tree_exit:
TREE_UNLOCK(&search.qpdb->tree_lock, &tlocktype);
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);
}
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;
* 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))
{
/*
* 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);
/*
* 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);
(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)) {
}
}
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
tree_exit:
TREE_UNLOCK(&search.qpdb->tree_lock, &tlocktype);
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));
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);
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))
{
/*
}
}
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
if (found == NULL) {
return ISC_R_NOTFOUND;
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);
}
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,
{
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);
}
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;
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_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_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]);
}
/*
}
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);
static void
qpcache_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_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
- "calling free_qpdb(%s)", buf);
- free_qpdb(qpdb, true);
- }
- }
+ qpcache_detach(&qpdb);
}
static void
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;
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);
}
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 *
}
static void
-qpcache_detachnode(dns_db_t *db, dns_dbnode_t **targetp DNS__DB_FLARG) {
+qpcache_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(&nodelock->lock, &nlocktype);
- INSIST(tlocktype == isc_rwlocktype_none);
-
- *targetp = NULL;
+ NODE_UNLOCK(nlock, &nlocktype);
- 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_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
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;
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);
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);
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);
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;
}
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
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
.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
*/
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,
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]);
}
/*
qpcnode_t *qpnode = (qpcnode_t *)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;
}
}
- NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
iterator->current = header;
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;
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);
}
}
- NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
iterator->current = header;
qpcnode_t *qpnode = (qpcnode_t *)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);
}
/*
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;
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);
#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
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;
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
*/
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);
}
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;
}
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);
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_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_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DB,
+ ISC_LOG_DEBUG(1), "called %s(%s)", __func__, buf);
call_rcu(&qpdb->rcu_head, free_db_rcu);
}
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);
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_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_DB, ISC_LOG_DEBUG(1),
- "calling free_qpdb(%s)", buf);
- free_qpdb(qpdb, true);
- }
- }
+ qpzonedb_detach(&qpdb);
}
static qpznode_t *
.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;
}
*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;
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);
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]);
}
/*
if (result != ISC_R_SUCCESS) {
INSIST(result != ISC_R_EXISTS);
- free_qpdb(qpdb, false);
+ qpzonedb_detach(&qpdb);
return result;
}
if (result != ISC_R_SUCCESS) {
INSIST(result != ISC_R_EXISTS);
- free_qpdb(qpdb, false);
+ qpzonedb_detach(&qpdb);
return result;
}
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
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;
}
/* 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)) {
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 {
}
}
unlock:
- NODE_UNLOCK(&(qpdb->node_locks[node->locknum].lock), &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
}
static void
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)) {
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));
}
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);
}
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) {
}
}
- NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
if (close_version) {
closeversion(db, (dns_dbversion_t **)&version,
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);
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))
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);
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;
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;
}
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;
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;
}
result = ISC_R_SUCCESS;
}
RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
- NODE_UNLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
return result;
}
}
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) {
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) {
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 &&
break;
}
}
- NODE_UNLOCK(nodelock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
if (header != NULL) {
break;
}
*/
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
active = (header != NULL);
wild = node->wild;
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
if (wild) {
qpznode_t *wnode = NULL;
* 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)
{
break;
}
}
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
if (header != NULL ||
activeempty(search, &wit, wname))
{
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)
{
&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);
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.
}
}
- NODE_UNLOCK(&(search->qpdb->node_locks[node->locknum].lock),
- &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
return result;
}
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));
* 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) {
/*
if (header->type == dns_rdatatype_nsec3 &&
!matchparams(header, &search))
{
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
goto partial_match;
}
/*
if (!wild) {
unsigned int len = search.chain.len - 1;
if (len > 0) {
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
dns_qpchain_node(&search.chain, len - 1, NULL,
(void **)&node, NULL);
dns_name_copy(&node->name, foundname);
*
* Return the delegation.
*/
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
result = qpzone_setup_delegation(
&search, nodep, foundname, rdataset,
sigrdataset DNS__DB_FLARG_PASS);
goto node_exit;
}
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
result = find_closest_nsec(
&search, nodep, foundname, rdataset,
sigrdataset, false,
}
node_exit:
- NODE_UNLOCK(lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
tree_exit:
if (nsec3) {
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) {
}
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);
- 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);
+ qpzonedb_ref(qpdb);
- *targetp = NULL;
+ NODE_RDLOCK(nlock, &nlocktype);
+ decref(qpdb, node, 0, &nlocktype DNS__DB_FLARG_PASS);
+ NODE_UNLOCK(nlock, &nlocktype);
- 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_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_DB, ISC_LOG_DEBUG(1),
- "calling free_qpdb(%s)", buf);
- free_qpdb(qpdb, true);
- }
- }
+ qpzonedb_detach(&qpdb);
}
static unsigned int
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
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
qpz_version_t *version = (qpz_version_t *)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;
}
}
- NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
qrditer->current = header;
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);
}
}
- NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
qrditer->current = header;
qpznode_t *node = (qpznode_t *)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);
}
/*
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
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;
* (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) {
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);
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);
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;
}
unlock:
- NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
+ NODE_UNLOCK(nlock, &nlocktype);
return result;
}
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);
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;
}
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;
}
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) {
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,
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));
/* 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);
}
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,
/* 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));
/* 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));
}