]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Make the TTL-based cleaning more aggressive
authorOndřej Surý <ondrej@isc.org>
Tue, 20 Feb 2024 07:50:58 +0000 (08:50 +0100)
committerOndřej Surý <ondrej@isc.org>
Thu, 29 Feb 2024 11:57:06 +0000 (12:57 +0100)
It was discovered that the TTL-based cleaning could build up
a significant backlog of the rdataset headers during the periods where
the top of the TTL heap isn't expired yet.  Make the TTL-based cleaning
more aggressive by cleaning more headers from the heap when we are
adding new header into the RBTDB.

lib/dns/rbtdb.c

index d813bb4d89d2a3bc1215eb879bb0cfe95eeb27b2..5be2ae23e7dba51f834cd54f3a40518bd8b8fda3 100644 (file)
 #define DEFAULT_CACHE_NODE_LOCK_COUNT 17
 #endif /* DNS_RBTDB_CACHE_NODE_LOCK_COUNT */
 
+/*
+ * This defines the number of headers that we try to expire each time the
+ * expire_ttl_headers() is run.  The number should be small enough, so the
+ * TTL-based header expiration doesn't take too long, but it should be large
+ * enough, so we expire enough headers if their TTL is clustered.
+ */
+#define DNS_RBTDB_EXPIRE_TTL_COUNT 10
+
 static void
 delete_callback(void *data, void *arg);
 static void
@@ -3164,6 +3172,11 @@ cleanup:
        return (result);
 }
 
+static void
+expire_ttl_headers(dns_rbtdb_t *rbtdb, unsigned int locknum,
+                  isc_rwlocktype_t *tlocktypep, isc_stdtime_t now,
+                  bool cache_is_overmem DNS__DB_FLARG);
+
 isc_result_t
 dns__rbtdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
                       dns_dbversion_t *version, isc_stdtime_t now,
@@ -3174,7 +3187,6 @@ dns__rbtdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
        dns_rbtdb_version_t *rbtversion = version;
        isc_region_t region;
        dns_slabheader_t *newheader = NULL;
-       dns_slabheader_t *header = NULL;
        isc_result_t result;
        bool delegating;
        bool newnsec;
@@ -3346,14 +3358,8 @@ dns__rbtdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
                                           rbtnode->locknum DNS__DB_FLARG_PASS);
                }
 
-               header = isc_heap_element(rbtdb->heaps[rbtnode->locknum], 1);
-               if (header != NULL && header->ttl + STALE_TTL(header, rbtdb) <
-                                             now - RBTDB_VIRTUAL)
-               {
-                       dns__cacherbt_expireheader(
-                               header, &tlocktype,
-                               dns_expire_ttl DNS__DB_FLARG_PASS);
-               }
+               expire_ttl_headers(rbtdb, rbtnode->locknum, &tlocktype, now,
+                                  cache_is_overmem DNS__DB_FLARG_PASS);
 
                /*
                 * If we've been holding a write lock on the tree just for
@@ -4879,3 +4885,42 @@ dns__rbtdb_deletedata(dns_db_t *db ISC_ATTR_UNUSED,
                }
        }
 }
+
+/*
+ * Caller must be holding the node write lock.
+ */
+static void
+expire_ttl_headers(dns_rbtdb_t *rbtdb, unsigned int locknum,
+                  isc_rwlocktype_t *tlocktypep, isc_stdtime_t now,
+                  bool cache_is_overmem DNS__DB_FLARG) {
+       isc_heap_t *heap = rbtdb->heaps[locknum];
+
+       for (size_t i = 0; i < DNS_RBTDB_EXPIRE_TTL_COUNT; i++) {
+               dns_slabheader_t *header = isc_heap_element(heap, 1);
+
+               if (header == NULL) {
+                       /* No headers left on this TTL heap; exit cleaning */
+                       return;
+               }
+
+               dns_ttl_t ttl = header->ttl;
+
+               if (!cache_is_overmem) {
+                       /* Only account for stale TTL if cache is not overmem */
+                       ttl += STALE_TTL(header, rbtdb);
+               }
+
+               if (ttl >= now - RBTDB_VIRTUAL) {
+                       /*
+                        * The header at the top of this TTL heap is not yet
+                        * eligible for expiry, so none of the other headers on
+                        * the same heap can be eligible for expiry, either;
+                        * exit cleaning.
+                        */
+                       return;
+               }
+
+               dns__cacherbt_expireheader(header, tlocktypep,
+                                          dns_expire_ttl DNS__DB_FLARG_PASS);
+       }
+}