mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-08 20:32:06 -04:00
Rewrite the GLUE cache in QP zone database
This is a second attempt to rewrite the GLUE cache to not use per
database version hash table. Instead of keeping a hash table indexed by
the node, use a directly linked list of GLUE records for each
slabheader. This was attempted before, but there was a data race caused
by the fact that the thread cleaning the GLUE records could be slower
than accessing the slab headers again and reinitializing the wait-free
stack.
The improved design builds on the previous design, but adds a new
dns_gluelist structure that has a pointer to the database version.
If a dns_gluelist belonging to a different (old) version is detected, it
is just detached from the slabheader and left for the closeversion() to
clean it up later.
(cherry picked from commit 29bde687b5)
This commit is contained in:
parent
ad952ffee6
commit
547f376f21
8 changed files with 339 additions and 463 deletions
259
lib/dns/db.c
259
lib/dns/db.c
|
|
@ -41,6 +41,8 @@
|
|||
#include <dns/rdataclass.h>
|
||||
#include <dns/rdataset.h>
|
||||
#include <dns/rdatasetiter.h>
|
||||
#include <dns/rdataslab.h>
|
||||
#include <dns/stats.h>
|
||||
|
||||
/***
|
||||
*** Private Types
|
||||
|
|
@ -1214,3 +1216,260 @@ dns__db_logtoomanyrecords(dns_db_t *db, const dns_name_t *name,
|
|||
(db->attributes & DNS_DBATTR_CACHE) != 0 ? "cache" : "zone",
|
||||
isc_result_totext(DNS_R_TOOMANYRECORDS), limit);
|
||||
}
|
||||
|
||||
void
|
||||
dns__db_free_glue(isc_mem_t *mctx, dns_glue_t *glue) {
|
||||
while (glue != NULL) {
|
||||
dns_glue_t *next = glue->next;
|
||||
|
||||
if (dns_rdataset_isassociated(&glue->rdataset_a)) {
|
||||
dns_rdataset_disassociate(&glue->rdataset_a);
|
||||
}
|
||||
if (dns_rdataset_isassociated(&glue->sigrdataset_a)) {
|
||||
dns_rdataset_disassociate(&glue->sigrdataset_a);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&glue->rdataset_aaaa)) {
|
||||
dns_rdataset_disassociate(&glue->rdataset_aaaa);
|
||||
}
|
||||
if (dns_rdataset_isassociated(&glue->sigrdataset_aaaa)) {
|
||||
dns_rdataset_disassociate(&glue->sigrdataset_aaaa);
|
||||
}
|
||||
|
||||
dns_rdataset_invalidate(&glue->rdataset_a);
|
||||
dns_rdataset_invalidate(&glue->sigrdataset_a);
|
||||
dns_rdataset_invalidate(&glue->rdataset_aaaa);
|
||||
dns_rdataset_invalidate(&glue->sigrdataset_aaaa);
|
||||
|
||||
dns_name_free(&glue->name, mctx);
|
||||
|
||||
isc_mem_put(mctx, glue, sizeof(*glue));
|
||||
|
||||
glue = next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns__db_destroy_gluelist(dns_gluelist_t **gluelistp) {
|
||||
REQUIRE(gluelistp != NULL);
|
||||
if (*gluelistp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
dns_gluelist_t *gluelist = *gluelistp;
|
||||
|
||||
dns__db_free_glue(gluelist->mctx, gluelist->glue);
|
||||
|
||||
isc_mem_putanddetach(&gluelist->mctx, gluelist, sizeof(*gluelist));
|
||||
}
|
||||
|
||||
void
|
||||
dns__db_free_gluelist_rcu(struct rcu_head *rcu_head) {
|
||||
dns_gluelist_t *gluelist = caa_container_of(rcu_head, dns_gluelist_t,
|
||||
rcu_head);
|
||||
dns__db_destroy_gluelist(&gluelist);
|
||||
}
|
||||
|
||||
void
|
||||
dns__db_cleanup_gluelists(struct cds_wfs_stack *glue_stack) {
|
||||
struct cds_wfs_head *head = __cds_wfs_pop_all(glue_stack);
|
||||
struct cds_wfs_node *node = NULL, *next = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
cds_wfs_for_each_blocking_safe(head, node, next) {
|
||||
dns_gluelist_t *gluelist =
|
||||
caa_container_of(node, dns_gluelist_t, wfs_node);
|
||||
dns_slabheader_t *header = rcu_xchg_pointer(&gluelist->header,
|
||||
NULL);
|
||||
(void)rcu_cmpxchg_pointer(&header->gluelist, gluelist, NULL);
|
||||
|
||||
call_rcu(&gluelist->rcu_head, dns__db_free_gluelist_rcu);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
#define IS_REQUIRED_GLUE(r) (((r)->attributes & DNS_RDATASETATTR_REQUIRED) != 0)
|
||||
|
||||
static void
|
||||
addglue_to_message(dns_glue_t *ge, dns_message_t *msg) {
|
||||
for (; ge != NULL; ge = ge->next) {
|
||||
dns_name_t *name = NULL;
|
||||
dns_rdataset_t *rdataset_a = NULL;
|
||||
dns_rdataset_t *sigrdataset_a = NULL;
|
||||
dns_rdataset_t *rdataset_aaaa = NULL;
|
||||
dns_rdataset_t *sigrdataset_aaaa = NULL;
|
||||
bool prepend_name = false;
|
||||
|
||||
dns_message_gettempname(msg, &name);
|
||||
|
||||
dns_name_copy(&ge->name, name);
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->rdataset_a)) {
|
||||
dns_message_gettemprdataset(msg, &rdataset_a);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->sigrdataset_a)) {
|
||||
dns_message_gettemprdataset(msg, &sigrdataset_a);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->rdataset_aaaa)) {
|
||||
dns_message_gettemprdataset(msg, &rdataset_aaaa);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->sigrdataset_aaaa)) {
|
||||
dns_message_gettemprdataset(msg, &sigrdataset_aaaa);
|
||||
}
|
||||
|
||||
if (rdataset_a != NULL) {
|
||||
dns_rdataset_clone(&ge->rdataset_a, rdataset_a);
|
||||
ISC_LIST_APPEND(name->list, rdataset_a, link);
|
||||
if (IS_REQUIRED_GLUE(rdataset_a)) {
|
||||
prepend_name = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (sigrdataset_a != NULL) {
|
||||
dns_rdataset_clone(&ge->sigrdataset_a, sigrdataset_a);
|
||||
ISC_LIST_APPEND(name->list, sigrdataset_a, link);
|
||||
}
|
||||
|
||||
if (rdataset_aaaa != NULL) {
|
||||
dns_rdataset_clone(&ge->rdataset_aaaa, rdataset_aaaa);
|
||||
ISC_LIST_APPEND(name->list, rdataset_aaaa, link);
|
||||
if (IS_REQUIRED_GLUE(rdataset_aaaa)) {
|
||||
prepend_name = true;
|
||||
}
|
||||
}
|
||||
if (sigrdataset_aaaa != NULL) {
|
||||
dns_rdataset_clone(&ge->sigrdataset_aaaa,
|
||||
sigrdataset_aaaa);
|
||||
ISC_LIST_APPEND(name->list, sigrdataset_aaaa, link);
|
||||
}
|
||||
|
||||
dns_message_addname(msg, name, DNS_SECTION_ADDITIONAL);
|
||||
|
||||
/*
|
||||
* When looking for required glue, dns_message_rendersection()
|
||||
* only processes the first rdataset associated with the first
|
||||
* name added to the ADDITIONAL section. dns_message_addname()
|
||||
* performs an append on the list of names in a given section,
|
||||
* so if any glue record was marked as required, we need to
|
||||
* move the name it is associated with to the beginning of the
|
||||
* list for the ADDITIONAL section or else required glue might
|
||||
* not be rendered.
|
||||
*/
|
||||
if (prepend_name) {
|
||||
ISC_LIST_UNLINK(msg->sections[DNS_SECTION_ADDITIONAL],
|
||||
name, link);
|
||||
ISC_LIST_PREPEND(msg->sections[DNS_SECTION_ADDITIONAL],
|
||||
name, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static dns_gluelist_t *
|
||||
new_gluelist(dns_db_t *db, dns_slabheader_t *header,
|
||||
const dns_dbversion_t *dbversion) {
|
||||
dns_gluelist_t *gluelist = isc_mem_get(db->mctx, sizeof(*gluelist));
|
||||
*gluelist = (dns_gluelist_t){
|
||||
.version = dbversion,
|
||||
.header = header,
|
||||
};
|
||||
|
||||
isc_mem_attach(db->mctx, &gluelist->mctx);
|
||||
|
||||
cds_wfs_node_init(&gluelist->wfs_node);
|
||||
|
||||
return gluelist;
|
||||
}
|
||||
|
||||
static dns_gluelist_t *
|
||||
create_gluelist(dns_db_t *db, dns_dbversion_t *dbversion, dns_dbnode_t *dbnode,
|
||||
dns_rdataset_t *rdataset, dns_additionaldatafunc_t add) {
|
||||
dns_slabheader_t *header = dns_slabheader_fromrdataset(rdataset);
|
||||
dns_glue_additionaldata_ctx_t ctx = {
|
||||
.db = db,
|
||||
.version = dbversion,
|
||||
.node = dbnode,
|
||||
};
|
||||
dns_gluelist_t *gluelist = new_gluelist(ctx.db, header, ctx.version);
|
||||
|
||||
/*
|
||||
* Get the owner name of the NS RRset - it will be necessary for
|
||||
* identifying required glue in glue_nsdname_cb() (by
|
||||
* determining which NS records in the delegation are
|
||||
* in-bailiwick).
|
||||
*/
|
||||
|
||||
(void)dns_rdataset_additionaldata(rdataset, dns_rootname, add, &ctx);
|
||||
|
||||
gluelist->glue = ctx.glue;
|
||||
|
||||
return gluelist;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns__db_addglue(dns_db_t *db, dns_dbversion_t *dbversion,
|
||||
dns_rdataset_t *rdataset, dns_message_t *msg,
|
||||
dns_additionaldatafunc_t add,
|
||||
struct cds_wfs_stack *glue_stack) {
|
||||
dns_dbnode_t *dbnode = (dns_dbnode_t *)rdataset->slab.node;
|
||||
dns_slabheader_t *header = dns_slabheader_fromrdataset(rdataset);
|
||||
dns_glue_t *glue = NULL;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
REQUIRE(rdataset->type == dns_rdatatype_ns);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
dns_gluelist_t *gluelist = rcu_dereference(header->gluelist);
|
||||
if (gluelist == NULL || gluelist->version != dbversion) {
|
||||
/* No or old glue list was found in the table. */
|
||||
|
||||
dns_gluelist_t *xchg_gluelist = gluelist;
|
||||
dns_gluelist_t *old_gluelist = (void *)-1;
|
||||
dns_gluelist_t *new_gluelist =
|
||||
create_gluelist(db, dbversion, dbnode, rdataset, add);
|
||||
|
||||
while (old_gluelist != xchg_gluelist &&
|
||||
(xchg_gluelist == NULL ||
|
||||
xchg_gluelist->version != dbversion))
|
||||
{
|
||||
old_gluelist = xchg_gluelist;
|
||||
xchg_gluelist = rcu_cmpxchg_pointer(
|
||||
&header->gluelist, old_gluelist, new_gluelist);
|
||||
}
|
||||
|
||||
if (old_gluelist == xchg_gluelist) {
|
||||
/* CAS was successful */
|
||||
cds_wfs_push(glue_stack, &new_gluelist->wfs_node);
|
||||
gluelist = new_gluelist;
|
||||
} else {
|
||||
dns__db_destroy_gluelist(&new_gluelist);
|
||||
gluelist = xchg_gluelist;
|
||||
}
|
||||
}
|
||||
|
||||
glue = gluelist->glue;
|
||||
|
||||
if (glue != NULL) {
|
||||
addglue_to_message(glue, msg);
|
||||
result = ISC_R_NOTFOUND;
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
dns_glue_t *
|
||||
dns__db_new_glue(isc_mem_t *mctx, const dns_name_t *name) {
|
||||
dns_glue_t *glue = isc_mem_get(mctx, sizeof(*glue));
|
||||
*glue = (dns_glue_t){
|
||||
.name = DNS_NAME_INITEMPTY,
|
||||
};
|
||||
|
||||
dns_name_dup(name, mctx, &glue->name);
|
||||
|
||||
return glue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,21 +120,31 @@ ISC_LANG_BEGINDECLS
|
|||
|
||||
struct dns_glue {
|
||||
struct dns_glue *next;
|
||||
dns_fixedname_t fixedname;
|
||||
dns_name_t name;
|
||||
dns_rdataset_t rdataset_a;
|
||||
dns_rdataset_t sigrdataset_a;
|
||||
dns_rdataset_t rdataset_aaaa;
|
||||
dns_rdataset_t sigrdataset_aaaa;
|
||||
|
||||
isc_mem_t *mctx;
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
dns_glue_t *glue_list;
|
||||
struct dns_gluelist {
|
||||
isc_mem_t *mctx;
|
||||
|
||||
const dns_dbversion_t *version;
|
||||
dns_slabheader_t *header;
|
||||
|
||||
struct dns_glue *glue;
|
||||
|
||||
struct rcu_head rcu_head;
|
||||
struct cds_wfs_node wfs_node;
|
||||
};
|
||||
|
||||
typedef struct dns_glue_additionaldata_ctx {
|
||||
dns_db_t *db;
|
||||
dns_dbversion_t *version;
|
||||
dns_name_t *nodename;
|
||||
dns_dbnode_t *node;
|
||||
|
||||
dns_glue_t *glue;
|
||||
} dns_glue_additionaldata_ctx_t;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -196,4 +206,20 @@ dns__db_logtoomanyrecords(dns_db_t *db, const dns_name_t *name,
|
|||
* the addition is to create a new rdataset or to merge to an existing one.
|
||||
*/
|
||||
|
||||
void
|
||||
dns__db_free_glue(isc_mem_t *mctx, dns_glue_t *glue);
|
||||
void
|
||||
dns__db_destroy_gluelist(dns_gluelist_t **gluelistp);
|
||||
void
|
||||
dns__db_free_gluelist_rcu(struct rcu_head *rcu_head);
|
||||
void
|
||||
dns__db_cleanup_gluelists(struct cds_wfs_stack *glue_stack);
|
||||
isc_result_t
|
||||
dns__db_addglue(dns_db_t *db, dns_dbversion_t *dbversion,
|
||||
dns_rdataset_t *rdataset, dns_message_t *msg,
|
||||
dns_additionaldatafunc_t add, struct cds_wfs_stack *glue_stack);
|
||||
|
||||
dns_glue_t *
|
||||
dns__db_new_glue(isc_mem_t *mctx, const dns_name_t *name);
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
|
|
|||
|
|
@ -132,9 +132,9 @@ struct dns_slabheader {
|
|||
*/
|
||||
unsigned char upper[32];
|
||||
|
||||
isc_heap_t *heap;
|
||||
dns_glue_t *glue_list;
|
||||
struct cds_wfs_node wfs_node;
|
||||
isc_heap_t *heap;
|
||||
|
||||
dns_gluelist_t *gluelist;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ typedef struct dns_forwarder dns_forwarder_t;
|
|||
typedef struct dns_fwdtable dns_fwdtable_t;
|
||||
typedef struct dns_geoip_databases dns_geoip_databases_t;
|
||||
typedef struct dns_glue dns_glue_t;
|
||||
typedef struct dns_gluelist dns_gluelist_t;
|
||||
typedef struct dns_iptable dns_iptable_t;
|
||||
typedef uint32_t dns_iterations_t;
|
||||
typedef struct dns_kasp dns_kasp_t;
|
||||
|
|
|
|||
243
lib/dns/qpzone.c
243
lib/dns/qpzone.c
|
|
@ -369,64 +369,6 @@ set_index(void *what, unsigned int idx) {
|
|||
h->heap_index = idx;
|
||||
}
|
||||
|
||||
static void
|
||||
freeglue(dns_glue_t *glue_list) {
|
||||
if (glue_list == (void *)-1) {
|
||||
return;
|
||||
}
|
||||
|
||||
dns_glue_t *glue = glue_list;
|
||||
while (glue != NULL) {
|
||||
dns_glue_t *next = glue->next;
|
||||
|
||||
if (dns_rdataset_isassociated(&glue->rdataset_a)) {
|
||||
dns_rdataset_disassociate(&glue->rdataset_a);
|
||||
}
|
||||
if (dns_rdataset_isassociated(&glue->sigrdataset_a)) {
|
||||
dns_rdataset_disassociate(&glue->sigrdataset_a);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&glue->rdataset_aaaa)) {
|
||||
dns_rdataset_disassociate(&glue->rdataset_aaaa);
|
||||
}
|
||||
if (dns_rdataset_isassociated(&glue->sigrdataset_aaaa)) {
|
||||
dns_rdataset_disassociate(&glue->sigrdataset_aaaa);
|
||||
}
|
||||
|
||||
dns_rdataset_invalidate(&glue->rdataset_a);
|
||||
dns_rdataset_invalidate(&glue->sigrdataset_a);
|
||||
dns_rdataset_invalidate(&glue->rdataset_aaaa);
|
||||
dns_rdataset_invalidate(&glue->sigrdataset_aaaa);
|
||||
|
||||
isc_mem_putanddetach(&glue->mctx, glue, sizeof(*glue));
|
||||
|
||||
glue = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_gluelist_rcu(struct rcu_head *rcu_head) {
|
||||
dns_glue_t *glue = caa_container_of(rcu_head, dns_glue_t, rcu_head);
|
||||
|
||||
freeglue(glue);
|
||||
}
|
||||
|
||||
static void
|
||||
free_gluetable(struct cds_wfs_stack *glue_stack) {
|
||||
struct cds_wfs_head *head = __cds_wfs_pop_all(glue_stack);
|
||||
struct cds_wfs_node *node = NULL, *next = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
cds_wfs_for_each_blocking_safe(head, node, next) {
|
||||
dns_slabheader_t *header =
|
||||
caa_container_of(node, dns_slabheader_t, wfs_node);
|
||||
dns_glue_t *glue = rcu_xchg_pointer(&header->glue_list, NULL);
|
||||
|
||||
call_rcu(&glue->rcu_head, free_gluelist_rcu);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void
|
||||
free_db_rcu(struct rcu_head *rcu_head) {
|
||||
qpzonedb_t *qpdb = caa_container_of(rcu_head, qpzonedb_t, rcu_head);
|
||||
|
|
@ -513,7 +455,7 @@ qpdb_destroy(dns_db_t *arg) {
|
|||
* node count below.
|
||||
*/
|
||||
if (qpdb->current_version != NULL) {
|
||||
free_gluetable(&qpdb->current_version->glue_stack);
|
||||
dns__db_cleanup_gluelists(&qpdb->current_version->glue_stack);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1475,7 +1417,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
|||
if (cleanup_version != NULL) {
|
||||
isc_refcount_destroy(&cleanup_version->references);
|
||||
INSIST(EMPTY(cleanup_version->changed_list));
|
||||
free_gluetable(&cleanup_version->glue_stack);
|
||||
dns__db_cleanup_gluelists(&cleanup_version->glue_stack);
|
||||
cds_wfs_destroy(&cleanup_version->glue_stack);
|
||||
isc_rwlock_destroy(&cleanup_version->rwlock);
|
||||
isc_mem_put(qpdb->common.mctx, cleanup_version,
|
||||
|
|
@ -4020,10 +3962,6 @@ deletedata(dns_db_t *db ISC_ATTR_UNUSED, dns_dbnode_t *node ISC_ATTR_UNUSED,
|
|||
RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
|
||||
}
|
||||
header->heap_index = 0;
|
||||
|
||||
if (header->glue_list) {
|
||||
freeglue(header->glue_list);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -4987,26 +4925,15 @@ nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name) {
|
|||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static dns_glue_t *
|
||||
new_gluelist(isc_mem_t *mctx, dns_name_t *name) {
|
||||
dns_glue_t *glue = isc_mem_get(mctx, sizeof(*glue));
|
||||
*glue = (dns_glue_t){ 0 };
|
||||
dns_name_t *gluename = dns_fixedname_initname(&glue->fixedname);
|
||||
|
||||
isc_mem_attach(mctx, &glue->mctx);
|
||||
dns_name_copy(name, gluename);
|
||||
|
||||
return glue;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
||||
dns_rdataset_t *unused DNS__DB_FLARG) {
|
||||
dns_rdataset_t *rdataset ISC_ATTR_UNUSED DNS__DB_FLARG) {
|
||||
dns_glue_additionaldata_ctx_t *ctx = NULL;
|
||||
isc_result_t result;
|
||||
dns_fixedname_t fixedname_a;
|
||||
dns_name_t *name_a = NULL;
|
||||
dns_rdataset_t rdataset_a, sigrdataset_a;
|
||||
const qpznode_t *node = NULL;
|
||||
qpznode_t *node_a = NULL;
|
||||
dns_fixedname_t fixedname_aaaa;
|
||||
dns_name_t *name_aaaa = NULL;
|
||||
|
|
@ -5014,8 +4941,6 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
qpznode_t *node_aaaa = NULL;
|
||||
dns_glue_t *glue = NULL;
|
||||
|
||||
UNUSED(unused);
|
||||
|
||||
/*
|
||||
* NS records want addresses in additional records.
|
||||
*/
|
||||
|
|
@ -5023,6 +4948,8 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
|
||||
ctx = (dns_glue_additionaldata_ctx_t *)arg;
|
||||
|
||||
node = (qpznode_t *)ctx->node;
|
||||
|
||||
name_a = dns_fixedname_initname(&fixedname_a);
|
||||
dns_rdataset_init(&rdataset_a);
|
||||
dns_rdataset_init(&sigrdataset_a);
|
||||
|
|
@ -5035,7 +4962,7 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
DNS_DBFIND_GLUEOK, 0, (dns_dbnode_t **)&node_a, name_a,
|
||||
&rdataset_a, &sigrdataset_a DNS__DB_FLARG_PASS);
|
||||
if (result == DNS_R_GLUE) {
|
||||
glue = new_gluelist(ctx->db->mctx, name_a);
|
||||
glue = dns__db_new_glue(ctx->db->mctx, name_a);
|
||||
|
||||
dns_rdataset_init(&glue->rdataset_a);
|
||||
dns_rdataset_init(&glue->sigrdataset_a);
|
||||
|
|
@ -5055,7 +4982,7 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
&sigrdataset_aaaa DNS__DB_FLARG_PASS);
|
||||
if (result == DNS_R_GLUE) {
|
||||
if (glue == NULL) {
|
||||
glue = new_gluelist(ctx->db->mctx, name_aaaa);
|
||||
glue = dns__db_new_glue(ctx->db->mctx, name_aaaa);
|
||||
|
||||
dns_rdataset_init(&glue->rdataset_a);
|
||||
dns_rdataset_init(&glue->sigrdataset_a);
|
||||
|
|
@ -5081,7 +5008,7 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
* attributes for the first rdataset associated with the first name
|
||||
* added to the ADDITIONAL section.
|
||||
*/
|
||||
if (glue != NULL && dns_name_issubdomain(name, ctx->nodename)) {
|
||||
if (glue != NULL && dns_name_issubdomain(name, &node->name)) {
|
||||
if (dns_rdataset_isassociated(&glue->rdataset_a)) {
|
||||
glue->rdataset_a.attributes |=
|
||||
DNS_RDATASETATTR_REQUIRED;
|
||||
|
|
@ -5093,8 +5020,8 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
}
|
||||
|
||||
if (glue != NULL) {
|
||||
glue->next = ctx->glue_list;
|
||||
ctx->glue_list = glue;
|
||||
glue->next = ctx->glue;
|
||||
ctx->glue = glue;
|
||||
}
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
|
|
@ -5125,162 +5052,30 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
return result;
|
||||
}
|
||||
|
||||
#define IS_REQUIRED_GLUE(r) (((r)->attributes & DNS_RDATASETATTR_REQUIRED) != 0)
|
||||
|
||||
static void
|
||||
addglue_to_message(dns_glue_t *ge, dns_message_t *msg) {
|
||||
for (; ge != NULL; ge = ge->next) {
|
||||
dns_name_t *name = NULL;
|
||||
dns_rdataset_t *rdataset_a = NULL;
|
||||
dns_rdataset_t *sigrdataset_a = NULL;
|
||||
dns_rdataset_t *rdataset_aaaa = NULL;
|
||||
dns_rdataset_t *sigrdataset_aaaa = NULL;
|
||||
dns_name_t *gluename = dns_fixedname_name(&ge->fixedname);
|
||||
bool prepend_name = false;
|
||||
|
||||
dns_message_gettempname(msg, &name);
|
||||
|
||||
dns_name_copy(gluename, name);
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->rdataset_a)) {
|
||||
dns_message_gettemprdataset(msg, &rdataset_a);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->sigrdataset_a)) {
|
||||
dns_message_gettemprdataset(msg, &sigrdataset_a);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->rdataset_aaaa)) {
|
||||
dns_message_gettemprdataset(msg, &rdataset_aaaa);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->sigrdataset_aaaa)) {
|
||||
dns_message_gettemprdataset(msg, &sigrdataset_aaaa);
|
||||
}
|
||||
|
||||
if (rdataset_a != NULL) {
|
||||
dns_rdataset_clone(&ge->rdataset_a, rdataset_a);
|
||||
ISC_LIST_APPEND(name->list, rdataset_a, link);
|
||||
if (IS_REQUIRED_GLUE(rdataset_a)) {
|
||||
prepend_name = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (sigrdataset_a != NULL) {
|
||||
dns_rdataset_clone(&ge->sigrdataset_a, sigrdataset_a);
|
||||
ISC_LIST_APPEND(name->list, sigrdataset_a, link);
|
||||
}
|
||||
|
||||
if (rdataset_aaaa != NULL) {
|
||||
dns_rdataset_clone(&ge->rdataset_aaaa, rdataset_aaaa);
|
||||
ISC_LIST_APPEND(name->list, rdataset_aaaa, link);
|
||||
if (IS_REQUIRED_GLUE(rdataset_aaaa)) {
|
||||
prepend_name = true;
|
||||
}
|
||||
}
|
||||
if (sigrdataset_aaaa != NULL) {
|
||||
dns_rdataset_clone(&ge->sigrdataset_aaaa,
|
||||
sigrdataset_aaaa);
|
||||
ISC_LIST_APPEND(name->list, sigrdataset_aaaa, link);
|
||||
}
|
||||
|
||||
dns_message_addname(msg, name, DNS_SECTION_ADDITIONAL);
|
||||
|
||||
/*
|
||||
* When looking for required glue, dns_message_rendersection()
|
||||
* only processes the first rdataset associated with the first
|
||||
* name added to the ADDITIONAL section. dns_message_addname()
|
||||
* performs an append on the list of names in a given section,
|
||||
* so if any glue record was marked as required, we need to
|
||||
* move the name it is associated with to the beginning of the
|
||||
* list for the ADDITIONAL section or else required glue might
|
||||
* not be rendered.
|
||||
*/
|
||||
if (prepend_name) {
|
||||
ISC_LIST_UNLINK(msg->sections[DNS_SECTION_ADDITIONAL],
|
||||
name, link);
|
||||
ISC_LIST_PREPEND(msg->sections[DNS_SECTION_ADDITIONAL],
|
||||
name, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static dns_glue_t *
|
||||
newglue(qpzonedb_t *qpdb, qpz_version_t *version, qpznode_t *node,
|
||||
dns_rdataset_t *rdataset) {
|
||||
dns_fixedname_t nodename;
|
||||
dns_glue_additionaldata_ctx_t ctx = {
|
||||
.db = (dns_db_t *)qpdb,
|
||||
.version = (dns_dbversion_t *)version,
|
||||
.nodename = dns_fixedname_initname(&nodename),
|
||||
};
|
||||
|
||||
/*
|
||||
* Get the owner name of the NS RRset - it will be necessary for
|
||||
* identifying required glue in glue_nsdname_cb() (by
|
||||
* determining which NS records in the delegation are
|
||||
* in-bailiwick).
|
||||
*/
|
||||
dns_name_copy(&node->name, ctx.nodename);
|
||||
|
||||
(void)dns_rdataset_additionaldata(rdataset, dns_rootname,
|
||||
glue_nsdname_cb, &ctx);
|
||||
|
||||
return ctx.glue_list;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
addglue(dns_db_t *db, dns_dbversion_t *dbversion, dns_rdataset_t *rdataset,
|
||||
dns_message_t *msg) {
|
||||
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||
qpz_version_t *version = dbversion;
|
||||
qpznode_t *node = (qpznode_t *)rdataset->slab.node;
|
||||
dns_slabheader_t *header = dns_slabheader_fromrdataset(rdataset);
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(rdataset->type == dns_rdatatype_ns);
|
||||
REQUIRE(qpdb == (qpzonedb_t *)rdataset->slab.db);
|
||||
REQUIRE(qpdb == version->qpdb);
|
||||
REQUIRE(!IS_STUB(qpdb));
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
dns_glue_t *glue = rcu_dereference(header->glue_list);
|
||||
if (glue == NULL) {
|
||||
/* No cached glue was found in the table. Get new glue. */
|
||||
glue = newglue(qpdb, version, node, rdataset);
|
||||
|
||||
/* Cache the glue or (void *)-1 if no glue was found. */
|
||||
dns_glue_t *old_glue = rcu_cmpxchg_pointer(
|
||||
&header->glue_list, NULL, (glue) ? glue : (void *)-1);
|
||||
if (old_glue != NULL) {
|
||||
/* Somebody else was faster */
|
||||
freeglue(glue);
|
||||
glue = old_glue;
|
||||
} else if (glue != NULL) {
|
||||
cds_wfs_push(&version->glue_stack, &header->wfs_node);
|
||||
}
|
||||
}
|
||||
|
||||
/* We have a cached result. Add it to the message and return. */
|
||||
result = dns__db_addglue(db, dbversion, rdataset, msg, glue_nsdname_cb,
|
||||
&version->glue_stack);
|
||||
|
||||
if (qpdb->gluecachestats != NULL) {
|
||||
isc_stats_increment(
|
||||
qpdb->gluecachestats,
|
||||
(glue == (void *)-1)
|
||||
? dns_gluecachestatscounter_hits_absent
|
||||
: dns_gluecachestatscounter_hits_present);
|
||||
}
|
||||
isc_statscounter_t counter =
|
||||
(result == ISC_R_SUCCESS)
|
||||
? dns_gluecachestatscounter_hits_present
|
||||
: dns_gluecachestatscounter_hits_absent;
|
||||
|
||||
/*
|
||||
* (void *)-1 is a special value that means no glue is present in the
|
||||
* zone.
|
||||
*/
|
||||
if (glue != (void *)-1) {
|
||||
addglue_to_message(glue, msg);
|
||||
isc_stats_increment(qpdb->gluecachestats, counter);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2091,18 +2091,6 @@ setgluecachestats(dns_db_t *db, isc_stats_t *stats) {
|
|||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static dns_glue_t *
|
||||
new_gluelist(isc_mem_t *mctx, dns_name_t *name) {
|
||||
dns_glue_t *glue = isc_mem_get(mctx, sizeof(*glue));
|
||||
*glue = (dns_glue_t){ 0 };
|
||||
dns_name_t *gluename = dns_fixedname_initname(&glue->fixedname);
|
||||
|
||||
isc_mem_attach(mctx, &glue->mctx);
|
||||
dns_name_copy(name, gluename);
|
||||
|
||||
return glue;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
||||
dns_rdataset_t *unused DNS__DB_FLARG) {
|
||||
|
|
@ -2117,6 +2105,8 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
dns_rdataset_t rdataset_aaaa, sigrdataset_aaaa;
|
||||
dns_rbtnode_t *node_aaaa = NULL;
|
||||
dns_glue_t *glue = NULL;
|
||||
dns_fixedname_t f_nodename;
|
||||
dns_name_t *nodename = dns_fixedname_initname(&f_nodename);
|
||||
|
||||
UNUSED(unused);
|
||||
|
||||
|
|
@ -2127,6 +2117,8 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
|
||||
ctx = (dns_glue_additionaldata_ctx_t *)arg;
|
||||
|
||||
dns__rbtdb_nodefullname(ctx->db, ctx->node, nodename);
|
||||
|
||||
name_a = dns_fixedname_initname(&fixedname_a);
|
||||
dns_rdataset_init(&rdataset_a);
|
||||
dns_rdataset_init(&sigrdataset_a);
|
||||
|
|
@ -2140,7 +2132,7 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
name_a, &rdataset_a,
|
||||
&sigrdataset_a DNS__DB_FLARG_PASS);
|
||||
if (result == DNS_R_GLUE) {
|
||||
glue = new_gluelist(ctx->db->mctx, name_a);
|
||||
glue = dns__db_new_glue(ctx->db->mctx, name_a);
|
||||
|
||||
dns_rdataset_init(&glue->rdataset_a);
|
||||
dns_rdataset_init(&glue->sigrdataset_a);
|
||||
|
|
@ -2160,7 +2152,7 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
&sigrdataset_aaaa DNS__DB_FLARG_PASS);
|
||||
if (result == DNS_R_GLUE) {
|
||||
if (glue == NULL) {
|
||||
glue = new_gluelist(ctx->db->mctx, name_aaaa);
|
||||
glue = dns__db_new_glue(ctx->db->mctx, name_aaaa);
|
||||
|
||||
dns_rdataset_init(&glue->rdataset_a);
|
||||
dns_rdataset_init(&glue->sigrdataset_a);
|
||||
|
|
@ -2186,7 +2178,10 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
* attributes for the first rdataset associated with the first name
|
||||
* added to the ADDITIONAL section.
|
||||
*/
|
||||
if (glue != NULL && dns_name_issubdomain(name, ctx->nodename)) {
|
||||
isc_result_t dns_rbt_fullnamefromnode(dns_rbtnode_t * node,
|
||||
dns_name_t * name);
|
||||
|
||||
if (glue != NULL && dns_name_issubdomain(name, nodename)) {
|
||||
if (dns_rdataset_isassociated(&glue->rdataset_a)) {
|
||||
glue->rdataset_a.attributes |=
|
||||
DNS_RDATASETATTR_REQUIRED;
|
||||
|
|
@ -2198,8 +2193,8 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
}
|
||||
|
||||
if (glue != NULL) {
|
||||
glue->next = ctx->glue_list;
|
||||
ctx->glue_list = glue;
|
||||
glue->next = ctx->glue;
|
||||
ctx->glue = glue;
|
||||
}
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
|
|
@ -2230,163 +2225,30 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
|||
return result;
|
||||
}
|
||||
|
||||
#define IS_REQUIRED_GLUE(r) (((r)->attributes & DNS_RDATASETATTR_REQUIRED) != 0)
|
||||
|
||||
static void
|
||||
addglue_to_message(dns_glue_t *ge, dns_message_t *msg) {
|
||||
for (; ge != NULL; ge = ge->next) {
|
||||
dns_name_t *name = NULL;
|
||||
dns_rdataset_t *rdataset_a = NULL;
|
||||
dns_rdataset_t *sigrdataset_a = NULL;
|
||||
dns_rdataset_t *rdataset_aaaa = NULL;
|
||||
dns_rdataset_t *sigrdataset_aaaa = NULL;
|
||||
dns_name_t *gluename = dns_fixedname_name(&ge->fixedname);
|
||||
bool prepend_name = false;
|
||||
|
||||
dns_message_gettempname(msg, &name);
|
||||
|
||||
dns_name_copy(gluename, name);
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->rdataset_a)) {
|
||||
dns_message_gettemprdataset(msg, &rdataset_a);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->sigrdataset_a)) {
|
||||
dns_message_gettemprdataset(msg, &sigrdataset_a);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->rdataset_aaaa)) {
|
||||
dns_message_gettemprdataset(msg, &rdataset_aaaa);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->sigrdataset_aaaa)) {
|
||||
dns_message_gettemprdataset(msg, &sigrdataset_aaaa);
|
||||
}
|
||||
|
||||
if (rdataset_a != NULL) {
|
||||
dns_rdataset_clone(&ge->rdataset_a, rdataset_a);
|
||||
ISC_LIST_APPEND(name->list, rdataset_a, link);
|
||||
if (IS_REQUIRED_GLUE(rdataset_a)) {
|
||||
prepend_name = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (sigrdataset_a != NULL) {
|
||||
dns_rdataset_clone(&ge->sigrdataset_a, sigrdataset_a);
|
||||
ISC_LIST_APPEND(name->list, sigrdataset_a, link);
|
||||
}
|
||||
|
||||
if (rdataset_aaaa != NULL) {
|
||||
dns_rdataset_clone(&ge->rdataset_aaaa, rdataset_aaaa);
|
||||
ISC_LIST_APPEND(name->list, rdataset_aaaa, link);
|
||||
if (IS_REQUIRED_GLUE(rdataset_aaaa)) {
|
||||
prepend_name = true;
|
||||
}
|
||||
}
|
||||
if (sigrdataset_aaaa != NULL) {
|
||||
dns_rdataset_clone(&ge->sigrdataset_aaaa,
|
||||
sigrdataset_aaaa);
|
||||
ISC_LIST_APPEND(name->list, sigrdataset_aaaa, link);
|
||||
}
|
||||
|
||||
dns_message_addname(msg, name, DNS_SECTION_ADDITIONAL);
|
||||
|
||||
/*
|
||||
* When looking for required glue, dns_message_rendersection()
|
||||
* only processes the first rdataset associated with the first
|
||||
* name added to the ADDITIONAL section. dns_message_addname()
|
||||
* performs an append on the list of names in a given section,
|
||||
* so if any glue record was marked as required, we need to
|
||||
* move the name it is associated with to the beginning of the
|
||||
* list for the ADDITIONAL section or else required glue might
|
||||
* not be rendered.
|
||||
*/
|
||||
if (prepend_name) {
|
||||
ISC_LIST_UNLINK(msg->sections[DNS_SECTION_ADDITIONAL],
|
||||
name, link);
|
||||
ISC_LIST_PREPEND(msg->sections[DNS_SECTION_ADDITIONAL],
|
||||
name, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static dns_glue_t *
|
||||
newglue(dns_rbtdb_t *rbtdb, dns_rbtdb_version_t *rbtversion,
|
||||
dns_rbtnode_t *node, dns_rdataset_t *rdataset) {
|
||||
dns_fixedname_t nodename;
|
||||
dns_glue_additionaldata_ctx_t ctx = {
|
||||
.db = (dns_db_t *)rbtdb,
|
||||
.version = (dns_dbversion_t *)rbtversion,
|
||||
.nodename = dns_fixedname_initname(&nodename),
|
||||
};
|
||||
|
||||
/*
|
||||
* Get the owner name of the NS RRset - it will be necessary for
|
||||
* identifying required glue in glue_nsdname_cb() (by
|
||||
* determining which NS records in the delegation are
|
||||
* in-bailiwick).
|
||||
*/
|
||||
dns__rbtdb_nodefullname((dns_db_t *)rbtdb, node, ctx.nodename);
|
||||
|
||||
(void)dns_rdataset_additionaldata(rdataset, dns_rootname,
|
||||
glue_nsdname_cb, &ctx);
|
||||
|
||||
return ctx.glue_list;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
addglue(dns_db_t *db, dns_dbversion_t *version, dns_rdataset_t *rdataset,
|
||||
addglue(dns_db_t *db, dns_dbversion_t *dbversion, dns_rdataset_t *rdataset,
|
||||
dns_message_t *msg) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
dns_rbtdb_version_t *rbtversion = version;
|
||||
dns_rbtnode_t *node = (dns_rbtnode_t *)rdataset->slab.node;
|
||||
dns_slabheader_t *header = dns_slabheader_fromrdataset(rdataset);
|
||||
dns_rbtdb_version_t *rbtversion = dbversion;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(rdataset->type == dns_rdatatype_ns);
|
||||
REQUIRE(rbtdb == (dns_rbtdb_t *)rdataset->slab.db);
|
||||
REQUIRE(rbtdb == rbtversion->rbtdb);
|
||||
REQUIRE(!IS_CACHE(rbtdb) && !IS_STUB(rbtdb));
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
dns_glue_t *glue = rcu_dereference(header->glue_list);
|
||||
if (glue == NULL) {
|
||||
/* No cached glue was found in the table. Get new glue. */
|
||||
glue = newglue(rbtdb, rbtversion, node, rdataset);
|
||||
|
||||
/* Cache the glue or (void *)-1 if no glue was found. */
|
||||
dns_glue_t *old_glue = rcu_cmpxchg_pointer(
|
||||
&header->glue_list, NULL, (glue) ? glue : (void *)-1);
|
||||
if (old_glue != NULL) {
|
||||
/* Somebody else was faster */
|
||||
dns__rbtdb_freeglue(glue);
|
||||
glue = old_glue;
|
||||
} else if (glue != NULL) {
|
||||
cds_wfs_push(&rbtversion->glue_stack,
|
||||
&header->wfs_node);
|
||||
}
|
||||
}
|
||||
|
||||
/* We have a cached result. Add it to the message and return. */
|
||||
result = dns__db_addglue(db, dbversion, rdataset, msg, glue_nsdname_cb,
|
||||
&rbtversion->glue_stack);
|
||||
|
||||
if (rbtdb->gluecachestats != NULL) {
|
||||
isc_stats_increment(
|
||||
rbtdb->gluecachestats,
|
||||
(glue == (void *)-1)
|
||||
? dns_gluecachestatscounter_hits_absent
|
||||
: dns_gluecachestatscounter_hits_present);
|
||||
}
|
||||
isc_statscounter_t counter =
|
||||
(result == ISC_R_SUCCESS)
|
||||
? dns_gluecachestatscounter_hits_present
|
||||
: dns_gluecachestatscounter_hits_absent;
|
||||
|
||||
/*
|
||||
* (void *)-1 is a special value that means no glue is present in the
|
||||
* zone.
|
||||
*/
|
||||
if (glue != (void *)-1) {
|
||||
addglue_to_message(glue, msg);
|
||||
isc_stats_increment(rbtdb->gluecachestats, counter);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -166,8 +166,6 @@ static void
|
|||
delete_callback(void *data, void *arg);
|
||||
static void
|
||||
prune_tree(void *arg);
|
||||
static void
|
||||
free_gluetable(dns_rbtdb_version_t *version);
|
||||
|
||||
static void
|
||||
rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG);
|
||||
|
|
@ -623,7 +621,7 @@ dns__rbtdb_destroy(dns_db_t *arg) {
|
|||
* node count below.
|
||||
*/
|
||||
if (rbtdb->current_version != NULL) {
|
||||
free_gluetable(rbtdb->current_version);
|
||||
dns__db_cleanup_gluelists(&rbtdb->current_version->glue_stack);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1947,7 +1945,7 @@ dns__rbtdb_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
|||
if (cleanup_version != NULL) {
|
||||
isc_refcount_destroy(&cleanup_version->references);
|
||||
INSIST(EMPTY(cleanup_version->changed_list));
|
||||
free_gluetable(cleanup_version);
|
||||
dns__db_cleanup_gluelists(&cleanup_version->glue_stack);
|
||||
cds_wfs_destroy(&cleanup_version->glue_stack);
|
||||
isc_rwlock_destroy(&cleanup_version->rwlock);
|
||||
isc_mem_put(rbtdb->common.mctx, cleanup_version,
|
||||
|
|
@ -4873,64 +4871,6 @@ dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
|
|||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
dns__rbtdb_freeglue(dns_glue_t *glue_list) {
|
||||
if (glue_list == (void *)-1) {
|
||||
return;
|
||||
}
|
||||
|
||||
dns_glue_t *glue = glue_list;
|
||||
while (glue != NULL) {
|
||||
dns_glue_t *next = glue->next;
|
||||
|
||||
if (dns_rdataset_isassociated(&glue->rdataset_a)) {
|
||||
dns_rdataset_disassociate(&glue->rdataset_a);
|
||||
}
|
||||
if (dns_rdataset_isassociated(&glue->sigrdataset_a)) {
|
||||
dns_rdataset_disassociate(&glue->sigrdataset_a);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&glue->rdataset_aaaa)) {
|
||||
dns_rdataset_disassociate(&glue->rdataset_aaaa);
|
||||
}
|
||||
if (dns_rdataset_isassociated(&glue->sigrdataset_aaaa)) {
|
||||
dns_rdataset_disassociate(&glue->sigrdataset_aaaa);
|
||||
}
|
||||
|
||||
dns_rdataset_invalidate(&glue->rdataset_a);
|
||||
dns_rdataset_invalidate(&glue->sigrdataset_a);
|
||||
dns_rdataset_invalidate(&glue->rdataset_aaaa);
|
||||
dns_rdataset_invalidate(&glue->sigrdataset_aaaa);
|
||||
|
||||
isc_mem_putanddetach(&glue->mctx, glue, sizeof(*glue));
|
||||
|
||||
glue = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_gluelist_rcu(struct rcu_head *rcu_head) {
|
||||
dns_glue_t *glue = caa_container_of(rcu_head, dns_glue_t, rcu_head);
|
||||
|
||||
dns__rbtdb_freeglue(glue);
|
||||
}
|
||||
|
||||
static void
|
||||
free_gluetable(dns_rbtdb_version_t *rbtversion) {
|
||||
struct cds_wfs_head *head = __cds_wfs_pop_all(&rbtversion->glue_stack);
|
||||
struct cds_wfs_node *node = NULL, *next = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
cds_wfs_for_each_blocking_safe(head, node, next) {
|
||||
dns_slabheader_t *header =
|
||||
caa_container_of(node, dns_slabheader_t, wfs_node);
|
||||
dns_glue_t *glue = rcu_xchg_pointer(&header->glue_list, NULL);
|
||||
|
||||
call_rcu(&glue->rcu_head, free_gluelist_rcu);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void
|
||||
dns__rbtdb_deletedata(dns_db_t *db ISC_ATTR_UNUSED,
|
||||
dns_dbnode_t *node ISC_ATTR_UNUSED, void *data) {
|
||||
|
|
@ -4958,10 +4898,6 @@ dns__rbtdb_deletedata(dns_db_t *db ISC_ATTR_UNUSED,
|
|||
if (header->closest != NULL) {
|
||||
dns_slabheader_freeproof(db->mctx, &header->closest);
|
||||
}
|
||||
} else {
|
||||
if (header->glue_list) {
|
||||
dns__rbtdb_freeglue(header->glue_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1081,15 +1081,12 @@ dns_slabheader_reset(dns_slabheader_t *h, dns_db_t *db, dns_dbnode_t *node) {
|
|||
ISC_LINK_INIT(h, link);
|
||||
h->heap_index = 0;
|
||||
h->heap = NULL;
|
||||
h->glue_list = NULL;
|
||||
h->db = db;
|
||||
h->node = node;
|
||||
|
||||
atomic_init(&h->attributes, 0);
|
||||
atomic_init(&h->last_refresh_fail_ts, 0);
|
||||
|
||||
cds_wfs_node_init(&h->wfs_node);
|
||||
|
||||
STATIC_ASSERT((sizeof(h->attributes) == 2),
|
||||
"The .attributes field of dns_slabheader_t needs to be "
|
||||
"16-bit int type exactly.");
|
||||
|
|
|
|||
Loading…
Reference in a new issue