diff --git a/lib/dns/include/dns/rdataslab.h b/lib/dns/include/dns/rdataslab.h index cf2c8f1567..c81fe9777f 100644 --- a/lib/dns/include/dns/rdataslab.h +++ b/lib/dns/include/dns/rdataslab.h @@ -102,12 +102,16 @@ struct dns_slabheader { * both head and tail pointers, and is doubly linked. */ - struct dns_slabheader *next; + union { + struct dns_slabheader *next; + struct dns_slabheader *up; + }; /*%< * If this is the top header for an rdataset, 'next' points * to the top header for the next rdataset (i.e., the next type). - * Otherwise, it points up to the header whose down pointer points - * at this header. + * + * Otherwise 'up' points up to the header whose down pointer points at + * this header. */ struct dns_slabheader *down; @@ -322,3 +326,9 @@ dns_slabheader_freeproof(isc_mem_t *mctx, dns_slabheader_proof_t **proof); /*%< * Free all memory associated with a nonexistence proof. */ + +dns_slabheader_t * +dns_slabheader_top(dns_slabheader_t *header); +/*%< + * Return the top header for the type or the negtype + */ diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index c59d4e0f95..54593ff91e 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -3133,7 +3133,7 @@ find_header: } else { qpnode->data = newheader; } - newheader->next = topheader->next; + newheader->next = header->next; dns_slabheader_destroy(&header); } else { idx = HEADERNODE(newheader)->locknum; @@ -3152,9 +3152,9 @@ find_header: } else { qpnode->data = newheader; } - newheader->next = topheader->next; - newheader->down = topheader; - topheader->next = newheader; + newheader->next = header->next; + newheader->down = header; + header->up = newheader; mark_ancient(header); if (sigheader != NULL) { mark_ancient(sigheader); @@ -3202,14 +3202,12 @@ find_header: } newheader->next = topheader->next; newheader->down = topheader; - topheader->next = newheader; + topheader->up = newheader; qpnode->dirty = 1; } else { /* * No rdatasets of the given type exist at the node. */ - INSIST(newheader->down == NULL); - if (prio_header(newheader)) { /* This is a priority type, prepend it */ newheader->next = qpnode->data; @@ -3779,9 +3777,8 @@ rdatasetiter_next(dns_rdatasetiter_t *it DNS__DB_FLARG) { 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, *top_next = NULL; - dns_typepair_t type, negtype; - dns_rdatatype_t rdtype, covers; + dns_slabheader_t *header = NULL; + dns_slabheader_t *topheader = NULL, *topheader_next = NULL; isc_rwlocktype_t nlocktype = isc_rwlocktype_none; isc_rwlock_t *nlock = &qpdb->buckets[qpnode->locknum].lock; bool expiredok = EXPIREDOK(iterator); @@ -3793,36 +3790,23 @@ rdatasetiter_next(dns_rdatasetiter_t *it DNS__DB_FLARG) { NODE_RDLOCK(nlock, &nlocktype); - type = header->type; - rdtype = DNS_TYPEPAIR_TYPE(header->type); - if (NEGATIVE(header)) { - covers = DNS_TYPEPAIR_COVERS(header->type); - negtype = DNS_TYPEPAIR_VALUE(covers, 0); - } else { - negtype = DNS_TYPEPAIR_VALUE(0, rdtype); - } - /* - * Find the start of the header chain for the next type - * by walking back up the list. + * Find the start of the header chain for the next type. */ - top_next = header->next; - while (top_next != NULL && - (top_next->type == type || top_next->type == negtype)) - { - top_next = top_next->next; - } - if (expiredok) { + topheader = dns_slabheader_top(header); + topheader_next = topheader->next; + + if (expiredok && header->down != NULL) { /* * Keep walking down the list if possible or * start the next type. */ - header = header->down != NULL ? header->down : top_next; + header = header->down; } else { - header = top_next; + header = topheader->next; } - for (; header != NULL; header = top_next) { - top_next = header->next; + for (; header != NULL; header = topheader_next) { + topheader_next = header->next; do { if (expiredok) { if (!NONEXISTENT(header)) { @@ -3842,14 +3826,10 @@ rdatasetiter_next(dns_rdatasetiter_t *it DNS__DB_FLARG) { break; } /* - * Find the start of the header chain for the next type - * by walking back up the list. + * Find the start of the header chain for the next type. */ - while (top_next != NULL && - (top_next->type == type || top_next->type == negtype)) - { - top_next = top_next->next; - } + topheader = dns_slabheader_top(header); + topheader_next = topheader->next; } NODE_UNLOCK(nlock, &nlocktype); diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index e0ddab3bfb..4bb17b6fb4 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -775,7 +775,7 @@ qpznode_acquire(qpzonedb_t *qpdb, qpznode_t *node DNS__DB_FLARG) { static void clean_zone_node(qpznode_t *node, uint32_t least_serial) { dns_slabheader_t *current = NULL, *dcurrent = NULL; - dns_slabheader_t *down_next = NULL, *dparent = NULL; + dns_slabheader_t *dcurrent_down = NULL, *dparent = NULL; dns_slabheader_t *top_prev = NULL, *top_next = NULL; bool still_dirty = false; @@ -794,17 +794,17 @@ clean_zone_node(qpznode_t *node, uint32_t least_serial) { */ dparent = current; for (dcurrent = current->down; dcurrent != NULL; - dcurrent = down_next) + dcurrent = dcurrent_down) { - down_next = dcurrent->down; + dcurrent_down = dcurrent->down; INSIST(dcurrent->serial <= dparent->serial); if (dcurrent->serial == dparent->serial || IGNORE(dcurrent)) { - if (down_next != NULL) { - down_next->next = dparent; + if (dcurrent_down != NULL) { + dcurrent_down->up = dparent; } - dparent->down = down_next; + dparent->down = dcurrent_down; dns_slabheader_destroy(&dcurrent); } else { dparent = dcurrent; @@ -815,9 +815,10 @@ clean_zone_node(qpznode_t *node, uint32_t least_serial) { * We've now eliminated all IGNORE datasets with the possible * exception of current, which we now check. */ - if (IGNORE(current)) { - down_next = current->down; - if (down_next == NULL) { + dcurrent = current; + if (IGNORE(dcurrent)) { + dcurrent_down = current->down; + if (dcurrent_down == NULL) { if (top_prev != NULL) { top_prev->next = current->next; } else { @@ -835,13 +836,13 @@ clean_zone_node(qpznode_t *node, uint32_t least_serial) { * current. */ if (top_prev != NULL) { - top_prev->next = down_next; + top_prev->next = dcurrent_down; } else { - node->data = down_next; + node->data = dcurrent_down; } - down_next->next = top_next; + dcurrent_down->next = top_next; dns_slabheader_destroy(¤t); - current = down_next; + current = dcurrent_down; } } @@ -851,9 +852,9 @@ clean_zone_node(qpznode_t *node, uint32_t least_serial) { */ dparent = current; for (dcurrent = current->down; dcurrent != NULL; - dcurrent = down_next) + dcurrent = dcurrent_down) { - down_next = dcurrent->down; + dcurrent_down = dcurrent->down; if (dcurrent->serial < least_serial) { break; } @@ -866,10 +867,10 @@ clean_zone_node(qpznode_t *node, uint32_t least_serial) { */ if (dcurrent != NULL) { do { - down_next = dcurrent->down; + dcurrent_down = dcurrent->down; INSIST(dcurrent->serial <= least_serial); dns_slabheader_destroy(&dcurrent); - dcurrent = down_next; + dcurrent = dcurrent_down; } while (dcurrent != NULL); dparent->down = NULL; } @@ -1980,7 +1981,7 @@ add(qpzonedb_t *qpdb, qpznode_t *node, const dns_name_t *nodename, } newheader->next = topheader->next; newheader->down = topheader; - topheader->next = newheader; + topheader->up = newheader; node->dirty = true; if (changed != NULL) { changed->dirty = true; @@ -2023,7 +2024,7 @@ add(qpzonedb_t *qpdb, qpznode_t *node, const dns_name_t *nodename, } newheader->next = topheader->next; newheader->down = topheader; - topheader->next = newheader; + topheader->up = newheader; if (changed != NULL) { changed->dirty = true; } @@ -4109,9 +4110,8 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) { qpzonedb_t *qpdb = (qpzonedb_t *)(qrditer->common.db); 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; - dns_typepair_t type, negtype; - dns_rdatatype_t rdtype; + dns_slabheader_t *header = NULL; + dns_slabheader_t *topheader, *topheader_next = NULL; isc_rwlocktype_t nlocktype = isc_rwlocktype_none; isc_rwlock_t *nlock = &qpdb->buckets[node->locknum].lock; @@ -4122,22 +4122,14 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) { NODE_RDLOCK(nlock, &nlocktype); - type = header->type; - rdtype = DNS_TYPEPAIR_TYPE(header->type); - negtype = DNS_TYPEPAIR_VALUE(0, rdtype); - /* - * Find the start of the header chain for the next type - * by walking back up the list. + * Find the start of the header chain for the next type. */ - top_next = header->next; - while (top_next != NULL && - (top_next->type == type || top_next->type == negtype)) - { - top_next = top_next->next; - } - for (header = top_next; header != NULL; header = top_next) { - top_next = header->next; + topheader = dns_slabheader_top(header); + topheader_next = topheader->next; + + for (header = topheader_next; header != NULL; header = topheader_next) { + topheader_next = header->next; do { if (header->serial <= version->serial && !IGNORE(header)) @@ -4154,14 +4146,10 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) { break; } /* - * Find the start of the header chain for the next type - * by walking back up the list. + * Find the start of the header chain for the next type. */ - while (top_next != NULL && - (top_next->type == type || top_next->type == negtype)) - { - top_next = top_next->next; - } + topheader = dns_slabheader_top(header); + topheader_next = topheader->next; } NODE_UNLOCK(nlock, &nlocktype); diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c index c5e0ffbf91..ce0dfeb3f4 100644 --- a/lib/dns/rdataslab.c +++ b/lib/dns/rdataslab.c @@ -39,6 +39,9 @@ #define NONEXISTENT(header) \ ((atomic_load_acquire(&(header)->attributes) & \ DNS_SLABHEADERATTR_NONEXISTENT) != 0) +#define NEGATIVE(header) \ + ((atomic_load_acquire(&(header)->attributes) & \ + DNS_SLABHEADERATTR_NEGATIVE) != 0) /* * The rdataslab structure allows iteration to occur in both load order @@ -1188,3 +1191,30 @@ rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) { unlock: dns_db_unlocknode(header->db, header->node, isc_rwlocktype_read); } + +dns_slabheader_t * +dns_slabheader_top(dns_slabheader_t *header) { + dns_typepair_t type, negtype; + dns_rdatatype_t rdtype, covers; + + type = header->type; + rdtype = DNS_TYPEPAIR_TYPE(header->type); + if (NEGATIVE(header)) { + covers = DNS_TYPEPAIR_COVERS(header->type); + negtype = DNS_TYPEPAIR_VALUE(covers, 0); + } else { + negtype = DNS_TYPEPAIR_VALUE(0, rdtype); + } + + /* + * Find the start of the header chain for the next type + * by walking back up the list. + */ + while (header->up != NULL && + (header->up->type == type || header->up->type == negtype)) + { + header = header->up; + } + + return header; +}