From 5972ee2cd599036d09f171a94701a6187fc6e668 Mon Sep 17 00:00:00 2001 From: Colin Vidal Date: Thu, 15 Jan 2026 17:36:50 +0100 Subject: [PATCH] resolver: copy fetch responses and send events in one go Instead of first copying query response data into each fetch response and then iterating again to send the response to the caller, perform both operations in one go. Also removed some duplicate code. --- lib/dns/resolver.c | 159 +++++++++++++++++---------------------------- 1 file changed, 61 insertions(+), 98 deletions(-) diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index aae71053f0..dbc3a3bb8d 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -1624,35 +1624,41 @@ static void spillattimer_countdown(void *arg); static void -clone_results(fetchctx_t *fctx) { - REQUIRE(!ISC_LIST_EMPTY(fctx->resps)); +copy_to_resp(fetchctx_t *fctx, dns_fetchresponse_t *resp) { + resp->result = fctx->resp_result; - /* - * Set up any other resps to have the same data as the first. - * Caller must be holding the appropriate lock. - */ + dns_name_copy(dns_fixedname_name(&fctx->resp_foundname), + resp->foundname); - FCTXTRACE("clone_results"); + dns_db_attach(fctx->resp_db, &resp->db); + dns_db_attachnode(fctx->resp_node, &resp->node); - ISC_LIST_FOREACH(fctx->resps, resp, link) { - resp->result = fctx->resp_result; - dns_name_copy(dns_fixedname_name(&fctx->resp_foundname), - resp->foundname); - dns_db_attach(fctx->resp_db, &resp->db); - dns_db_attachnode(fctx->resp_node, &resp->node); - - if (dns_rdataset_isassociated(&fctx->resp_rdataset)) { - dns_rdataset_clone(&fctx->resp_rdataset, - resp->rdataset); - } - - if (resp->sigrdataset != NULL && - dns_rdataset_isassociated(&fctx->resp_sigrdataset)) - { - dns_rdataset_clone(&fctx->resp_sigrdataset, - resp->sigrdataset); - } + if (dns_rdataset_isassociated(&fctx->resp_rdataset)) { + dns_rdataset_clone(&fctx->resp_rdataset, resp->rdataset); } + if (resp->sigrdataset != NULL && + dns_rdataset_isassociated(&fctx->resp_sigrdataset)) + { + dns_rdataset_clone(&fctx->resp_sigrdataset, resp->sigrdataset); + } +} + +static void +pull_from_resp(dns_fetchresponse_t *resp, fetchctx_t *fctx) { + if (dns_rdataset_isassociated(resp->rdataset)) { + dns_rdataset_clone(resp->rdataset, &fctx->resp_rdataset); + } + if (dns_rdataset_isassociated(resp->sigrdataset)) { + dns_rdataset_clone(resp->sigrdataset, &fctx->resp_sigrdataset); + } + if (resp->db != NULL) { + dns_db_attach(resp->db, &fctx->resp_db); + } + if (resp->node != NULL) { + dns_db_attachnode(resp->node, &fctx->resp_node); + } + dns_name_copy(resp->foundname, + dns_fixedname_name(&fctx->resp_foundname)); } static void @@ -1668,9 +1674,6 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) { REQUIRE(fctx->state == fetchstate_done); - if (result == ISC_R_SUCCESS) { - clone_results(fctx); - } FCTXTRACE("sendevents"); /* @@ -1683,6 +1686,9 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) { ISC_LIST_FOREACH(fctx->resps, resp, link) { ISC_LIST_UNLINK(fctx->resps, resp, link); + if (result == ISC_R_SUCCESS) { + copy_to_resp(fctx, resp); + } count++; resp->vresult = fctx->vresult; @@ -4331,6 +4337,26 @@ done: } } +static void +clear_resp(dns_fetchresponse_t **respp) { + dns_fetchresponse_t *resp = *respp; + + if (resp == NULL) { + return; + } + + if (resp->node != NULL) { + dns_db_detachnode(&resp->node); + } + if (resp->db != NULL) { + dns_db_detach(&resp->db); + } + dns_rdataset_cleanup(resp->rdataset); + dns_rdataset_cleanup(resp->sigrdataset); + + dns_resolver_freefresp(respp); +} + static void resume_qmin(void *arg) { dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg; @@ -4340,10 +4366,6 @@ resume_qmin(void *arg) { unsigned int findoptions = 0; dns_name_t *fname = NULL, *dcname = NULL; dns_fixedname_t ffixed, dcfixed; - dns_rdataset_t rdataset; - dns_rdataset_t sigrdataset; - dns_db_t *db = NULL; - dns_dbnode_t *node = NULL; REQUIRE(VALID_FCTX(fctx)); @@ -4356,32 +4378,8 @@ resume_qmin(void *arg) { fname = dns_fixedname_initname(&ffixed); dcname = dns_fixedname_initname(&dcfixed); - dns_rdataset_init(&rdataset); - dns_rdataset_init(&sigrdataset); - - if (resp->node != NULL) { - dns_db_attachnode(resp->node, &node); - dns_db_detachnode(&resp->node); - } - if (resp->db != NULL) { - dns_db_attach(resp->db, &db); - dns_db_detach(&resp->db); - } - - if (dns_rdataset_isassociated(resp->rdataset)) { - dns_rdataset_clone(resp->rdataset, &rdataset); - dns_rdataset_disassociate(resp->rdataset); - } - if (dns_rdataset_isassociated(resp->sigrdataset)) { - dns_rdataset_clone(resp->sigrdataset, &sigrdataset); - dns_rdataset_disassociate(resp->sigrdataset); - } - dns_name_copy(resp->foundname, fname); - result = resp->result; - dns_resolver_freefresp(&resp); - LOCK(&fctx->lock); if (SHUTTINGDOWN(fctx)) { result = ISC_R_SHUTTINGDOWN; @@ -4413,22 +4411,7 @@ resume_qmin(void *arg) { if (result == DNS_R_NXDOMAIN && fctx->qmin_labels == dns_name_countlabels(fctx->name)) { - if (dns_rdataset_isassociated(&rdataset)) { - dns_rdataset_clone(&rdataset, - &fctx->resp_rdataset); - } - if (dns_rdataset_isassociated(&sigrdataset)) { - dns_rdataset_clone(&sigrdataset, - &fctx->resp_sigrdataset); - } - if (db != NULL) { - dns_db_attach(db, &fctx->resp_db); - } - if (node != NULL) { - dns_db_attachnode(node, &fctx->resp_node); - } - dns_name_copy(fname, dns_fixedname_name( - &fctx->resp_foundname)); + pull_from_resp(resp, fctx); goto cleanup; } @@ -4472,25 +4455,10 @@ resume_qmin(void *arg) { fctx->type != dns_rdatatype_sig && fctx->type != dns_rdatatype_rrsig) { - if (dns_rdataset_isassociated(&rdataset)) { - dns_rdataset_clone(&rdataset, - &fctx->resp_rdataset); - } - if (dns_rdataset_isassociated(&sigrdataset)) { - dns_rdataset_clone(&sigrdataset, - &fctx->resp_sigrdataset); - } - if (db != NULL) { - dns_db_attach(db, &fctx->resp_db); - } - if (node != NULL) { - dns_db_attachnode(node, &fctx->resp_node); - } - dns_name_copy(fname, dns_fixedname_name( - &fctx->resp_foundname)); + pull_from_resp(resp, fctx); if (result == DNS_R_CNAME && - dns_rdataset_isassociated(&rdataset) && + dns_rdataset_isassociated(resp->rdataset) && fctx->type == dns_rdatatype_cname) { LOCK(&fctx->lock); @@ -4525,6 +4493,7 @@ resume_qmin(void *arg) { break; } + clear_resp(&resp); dns_rdataset_cleanup(&fctx->nameservers); if (dns_rdatatype_atparent(fctx->type)) { @@ -4564,14 +4533,8 @@ resume_qmin(void *arg) { fctx_try(fctx, true); cleanup: - if (node != NULL) { - dns_db_detachnode(&node); - } - if (db != NULL) { - dns_db_detach(&db); - } - dns_rdataset_cleanup(&rdataset); - dns_rdataset_cleanup(&sigrdataset); + clear_resp(&resp); + if (result != ISC_R_SUCCESS) { /* An error occurred, tear down whole fctx */ fctx_failure_unref(fctx, result); @@ -10859,7 +10822,7 @@ dns_resolver_freefresp(dns_fetchresponse_t **frespp) { } dns_fetchresponse_t *fresp = *frespp; - *frespp = NULL; + isc_mem_putanddetach(&fresp->mctx, fresp, sizeof(*fresp)); }