2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

Run the RPZ update as offloaded work

Previously, the RPZ updates ran quantized on the main nm_worker loops.
As the quantum was set to 1024, this might lead to service
interruptions when large RPZ update was processed.

Change the RPZ update process to run as the offloaded work.  The update
and cleanup loops were refactored to do as little locking of the
maintenance lock as possible for the shortest periods of time and the db
iterator is being paused for every iteration, so we don't hold the rbtdb
tree lock for prolonged periods of time.
This commit is contained in:
Ondřej Surý
2022-03-07 13:55:03 +01:00
parent b6e885c97f
commit f106d0ed2b
3 changed files with 264 additions and 371 deletions

View File

@@ -88,11 +88,6 @@
#define DNS_RPZ_HTSIZE_MAX 24
#define DNS_RPZ_HTSIZE_DIV 3
/*
* Maximum number of nodes to process per quantum
*/
#define DNS_RPZ_QUANTUM 1024
static void
update_from_db(dns_rpz_zone_t *rpz);
@@ -172,6 +167,9 @@ struct dns_rpz_nm_data {
dns_rpz_nm_zbits_t wild;
};
static isc_result_t
rpz_shuttingdown(dns_rpz_zone_t *rpz);
static isc_result_t
rpz_add(dns_rpz_zone_t *rpz, const dns_name_t *src_name);
static void
@@ -1522,7 +1520,7 @@ dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp) {
/*
* This will never be used, but costs us nothing and
* simplifies update_from_db
* simplifies update_from_db().
*/
isc_ht_init(&rpz->nodes, rpzs->mctx, 1, ISC_HT_CASE_SENSITIVE);
@@ -1556,7 +1554,6 @@ isc_result_t
dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg) {
dns_rpz_zone_t *rpz = (dns_rpz_zone_t *)fn_arg;
isc_time_t now;
uint64_t tdiff;
isc_result_t result = ISC_R_SUCCESS;
char dname[DNS_NAME_FORMATSIZE];
@@ -1581,15 +1578,18 @@ dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg) {
dns_db_attach(db, &rpz->db);
}
dns_name_format(&rpz->origin, dname, DNS_NAME_FORMATSIZE);
if (!rpz->updatepending && !rpz->updaterunning) {
uint64_t tdiff;
rpz->updatepending = true;
isc_time_now(&now);
tdiff = isc_time_microdiff(&now, &rpz->lastupdated) / 1000000;
if (tdiff < rpz->min_update_interval) {
uint64_t defer = rpz->min_update_interval - tdiff;
isc_interval_t interval;
dns_name_format(&rpz->origin, dname,
DNS_NAME_FORMATSIZE);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
"rpz: %s: new zone version came "
@@ -1601,9 +1601,6 @@ dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg) {
result = isc_timer_reset(rpz->updatetimer,
isc_timertype_once, &interval,
true);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
} else {
isc_event_t *event = NULL;
@@ -1619,7 +1616,6 @@ dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg) {
}
} else {
rpz->updatepending = true;
dns_name_format(&rpz->origin, dname, DNS_NAME_FORMATSIZE);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
"rpz: %s: update already queued or running",
@@ -1629,8 +1625,6 @@ dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg) {
}
dns_db_currentversion(rpz->db, &rpz->dbversion);
}
cleanup:
UNLOCK(&rpz->rpzs->maint_lock);
return (result);
@@ -1662,18 +1656,75 @@ dns_rpz_update_taskaction(isc_task_t *task, isc_event_t *event) {
UNLOCK(&rpz->rpzs->maint_lock);
}
static void
update_rpz_done_cb(void *data, isc_result_t result) {
dns_rpz_zone_t *rpz = (dns_rpz_zone_t *)data;
char dname[DNS_NAME_FORMATSIZE];
if (result == ISC_R_SUCCESS && rpz->updateresult != ISC_R_SUCCESS) {
result = rpz->updateresult;
}
LOCK(&rpz->rpzs->maint_lock);
rpz->updaterunning = false;
dns_name_format(&rpz->origin, dname, DNS_NAME_FORMATSIZE);
/* If there's no update pending, finish. */
if (!rpz->updatepending) {
goto done;
}
/* If there's an update pending, schedule it */
if (rpz->min_update_interval > 0) {
uint64_t defer = rpz->min_update_interval;
isc_interval_t interval;
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
"rpz: %s: new zone version came "
"too soon, deferring update for "
"%" PRIu64 " seconds",
dname, defer);
isc_interval_set(&interval, (unsigned int)defer, 0);
isc_timer_reset(rpz->updatetimer, isc_timertype_once, &interval,
true);
} else {
isc_event_t *event = NULL;
INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
ISC_EVENT_INIT(&rpz->updateevent, sizeof(rpz->updateevent), 0,
NULL, DNS_EVENT_RPZUPDATED,
dns_rpz_update_taskaction, rpz, rpz, NULL, NULL);
event = &rpz->updateevent;
isc_task_send(rpz->rpzs->updater, &event);
}
done:
dns_db_closeversion(rpz->updb, &rpz->updbversion, false);
dns_db_detach(&rpz->updb);
UNLOCK(&rpz->rpzs->maint_lock);
rpz_detach(&rpz);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
ISC_LOG_INFO, "rpz: %s: reload done: %s", dname,
isc_result_totext(result));
}
static isc_result_t
setup_update(dns_rpz_zone_t *rpz) {
update_nodes(dns_rpz_zone_t *rpz, isc_ht_t *newnodes) {
isc_result_t result;
dns_dbiterator_t *updbit = NULL;
dns_name_t *name = NULL;
dns_fixedname_t fixname;
char domain[DNS_NAME_FORMATSIZE];
dns_name_format(&rpz->origin, domain, DNS_NAME_FORMATSIZE);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
ISC_LOG_INFO, "rpz: %s: reload start", domain);
isc_ht_init(&rpz->newnodes, rpz->rpzs->mctx, 1, ISC_HT_CASE_SENSITIVE);
name = dns_fixedname_initname(&fixname);
result = dns_db_createiterator(rpz->updb, DNS_DB_NONSEC3, &rpz->updbit);
result = dns_db_createiterator(rpz->updb, DNS_DB_NONSEC3, &updbit);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
@@ -1682,8 +1733,8 @@ setup_update(dns_rpz_zone_t *rpz) {
goto cleanup;
}
result = dns_dbiterator_first(rpz->updbit);
if (result != ISC_R_SUCCESS) {
result = dns_dbiterator_first(updbit);
if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
"rpz: %s: failed to get db iterator - %s", domain,
@@ -1691,220 +1742,30 @@ setup_update(dns_rpz_zone_t *rpz) {
goto cleanup;
}
result = dns_dbiterator_pause(rpz->updbit);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
"rpz: %s: failed to pause db iterator - %s",
domain, isc_result_totext(result));
goto cleanup;
}
cleanup:
if (result != ISC_R_SUCCESS) {
if (rpz->updbit != NULL) {
dns_dbiterator_destroy(&rpz->updbit);
}
if (rpz->newnodes != NULL) {
isc_ht_destroy(&rpz->newnodes);
}
dns_db_closeversion(rpz->updb, &rpz->updbversion, false);
}
return (result);
}
static void
finish_update(dns_rpz_zone_t *rpz) {
LOCK(&rpz->rpzs->maint_lock);
rpz->updaterunning = false;
/*
* If there's an update pending, schedule it.
*/
if (rpz->updatepending) {
if (rpz->min_update_interval > 0) {
uint64_t defer = rpz->min_update_interval;
char dname[DNS_NAME_FORMATSIZE];
isc_interval_t interval;
dns_name_format(&rpz->origin, dname,
DNS_NAME_FORMATSIZE);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
"rpz: %s: new zone version came "
"too soon, deferring update for "
"%" PRIu64 " seconds",
dname, defer);
isc_interval_set(&interval, (unsigned int)defer, 0);
isc_timer_reset(rpz->updatetimer, isc_timertype_once,
&interval, true);
} else {
isc_event_t *event = NULL;
INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
ISC_EVENT_INIT(&rpz->updateevent,
sizeof(rpz->updateevent), 0, NULL,
DNS_EVENT_RPZUPDATED,
dns_rpz_update_taskaction, rpz, rpz,
NULL, NULL);
event = &rpz->updateevent;
isc_task_send(rpz->rpzs->updater, &event);
}
}
UNLOCK(&rpz->rpzs->maint_lock);
}
static void
cleanup_quantum(isc_task_t *task, isc_event_t *event) {
isc_result_t result = ISC_R_SUCCESS;
char domain[DNS_NAME_FORMATSIZE];
dns_rpz_zone_t *rpz = NULL;
isc_ht_iter_t *iter = NULL;
dns_fixedname_t fname;
dns_name_t *name = NULL;
int count = 0;
UNUSED(task);
REQUIRE(event != NULL);
REQUIRE(event->ev_sender != NULL);
rpz = (dns_rpz_zone_t *)event->ev_sender;
iter = (isc_ht_iter_t *)event->ev_arg;
isc_event_free(&event);
if (iter == NULL) {
/*
* Iterate over old ht with existing nodes deleted to
* delete deleted nodes from RPZ
*/
isc_ht_iter_create(rpz->nodes, &iter);
}
name = dns_fixedname_initname(&fname);
LOCK(&rpz->rpzs->maint_lock);
/* Check that we aren't shutting down. */
if (rpz->rpzs->zones[rpz->num] == NULL) {
UNLOCK(&rpz->rpzs->maint_lock);
goto cleanup;
}
for (result = isc_ht_iter_first(iter);
result == ISC_R_SUCCESS && count++ < DNS_RPZ_QUANTUM;
result = isc_ht_iter_delcurrent_next(iter))
{
isc_region_t region;
unsigned char *key = NULL;
size_t keysize;
isc_ht_iter_currentkey(iter, &key, &keysize);
region.base = key;
region.length = (unsigned int)keysize;
dns_name_fromregion(name, &region);
rpz_del(rpz, name);
}
if (result == ISC_R_SUCCESS) {
isc_event_t *nevent = NULL;
/*
* We finished a quantum; trigger the next one and return.
*/
INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
ISC_EVENT_INIT(&rpz->updateevent, sizeof(rpz->updateevent), 0,
NULL, DNS_EVENT_RPZUPDATED, cleanup_quantum,
iter, rpz, NULL, NULL);
nevent = &rpz->updateevent;
isc_task_send(rpz->rpzs->updater, &nevent);
UNLOCK(&rpz->rpzs->maint_lock);
return;
} else if (result == ISC_R_NOMORE) {
isc_ht_t *tmpht = NULL;
/*
* Done with cleanup of deleted nodes; finalize
* the update.
*/
tmpht = rpz->nodes;
rpz->nodes = rpz->newnodes;
rpz->newnodes = tmpht;
UNLOCK(&rpz->rpzs->maint_lock);
finish_update(rpz);
dns_name_format(&rpz->origin, domain, DNS_NAME_FORMATSIZE);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
"rpz: %s: reload done", domain);
} else {
UNLOCK(&rpz->rpzs->maint_lock);
}
/*
* If we're here, we're finished or something went wrong.
*/
cleanup:
if (iter != NULL) {
isc_ht_iter_destroy(&iter);
}
if (rpz->newnodes != NULL) {
isc_ht_destroy(&rpz->newnodes);
}
dns_db_closeversion(rpz->updb, &rpz->updbversion, false);
dns_db_detach(&rpz->updb);
rpz_detach(&rpz);
}
static void
update_quantum(isc_task_t *task, isc_event_t *event) {
isc_result_t result = ISC_R_SUCCESS;
dns_dbnode_t *node = NULL;
dns_rpz_zone_t *rpz = NULL;
char domain[DNS_NAME_FORMATSIZE];
dns_fixedname_t fixname;
dns_name_t *name = NULL;
isc_event_t *nevent = NULL;
int count = 0;
UNUSED(task);
REQUIRE(event != NULL);
REQUIRE(event->ev_arg != NULL);
rpz = (dns_rpz_zone_t *)event->ev_arg;
isc_event_free(&event);
REQUIRE(rpz->updbit != NULL);
REQUIRE(rpz->newnodes != NULL);
name = dns_fixedname_initname(&fixname);
dns_name_format(&rpz->origin, domain, DNS_NAME_FORMATSIZE);
LOCK(&rpz->rpzs->maint_lock);
/* Check that we aren't shutting down. */
if (rpz->rpzs->zones[rpz->num] == NULL) {
UNLOCK(&rpz->rpzs->maint_lock);
goto cleanup;
}
while (result == ISC_R_SUCCESS && count++ < DNS_RPZ_QUANTUM) {
while (result == ISC_R_SUCCESS) {
char namebuf[DNS_NAME_FORMATSIZE];
dns_rdatasetiter_t *rdsiter = NULL;
dns_dbnode_t *node = NULL;
result = dns_dbiterator_current(rpz->updbit, &node, name);
result = rpz_shuttingdown(rpz);
if (result != ISC_R_SUCCESS) {
dns_db_detachnode(rpz->updb, &node);
goto cleanup;
}
result = dns_dbiterator_current(updbit, &node, name);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
"rpz: %s: failed to get dbiterator - %s",
domain, isc_result_totext(result));
dns_db_detachnode(rpz->updb, &node);
break;
goto cleanup;
}
result = dns_dbiterator_pause(updbit);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = dns_db_allrdatasets(rpz->updb, node, rpz->updbversion,
0, &rdsiter);
if (result != ISC_R_SUCCESS) {
@@ -1914,12 +1775,15 @@ update_quantum(isc_task_t *task, isc_event_t *event) {
"rrdatasets - %s",
domain, isc_result_totext(result));
dns_db_detachnode(rpz->updb, &node);
break;
goto cleanup;
}
result = dns_rdatasetiter_first(rdsiter);
dns_rdatasetiter_destroy(&rdsiter);
if (result != ISC_R_SUCCESS) { /* empty non-terminal */
dns_db_detachnode(rpz->updb, &node);
if (result != ISC_R_SUCCESS) { /* skip empty non-terminal */
if (result != ISC_R_NOMORE) {
isc_log_write(
dns_lctx, DNS_LOGCATEGORY_GENERAL,
@@ -1928,14 +1792,13 @@ update_quantum(isc_task_t *task, isc_event_t *event) {
"rdatasetiter",
domain, isc_result_totext(result));
}
dns_db_detachnode(rpz->updb, &node);
result = dns_dbiterator_next(rpz->updbit);
continue;
goto next;
}
dns_name_downcase(name, name, NULL);
result = isc_ht_add(rpz->newnodes, name->ndata, name->length,
rpz);
/* Add entry to the new nodes table */
result = isc_ht_add(newnodes, name->ndata, name->length, rpz);
if (result != ISC_R_SUCCESS) {
dns_name_format(name, namebuf, sizeof(namebuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
@@ -1943,131 +1806,170 @@ update_quantum(isc_task_t *task, isc_event_t *event) {
"rpz: %s, adding node %s to HT error %s",
domain, namebuf,
isc_result_totext(result));
dns_db_detachnode(rpz->updb, &node);
result = dns_dbiterator_next(rpz->updbit);
continue;
goto next;
}
/* Does the entry exist in the old nodes table? */
result = isc_ht_find(rpz->nodes, name->ndata, name->length,
NULL);
if (result == ISC_R_SUCCESS) {
if (result == ISC_R_SUCCESS) { /* found */
isc_ht_delete(rpz->nodes, name->ndata, name->length);
} else { /* not found */
result = rpz_add(rpz, name);
if (result != ISC_R_SUCCESS) {
dns_name_format(name, namebuf, sizeof(namebuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER,
ISC_LOG_ERROR,
"rpz: %s: adding node %s "
"to RPZ error %s",
domain, namebuf,
isc_result_totext(result));
} else {
dns_name_format(name, namebuf, sizeof(namebuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER,
ISC_LOG_DEBUG(3),
"rpz: %s: adding node %s", domain,
namebuf);
}
goto next;
}
dns_db_detachnode(rpz->updb, &node);
result = dns_dbiterator_next(rpz->updbit);
}
if (result == ISC_R_SUCCESS) {
/*
* Pause the iterator so that the DB is not locked.
* Only the single rpz updates are serialized, so we need to
* lock here because we can be processing more updates to
* different rpz zones at the same time
*/
dns_dbiterator_pause(rpz->updbit);
/*
* We finished a quantum; trigger the next one and return.
*/
INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
ISC_EVENT_INIT(&rpz->updateevent, sizeof(rpz->updateevent), 0,
NULL, DNS_EVENT_RPZUPDATED, update_quantum, rpz,
rpz, NULL, NULL);
nevent = &rpz->updateevent;
isc_task_send(rpz->rpzs->updater, &nevent);
LOCK(&rpz->rpzs->maint_lock);
result = rpz_add(rpz, name);
UNLOCK(&rpz->rpzs->maint_lock);
return;
} else if (result == ISC_R_NOMORE) {
/*
* Done with the new database; now we just need to
* clean up the old.
*/
dns_dbiterator_destroy(&rpz->updbit);
INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
ISC_EVENT_INIT(&rpz->updateevent, sizeof(rpz->updateevent), 0,
NULL, DNS_EVENT_RPZUPDATED, cleanup_quantum,
NULL, rpz, NULL, NULL);
nevent = &rpz->updateevent;
isc_task_send(rpz->rpzs->updater, &nevent);
UNLOCK(&rpz->rpzs->maint_lock);
return;
if (result != ISC_R_SUCCESS) {
dns_name_format(name, namebuf, sizeof(namebuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
"rpz: %s: adding node %s "
"to RPZ error %s",
domain, namebuf,
isc_result_totext(result));
} else if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
dns_name_format(name, namebuf, sizeof(namebuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
"rpz: %s: adding node %s", domain,
namebuf);
}
next:
result = dns_dbiterator_next(updbit);
}
INSIST(result != ISC_R_SUCCESS);
if (result == ISC_R_NOMORE) {
result = ISC_R_SUCCESS;
}
/*
* If we're here, something went wrong, so clean up.
*/
UNLOCK(&rpz->rpzs->maint_lock);
cleanup:
if (rpz->updbit != NULL) {
dns_dbiterator_destroy(&rpz->updbit);
dns_dbiterator_destroy(&updbit);
return (result);
}
static isc_result_t
cleanup_nodes(dns_rpz_zone_t *rpz) {
isc_result_t result;
isc_ht_iter_t *iter = NULL;
dns_name_t *name = NULL;
dns_fixedname_t fixname;
name = dns_fixedname_initname(&fixname);
isc_ht_iter_create(rpz->nodes, &iter);
for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS;
result = isc_ht_iter_delcurrent_next(iter))
{
isc_region_t region;
unsigned char *key = NULL;
size_t keysize;
result = rpz_shuttingdown(rpz);
if (result != ISC_R_SUCCESS) {
break;
}
isc_ht_iter_currentkey(iter, &key, &keysize);
region.base = key;
region.length = (unsigned int)keysize;
dns_name_fromregion(name, &region);
LOCK(&rpz->rpzs->maint_lock);
rpz_del(rpz, name);
UNLOCK(&rpz->rpzs->maint_lock);
}
if (rpz->newnodes != NULL) {
isc_ht_destroy(&rpz->newnodes);
INSIST(result != ISC_R_SUCCESS);
if (result == ISC_R_NOMORE) {
result = ISC_R_SUCCESS;
}
dns_db_closeversion(rpz->updb, &rpz->updbversion, false);
dns_db_detach(&rpz->updb);
rpz_detach(&rpz);
isc_ht_iter_destroy(&iter);
return (result);
}
static isc_result_t
rpz_shuttingdown(dns_rpz_zone_t *rpz) {
bool shuttingdown = false;
LOCK(&rpz->rpzs->maint_lock);
/* Check that we aren't shutting down. */
shuttingdown = (rpz->rpzs->zones[rpz->num] == NULL);
UNLOCK(&rpz->rpzs->maint_lock);
if (shuttingdown) {
return (ISC_R_SHUTTINGDOWN);
}
return (ISC_R_SUCCESS);
}
static void
update_from_db(dns_rpz_zone_t *rpz) {
dns_rpz_zone_t *rpz_zone = NULL;
update_rpz_cb(void *data) {
dns_rpz_zone_t *rpz = (dns_rpz_zone_t *)data;
isc_result_t result = ISC_R_SUCCESS;
isc_ht_t *newnodes = NULL;
REQUIRE(rpz != NULL);
REQUIRE(DNS_DB_VALID(rpz->db));
REQUIRE(rpz->updb == NULL);
REQUIRE(rpz->updbversion == NULL);
REQUIRE(rpz->updbit == NULL);
REQUIRE(rpz->newnodes == NULL);
REQUIRE(rpz->nodes != NULL);
rpz_attach(rpz, &(dns_rpz_zone_t *){ NULL });
dns_db_attach(rpz->db, &rpz->updb);
rpz->updbversion = rpz->dbversion;
rpz->dbversion = NULL;
result = setup_update(rpz);
result = rpz_shuttingdown(rpz);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
event = &rpz->updateevent;
INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
ISC_EVENT_INIT(&rpz->updateevent, sizeof(rpz->updateevent), 0, NULL,
DNS_EVENT_RPZUPDATED, update_quantum, rpz, rpz, NULL,
NULL);
isc_task_send(rpz->rpzs->updater, &event);
return;
isc_ht_init(&newnodes, rpz->rpzs->mctx, 1, ISC_HT_CASE_SENSITIVE);
result = update_nodes(rpz, newnodes);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
result = cleanup_nodes(rpz);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
/* Finalize the update */
ISC_SWAP(rpz->nodes, newnodes);
cleanup:
if (rpz->updbit != NULL) {
dns_dbiterator_destroy(&rpz->updbit);
}
if (rpz->newnodes != NULL) {
isc_ht_destroy(&rpz->newnodes);
}
dns_db_closeversion(rpz->updb, &rpz->updbversion, false);
dns_db_detach(&rpz->updb);
rpz_detach(&rpz);
isc_ht_destroy(&newnodes);
rpz->updateresult = result;
}
static void
update_from_db(dns_rpz_zone_t *rpz) {
char domain[DNS_NAME_FORMATSIZE];
dns_rpz_zone_t *rpz_zone = NULL;
REQUIRE(isc_nm_tid() >= 0);
REQUIRE(rpz != NULL);
REQUIRE(DNS_DB_VALID(rpz->db));
REQUIRE(rpz->updb == NULL);
REQUIRE(rpz->updbversion == NULL);
rpz_attach(rpz, &rpz_zone);
dns_db_attach(rpz->db, &rpz->updb);
rpz->updbversion = rpz->dbversion;
rpz->dbversion = NULL;
dns_name_format(&rpz->origin, domain, DNS_NAME_FORMATSIZE);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
ISC_LOG_INFO, "rpz: %s: reload start", domain);
isc_nm_work_offload(isc_task_getnetmgr(rpz->rpzs->updater),
update_rpz_cb, update_rpz_done_cb, rpz_zone);
}
/*
@@ -2154,22 +2056,8 @@ rpz_destroy(dns_rpz_zone_t *rpz) {
dns_rpz_dbupdate_callback, rpz);
dns_db_detach(&rpz->db);
}
if (rpz->updaterunning) {
isc_task_purgeevent(rpzs->updater, &rpz->updateevent);
if (rpz->updbit != NULL) {
dns_dbiterator_destroy(&rpz->updbit);
}
if (rpz->newnodes != NULL) {
isc_ht_destroy(&rpz->newnodes);
}
if (rpz->updb != NULL) {
if (rpz->updbversion != NULL) {
dns_db_closeversion(rpz->updb,
&rpz->updbversion, false);
}
dns_db_detach(&rpz->updb);
}
}
INSIST(!rpz->updaterunning);
isc_timer_destroy(&rpz->updatetimer);
@@ -2214,20 +2102,19 @@ dns_rpz_detach_rpzs(dns_rpz_zones_t **rpzsp) {
*rpzsp = NULL;
if (isc_refcount_decrement(&rpzs->refs) == 1) {
LOCK(&rpzs->maint_lock);
/*
* Forget the last of view's rpz machinery after
* Forget the last of the view's rpz machinery after
* the last reference.
*/
LOCK(&rpzs->maint_lock);
for (dns_rpz_num_t rpz_num = 0; rpz_num < DNS_RPZ_MAX_ZONES;
++rpz_num) {
dns_rpz_zone_t *rpz = rpzs->zones[rpz_num];
rpzs->zones[rpz_num] = NULL;
if (rpz != NULL) {
rpz_detach(&rpz);
if (rpzs->zones[rpz_num] != NULL) {
rpz_detach(&rpzs->zones[rpz_num]);
}
}
UNLOCK(&rpzs->maint_lock);
rpz_detach_rpzs(&rpzs);
}
}