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

refactor update processing to use loop callbacks

update processing now uses loop callbacks instead of task events.
This commit is contained in:
Evan Hunt
2022-10-26 23:35:47 -07:00
committed by Ondřej Surý
parent 6d7fdb884c
commit 327b95566d
3 changed files with 64 additions and 92 deletions

View File

@@ -14,6 +14,7 @@
#include <inttypes.h>
#include <stdbool.h>
#include <isc/async.h>
#include <isc/netaddr.h>
#include <isc/serial.h>
#include <isc/stats.h>
@@ -24,7 +25,6 @@
#include <dns/dbiterator.h>
#include <dns/diff.h>
#include <dns/dnssec.h>
#include <dns/events.h>
#include <dns/fixedname.h>
#include <dns/journal.h>
#include <dns/keyvalues.h>
@@ -222,11 +222,11 @@ struct rr {
dns_rdata_t rdata;
};
typedef struct update_event update_event_t;
typedef struct update update_t;
struct update_event {
ISC_EVENT_COMMON(update_event_t);
struct update {
dns_zone_t *zone;
ns_client_t *client;
isc_result_t result;
dns_message_t *answer;
const dns_ssurule_t **rules;
@@ -261,13 +261,13 @@ typedef struct {
*/
static void
update_action(isc_task_t *task, isc_event_t *event);
update_action(void *arg);
static void
updatedone_action(isc_task_t *task, isc_event_t *event);
updatedone_action(void *arg);
static isc_result_t
send_forward_event(ns_client_t *client, dns_zone_t *zone);
send_forward(ns_client_t *client, dns_zone_t *zone);
static void
forward_done(isc_task_t *task, isc_event_t *event);
forward_done(void *arg);
static isc_result_t
add_rr_prepare_action(void *data, rr_t *rr);
static isc_result_t
@@ -1644,10 +1644,8 @@ check_soa_increment(dns_db_t *db, dns_dbversion_t *ver,
*/
static isc_result_t
send_update_event(ns_client_t *client, dns_zone_t *zone) {
send_update(ns_client_t *client, dns_zone_t *zone) {
isc_result_t result = ISC_R_SUCCESS;
update_event_t *event = NULL;
isc_task_t *zonetask = NULL;
dns_ssutable_t *ssutable = NULL;
dns_message_t *request = client->message;
isc_mem_t *mctx = client->manager->mctx;
@@ -1660,6 +1658,7 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
dns_zoneopt_t options;
dns_db_t *db = NULL;
dns_dbversion_t *ver = NULL;
update_t *uev = NULL;
CHECK(dns_zone_getdb(zone, &db));
zonename = dns_db_origin(db);
@@ -1894,18 +1893,18 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
CHECK(DNS_R_DROP);
}
event = (update_event_t *)isc_event_allocate(
client->manager->mctx, client, DNS_EVENT_UPDATE, update_action,
client, sizeof(*event));
event->zone = zone;
event->result = ISC_R_SUCCESS;
event->rules = rules;
event->ruleslen = ruleslen;
rules = NULL;
uev = isc_mem_get(client->manager->mctx, sizeof(*uev));
*uev = (update_t){
.zone = zone,
.client = client,
.rules = rules,
.ruleslen = ruleslen,
.result = ISC_R_SUCCESS,
};
isc_nmhandle_attach(client->handle, &client->updatehandle);
dns_zone_gettask(zone, &zonetask);
isc_task_send(zonetask, ISC_EVENT_PTR(&event));
isc_async_run(dns_zone_getloop(zone), update_action, uev);
rules = NULL;
failure:
if (db != NULL) {
@@ -2024,12 +2023,12 @@ ns_update_start(ns_client_t *client, isc_nmhandle_t *handle,
FAIL(sigresult);
}
dns_message_clonebuffer(client->message);
CHECK(send_update_event(client, zone));
CHECK(send_update(client, zone));
break;
case dns_zone_secondary:
case dns_zone_mirror:
dns_message_clonebuffer(client->message);
CHECK(send_forward_event(client, zone));
CHECK(send_forward(client, zone));
break;
default:
FAILC(DNS_R_NOTAUTH, "not authoritative for update zone");
@@ -2043,7 +2042,7 @@ failure:
/*
* We failed without having sent an update event to the zone.
* We are still in the client task context, so we can
* We are still in the client context, so we can
* simply give an error response without switching tasks.
*/
if (result == DNS_R_DROP) {
@@ -2882,10 +2881,10 @@ isdnssec(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype) {
}
static void
update_action(isc_task_t *task, isc_event_t *event) {
update_event_t *uev = (update_event_t *)event;
update_action(void *arg) {
update_t *uev = (update_t *)arg;
dns_zone_t *zone = uev->zone;
ns_client_t *client = (ns_client_t *)event->ev_arg;
ns_client_t *client = uev->client;
const dns_ssurule_t **rules = uev->rules;
size_t rule = 0, ruleslen = uev->ruleslen;
isc_result_t result;
@@ -2910,8 +2909,6 @@ update_action(isc_task_t *task, isc_event_t *event) {
uint32_t maxrecords;
uint64_t records;
INSIST(event->ev_type == DNS_EVENT_UPDATE);
dns_diff_init(mctx, &diff);
dns_diff_init(mctx, &temp);
@@ -3588,29 +3585,20 @@ common:
dns_ssutable_detach(&ssutable);
}
isc_task_detach(&task);
uev->result = result;
if (zone != NULL) {
INSIST(uev->zone == zone); /* we use this later */
}
uev->ev_type = DNS_EVENT_UPDATEDONE;
uev->ev_action = updatedone_action;
isc_task_send(client->manager->task, &event);
isc_async_run(client->manager->loop, updatedone_action, uev);
INSIST(ver == NULL);
INSIST(event == NULL);
}
static void
updatedone_action(isc_task_t *task, isc_event_t *event) {
update_event_t *uev = (update_event_t *)event;
ns_client_t *client = (ns_client_t *)event->ev_arg;
updatedone_action(void *arg) {
update_t *uev = (update_t *)arg;
ns_client_t *client = uev->client;
UNUSED(task);
REQUIRE(event->ev_type == DNS_EVENT_UPDATEDONE);
REQUIRE(task == client->manager->task);
REQUIRE(client->updatehandle == client->handle);
switch (uev->result) {
@@ -3624,14 +3612,14 @@ updatedone_action(isc_task_t *task, isc_event_t *event) {
inc_stats(client, uev->zone, ns_statscounter_updatefail);
break;
}
if (uev->zone != NULL) {
dns_zone_detach(&uev->zone);
}
respond(client, uev->result);
isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota });
isc_event_free(&event);
if (uev->zone != NULL) {
dns_zone_detach(&uev->zone);
}
isc_mem_put(client->manager->mctx, uev, sizeof(*uev));
isc_nmhandle_detach(&client->updatehandle);
}
@@ -3639,85 +3627,74 @@ updatedone_action(isc_task_t *task, isc_event_t *event) {
* Update forwarding support.
*/
static void
forward_fail(isc_task_t *task, isc_event_t *event) {
ns_client_t *client = (ns_client_t *)event->ev_arg;
UNUSED(task);
forward_fail(void *arg) {
update_t *uev = (update_t *)arg;
ns_client_t *client = uev->client;
respond(client, DNS_R_SERVFAIL);
isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota });
isc_event_free(&event);
isc_mem_put(client->manager->mctx, uev, sizeof(*uev));
isc_nmhandle_detach(&client->updatehandle);
}
static void
forward_callback(void *arg, isc_result_t result, dns_message_t *answer) {
update_event_t *uev = arg;
ns_client_t *client = uev->ev_arg;
update_t *uev = (update_t *)arg;
ns_client_t *client = uev->client;
dns_zone_t *zone = uev->zone;
if (result != ISC_R_SUCCESS) {
INSIST(answer == NULL);
uev->ev_type = DNS_EVENT_UPDATEDONE;
uev->ev_action = forward_fail;
inc_stats(client, zone, ns_statscounter_updatefwdfail);
isc_async_run(client->manager->loop, forward_fail, uev);
} else {
uev->ev_type = DNS_EVENT_UPDATEDONE;
uev->ev_action = forward_done;
uev->answer = answer;
inc_stats(client, zone, ns_statscounter_updaterespfwd);
isc_async_run(client->manager->loop, forward_done, uev);
}
isc_task_send(client->manager->task, ISC_EVENT_PTR(&uev));
dns_zone_detach(&zone);
}
static void
forward_done(isc_task_t *task, isc_event_t *event) {
update_event_t *uev = (update_event_t *)event;
ns_client_t *client = (ns_client_t *)event->ev_arg;
UNUSED(task);
forward_done(void *arg) {
update_t *uev = (update_t *)arg;
ns_client_t *client = uev->client;
ns_client_sendraw(client, uev->answer);
dns_message_detach(&uev->answer);
isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota });
isc_event_free(&event);
isc_mem_put(client->manager->mctx, uev, sizeof(*uev));
isc_nmhandle_detach(&client->reqhandle);
isc_nmhandle_detach(&client->updatehandle);
}
static void
forward_action(isc_task_t *task, isc_event_t *event) {
update_event_t *uev = (update_event_t *)event;
forward_action(void *arg) {
update_t *uev = (update_t *)arg;
dns_zone_t *zone = uev->zone;
ns_client_t *client = (ns_client_t *)event->ev_arg;
ns_client_t *client = uev->client;
isc_result_t result;
result = dns_zone_forwardupdate(zone, client->message, forward_callback,
event);
uev);
if (result != ISC_R_SUCCESS) {
uev->ev_type = DNS_EVENT_UPDATEDONE;
uev->ev_action = forward_fail;
isc_task_send(client->manager->task, &event);
isc_async_run(client->manager->loop, forward_fail, uev);
inc_stats(client, zone, ns_statscounter_updatefwdfail);
dns_zone_detach(&zone);
} else {
inc_stats(client, zone, ns_statscounter_updatereqfwd);
}
isc_task_detach(&task);
}
static isc_result_t
send_forward_event(ns_client_t *client, dns_zone_t *zone) {
send_forward(ns_client_t *client, dns_zone_t *zone) {
isc_result_t result = ISC_R_SUCCESS;
char namebuf[DNS_NAME_FORMATSIZE];
char classbuf[DNS_RDATACLASS_FORMATSIZE];
isc_result_t result = ISC_R_SUCCESS;
update_event_t *event = NULL;
isc_task_t *zonetask = NULL;
update_t *uev = NULL;
result = checkupdateacl(client, dns_zone_getforwardacl(zone),
"update forwarding", dns_zone_getorigin(zone),
@@ -3737,13 +3714,12 @@ send_forward_event(ns_client_t *client, dns_zone_t *zone) {
return (DNS_R_DROP);
}
event = (update_event_t *)isc_event_allocate(
client->manager->mctx, client, DNS_EVENT_UPDATE, forward_action,
NULL, sizeof(*event));
event->zone = zone;
event->result = ISC_R_SUCCESS;
event->ev_arg = client;
uev = isc_mem_get(client->manager->mctx, sizeof(*uev));
*uev = (update_t){
.zone = zone,
.client = client,
.result = ISC_R_SUCCESS,
};
dns_name_format(dns_zone_getorigin(zone), namebuf, sizeof(namebuf));
dns_rdataclass_format(dns_zone_getclass(zone), classbuf,
@@ -3753,12 +3729,8 @@ send_forward_event(ns_client_t *client, dns_zone_t *zone) {
LOGLEVEL_PROTOCOL, "forwarding update for zone '%s/%s'",
namebuf, classbuf);
dns_zone_gettask(zone, &zonetask);
isc_nmhandle_attach(client->handle, &client->updatehandle);
isc_task_send(zonetask, ISC_EVENT_PTR(&event));
isc_async_run(dns_zone_getloop(zone), forward_action, uev);
if (event != NULL) {
isc_event_free(ISC_EVENT_PTR(&event));
}
return (result);
}