From: Ondřej Surý Date: Tue, 28 Oct 2025 22:11:37 +0000 (+0100) Subject: Create list of dirty dirty headers that needs cleaning X-Git-Tag: v9.21.17~51^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e93eed28f7c157f5b79d92a57675b68640a71989;p=thirdparty%2Fbind9.git Create list of dirty dirty headers that needs cleaning Instead of just flagging the qpcache node to be dirty, add the headers to be cleaned to the dirty list and when cleaning the node, only walk through the dirty node, not all the slabtops. --- diff --git a/lib/dns/include/dns/rdataslab.h b/lib/dns/include/dns/rdataslab.h index b160f3494d2..421c7df8aa6 100644 --- a/lib/dns/include/dns/rdataslab.h +++ b/lib/dns/include/dns/rdataslab.h @@ -113,6 +113,11 @@ struct dns_slabheader { dns_slabheader_proof_t *noqname; dns_slabheader_proof_t *closest; + /*% + * Used for cleaning. + */ + ISC_LINK(dns_slabheader_t) dirtylink; + /*% * Points to the top slabtop structure for the type. */ diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index 725d51fe9c5..52ea84506c5 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -152,15 +153,7 @@ struct qpcnode { struct cds_list_head types_list; struct cds_list_head *data; - /*% - * NOTE: The 'dirty' flag is protected by the node lock, so - * this bitfield has to be separated from the one above. - * We don't want it to share the same qword with bits - * that can be accessed without the node lock. - */ - uint8_t : 0; - uint8_t dirty : 1; - uint8_t : 0; + ISC_LIST(dns_slabheader_t) dirty; /*% * Used for dead nodes cleaning. This linked list is used to mark nodes @@ -579,7 +572,17 @@ clean_cache_node(qpcache_t *qpdb, qpcnode_t *node) { * Caller must be holding the node lock. */ - DNS_SLABTOP_FOREACH(top, node->data) { + /* + * We can't use ordinary loop because multiple headers to be cleaned can + * be stashed under a single slabtop. + */ + for (dns_slabheader_t *dirty = ISC_LIST_HEAD(node->dirty); + dirty != NULL; dirty = ISC_LIST_HEAD(node->dirty)) + { + dns_slabtop_t *top = dirty->top; + + ISC_LIST_UNLINK(node->dirty, dirty, dirtylink); + clean_cache_headers(top); /* @@ -617,8 +620,6 @@ clean_cache_node(qpcache_t *qpdb, qpcnode_t *node) { dns_slabtop_destroy(((dns_db_t *)qpdb)->mctx, &top); } } - - node->dirty = false; } /* @@ -767,7 +768,7 @@ qpcnode_release(qpcache_t *qpdb, qpcnode_t *node, isc_rwlocktype_t *nlocktypep, } /* Handle easy and typical case first. */ - if (!node->dirty && !cds_list_empty(node->data)) { + if (ISC_LIST_EMPTY(node->dirty) && !cds_list_empty(node->data)) { goto unref; } @@ -794,7 +795,7 @@ qpcnode_release(qpcache_t *qpdb, qpcnode_t *node, isc_rwlocktype_t *nlocktypep, } } - if (node->dirty) { + if (!ISC_LIST_EMPTY(node->dirty)) { clean_cache_node(qpdb, node); } @@ -926,7 +927,9 @@ static void mark_ancient(dns_slabheader_t *header) { setttl(header, 0); mark(header, DNS_SLABHEADERATTR_ANCIENT); - HEADERNODE(header)->dirty = 1; + if (!ISC_LINK_LINKED(header, dirtylink)) { + ISC_LIST_APPEND(HEADERNODE(header)->dirty, header, dirtylink); + } } /* @@ -2425,6 +2428,7 @@ new_qpcnode(qpcache_t *qpdb, const dns_name_t *name, dns_namespace_t nspace) { .nspace = nspace, .references = ISC_REFCOUNT_INITIALIZER(1), .locknum = isc_random_uniform(qpdb->buckets_count), + .dirty = ISC_LIST_INITIALIZER, }; isc_mem_attach(qpdb->common.mctx, &newdata->mctx); @@ -3741,6 +3745,10 @@ qpcnode_deletedata(dns_dbnode_t *node ISC_ATTR_UNUSED, void *data) { dns_slabheader_t *header = data; qpcache_t *qpdb = HEADERNODE(header)->qpdb; + if (ISC_LINK_LINKED(header, dirtylink)) { + ISC_LIST_UNLINK(HEADERNODE(header)->dirty, header, dirtylink); + } + if (header->heap != NULL && header->heap_index != 0) { isc_heap_delete(header->heap, header->heap_index); } diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c index 2fa0f30c1b0..2754b9ec701 100644 --- a/lib/dns/rdataslab.c +++ b/lib/dns/rdataslab.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -327,6 +328,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, .typepair = typepair, .trust = rdataset->trust, .ttl = rdataset->ttl, + .dirtylink = ISC_LINK_INITIALIZER, }; } @@ -833,6 +835,8 @@ dns_slabheader_reset(dns_slabheader_t *h, dns_dbnode_t *node) { atomic_init(&h->attributes, 0); atomic_init(&h->last_refresh_fail_ts, 0); + ISC_LINK_INIT(h, dirtylink); + STATIC_ASSERT(sizeof(h->attributes) == 2, "The .attributes field of dns_slabheader_t needs to be " "16-bit int type exactly."); @@ -845,6 +849,7 @@ dns_slabheader_new(isc_mem_t *mctx, dns_dbnode_t *node) { h = isc_mem_get(mctx, sizeof(*h)); *h = (dns_slabheader_t){ .node = node, + .dirtylink = ISC_LINK_INITIALIZER, }; return h; }