*/
isc_refcount_t references;
isc_refcount_t erefs;
- void *data;
+
+ dns_slabtop_t *data;
/*%
* NOTE: The 'dirty' flag is protected by the node lock, so
typedef struct qpc_rditer {
dns_rdatasetiter_t common;
- dns_slabheader_t *current;
+ dns_slabtop_t *current;
} qpc_rditer_t;
static void
static void
clean_cache_node(qpcache_t *qpdb, qpcnode_t *node) {
- dns_slabheader_t *current = NULL, *top_prev = NULL, *top_next = NULL;
+ dns_slabtop_t *top = NULL, *top_prev = NULL, *top_next = NULL;
/*
* Caller must be holding the node lock.
*/
- for (current = node->data; current != NULL; current = top_next) {
- top_next = current->next;
- clean_stale_headers(current);
+ for (top = node->data; top != NULL; top = top_next) {
+ top_next = top->next;
+ clean_stale_headers(top->header);
+
/*
- * If current is nonexistent, ancient, or stale and
+ * If current header is nonexistent, ancient, or stale and
* we are not keeping stale, we can clean it up.
*/
- if (!EXISTS(current) || ANCIENT(current) ||
- (STALE(current) && !KEEPSTALE(qpdb)))
+ if (!EXISTS(top->header) || ANCIENT(top->header) ||
+ (STALE(top->header) && !KEEPSTALE(qpdb)))
{
+ dns_slabheader_destroy(&top->header);
+ }
+
+ /*
+ * If current slabtype is empty, we can also clean it up.
+ */
+ if (top->header == NULL) {
if (top_prev != NULL) {
- top_prev->next = current->next;
+ top_prev->next = top->next;
} else {
- node->data = current->next;
+ node->data = top->next;
}
- dns_slabheader_destroy(¤t);
+ dns_slabtop_destroy(((dns_db_t *)qpdb)->mctx, &top);
} else {
- top_prev = current;
+ top_prev = top;
}
}
node->dirty = 0;
}
static bool
-check_stale_header(dns_slabheader_t *header, qpc_search_t *search,
- dns_slabheader_t **header_prev) {
+check_stale_header(dns_slabheader_t *header, qpc_search_t *search) {
if (ACTIVE(header, search->now)) {
- *header_prev = header;
return false;
}
if (!ZEROTTL(header) && KEEPSTALE(search->qpdb) && stale > search->now)
{
mark(header, DNS_SLABHEADERATTR_STALE);
- *header_prev = header;
/*
* If DNS_DBFIND_STALESTART is set then it means we
* failed to resolve the name during recursion, in
return (search->options & DNS_DBFIND_STALEOK) == 0;
}
- *header_prev = header;
return true;
}
static isc_result_t
check_zonecut(qpcnode_t *node, void *arg DNS__DB_FLARG) {
qpc_search_t *search = arg;
- dns_slabheader_t *header = NULL;
- dns_slabheader_t *header_prev = NULL, *header_next = NULL;
+ dns_slabtop_t *top = NULL;
dns_slabheader_t *found = NULL, *foundsig = NULL;
isc_result_t result;
isc_rwlock_t *nlock = NULL;
/*
* 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(header, search, &header_prev)) {
+ for (top = node->data; top != NULL; top = top->next) {
+ if (check_stale_header(top->header, search)) {
continue;
}
- if (both_headers(header, dns_rdatatype_dname, &found,
+ if (both_headers(top->header, dns_rdatatype_dname, &found,
&foundsig))
{
break;
qpdb = search->qpdb;
for (int i = dns_qpchain_length(&search->chain) - 1; i >= 0; i--) {
- dns_slabheader_t *header = NULL;
- dns_slabheader_t *header_prev = NULL, *header_next = NULL;
+ dns_slabtop_t *top = NULL;
dns_slabheader_t *found = NULL, *foundsig = NULL;
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
/*
* Look for NS and RRSIG NS rdatasets.
*/
- for (header = node->data; header != NULL; header = header_next)
- {
- header_next = header->next;
- if (check_stale_header(header, search, &header_prev)) {
+ for (top = node->data; top != NULL; top = top->next) {
+ if (check_stale_header(top->header, search)) {
continue;
}
- if (both_headers(header, dns_rdatatype_ns, &found,
+ if (both_headers(top->header, dns_rdatatype_ns, &found,
&foundsig))
{
break;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
dns_slabheader_t *found = NULL, *foundsig = NULL;
- dns_slabheader_t *header = NULL;
- dns_slabheader_t *header_next = NULL, *header_prev = NULL;
+ dns_slabtop_t *top = NULL;
/*
* Look for the node in the auxilary tree.
nlock = &search->qpdb->buckets[node->locknum].lock;
NODE_RDLOCK(nlock, &nlocktype);
- for (header = node->data; header != NULL; header = header_next) {
- header_next = header->next;
- if (check_stale_header(header, search, &header_prev)) {
+ for (top = node->data; top != NULL; top = top->next) {
+ if (check_stale_header(top->header, search)) {
continue;
}
- if (both_headers(header, dns_rdatatype_nsec, &found, &foundsig))
+ if (both_headers(top->header, dns_rdatatype_nsec, &found,
+ &foundsig))
{
break;
}
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
- dns_slabheader_t *header = NULL;
- dns_slabheader_t *header_prev = NULL, *header_next = NULL;
+ dns_slabtop_t *top = NULL;
dns_slabheader_t *found = NULL, *nsheader = NULL;
dns_slabheader_t *foundsig = NULL, *nssig = NULL, *cnamesig = NULL;
dns_slabheader_t *nsecheader = NULL, *nsecsig = NULL;
nsecsig = NULL;
cnamesig = NULL;
empty_node = true;
- header_prev = NULL;
- for (header = node->data; header != NULL; header = header_next) {
- header_next = header->next;
- if (check_stale_header(header, &search, &header_prev)) {
+ for (top = node->data; top != NULL; top = top->next) {
+ if (check_stale_header(top->header, &search)) {
continue;
}
- if (!EXISTS(header) || ANCIENT(header)) {
+ if (!EXISTS(top->header) || ANCIENT(top->header)) {
continue;
}
*/
empty_node = false;
- if (header->noqname != NULL &&
- header->trust == dns_trust_secure)
+ if (top->header->noqname != NULL &&
+ top->header->trust == dns_trust_secure)
{
found_noqname = true;
}
- if (!NEGATIVE(header)) {
+ if (!NEGATIVE(top->header)) {
all_negative = false;
}
bool match = false;
- if (related_headers(header, typepair, sigpair, &found,
+ if (related_headers(top->header, typepair, sigpair, &found,
&foundsig, &match) &&
!MISSING_ANSWER(found, options))
{
continue;
}
- if (NEGATIVE(header)) {
+ if (NEGATIVE(top->header)) {
/*
* FIXME: As of now, we are not interested in
* the negative headers. This could be
continue;
}
- switch (header->typepair) {
+ switch (top->typepair) {
case dns_rdatatype_cname:
if (!cname_ok) {
break;
}
- found = header;
+ found = top->header;
if (cnamesig != NULL) {
/* We already have CNAME signature */
foundsig = cnamesig;
break;
}
- cnamesig = header;
+ cnamesig = top->header;
break;
case dns_rdatatype_ns:
/* Remember the NS rdataset */
- nsheader = header;
+ nsheader = top->header;
break;
case DNS_SIGTYPEPAIR(dns_rdatatype_ns):
/* ...and its signature */
- nssig = header;
+ nssig = top->header;
break;
case dns_rdatatype_nsec:
- nsecheader = header;
+ nsecheader = top->header;
break;
case DNS_SIGTYPEPAIR(dns_rdatatype_nsec):
- nsecsig = header;
+ nsecsig = top->header;
break;
default:
if (typepair == dns_typepair_any) {
/* QTYPE==ANY, so any anwers will do */
- found = header;
+ found = top->header;
break;
}
}
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
dns_name_t *foundname, dns_name_t *dcname,
isc_rwlocktype_t *tlocktype) {
- dns_slabheader_t *header = NULL;
- dns_slabheader_t *header_prev = NULL, *header_next = NULL;
+ dns_slabtop_t *top = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &search->qpdb->buckets[node->locknum].lock;
dns_slabheader_t *found = NULL, *foundsig = NULL;
NODE_RDLOCK(nlock, &nlocktype);
- for (header = node->data; header != NULL; header = header_next) {
- header_next = header->next;
- bool ns = header->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) ||
- header->typepair == DNS_SIGTYPEPAIR(dns_rdatatype_ns);
- if (check_stale_header(header, search, &header_prev)) {
+ for (top = node->data; top != NULL; top = top->next) {
+ bool ns = top->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) ||
+ top->typepair == DNS_SIGTYPEPAIR(dns_rdatatype_ns);
+ if (check_stale_header(top->header, search)) {
if (ns) {
/*
* We found a cached NS, but was either
continue;
}
- if (both_headers(header, dns_rdatatype_ns, &found, &foundsig)) {
+ if (both_headers(top->header, dns_rdatatype_ns, &found,
+ &foundsig))
+ {
break;
}
}
dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
qpcache_t *qpdb = (qpcache_t *)db;
qpcnode_t *qpnode = (qpcnode_t *)node;
- dns_slabheader_t *header = NULL;
- dns_slabheader_t *header_prev = NULL, *header_next = NULL;
+ dns_slabtop_t *top = NULL;
dns_slabheader_t *found = NULL, *foundsig = NULL;
dns_typepair_t typepair, sigpair;
isc_result_t result = ISC_R_SUCCESS;
sigpair = !dns_rdatatype_issig(type) ? DNS_SIGTYPEPAIR(type)
: dns_typepair_none;
- for (header = qpnode->data; header != NULL; header = header_next) {
- header_next = header->next;
-
- if (check_stale_header(header, &search, &header_prev)) {
+ for (top = qpnode->data; top != NULL; top = top->next) {
+ if (check_stale_header(top->header, &search)) {
continue;
}
- if (related_headers(header, typepair, sigpair, &found,
+ if (related_headers(top->header, typepair, sigpair, &found,
&foundsig, NULL))
{
break;
}
static bool
-prio_header(dns_slabheader_t *header) {
- return prio_type(header->typepair);
+prio_header(dns_slabtop_t *top) {
+ return prio_type(top->typepair);
}
static void
}
static isc_result_t
-add(qpcache_t *qpdb, qpcnode_t *qpnode,
- const dns_name_t *nodename ISC_ATTR_UNUSED, dns_slabheader_t *newheader,
+add(qpcache_t *qpdb, qpcnode_t *qpnode, dns_slabheader_t *newheader,
unsigned int options, dns_rdataset_t *addedrdataset, isc_stdtime_t now,
isc_rwlocktype_t nlocktype, isc_rwlocktype_t tlocktype DNS__DB_FLARG) {
- dns_slabheader_t *topheader = NULL, *topheader_prev = NULL;
+ dns_slabtop_t *top = NULL;
+ dns_slabtop_t *priotop = NULL, *expiretop = NULL;
dns_slabheader_t *header = NULL, *sigheader = NULL;
- dns_slabheader_t *prioheader = NULL, *expireheader = NULL;
dns_trust_t trust;
uint32_t ntypes = 0;
dns_rdatatype_t rdtype = DNS_TYPEPAIR_TYPE(newheader->typepair);
* only rdataset that can be found at this
* node is the negative cache entry.
*/
- for (topheader = qpnode->data;
- topheader != NULL;
- topheader = topheader->next)
+ for (top = qpnode->data; top != NULL;
+ top = top->next)
{
- mark_ancient(topheader);
+ mark_ancient(top->header);
}
goto find_header;
}
* Otherwise look for any RRSIGs of the given
* type so they can be marked ancient later.
*/
- for (topheader = qpnode->data; topheader != NULL;
- topheader = topheader->next)
- {
- if (topheader->typepair == sigpair) {
- sigheader = topheader;
+ for (top = qpnode->data; top != NULL; top = top->next) {
+ if (top->typepair == sigpair) {
+ sigheader = top->header;
break;
}
}
* We're adding something that isn't a
* negative cache entry.
*/
- for (topheader = qpnode->data; topheader != NULL;
- topheader = topheader->next)
- {
+ for (top = qpnode->data; top != NULL; top = top->next) {
/*
* Look for any existing negative cache
* entries.
*/
- if (!NEGATIVE(topheader)) {
+ if (!NEGATIVE(top->header)) {
continue;
}
* If we find a cached NXDOMAIN, don't
* cache anything else.
*/
- if (topheader->typepair == dns_typepair_any) {
+ if (top->typepair == dns_typepair_any) {
break;
}
* for which we have a cached NODATA record.
*/
if (newheader->typepair == sigpair &&
- DNS_TYPEPAIR_TYPE(topheader->typepair) ==
- covers)
+ DNS_TYPEPAIR_TYPE(top->typepair) == covers)
{
break;
}
}
- if (topheader != NULL && EXISTS(topheader) &&
- ACTIVE(topheader, now))
+ if (top != NULL && EXISTS(top->header) &&
+ ACTIVE(top->header, now))
{
/*
* Found one.
*/
- if (trust < topheader->trust) {
+ if (trust < top->header->trust) {
/*
* The NXDOMAIN/NODATA(QTYPE=ANY)
* is more trusted.
*/
if (addedrdataset != NULL) {
bindrdataset(
- qpdb, qpnode, topheader,
- now, nlocktype,
- tlocktype,
+ qpdb, qpnode,
+ top->header, now,
+ nlocktype, tlocktype,
addedrdataset
DNS__DB_FLARG_PASS);
}
* The new rdataset is better. Expire the
* ncache entry.
*/
- mark_ancient(topheader);
- topheader = NULL;
+ mark_ancient(top->header);
+ top = NULL;
goto find_header;
}
}
}
- for (topheader = qpnode->data; topheader != NULL;
- topheader = topheader->next)
- {
- if (ACTIVE(topheader, now)) {
+ for (top = qpnode->data; top != NULL; top = top->next) {
+ if (ACTIVE(top->header, now)) {
++ntypes;
- expireheader = topheader;
+ expiretop = top;
}
- if (prio_header(topheader)) {
- prioheader = topheader;
+ if (prio_header(top)) {
+ priotop = top;
}
- if (topheader->typepair == newheader->typepair) {
+ if (top->typepair == newheader->typepair) {
break;
}
- topheader_prev = topheader;
}
find_header:
/*
- * If header isn't NULL, we've found the right type.
+ * If top isn't NULL, we've found the right type.
*/
- header = topheader;
- if (header != NULL) {
+ if (top != NULL) {
+ header = top->header;
/*
* Deleting an already non-existent rdataset has no effect.
*/
* normally further down.
*/
if (ACTIVE(header, now) &&
- header->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) &&
+ top->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) &&
EXISTS(header) && EXISTS(newheader) &&
header->trust >= newheader->trust &&
dns_rdataslab_equalx(header, newheader,
qpdb->common.rdclass,
- DNS_TYPEPAIR_TYPE(header->typepair)))
+ DNS_TYPEPAIR_TYPE(top->typepair)))
{
/*
* Honour the new ttl if it is less than the
* ensures the delegations that are withdrawn are honoured.
*/
if (ACTIVE(header, now) &&
- header->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) &&
+ top->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) &&
EXISTS(header) && EXISTS(newheader) &&
header->trust <= newheader->trust)
{
}
if (ACTIVE(header, now) &&
(options & DNS_DBADD_PREFETCH) == 0 &&
- (header->typepair == DNS_TYPEPAIR(dns_rdatatype_a) ||
- header->typepair == DNS_TYPEPAIR(dns_rdatatype_aaaa) ||
- header->typepair == DNS_TYPEPAIR(dns_rdatatype_ds) ||
- header->typepair == DNS_SIGTYPEPAIR(dns_rdatatype_ds)) &&
+ (top->typepair == DNS_TYPEPAIR(dns_rdatatype_a) ||
+ top->typepair == DNS_TYPEPAIR(dns_rdatatype_aaaa) ||
+ top->typepair == DNS_TYPEPAIR(dns_rdatatype_ds) ||
+ top->typepair == DNS_SIGTYPEPAIR(dns_rdatatype_ds)) &&
EXISTS(header) && EXISTS(newheader) &&
header->trust >= newheader->trust &&
dns_rdataslab_equal(header, newheader))
qpcache_miss(qpdb, newheader, &nlocktype,
&tlocktype DNS__DB_FLARG_PASS);
- if (topheader_prev != NULL) {
- topheader_prev->next = newheader;
- } else {
- qpnode->data = newheader;
- }
- newheader->next = topheader->next;
- newheader->down = topheader;
- topheader->next = newheader;
+ top->header = newheader;
+ newheader->top = top;
+ newheader->down = header;
+
mark_ancient(header);
if (sigheader != NULL) {
mark_ancient(sigheader);
/* No rdatasets of the given type exist at the node. */
INSIST(newheader->down == NULL);
+ dns_slabtop_t *newtop = dns_slabtop_new(
+ ((dns_db_t *)qpdb)->mctx, newheader->typepair);
qpcache_miss(qpdb, newheader, &nlocktype,
&tlocktype DNS__DB_FLARG_PASS);
- if (prio_header(newheader)) {
+
+ newtop->header = newheader;
+ newheader->top = newtop;
+
+ if (prio_header(newtop)) {
/* This is a priority type, prepend it */
- newheader->next = qpnode->data;
- qpnode->data = newheader;
- } else if (prioheader != NULL) {
+ newtop->next = qpnode->data;
+ qpnode->data = newtop;
+ } else if (priotop != NULL) {
/* Append after the priority headers */
- newheader->next = prioheader->next;
- prioheader->next = newheader;
+ newtop->next = priotop->next;
+ priotop->next = newtop;
} else {
/* There were no priority headers */
- newheader->next = qpnode->data;
- qpnode->data = newheader;
+ newtop->next = qpnode->data;
+ qpnode->data = newtop;
}
if (overmaxtype(qpdb, ntypes)) {
- if (expireheader == NULL) {
- expireheader = newheader;
+ if (expiretop == NULL) {
+ expiretop = newtop;
}
- if (NEGATIVE(newheader) && !prio_header(newheader)) {
+ if (NEGATIVE(newheader) && !prio_header(newtop)) {
/*
* Add the new non-priority negative
* header to the database only
* temporarily.
*/
- expireheader = newheader;
+ expiretop = newtop;
}
- mark_ancient(expireheader);
+ mark_ancient(expiretop->header);
/*
* FIXME: In theory, we should mark the RRSIG
* and the header at the same time, but there is
qpnode->havensec = true;
}
- result = add(qpdb, qpnode, name, newheader, options, addedrdataset, now,
+ result = add(qpdb, qpnode, newheader, options, addedrdataset, now,
nlocktype, tlocktype DNS__DB_FLARG_PASS);
if (result == ISC_R_SUCCESS) {
nlock = &qpdb->buckets[qpnode->locknum].lock;
NODE_WRLOCK(nlock, &nlocktype);
- result = add(qpdb, qpnode, NULL, newheader, DNS_DBADD_FORCE, NULL, 0,
+ result = add(qpdb, qpnode, newheader, DNS_DBADD_FORCE, NULL, 0,
nlocktype, isc_rwlocktype_none DNS__DB_FLARG_PASS);
if (result != ISC_R_SUCCESS) {
dns_slabheader_destroy(&newheader);
qpc_rditer_t *iterator = (qpc_rditer_t *)it;
qpcache_t *qpdb = (qpcache_t *)(iterator->common.db);
qpcnode_t *qpnode = (qpcnode_t *)iterator->common.node;
- dns_slabheader_t *header = NULL;
+ dns_slabtop_t *top = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &qpdb->buckets[qpnode->locknum].lock;
NODE_RDLOCK(nlock, &nlocktype);
- for (header = qpnode->data; header != NULL; header = header->next) {
- if ((EXPIREDOK(iterator) && EXISTS(header)) ||
- iterator_active(qpdb, iterator, header))
+ for (top = qpnode->data; top != NULL; top = top->next) {
+ if ((EXPIREDOK(iterator) && EXISTS(top->header)) ||
+ iterator_active(qpdb, iterator, top->header))
{
break;
}
NODE_UNLOCK(nlock, &nlocktype);
- iterator->current = header;
+ iterator->current = top;
- if (header == NULL) {
+ if (top == NULL) {
return ISC_R_NOMORE;
}
qpc_rditer_t *iterator = (qpc_rditer_t *)it;
qpcache_t *qpdb = (qpcache_t *)(iterator->common.db);
qpcnode_t *qpnode = (qpcnode_t *)iterator->common.node;
- dns_slabheader_t *header = NULL;
+ dns_slabtop_t *top = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &qpdb->buckets[qpnode->locknum].lock;
- header = iterator->current;
- if (header == NULL) {
+ top = iterator->current;
+ if (top == NULL) {
return ISC_R_NOMORE;
}
NODE_RDLOCK(nlock, &nlocktype);
- for (header = header->next; header != NULL; header = header->next) {
- if ((EXPIREDOK(iterator) && EXISTS(header)) ||
- iterator_active(qpdb, iterator, header))
+ for (top = top->next; top != NULL; top = top->next) {
+ if ((EXPIREDOK(iterator) && EXISTS(top->header)) ||
+ iterator_active(qpdb, iterator, top->header))
{
break;
}
NODE_UNLOCK(nlock, &nlocktype);
- iterator->current = header;
+ iterator->current = top;
- if (header == NULL) {
+ if (top == NULL) {
return ISC_R_NOMORE;
}
qpc_rditer_t *iterator = (qpc_rditer_t *)it;
qpcache_t *qpdb = (qpcache_t *)(iterator->common.db);
qpcnode_t *qpnode = (qpcnode_t *)iterator->common.node;
- dns_slabheader_t *header = NULL;
+ dns_slabtop_t *top = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &qpdb->buckets[qpnode->locknum].lock;
- header = iterator->current;
- REQUIRE(header != NULL);
+ top = iterator->current;
+ REQUIRE(top != NULL);
NODE_RDLOCK(nlock, &nlocktype);
- bindrdataset(qpdb, qpnode, header, iterator->common.now, nlocktype,
+ bindrdataset(qpdb, qpnode, top->header, iterator->common.now, nlocktype,
isc_rwlocktype_none, rdataset DNS__DB_FLARG_PASS);
NODE_UNLOCK(nlock, &nlocktype);
qpcnode_deletedata(dns_dbnode_t *node ISC_ATTR_UNUSED, void *data) {
dns_slabheader_t *header = data;
qpcache_t *qpdb = HEADERNODE(header)->qpdb;
-
int idx = HEADERNODE(header)->locknum;
if (header->heap != NULL && header->heap_index != 0) {
isc_heap_delete(header->heap, header->heap_index);
}
+ /*
+ * This place is the only place where we actually need header->typepair.
+ */
update_rrsetstats(qpdb->rrsetstats, header->typepair,
atomic_load_acquire(&header->attributes), false);
};
static void
-qpcnode_destroy(qpcnode_t *data) {
- dns_slabheader_t *current = NULL, *next = NULL;
-
- for (current = data->data; current != NULL; current = next) {
- dns_slabheader_t *down = current->down, *down_next = NULL;
+qpcnode_destroy(qpcnode_t *qpnode) {
+ dns_slabtop_t *top = NULL, *top_next = NULL;
+ dns_db_t *db = (dns_db_t *)qpnode->qpdb;
- next = current->next;
+ for (top = qpnode->data; top != NULL; top = top_next) {
+ top_next = top->next;
- for (down = current->down; down != NULL; down = down_next) {
+ dns_slabheader_t *down = NULL, *down_next = NULL;
+ for (down = top->header; down != NULL; down = down_next) {
down_next = down->down;
dns_slabheader_destroy(&down);
}
+ top->header = NULL;
- dns_slabheader_destroy(¤t);
+ dns_slabtop_destroy(db->mctx, &top);
}
- dns_name_free(&data->name, data->mctx);
- isc_mem_putanddetach(&data->mctx, data, sizeof(qpcnode_t));
+ dns_name_free(&qpnode->name, qpnode->mctx);
+ isc_mem_putanddetach(&qpnode->mctx, qpnode, sizeof(qpcnode_t));
}
#ifdef DNS_DB_NODETRACE
atomic_bool wild;
atomic_bool delegating;
atomic_bool dirty;
- void *data;
+ dns_slabtop_t *data;
};
struct qpzonedb {
typedef struct qpdb_rdatasetiter {
dns_rdatasetiter_t common;
+ dns_slabtop_t *currenttop;
dns_slabheader_t *current;
} qpdb_rdatasetiter_t;
static void
clean_zone_node(qpznode_t *node, uint32_t least_serial) {
- dns_slabheader_t *current = NULL, *dcurrent = NULL;
- dns_slabheader_t *dcurrent_down = NULL, *dparent = NULL;
- dns_slabheader_t *top_prev = NULL, *top_next = NULL;
+ dns_slabtop_t *top = NULL, *top_prev = NULL, *top_next = NULL;
bool still_dirty = false;
+ dns_db_t *db = (dns_db_t *)node->qpdb;
/*
* Caller must be holding the node lock.
*/
REQUIRE(least_serial != 0);
- for (current = node->data; current != NULL; current = top_next) {
- top_next = current->next;
+ for (top = node->data; top != NULL; top = top_next) {
+ top_next = top->next;
+
+ INSIST(top->header != NULL);
/*
* First, we clean up any instances of multiple rdatasets
* with the same serial number, or that have the IGNORE
* attribute.
*/
- dparent = current;
- for (dcurrent = current->down; dcurrent != NULL;
+ dns_slabheader_t *dcurrent = NULL;
+ dns_slabheader_t *dcurrent_down = NULL, *dparent = NULL;
+
+ dparent = top->header;
+ for (dcurrent = dparent->down; dcurrent != NULL;
dcurrent = dcurrent_down)
{
dcurrent_down = dcurrent->down;
if (dcurrent->serial == dparent->serial ||
IGNORE(dcurrent))
{
- if (dcurrent_down != NULL) {
- dcurrent_down->up = dparent;
- }
dparent->down = dcurrent_down;
dns_slabheader_destroy(&dcurrent);
} else {
* We've now eliminated all IGNORE datasets with the possible
* exception of current, which we now check.
*/
- dcurrent = current;
+ dcurrent = top->header;
if (IGNORE(dcurrent)) {
- dcurrent_down = current->down;
- if (dcurrent_down == NULL) {
- if (top_prev != NULL) {
- top_prev->next = current->next;
- } else {
- node->data = current->next;
- }
- dns_slabheader_destroy(¤t);
- /*
- * current no longer exists, so we can
- * just continue with the loop.
- */
- continue;
- } else {
- /*
- * Pull up current->down, making it the new
- * current.
- */
- if (top_prev != NULL) {
- top_prev->next = dcurrent_down;
- } else {
- node->data = dcurrent_down;
- }
- dcurrent_down->next = top_next;
- dns_slabheader_destroy(¤t);
- current = dcurrent_down;
- }
+ top->header = dcurrent->down;
+ dns_slabheader_destroy(&dcurrent);
+ }
+
+ if (top->header == NULL) {
+ goto empty;
}
/*
- * We now try to find the first down node less than the
- * least serial.
+ * We now try to find the first down node less than the least
+ * serial, and if there are such rdatasets, delete it and any
+ * older versions.
*/
- dparent = current;
- for (dcurrent = current->down; dcurrent != NULL;
+ dparent = top->header;
+ for (dcurrent = dparent->down; dcurrent != NULL;
dcurrent = dcurrent_down)
{
dcurrent_down = dcurrent->down;
if (dcurrent->serial < least_serial) {
- break;
- }
- dparent = dcurrent;
- }
-
- /*
- * If there is a such an rdataset, delete it and any older
- * versions.
- */
- if (dcurrent != NULL) {
- do {
- dcurrent_down = dcurrent->down;
- INSIST(dcurrent->serial <= least_serial);
+ dparent->down = dcurrent_down;
dns_slabheader_destroy(&dcurrent);
- dcurrent = dcurrent_down;
- } while (dcurrent != NULL);
- dparent->down = NULL;
+ } else {
+ dparent = dcurrent;
+ }
}
- /*
- * Note. The serial number of 'current' might be less than
- * least_serial too, but we cannot delete it because it is
- * the most recent version.
- */
- if (current->down != NULL) {
+ if (top->header == NULL) {
+ empty:
+ if (top_prev != NULL) {
+ top_prev->next = top->next;
+ } else {
+ node->data = top->next;
+ }
+ dns_slabtop_destroy(db->mctx, &top);
+ } else {
+ /*
+ * Note. The serial number of 'current' might be less
+ * than least_serial too, but we cannot delete it
+ * because it is the most recent version.
+ */
still_dirty = true;
+ top_prev = top;
}
- top_prev = current;
}
if (!still_dirty) {
node->dirty = false;
setnsec3parameters(dns_db_t *db, qpz_version_t *version) {
qpznode_t *node = NULL;
dns_rdata_nsec3param_t nsec3param;
- dns_rdata_t rdata = DNS_RDATA_INIT;
isc_region_t region;
isc_result_t result;
- dns_slabheader_t *header = NULL, *header_next = NULL;
+ dns_slabtop_t *top = NULL;
unsigned char *raw; /* RDATASLAB */
unsigned int count, length;
qpzonedb_t *qpdb = (qpzonedb_t *)db;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
+ dns_slabheader_t *found = NULL;
version->havensec3 = false;
node = qpdb->origin;
nlock = qpzone_get_lock(node);
+
NODE_RDLOCK(nlock, &nlocktype);
- for (header = node->data; header != NULL; header = header_next) {
- header_next = header->next;
- do {
- if (header->serial <= version->serial &&
- !IGNORE(header))
- {
- if (!EXISTS(header)) {
- header = NULL;
- }
- break;
- } else {
- header = header->down;
- }
- } while (header != NULL);
- if (header != NULL &&
- (header->typepair == dns_rdatatype_nsec3param))
+ top = node->data;
+ while (top != NULL && top->typepair != dns_rdatatype_nsec3param) {
+ top = top->next;
+ }
+ if (top != NULL) {
+ dns_slabheader_t *header = top->header;
+ while (header != NULL &&
+ (IGNORE(header) || header->serial > version->serial))
{
- /*
- * Find an NSEC3PARAM with a supported algorithm.
- */
- raw = dns_slabheader_raw(header);
- count = raw[0] * 256 + raw[1]; /* count */
+ header = header->down;
+ }
+
+ if (header != NULL && EXISTS(header)) {
+ found = header;
+ }
+ }
+
+ if (found != NULL) {
+ /*
+ * Find an NSEC3PARAM with a supported algorithm.
+ */
+ raw = dns_slabheader_raw(found);
+ count = raw[0] * 256 + raw[1]; /* count */
+ raw += DNS_RDATASET_LENGTH;
+ while (count-- > 0U) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ length = raw[0] * 256 + raw[1];
raw += DNS_RDATASET_LENGTH;
- while (count-- > 0U) {
- length = raw[0] * 256 + raw[1];
- raw += DNS_RDATASET_LENGTH;
- region.base = raw;
- region.length = length;
- raw += length;
- dns_rdata_fromregion(
- &rdata, qpdb->common.rdclass,
- dns_rdatatype_nsec3param, ®ion);
- result = dns_rdata_tostruct(&rdata, &nsec3param,
- NULL);
- INSIST(result == ISC_R_SUCCESS);
- dns_rdata_reset(&rdata);
+ region.base = raw;
+ region.length = length;
+ raw += length;
+ dns_rdata_fromregion(&rdata, qpdb->common.rdclass,
+ dns_rdatatype_nsec3param, ®ion);
+ result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+ INSIST(result == ISC_R_SUCCESS);
- if (nsec3param.hash != DNS_NSEC3_UNKNOWNALG &&
- !dns_nsec3_supportedhash(nsec3param.hash))
- {
- continue;
- }
+ if (nsec3param.hash != DNS_NSEC3_UNKNOWNALG &&
+ !dns_nsec3_supportedhash(nsec3param.hash))
+ {
+ continue;
+ }
- if (nsec3param.flags != 0) {
- continue;
- }
+ if (nsec3param.flags != 0) {
+ continue;
+ }
- memmove(version->salt, nsec3param.salt,
- nsec3param.salt_length);
- version->hash = nsec3param.hash;
- version->salt_length = nsec3param.salt_length;
- version->iterations = nsec3param.iterations;
- version->flags = nsec3param.flags;
- version->havensec3 = true;
- /*
- * Look for a better algorithm than the
- * unknown test algorithm.
- */
- if (nsec3param.hash != DNS_NSEC3_UNKNOWNALG) {
- goto unlock;
- }
+ memmove(version->salt, nsec3param.salt,
+ nsec3param.salt_length);
+ version->hash = nsec3param.hash;
+ version->salt_length = nsec3param.salt_length;
+ version->iterations = nsec3param.iterations;
+ version->flags = nsec3param.flags;
+ version->havensec3 = true;
+ /*
+ * Look for a better algorithm than the
+ * unknown test algorithm.
+ */
+ if (nsec3param.hash != DNS_NSEC3_UNKNOWNALG) {
+ goto unlock;
}
}
}
static void
rollback_node(qpznode_t *node, uint32_t serial) {
- dns_slabheader_t *header = NULL, *dcurrent = NULL;
+ dns_slabtop_t *top = NULL;
bool make_dirty = false;
/*
* 'serial'. When the reference count goes to zero, these rdatasets
* will be cleaned up; until that time, they will be ignored.
*/
- for (header = node->data; header != NULL; header = header->next) {
+ for (top = node->data; top != NULL; top = top->next) {
+ dns_slabheader_t *header = top->header;
+
if (header->serial == serial) {
DNS_SLABHEADER_SETATTR(header,
DNS_SLABHEADERATTR_IGNORE);
make_dirty = true;
}
- for (dcurrent = header->down; dcurrent != NULL;
- dcurrent = dcurrent->down)
+
+ for (header = header->down; header != NULL;
+ header = header->down)
{
- if (dcurrent->serial == serial) {
+ if (header->serial == serial) {
DNS_SLABHEADER_SETATTR(
- dcurrent, DNS_SLABHEADERATTR_IGNORE);
+ header, DNS_SLABHEADERATTR_IGNORE);
make_dirty = true;
}
}
dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
qpzonedb_t *qpdb = (qpzonedb_t *)db;
qpznode_t *node = (qpznode_t *)dbnode;
- dns_slabheader_t *header = NULL, *header_next = NULL;
+ dns_slabtop_t *top = NULL;
dns_slabheader_t *found = NULL, *foundsig = NULL;
uint32_t serial;
qpz_version_t *version = (qpz_version_t *)dbversion;
sigpair = dns_typepair_none;
}
- for (header = node->data; header != NULL; header = header_next) {
- header_next = header->next;
+ for (top = node->data; top != NULL; top = top->next) {
+ dns_slabheader_t *header = top->header;
do {
if (header->serial <= serial && !IGNORE(header)) {
if (!EXISTS(header)) {
* We have an active, extant rdataset. If it's a
* type we're looking for, remember it.
*/
- if (header->typepair == typepair) {
+ if (top->typepair == typepair) {
found = header;
if (foundsig != NULL) {
break;
}
- } else if (header->typepair == sigpair) {
+ } else if (top->typepair == sigpair) {
foundsig = header;
if (found != NULL) {
break;
static bool
delegating_type(qpzonedb_t *qpdb, qpznode_t *node, dns_typepair_t typepair) {
- return typepair == dns_rdatatype_dname ||
- (typepair == dns_rdatatype_ns &&
+ return typepair == DNS_TYPEPAIR(dns_rdatatype_dname) ||
+ (typepair == DNS_TYPEPAIR(dns_rdatatype_ns) &&
(node != qpdb->origin || IS_STUB(qpdb)));
}
static bool
cname_and_other(qpznode_t *node, uint32_t serial) {
- dns_slabheader_t *header = NULL, *header_next = NULL;
bool cname = false, other = false;
dns_rdatatype_t rdtype;
+ dns_slabtop_t *top = NULL;
/*
* Look for CNAME and "other data" rdatasets active in our version.
* ("Other data" is any rdataset whose type is not KEY, NSEC, SIG
* or RRSIG.
*/
- for (header = node->data; header != NULL; header = header_next) {
- header_next = header->next;
+ for (top = node->data; top != NULL; top = top->next) {
+ dns_slabheader_t *header = top->header;
- rdtype = DNS_TYPEPAIR_TYPE(header->typepair);
+ rdtype = DNS_TYPEPAIR_TYPE(top->typepair);
if (rdtype == dns_rdatatype_cname) {
do {
if (header->serial <= serial && !IGNORE(header))
header = header->down;
} while (header != NULL);
if (header != NULL) {
- if (!prio_type(header->typepair)) {
+ if (!prio_type(rdtype)) {
/*
* CNAME is in the priority list, so if
* we are done with priority types, we
bool loading, dns_rdataset_t *addedrdataset,
isc_stdtime_t now ISC_ATTR_UNUSED DNS__DB_FLARG) {
qpz_changed_t *changed = NULL;
- dns_slabheader_t *topheader = NULL, *topheader_prev = NULL;
- dns_slabheader_t *prioheader = NULL;
- dns_slabheader_t *header = NULL;
+ dns_slabtop_t *top = NULL;
+ dns_slabtop_t *priotop = NULL;
dns_slabheader_t *merged = NULL;
isc_result_t result;
bool merge = false;
}
ntypes = 0;
- for (topheader = node->data; topheader != NULL;
- topheader = topheader->next)
- {
+ for (top = node->data; top != NULL; top = top->next) {
++ntypes;
- if (prio_type(topheader->typepair)) {
- prioheader = topheader;
+ if (prio_type(top->typepair)) {
+ priotop = top;
}
- if (topheader->typepair == newheader->typepair) {
+ if (top->typepair == newheader->typepair) {
break;
}
- topheader_prev = topheader;
}
/*
* IGNORE rdatasets between the top of the chain and the first real
* data. We skip over them.
*/
- header = topheader;
- while (header != NULL && IGNORE(header)) {
- header = header->down;
+ dns_slabheader_t *header = NULL, *header_prev = NULL;
+ if (top != NULL) {
+ header = top->header;
+ while (header != NULL && IGNORE(header)) {
+ header_prev = header;
+ header = header->down;
+ }
}
+
if (header != NULL) {
/*
* If 'merge' is true and header isn't empty/nonexistent,
}
}
- INSIST(version->serial >= topheader->serial);
+ INSIST(version->serial >= top->header->serial);
+ INSIST(top->typepair == newheader->typepair);
+
if (loading) {
newheader->down = NULL;
if (RESIGN(newheader)) {
* Since we don't generate changed records when
* loading, we MUST clean up 'header' now.
*/
- if (topheader_prev != NULL) {
- topheader_prev->next = newheader;
- } else {
- node->data = newheader;
- }
- newheader->next = topheader->next;
+ newheader->top = top;
+ top->header = newheader;
maybe_update_recordsandsize(false, version, header,
nodename->length);
+
dns_slabheader_destroy(&header);
} else {
if (RESIGN(newheader)) {
resigndelete(qpdb, version,
header DNS__DB_FLARG_PASS);
}
- if (topheader_prev != NULL) {
- topheader_prev->next = newheader;
+
+ if (header_prev != NULL) {
+ header_prev->down = newheader;
} else {
- node->data = newheader;
+ top->header = newheader;
}
- newheader->next = topheader->next;
- newheader->down = topheader;
- topheader->up = newheader;
+
+ newheader->top = top;
+ newheader->down = header;
+
node->dirty = true;
if (changed != NULL) {
changed->dirty = true;
resigndelete(qpdb, version, header DNS__DB_FLARG_PASS);
}
- if (topheader != NULL) {
+ if (top != NULL) {
/*
* We have a list of rdatasets of the given type,
* but they're all marked IGNORE. We simply insert
* we INSIST on it.
*/
INSIST(!loading);
- INSIST(version->serial >= topheader->serial);
- if (topheader_prev != NULL) {
- topheader_prev->next = newheader;
- } else {
- node->data = newheader;
- }
- newheader->next = topheader->next;
- newheader->down = topheader;
- topheader->up = newheader;
+ INSIST(version->serial >= top->header->serial);
+ newheader->top = top;
+ newheader->down = top->header;
+ top->header = newheader;
if (changed != NULL) {
changed->dirty = true;
}
return DNS_R_TOOMANYRECORDS;
}
- INSIST(newheader->down == NULL);
+ dns_slabtop_t *newtop = dns_slabtop_new(
+ ((dns_db_t *)qpdb)->mctx, newheader->typepair);
+
+ newheader->top = newtop;
+ newtop->header = newheader;
if (prio_type(newheader->typepair)) {
/* This is a priority type, prepend it */
- newheader->next = node->data;
- node->data = newheader;
- } else if (prioheader != NULL) {
+ newtop->next = node->data;
+ node->data = newtop;
+ } else if (priotop != NULL) {
/* Append after the priority headers */
- newheader->next = prioheader->next;
- prioheader->next = newheader;
+ newtop->next = priotop->next;
+ priotop->next = newtop;
} else {
/* There were no priority headers */
- newheader->next = node->data;
- node->data = newheader;
+ newtop->next = node->data;
+ node->data = newtop;
}
}
}
static bool
matchparams(dns_slabheader_t *header, qpz_search_t *search) {
- dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_nsec3_t nsec3;
unsigned char *raw = NULL;
unsigned int rdlen, count;
isc_region_t region;
isc_result_t result;
- REQUIRE(header->typepair == dns_rdatatype_nsec3);
+ REQUIRE(header->typepair == DNS_TYPEPAIR(dns_rdatatype_nsec3));
raw = (unsigned char *)header + sizeof(*header);
count = raw[0] * 256 + raw[1]; /* count */
raw += DNS_RDATASET_LENGTH;
while (count-- > 0) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
rdlen = raw[0] * 256 + raw[1];
raw += DNS_RDATASET_LENGTH;
region.base = raw;
{
return true;
}
- dns_rdata_reset(&rdata);
}
return false;
}
NODE_UNLOCK(nlock, &nlocktype);
}
- if (typepair == dns_rdatatype_dname) {
+ if (typepair == DNS_TYPEPAIR(dns_rdatatype_dname)) {
return DNS_R_DNAME;
}
return DNS_R_DELEGATION;
dns_name_t *nodename = dns_fixedname_initname(&fnodename);
qpznode_t *node = NULL;
isc_result_t result = ISC_R_SUCCESS;
- dns_slabheader_t *header = NULL;
result = dns_qpiter_current(it, nodename, (void **)&node, NULL);
while (result == ISC_R_SUCCESS) {
isc_rwlock_t *nlock = qpzone_get_lock(node);
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
- dns_slabheader_t *header_next = NULL;
+ dns_slabtop_t *top = NULL;
+ dns_slabheader_t *found = NULL;
NODE_RDLOCK(nlock, &nlocktype);
- for (header = node->data; header != NULL; header = header_next)
- {
- header_next = header->next;
- while (header != NULL) {
- if (header->serial <= search->serial &&
- !IGNORE(header))
- {
- if (!EXISTS(header)) {
- header = NULL;
- }
- break;
- } else {
- header = header->down;
- }
+ for (top = node->data; top != NULL; top = top->next) {
+ dns_slabheader_t *header = top->header;
+ while (header != NULL &&
+ (IGNORE(header) ||
+ header->serial > search->serial))
+ {
+ header = header->down;
}
- if (header != NULL) {
+ if (header != NULL && EXISTS(header)) {
+ found = header;
break;
}
}
NODE_UNLOCK(nlock, &nlocktype);
- if (header != NULL) {
+ if (found != NULL) {
break;
}
static isc_result_t
find_wildcard(qpz_search_t *search, qpznode_t **nodep, const dns_name_t *qname,
dns_namespace_t nspace) {
- dns_slabheader_t *header = NULL;
+ dns_slabtop_t *top = NULL;
+ dns_slabheader_t *found = NULL;
isc_result_t result = ISC_R_NOTFOUND;
/*
* may not need the information, because it simplifies the
* locking and code flow.
*/
- for (header = node->data; header != NULL; header = header->next)
- {
+ for (top = node->data; top != NULL; top = top->next) {
+ dns_slabheader_t *header = top->header;
if (header->serial <= search->serial &&
!IGNORE(header) && EXISTS(header))
{
+ found = header;
break;
}
}
- active = (header != NULL);
+ active = (found != NULL);
wild = node->wild;
NODE_UNLOCK(nlock, &nlocktype);
*/
nlock = qpzone_get_lock(wnode);
NODE_RDLOCK(nlock, &nlocktype);
- for (header = wnode->data; header != NULL;
- header = header->next)
+ for (top = wnode->data; top != NULL;
+ top = top->next)
{
+ dns_slabheader_t *header = top->header;
if (header->serial <= search->serial &&
!IGNORE(header) && EXISTS(header))
{
+ found = header;
break;
}
}
NODE_UNLOCK(nlock, &nlocktype);
- if (header != NULL ||
+ if (found != NULL ||
activeempty(search, &wit, wname))
{
if (wildcard_blocked(search, qname,
dns_rdataset_t *sigrdataset, bool nsec3,
bool secure DNS__DB_FLARG) {
qpznode_t *node = NULL, *prevnode = NULL;
- dns_slabheader_t *header = NULL, *header_next = NULL;
dns_qpiter_t nseciter;
bool empty_node;
isc_result_t result;
}
again:
do {
+ dns_slabtop_t *top = NULL;
dns_slabheader_t *found = NULL, *foundsig = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = qpzone_get_lock(node);
NODE_RDLOCK(nlock, &nlocktype);
empty_node = true;
- for (header = node->data; header != NULL; header = header_next)
- {
- header_next = header->next;
+ for (top = node->data; top != NULL; top = top->next) {
+ dns_slabheader_t *header = top->header;
/*
* Look for an active, extant NSEC or RRSIG NSEC.
*/
* active rdataset at this node.
*/
empty_node = false;
- if (header->typepair == typepair) {
+ if (top->typepair == typepair) {
found = header;
if (foundsig != NULL) {
break;
}
- } else if (header->typepair == sigpair) {
+ } else if (top->typepair == sigpair) {
foundsig = header;
if (found != NULL) {
break;
}
if (!empty_node) {
if (found != NULL && search->version->havensec3 &&
- found->typepair == dns_rdatatype_nsec3 &&
+ found->typepair ==
+ DNS_TYPEPAIR(dns_rdatatype_nsec3) &&
!matchparams(found, search))
{
empty_node = true;
static isc_result_t
qpzone_check_zonecut(qpznode_t *node, void *arg DNS__DB_FLARG) {
qpz_search_t *search = arg;
- dns_slabheader_t *header = NULL, *header_next = NULL;
+ dns_slabtop_t *top = NULL;
dns_slabheader_t *dname_header = NULL, *sigdname_header = NULL;
dns_slabheader_t *ns_header = NULL;
dns_slabheader_t *found = NULL;
/*
* Look for an NS or DNAME rdataset active in our version.
*/
- for (header = node->data; header != NULL; header = header_next) {
- header_next = header->next;
- if (header->typepair == dns_rdatatype_ns ||
- header->typepair == dns_rdatatype_dname ||
- header->typepair == DNS_SIGTYPEPAIR(dns_rdatatype_dname))
+ for (top = node->data; top != NULL; top = top->next) {
+ dns_slabheader_t *header = top->header;
+ if (top->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) ||
+ top->typepair == DNS_TYPEPAIR(dns_rdatatype_dname) ||
+ top->typepair == DNS_SIGTYPEPAIR(dns_rdatatype_dname))
{
do {
if (header->serial <= search->serial &&
}
} while (header != NULL);
if (header != NULL) {
- if (header->typepair == dns_rdatatype_dname) {
+ if (top->typepair ==
+ DNS_TYPEPAIR(dns_rdatatype_dname))
+ {
dname_header = header;
- } else if (header->typepair ==
+ } else if (top->typepair ==
DNS_SIGTYPEPAIR(dns_rdatatype_dname))
{
sigdname_header = header;
bool maybe_zonecut = false, at_zonecut = false;
bool wild = false, empty_node = false;
bool nsec3 = false;
- dns_slabheader_t *header = NULL, *header_next = NULL;
+ dns_slabtop_t *top = NULL;
dns_slabheader_t *found = NULL, *nsecheader = NULL;
dns_slabheader_t *foundsig = NULL, *cnamesig = NULL, *nsecsig = NULL;
dns_typepair_t sigpair;
sigpair = DNS_SIGTYPEPAIR(type);
empty_node = true;
- for (header = node->data; header != NULL; header = header_next) {
- header_next = header->next;
+ for (top = node->data; top != NULL; top = top->next) {
+ dns_slabheader_t *header = top->header;
/*
* Look for an active, extant rdataset.
*/
* Do special zone cut handling, if requested.
*/
if (maybe_zonecut &&
- header->typepair == dns_rdatatype_ns)
+ top->typepair == DNS_TYPEPAIR(dns_rdatatype_ns))
{
/*
* We increment the reference count on node to
* If the NSEC3 record doesn't match the chain
* we are using behave as if it isn't here.
*/
- if (header->typepair == dns_rdatatype_nsec3 &&
+ if (top->typepair ==
+ DNS_TYPEPAIR(dns_rdatatype_nsec3) &&
!matchparams(header, &search))
{
NODE_UNLOCK(nlock, &nlocktype);
* If we found a type we were looking for,
* remember it.
*/
- if (header->typepair == type ||
+ if (top->typepair == type ||
type == dns_rdatatype_any ||
- (header->typepair == dns_rdatatype_cname &&
+ (top->typepair ==
+ DNS_TYPEPAIR(dns_rdatatype_cname) &&
cname_ok))
{
/*
* We've found the answer!
*/
found = header;
- if (header->typepair == dns_rdatatype_cname &&
+ if (top->typepair ==
+ DNS_TYPEPAIR(dns_rdatatype_cname) &&
cname_ok)
{
/*
if (!maybe_zonecut && foundsig != NULL) {
break;
}
- } else if (header->typepair == sigpair) {
+ } else if (top->typepair == sigpair) {
/*
* We've found the RRSIG rdataset for our
* target type. Remember it.
if (!maybe_zonecut && found != NULL) {
break;
}
- } else if (header->typepair == dns_rdatatype_nsec &&
+ } else if (top->typepair ==
+ DNS_TYPEPAIR(dns_rdatatype_nsec) &&
!search.version->havensec3)
{
/*
* we might need it later.
*/
nsecheader = header;
- } else if (header->typepair ==
+ } else if (top->typepair ==
DNS_SIGTYPEPAIR(
dns_rdatatype_nsec) &&
!search.version->havensec3)
*/
nsecsig = header;
} else if (cname_ok &&
- header->typepair ==
+ top->typepair ==
DNS_SIGTYPEPAIR(dns_rdatatype_cname))
{
/*
* We found what we were looking for, or we found a CNAME.
*/
if (type != found->typepair && type != dns_rdatatype_any &&
- found->typepair == dns_rdatatype_cname)
+ found->typepair == DNS_TYPEPAIR(dns_rdatatype_cname))
{
/*
* We weren't doing an ANY query and we found a CNAME instead
qpdb_rdatasetiter_t *qrditer = (qpdb_rdatasetiter_t *)iterator;
qpznode_t *node = (qpznode_t *)qrditer->common.node;
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 = qpzone_get_lock(node);
+ dns_slabheader_t *found = NULL;
+ dns_slabtop_t *top = NULL;
NODE_RDLOCK(nlock, &nlocktype);
- for (header = node->data; header != NULL; header = top_next) {
- top_next = header->next;
- do {
- if (header->serial <= version->serial &&
- !IGNORE(header))
- {
- if (!EXISTS(header)) {
- header = NULL;
- }
- break;
- } else {
- header = header->down;
- }
- } while (header != NULL);
- if (header != NULL) {
+ for (top = node->data; top != NULL; top = top->next) {
+ dns_slabheader_t *header = top->header;
+ while (header != NULL &&
+ (IGNORE(header) || header->serial > version->serial))
+ {
+ header = header->down;
+ }
+
+ if (header != NULL && EXISTS(header)) {
+ found = header;
break;
}
}
NODE_UNLOCK(nlock, &nlocktype);
- qrditer->current = header;
+ qrditer->currenttop = top;
+ qrditer->current = found;
- if (header == NULL) {
+ if (top == NULL) {
return ISC_R_NOMORE;
}
qpdb_rdatasetiter_t *qrditer = (qpdb_rdatasetiter_t *)iterator;
qpznode_t *node = (qpznode_t *)qrditer->common.node;
qpz_version_t *version = (qpz_version_t *)qrditer->common.version;
- dns_slabheader_t *header = NULL;
- dns_slabheader_t *topheader, *topheader_next = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = qpzone_get_lock(node);
+ dns_slabtop_t *top = qrditer->currenttop;
+ dns_slabheader_t *found = NULL;
- header = qrditer->current;
- if (header == NULL) {
+ if (top == NULL) {
return ISC_R_NOMORE;
}
/*
* Find the start of the header chain for the next type.
*/
- topheader = dns_slabheader_top(header);
+ for (top = top->next; top != NULL; top = top->next) {
+ dns_slabheader_t *header = top->header;
+ while (header != NULL &&
+ (IGNORE(header) || header->serial > version->serial))
+ {
+ header = header->down;
+ }
- for (header = topheader->next; header != NULL; header = topheader_next)
- {
- topheader_next = header->next;
- do {
- if (header->serial <= version->serial &&
- !IGNORE(header))
- {
- if (!EXISTS(header)) {
- header = NULL;
- }
- break;
- } else {
- header = header->down;
- }
- } while (header != NULL);
- if (header != NULL) {
+ if (header != NULL && EXISTS(header)) {
+ found = header;
break;
}
-
- /*
- * Find the start of the header chain for the next type.
- */
- topheader = topheader->next;
}
NODE_UNLOCK(nlock, &nlocktype);
- qrditer->current = header;
+ qrditer->currenttop = top;
+ qrditer->current = found;
- if (header == NULL) {
+ if (top == NULL) {
return ISC_R_NOMORE;
}
dns_rdataset_t *rdataset DNS__DB_FLARG) {
qpdb_rdatasetiter_t *qrditer = (qpdb_rdatasetiter_t *)iterator;
qpzonedb_t *qpdb = (qpzonedb_t *)(qrditer->common.db);
- qpznode_t *node = (qpznode_t *)qrditer->common.node;
- dns_slabheader_t *header = NULL;
+ qpznode_t *qpnode = (qpznode_t *)qrditer->common.node;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
- isc_rwlock_t *nlock = qpzone_get_lock(node);
+ isc_rwlock_t *nlock = qpzone_get_lock(qpnode);
+ dns_slabheader_t *header = qrditer->current;
- header = qrditer->current;
REQUIRE(header != NULL);
NODE_RDLOCK(nlock, &nlocktype);
- bindrdataset(qpdb, node, header, rdataset DNS__DB_FLARG_PASS);
+ bindrdataset(qpdb, qpnode, header, rdataset DNS__DB_FLARG_PASS);
NODE_UNLOCK(nlock, &nlocktype);
}
qpz_version_t *version = (qpz_version_t *)dbversion;
dns_fixedname_t fname;
dns_name_t *nodename = dns_fixedname_initname(&fname);
- dns_slabheader_t *topheader = NULL, *topheader_prev = NULL;
- dns_slabheader_t *header = NULL, *newheader = NULL;
+ dns_slabtop_t *top = NULL;
+ dns_slabheader_t *newheader = NULL;
dns_slabheader_t *subresult = NULL;
isc_region_t region;
isc_result_t result;
NODE_WRLOCK(nlock, &nlocktype);
changed = add_changed(newheader, version DNS__DB_FLARG_PASS);
- for (topheader = node->data; topheader != NULL;
- topheader = topheader->next)
- {
- if (topheader->typepair == newheader->typepair) {
+ for (top = node->data; top != NULL; top = top->next) {
+ if (top->typepair == newheader->typepair) {
break;
}
- topheader_prev = topheader;
}
/*
* If header isn't NULL, we've found the right type. There may be
* IGNORE rdatasets between the top of the chain and the first real
* data. We skip over them.
*/
- header = topheader;
- while (header != NULL && IGNORE(header)) {
- header = header->down;
+ dns_slabheader_t *header = NULL;
+ if (top != NULL) {
+ header = top->header;
+ while (header != NULL && IGNORE(header)) {
+ header = header->down;
+ }
}
if (header != NULL && EXISTS(header)) {
unsigned int flags = 0;
result = dns_rdataslab_subtract(
header, newheader, qpdb->common.mctx,
qpdb->common.rdclass,
- DNS_TYPEPAIR_TYPE(header->typepair), flags,
+ DNS_TYPEPAIR_TYPE(top->typepair), flags,
&subresult);
}
if (result == ISC_R_SUCCESS) {
newheader = dns_slabheader_new(db->mctx,
(dns_dbnode_t *)node);
newheader->ttl = 0;
- newheader->typepair = topheader->typepair;
+ newheader->typepair = top->typepair;
atomic_init(&newheader->attributes,
DNS_SLABHEADERATTR_NONEXISTENT);
newheader->serial = version->serial;
}
/*
- * If we're here, we want to link newheader in front of
- * topheader.
+ * If we're here, we want to link newheader at the top.
*/
- INSIST(version->serial >= topheader->serial);
+ INSIST(version->serial >= top->header->serial);
maybe_update_recordsandsize(false, version, header,
nodename->length);
- if (topheader_prev != NULL) {
- topheader_prev->next = newheader;
- } else {
- node->data = newheader;
- }
- newheader->next = topheader->next;
- newheader->down = topheader;
- topheader->next = newheader;
+
+ newheader->top = top;
+ newheader->down = top->header;
+ top->header = newheader;
+
node->dirty = true;
changed->dirty = true;
resigndelete(qpdb, version, header DNS__DB_FLARG_PASS);
static void
destroy_qpznode(qpznode_t *node) {
- dns_slabheader_t *current = NULL, *next = NULL;
-
- for (current = node->data; current != NULL; current = next) {
- dns_slabheader_t *down = current->down, *down_next = NULL;
+ dns_slabtop_t *top = NULL, *top_next = NULL;
+ dns_db_t *db = (dns_db_t *)node->qpdb;
- next = current->next;
+ for (top = node->data; top != NULL; top = top_next) {
+ top_next = top->next;
- for (down = current->down; down != NULL; down = down_next) {
+ dns_slabheader_t *down = NULL, *down_next = NULL;
+ for (down = top->header; down != NULL; down = down_next) {
down_next = down->down;
dns_slabheader_destroy(&down);
}
+ top->header = NULL;
- dns_slabheader_destroy(¤t);
+ dns_slabtop_destroy(db->mctx, &top);
}
qpz_heap_unref(node->heap);