diff --git a/lib/dns/qp.c b/lib/dns/qp.c index 3805845b91..79a0b8e6ee 100644 --- a/lib/dns/qp.c +++ b/lib/dns/qp.c @@ -1785,10 +1785,14 @@ dns_qpchain_init(dns_qpreadable_t qpr, dns_qpchain_t *chain) { REQUIRE(QP_VALID(qp)); REQUIRE(chain != NULL); - *chain = (dns_qpchain_t){ - .magic = QPCHAIN_MAGIC, - .qp = qp, - }; + /* + * dns_qpchain_t contains a 2kb buffer, which is slow to + * zero-initialize. Therefore we avoid designated initializers, and + * initialize each field manually. + */ + chain->magic = QPCHAIN_MAGIC; + chain->qp = qp; + chain->len = 0; } unsigned int @@ -1821,10 +1825,19 @@ dns_qpiter_init(dns_qpreadable_t qpr, dns_qpiter_t *qpi) { dns_qpreader_t *qp = dns_qpreader(qpr); REQUIRE(QP_VALID(qp)); REQUIRE(qpi != NULL); - *qpi = (dns_qpiter_t){ - .qp = qp, - .magic = QPITER_MAGIC, - }; + + /* + * dns_qpiter_t contains a 4kb buffer, which is slow to zero-initialize. + * Therefore we avoid designated initializers, and initialize each + * field manually. + */ + qpi->qp = qp; + qpi->sp = 0; + qpi->magic = QPITER_MAGIC; + /* + * The top of the stack must be initialized. + */ + qpi->stack[qpi->sp] = NULL; } /* diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index 1b50608203..3b7f5680b1 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -1458,6 +1458,29 @@ find_coveringnsec(qpc_search_t *search, const dns_name_t *name, (DNS_TRUST_PENDING((found)->trust) && \ (((options) & DNS_DBFIND_PENDINGOK) == 0))) +static void +qpc_search_init(qpc_search_t *search, qpcache_t *db, unsigned int options, + isc_stdtime_t now) { + /* + * qpc_search_t contains two structures with large buffers (dns_qpiter_t + * and dns_qpchain_t). Those two structures will be initialized later by + * dns_qp_lookup anyway. + * To avoid the overhead of zero initialization, we avoid designated + * initializers and initialize all "small" fields manually. + */ + search->qpdb = (qpcache_t *)db; + search->options = options; + /* + * qpch->in - Init by dns_qp_lookup + * qpiter - Init by dns_qp_lookup + */ + search->need_cleanup = false; + search->now = now ? now : isc_stdtime_now(); + search->zonecut = NULL; + search->zonecut_header = NULL; + search->zonecut_sigheader = NULL; +} + static isc_result_t qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, dns_rdatatype_t type, unsigned int options, isc_stdtime_t __now, @@ -1479,11 +1502,9 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, dns_slabheader_t *foundsig = NULL, *nssig = NULL, *cnamesig = NULL; dns_slabheader_t *nsecheader = NULL, *nsecsig = NULL; dns_typepair_t sigtype, negtype; - qpc_search_t search = (qpc_search_t){ - .qpdb = (qpcache_t *)db, - .options = options, - .now = __now ? __now : isc_stdtime_now(), - }; + + qpc_search_t search; + qpc_search_init(&search, (qpcache_t *)db, options, __now); REQUIRE(VALID_QPDB((qpcache_t *)db)); REQUIRE(version == NULL); diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index 9ede2dfa4c..4c60d4c17d 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -3326,6 +3326,34 @@ qpzone_check_zonecut(qpznode_t *node, void *arg DNS__DB_FLARG) { return result; } +static void +qpz_search_init(qpz_search_t *search, qpzonedb_t *db, qpz_version_t *version, + unsigned int options) { + /* + * qpz_search_t contains two structures with large buffers (dns_qpiter_t + * and dns_qpchain_t). Those two structures will be initialized later by + * dns_qp_lookup anyway. + * To avoid the overhead of zero initialization, we avoid designated + * initializers and initialize all "small" fields manually. + */ + search->qpdb = db; + search->version = version; + search->qpr = (dns_qpread_t){}; + search->serial = version->serial; + search->options = options; + /* + * qpch->in -- init in dns_qp_lookup + * qpiter -- init in dns_qp_lookup + */ + search->copy_name = false; + search->need_cleanup = false; + search->wild = false; + search->zonecut = NULL; + search->zonecut_header = NULL; + search->zonecut_sigheader = NULL; + dns_fixedname_init(&search->zonecut_name); +} + static isc_result_t qpzone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, dns_rdatatype_t type, unsigned int options, @@ -3335,7 +3363,6 @@ qpzone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, isc_result_t result; qpzonedb_t *qpdb = (qpzonedb_t *)db; qpznode_t *node = NULL; - qpz_search_t search; bool cname_ok = true, close_version = false; bool maybe_zonecut = false, at_zonecut = false; bool wild = false, empty_node = false; @@ -3361,13 +3388,9 @@ qpzone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, close_version = true; } - search = (qpz_search_t){ - .qpdb = (qpzonedb_t *)db, - .version = (qpz_version_t *)version, - .serial = ((qpz_version_t *)version)->serial, - .options = options, - }; - dns_fixedname_init(&search.zonecut_name); + qpz_search_t search; + qpz_search_init(&search, (qpzonedb_t *)db, (qpz_version_t *)version, + options); if ((options & DNS_DBFIND_FORCENSEC3) != 0) { dns_qpmulti_query(qpdb->nsec3, &search.qpr);