From: Evan Hunt Date: Wed, 10 Sep 2025 21:05:42 +0000 (-0700) Subject: minimize calls to dns_zone_gethooktable per qctx X-Git-Tag: v9.21.14~50^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=637e8d01d2433fbd7b9b56565e9ed59f33e4f759;p=thirdparty%2Fbind9.git minimize calls to dns_zone_gethooktable per qctx add a 'zhooks' member to the query_ctx structure, so that we only need to look up the hook table for the zone once when iniitalizing a qctx, and not once for every hook point. --- diff --git a/lib/dns/zone.c b/lib/dns/zone.c index dd16e4ce6e2..dfd97c2a360 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -24874,7 +24874,7 @@ dns_zone_setrad(dns_zone_t *zone, dns_name_t *name) { rcu_read_unlock(); } -void * +inline void * dns_zone_gethooktable(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); return zone->hooktable; diff --git a/lib/ns/include/ns/query.h b/lib/ns/include/ns/query.h index 9fb6568837f..630e9cdf27b 100644 --- a/lib/ns/include/ns/query.h +++ b/lib/ns/include/ns/query.h @@ -229,6 +229,8 @@ struct query_ctx { dns_view_t *view; /* client view */ + void *zhooks; /* zone hook table */ + bool allocated; /* qctx needs to be freed when destroying */ isc_result_t result; /* query result */ diff --git a/lib/ns/query.c b/lib/ns/query.c index 0a5a8c1b8ce..a7127f97024 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -259,17 +259,12 @@ acquire_recursionquota(ns_client_t *client); static void release_recursionquota(ns_client_t *client); -static ns_hookresult_t +static inline ns_hookresult_t ns__query_callhook(uint8_t id, query_ctx_t *qctx, isc_result_t *result, ns_hooktable_t *hooktab) { isc_result_t hookresult = *result; - ns_hook_t *hook; + ns_hook_t *hook = ISC_LIST_HEAD((*hooktab)[id]); - if (hooktab == NULL) { - return NS_HOOK_CONTINUE; - } - - hook = ISC_LIST_HEAD((*hooktab)[id]); while (hook != NULL) { ns_hook_action_t func = hook->action; void *data = hook->action_data; @@ -291,20 +286,15 @@ ns__query_callhook(uint8_t id, query_ctx_t *qctx, isc_result_t *result, return NS_HOOK_CONTINUE; } -static void +static inline void ns__query_callhook_noreturn(uint8_t id, query_ctx_t *qctx, ns_hooktable_t *hooktab) { - ns_hook_t *hook; - isc_result_t dummyres; + ns_hook_t *hook = ISC_LIST_HEAD((*hooktab)[id]); - if (hooktab == NULL) { - return; - } - - hook = ISC_LIST_HEAD((*hooktab)[id]); while (hook != NULL) { ns_hook_action_t func = hook->action; void *data = hook->action_data; + isc_result_t dummyres; INSIST(func != NULL); @@ -313,28 +303,6 @@ ns__query_callhook_noreturn(uint8_t id, query_ctx_t *qctx, } } -static ns_hooktable_t * -ns__zone_hooktab(query_ctx_t *qctx) { - ns_hooktable_t *hooktab = NULL; - - if (qctx != NULL && qctx->client->query.authzone != NULL) { - hooktab = dns_zone_gethooktable(qctx->client->query.authzone); - } - - return hooktab; -} - -static ns_hooktable_t * -ns__view_hooktab(query_ctx_t *qctx) { - ns_hooktable_t *hooktab = NULL; - - if (qctx != NULL && qctx->view != NULL) { - hooktab = qctx->view->hooktable; - } - - return hooktab; -} - /* * Call the specified hook function in every configured module that implements * that function. If any hook function returns NS_HOOK_RETURN, we @@ -345,21 +313,24 @@ ns__view_hooktab(query_ctx_t *qctx) { * is a macro instead of a static function; it needs to be able to use * 'goto cleanup' regardless of the return value.) */ -#define CALL_HOOK(_id, _qctx) \ - if (ns__query_callhook(_id, _qctx, &result, \ - ns__zone_hooktab(_qctx)) == NS_HOOK_RETURN) \ - { \ - goto cleanup; \ - } \ - if (ns__query_callhook(_id, _qctx, &result, \ - ns__view_hooktab(_qctx)) == NS_HOOK_RETURN) \ - { \ - goto cleanup; \ - } \ - if (ns__query_callhook(_id, _qctx, &result, ns__hook_table) == \ - NS_HOOK_RETURN) \ - { \ - goto cleanup; \ +#define CALL_HOOK(_id, _qctx) \ + if ((_qctx)->zhooks != NULL && \ + ns__query_callhook(_id, _qctx, &result, (_qctx)->zhooks) == \ + NS_HOOK_RETURN) \ + { \ + goto cleanup; \ + } \ + if ((_qctx)->view != NULL && (_qctx)->view->hooktable != NULL && \ + ns__query_callhook(_id, _qctx, &result, \ + (_qctx)->view->hooktable) == NS_HOOK_RETURN) \ + { \ + goto cleanup; \ + } \ + if (ns__hook_table != NULL && \ + ns__query_callhook(_id, _qctx, &result, ns__hook_table) == \ + NS_HOOK_RETURN) \ + { \ + goto cleanup; \ } /* @@ -372,9 +343,16 @@ ns__view_hooktab(query_ctx_t *qctx) { * macro for symmetry with CALL_HOOK above.) */ #define CALL_HOOK_NORETURN(_id, _qctx) \ - ns__query_callhook_noreturn(_id, _qctx, ns__zone_hooktab(_qctx)); \ - ns__query_callhook_noreturn(_id, _qctx, ns__view_hooktab(_qctx)); \ - ns__query_callhook_noreturn(_id, _qctx, ns__hook_table); + if ((_qctx)->zhooks != NULL) { \ + ns__query_callhook_noreturn(_id, _qctx, (_qctx)->zhooks); \ + } \ + if ((_qctx)->view != NULL && (_qctx)->view->hooktable != NULL) { \ + ns__query_callhook_noreturn(_id, _qctx, \ + (_qctx)->view->hooktable); \ + } \ + if (ns__hook_table != NULL) { \ + ns__query_callhook_noreturn(_id, _qctx, ns__hook_table); \ + } /* * The functions defined below implement the query logic that previously lived @@ -822,15 +800,23 @@ ns_query_cancel(ns_client_t *client) { static void query_reset(ns_client_t *client, bool everything) { - query_ctx_t qctx = { .view = client->inner.view, .client = client }; - - CALL_HOOK_NORETURN(NS_QUERY_RESET, &qctx); + /*% + * Reset the query state of a client to its default state. + */ CTRACE(ISC_LOG_DEBUG(3), "query_reset"); - /*% - * Reset the query state of a client to its default state. + /* + * Set up a transient qctx so we can call the NS_QUERY_RESET hook; + * this will free resources being held by plugins for this + * query, if any were configured. */ + query_ctx_t qctx = { .view = client->inner.view, .client = client }; + if (client->query.authzone != NULL) { + qctx.zhooks = dns_zone_gethooktable(client->query.authzone); + } + + CALL_HOOK_NORETURN(NS_QUERY_RESET, &qctx); /* * Cancel the fetch if it's running. @@ -5184,6 +5170,7 @@ qctx_freedata(query_ctx_t *qctx) { if (qctx->zone != NULL) { dns_zone_detach(&qctx->zone); + qctx->zhooks = NULL; } if (qctx->zdb != NULL) { @@ -5595,6 +5582,7 @@ ns__query_start(query_ctx_t *qctx) { } if (qctx->zone != NULL) { dns_zone_detach(&qctx->zone); + qctx->zhooks = NULL; } qctx->version = NULL; RESTORE(qctx->version, tversion); @@ -5683,6 +5671,8 @@ ns__query_start(query_ctx_t *qctx) { */ dns_zone_attach(qctx->zone, &qctx->client->query.authzone); + qctx->zhooks = + dns_zone_gethooktable(qctx->zone); CALL_HOOK(NS_QUERY_AUTHZONE_ATTACHED, qctx); } dns_db_attach(qctx->db, &qctx->client->query.authdb); @@ -8584,6 +8574,7 @@ query_zone_delegation(query_ctx_t *qctx) { } if (qctx->zone != NULL) { dns_zone_detach(&qctx->zone); + qctx->zhooks = NULL; } qctx->version = NULL; RESTORE(qctx->version, tversion);