]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Create a second pruning task for rbtdb with unlimited quantum
authorOndřej Surý <ondrej@isc.org>
Fri, 1 Mar 2024 11:43:15 +0000 (12:43 +0100)
committerOndřej Surý <ondrej@isc.org>
Wed, 6 Mar 2024 16:11:14 +0000 (17:11 +0100)
Previously, rbtdb->task had quantum of 1 because it was originally used
just for freeing RBTDB contents, which can happen on a "best effort"
basis (does not need to be prioritized).  However, when tree pruning was
implemented, it also started sending events to that task, enabling the
latter to become clogged up with a significant event backlog because it
only pruned a single RBTDB node per event.

To prioritize tree pruning (as it is necessary for enforcing the
configured memory use limit for the cache memory context), create a
second task with a virtually unlimited quantum (UINT_MAX) and send the
tree-pruning events to this new task, to ensure that all nodes scheduled
for pruning will be processed before further nodes are queued in a
similar fashion.

This change enables dropping the prunenodes list and restoring the
originally-used logic that allocates and sends a separate event for each
node to prune.

bin/tests/system/dyndb/driver/db.c
lib/dns/cache.c
lib/dns/db.c
lib/dns/include/dns/db.h
lib/dns/rbtdb.c
lib/dns/sdb.c
lib/dns/sdlz.c
lib/dns/zone.c

index 334fd549de38a1c549d45461ee7fe62d70d36e8f..96857224c2cfdbe30ddcbe04a444ab3551f94ee5 100644 (file)
@@ -420,12 +420,12 @@ overmem(dns_db_t *db, bool over) {
 }
 
 static void
-settask(dns_db_t *db, isc_task_t *task) {
+settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask) {
        sampledb_t *sampledb = (sampledb_t *)db;
 
        REQUIRE(VALID_SAMPLEDB(sampledb));
 
-       dns_db_settask(sampledb->rbtdb, task);
+       dns_db_settask(sampledb->rbtdb, task, prunetask);
 }
 
 static isc_result_t
