]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Split the slabheader and slabheader_proof methods
authorOndřej Surý <ondrej@sury.org>
Thu, 18 Jun 2026 09:23:37 +0000 (11:23 +0200)
committerOndřej Surý <ondrej@isc.org>
Mon, 22 Jun 2026 11:20:42 +0000 (13:20 +0200)
The noqname/closest proof pseudo-rdatasets share the slab data layout
but have a different lifecycle: they reference a bare proof slab owned
by the parent header and are torn down via dns_slabheader_freeproof(),
not the rdataset's own teardown.  Give them a dedicated
dns_rdataslab_proof_rdatasetmethods table with their own
disassociate/clone so the proof path can diverge from the real
bound-rdataset path -- a prerequisite for reference counting the real
headers without it ever reaching the proof slabs.

lib/dns/include/dns/rdataset.h
lib/dns/qpcache.c
lib/dns/rdataslab.c

index 187c289543b9a2fba272466ed72a5137add4e7d5..0d2681b61034b602f0da6706d24655dcef308cf9 100644 (file)
@@ -192,7 +192,6 @@ struct dns_rdataset {
                 * comments in rdataslab.c for details.)
                 */
                struct {
-                       struct dns_db          *db;
                        dns_dbnode_t           *node;
                        unsigned char          *raw;
                        unsigned char          *iter_pos;
index baa6f8ef0cd55f08acdc6e7bcc0c173bd0b64166..85ceb537e0e442e08238e7a512aa80c0eb219085 100644 (file)
@@ -1050,8 +1050,7 @@ bindrdataset(qpcache_t *qpdb, qpcnode_t *node, dns_slabheader_t *header,
                rdataset->ttl = 0;
        }
 
-       rdataset->slab.db = (dns_db_t *)qpdb;
-       rdataset->slab.node = (dns_dbnode_t *)node;
+       rdataset->slab.node = NULL;
        rdataset->slab.raw = header->raw;
        rdataset->slab.iter_pos = NULL;
        rdataset->slab.iter_count = 0;
index 6bbb0cd9715bdccdef3d622e1d379e508a376d14..d0d45a332513cce3513123eb7b8d06d19cea3325 100644 (file)
@@ -95,6 +95,27 @@ dns_rdatasetmethods_t dns_rdataslab_rdatasetmethods = {
        .getownercase = rdataset_getownercase,
 };
 
+static void
+slabheader_proof_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG);
+static void
+slabheader_proof_clone(const dns_rdataset_t *source,
+                      dns_rdataset_t *target DNS__DB_FLARG);
+
+dns_rdatasetmethods_t dns_rdataslab_proof_rdatasetmethods = {
+       .disassociate = slabheader_proof_disassociate,
+       .first = rdataset_first,
+       .next = rdataset_next,
+       .current = rdataset_current,
+       .clone = slabheader_proof_clone,
+       .count = rdataset_count,
+       .getnoqname = NULL,
+       .getclosest = NULL,
+       .settrust = NULL,
+       .expire = NULL,
+       .clearprefetch = NULL,
+       .getownercase = NULL,
+};
+
 /*% Note: the "const void *" are just to make qsort happy.  */
 static int
 compare_rdata(const void *p1, const void *p2) {
@@ -540,7 +561,8 @@ dns_slabheader_freeproof(isc_mem_t *mctx, dns_slabheader_proof_t **proofp) {
 
 static void
 rdataset_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) {
-       dns_dbnode_t *node = rdataset->slab.node;
+       dns_slabheader_t *header = rdataset_getheader(rdataset);
+       dns_dbnode_t *node = header->node;
 
        dns__db_detachnode(&node DNS__DB_FLARG_PASS);
 }
@@ -622,10 +644,11 @@ rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
 static void
 rdataset_clone(const dns_rdataset_t *source,
               dns_rdataset_t *target DNS__DB_FLARG) {
-       dns_dbnode_t *node = source->slab.node;
-       dns_dbnode_t *cloned_node = NULL;
+       dns_slabheader_t *header = rdataset_getheader(source);
+
+       dns__db_attachnode(header->node,
+                          &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
 
-       dns__db_attachnode(node, &cloned_node DNS__DB_FLARG_PASS);
        INSIST(!ISC_LINK_LINKED(target, link));
        *target = *source;
        ISC_LINK_INIT(target, link);
@@ -645,8 +668,8 @@ static isc_result_t
 rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
                    dns_rdataset_t *nsec,
                    dns_rdataset_t *nsecsig DNS__DB_FLARG) {
-       dns_db_t *db = rdataset->slab.db;
-       dns_dbnode_t *node = rdataset->slab.node;
+       dns_slabheader_t *header = rdataset_getheader(rdataset);
+       dns_dbnode_t *node = header->node;
        const dns_slabheader_proof_t *noqname = rdataset->slab.noqname;
 
        /*
@@ -661,12 +684,11 @@ rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
         */
        dns__db_attachnode(node, &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
        *nsec = (dns_rdataset_t){
-               .methods = &dns_rdataslab_rdatasetmethods,
-               .rdclass = db->rdclass,
+               .methods = &dns_rdataslab_proof_rdatasetmethods,
+               .rdclass = rdataset->rdclass,
                .type = noqname->type,
                .ttl = rdataset->ttl,
                .trust = rdataset->trust,
-               .slab.db = db,
                .slab.node = node,
                .slab.raw = noqname->neg,
                .link = nsec->link,
@@ -677,13 +699,12 @@ rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
 
        dns__db_attachnode(node, &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
        *nsecsig = (dns_rdataset_t){
-               .methods = &dns_rdataslab_rdatasetmethods,
-               .rdclass = db->rdclass,
+               .methods = &dns_rdataslab_proof_rdatasetmethods,
+               .rdclass = rdataset->rdclass,
                .type = dns_rdatatype_rrsig,
                .covers = noqname->type,
                .ttl = rdataset->ttl,
                .trust = rdataset->trust,
-               .slab.db = db,
                .slab.node = node,
                .slab.raw = noqname->negsig,
                .link = nsecsig->link,
@@ -701,8 +722,8 @@ static isc_result_t
 rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
                    dns_rdataset_t *nsec,
                    dns_rdataset_t *nsecsig DNS__DB_FLARG) {
-       dns_db_t *db = rdataset->slab.db;
-       dns_dbnode_t *node = rdataset->slab.node;
+       dns_slabheader_t *header = rdataset_getheader(rdataset);
+       dns_dbnode_t *node = header->node;
        const dns_slabheader_proof_t *closest = rdataset->slab.closest;
 
        /*
@@ -717,12 +738,11 @@ rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
         */
        dns__db_attachnode(node, &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
        *nsec = (dns_rdataset_t){
-               .methods = &dns_rdataslab_rdatasetmethods,
-               .rdclass = db->rdclass,
+               .methods = &dns_rdataslab_proof_rdatasetmethods,
+               .rdclass = rdataset->rdclass,
                .type = closest->type,
                .ttl = rdataset->ttl,
                .trust = rdataset->trust,
-               .slab.db = db,
                .slab.node = node,
                .slab.raw = closest->neg,
                .link = nsec->link,
@@ -733,13 +753,12 @@ rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
 
        dns__db_attachnode(node, &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
        *nsecsig = (dns_rdataset_t){
-               .methods = &dns_rdataslab_rdatasetmethods,
-               .rdclass = db->rdclass,
+               .methods = &dns_rdataslab_proof_rdatasetmethods,
+               .rdclass = rdataset->rdclass,
                .type = dns_rdatatype_rrsig,
                .covers = closest->type,
                .ttl = rdataset->ttl,
                .trust = rdataset->trust,
-               .slab.db = db,
                .slab.node = node,
                .slab.raw = closest->negsig,
                .link = nsecsig->link,
@@ -809,6 +828,32 @@ rdataset_getheader(const dns_rdataset_t *rdataset) {
        return (dns_slabheader_t *)(rawbuf - offsetof(dns_slabheader_t, raw));
 }
 
+/* Fixed Proof helper macros */
+
+static void
+slabheader_proof_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) {
+       dns_dbnode_t *node = rdataset->slab.node;
+
+       dns__db_detachnode(&node DNS__DB_FLARG_PASS);
+}
+
+static void
+slabheader_proof_clone(const dns_rdataset_t *source,
+                      dns_rdataset_t *target DNS__DB_FLARG) {
+       INSIST(!ISC_LINK_LINKED(target, link));
+       INSIST(target->slab.node == NULL);
+
+       *target = *source;
+
+       ISC_LINK_INIT(target, link);
+       target->slab.node = NULL;
+       dns__db_attachnode(source->slab.node,
+                          &target->slab.node DNS__DB_FLARG_PASS);
+
+       target->slab.iter_pos = NULL;
+       target->slab.iter_count = 0;
+}
+
 dns_slabtop_t *
 dns_slabtop_new(isc_mem_t *mctx, dns_typepair_t typepair) {
        dns_slabtop_t *top = isc_mem_get(mctx, sizeof(*top));