index 7ffb6f85b823a0cf7f1bc87520175cbbc6251ef9..fd944bd46f8c59f5b24f429101256e9e0be8c614 100644 (file)
@@ -187,7 +187,6 @@ dns_cache_create(isc_mem_t *cmctx, isc_mem_t *hmctx, isc_taskmgr_t *taskmgr,
        isc_result_t result;
        dns_cache_t *cache;
        int i, extra = 0;
-       isc_task_t *dbtask;
 
        REQUIRE(cachep != NULL);
        REQUIRE(*cachep == NULL);
@@ -258,15 +257,25 @@ dns_cache_create(isc_mem_t *cmctx, isc_mem_t *hmctx, isc_taskmgr_t *taskmgr,
                goto cleanup_dbargv;
        }
        if (taskmgr != NULL) {
-               dbtask = NULL;
+               isc_task_t *dbtask = NULL;
+               isc_task_t *prunetask = NULL;
+
                result = isc_task_create(taskmgr, 1, &dbtask);
                if (result != ISC_R_SUCCESS) {
                        goto cleanup_db;
                }
-
                isc_task_setname(dbtask, "cache_dbtask", NULL);
-               dns_db_settask(cache->db, dbtask);
+
+               result = isc_task_create(taskmgr, UINT_MAX, &prunetask);
+               if (result != ISC_R_SUCCESS) {
+                       isc_task_detach(&dbtask);
+                       goto cleanup_db;
+               }
+               isc_task_setname(prunetask, "cache_prunetask", NULL);
+
+               dns_db_settask(cache->db, dbtask, prunetask);
                isc_task_detach(&dbtask);
+               isc_task_detach(&prunetask);
        }
 
        cache->magic = CACHE_MAGIC;
index ac01785754bf4d148e647f337c66947ae711de8b..653b29ddec635769d2fdd109d83427de4ad5704e 100644 (file)
@@ -831,10 +831,10 @@ dns_db_hashsize(dns_db_t *db) {
 }
 
 void
-dns_db_settask(dns_db_t *db, isc_task_t *task) {
+dns_db_settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask) {
        REQUIRE(DNS_DB_VALID(db));
 
-       (db->methods->settask)(db, task);
+       (db->methods->settask)(db, task, prunetask);
 }
 
 isc_result_t
index bfad74693e72d7d21e24654c08309b952f45ffd3..584186872db7b0e33837bd981bc467da33f5554d 100644 (file)
@@ -139,7 +139,7 @@ typedef struct dns_dbmethods {
        unsigned int (*nodecount)(dns_db_t *db, dns_dbtree_t);
        bool (*ispersistent)(dns_db_t *db);
        void (*overmem)(dns_db_t *db, bool overmem);
-       void (*settask)(dns_db_t *db, isc_task_t *);
+       void (*settask)(dns_db_t *db, isc_task_t *, isc_task_t *);
        isc_result_t (*getoriginnode)(dns_db_t *db, dns_dbnode_t **nodep);
        void (*transfernode)(dns_db_t *db, dns_dbnode_t **sourcep,
                             dns_dbnode_t **targetp);
@@ -1391,13 +1391,14 @@ dns_db_hashsize(dns_db_t *db);
  */
 
 void
-dns_db_settask(dns_db_t *db, isc_task_t *task);
+dns_db_settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask);
 /*%<
  * If task is set then the final detach maybe performed asynchronously.
  *
  * Requires:
  * \li 'db' is a valid database.
- * \li 'task' to be valid or NULL.
+ * \li 'task' to be valid or NULL (default task to send events to).
+ * \li 'prunetask' to be valid or NULL (task to send tree-pruning events to).
  */
 
 bool
index 7cf556c26d860a80dc573fdb5676fa09b2c5ce56..d91be9ad7daeff30cf6693af9c1c71a1d5ee7dde 100644 (file)
@@ -466,6 +466,7 @@ struct dns_rbtdb {
        rbtdb_version_t *future_version;
        rbtdb_versionlist_t open_versions;
        isc_task_t *task;
+       isc_task_t *prunetask;
        dns_dbnode_t *soanode;
        dns_dbnode_t *nsnode;
 
@@ -1190,6 +1191,9 @@ free_rbtdb(dns_rbtdb_t *rbtdb, bool log, isc_event_t *event) {
        if (rbtdb->task != NULL) {
                isc_task_detach(&rbtdb->task);
        }
+       if (rbtdb->prunetask != NULL) {
+               isc_task_detach(&rbtdb->prunetask);
+       }
 
        RBTDB_DESTROYLOCK(&rbtdb->lock);
        rbtdb->common.magic = 0;
@@ -1894,7 +1898,7 @@ send_to_prune_tree(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
        db = NULL;
        attach((dns_db_t *)rbtdb, &db);
        ev->ev_sender = db;
-       isc_task_send(rbtdb->task, &ev);
+       isc_task_send(rbtdb->prunetask, &ev);
 }
 
 /*%
@@ -7824,7 +7828,7 @@ hashsize(dns_db_t *db) {
 }
 
 static void
-settask(dns_db_t *db, isc_task_t *task) {
+settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask) {
        dns_rbtdb_t *rbtdb;
 
        rbtdb = (dns_rbtdb_t *)db;
@@ -7838,6 +7842,12 @@ settask(dns_db_t *db, isc_task_t *task) {
        if (task != NULL) {
                isc_task_attach(task, &rbtdb->task);
        }
+       if (rbtdb->prunetask != NULL) {
+               isc_task_detach(&rbtdb->prunetask);
+       }
+       if (prunetask != NULL) {
+               isc_task_attach(prunetask, &rbtdb->prunetask);
+       }
        RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
 }
 
@@ -8515,6 +8525,7 @@ dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
        isc_refcount_init(&rbtdb->references, 1);
        rbtdb->attributes = 0;
        rbtdb->task = NULL;
+       rbtdb->prunetask = NULL;
        rbtdb->serve_stale_ttl = 0;
 
        /*
index 317eeb0b215feac9dae2a2b99f6bae08b9a1ed06..b58080a2faed30ad6b47c9b9a32a649b2f352b46 100644 (file)
@@ -1263,9 +1263,10 @@ overmem(dns_db_t *db, bool over) {
 }
 
 static void
-settask(dns_db_t *db, isc_task_t *task) {
+settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask) {
        UNUSED(db);
        UNUSED(task);
+       UNUSED(prunetask);
 }
 
 static dns_dbmethods_t sdb_methods = {
index 7ab08f6bc9874a93faca42e8bc0e7911f8243b7d..ff674488658b403308747f7898ffab262fc2e679 100644 (file)
@@ -1213,9 +1213,10 @@ overmem(dns_db_t *db, bool over) {
 }
 
 static void
-settask(dns_db_t *db, isc_task_t *task) {
+settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask) {
        UNUSED(db);
        UNUSED(task);
+       UNUSED(prunetask);
 }
 
 /*
index 156a6be0632754f68bc17436edf7ad3c612294c7..4c5423815b3d04a5ab89c15313713eabf1e2ed6b 100644 (file)
@@ -2339,7 +2339,7 @@ zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
                              isc_result_totext(result));
                goto cleanup;
        }
-       dns_db_settask(db, zone->task);
+       dns_db_settask(db, zone->task, zone->task);
 
        if (zone->type == dns_zone_primary ||
            zone->type == dns_zone_secondary || zone->type == dns_zone_mirror)
@@ -14776,7 +14776,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
                                             isc_result_totext(result));
                                goto cleanup;
                        }
-                       dns_db_settask(stub->db, zone->task);
+                       dns_db_settask(stub->db, zone->task, zone->task);
                }
 
                result = dns_db_newversion(stub->db, &stub->version);
@@ -16220,7 +16220,7 @@ dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
        isc_task_attach(task, &zone->task);
        ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
        if (zone->db != NULL) {
-               dns_db_settask(zone->db, zone->task);
+               dns_db_settask(zone->db, zone->task, zone->task);
        }
        ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
        UNLOCK_ZONE(zone);
@@ -17880,7 +17880,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
                zone_detachdb(zone);
        }
        zone_attachdb(zone, db);
-       dns_db_settask(zone->db, zone->task);
+       dns_db_settask(zone->db, zone->task, zone->task);
        DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
        return (ISC_R_SUCCESS);