]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
catz: use two pairs of dns_db_t and dns_dbversion_t in a catalog zone
authorAram Sargsyan <aram@isc.org>
Thu, 2 Mar 2023 08:52:25 +0000 (08:52 +0000)
committerAram Sargsyan <aram@isc.org>
Thu, 2 Mar 2023 18:57:16 +0000 (18:57 +0000)
As it is done in the RPZ module, use 'db' and 'dbversion' for the
database we are going to update to, and 'updb' and 'updbversion' for
the database we are working on.

Doing this should avoid a race between the 'dns__catz_update_cb()' and
'dns_catz_dbupdate_callback()' functions.

(cherry picked from commit d2ecff3c4a0d961041b860515858d258d40462d7)

lib/dns/catz.c

index 5f642494b198e5c3eb6520ac3f04912d849f515b..909b8a102ce4e2ec3c996badbab204e9f1be3b8c 100644 (file)
@@ -87,11 +87,13 @@ struct dns_catz_zone {
        dns_catz_options_t zoneoptions;
        isc_time_t lastupdated;
 
-       bool updatepending;         /* there is an update pending */
-       bool updaterunning;         /* there is an update running */
-       isc_result_t updateresult;  /* result from the offloaded work */
-       dns_db_t *db;               /* zones database */
-       dns_dbversion_t *dbversion; /* zones database version */
+       bool updatepending;           /* there is an update pending */
+       bool updaterunning;           /* there is an update running */
+       isc_result_t updateresult;    /* result from the offloaded work */
+       dns_db_t *db;                 /* zones database */
+       dns_dbversion_t *dbversion;   /* version we will be updating to */
+       dns_db_t *updb;               /* zones database we're working on */
+       dns_dbversion_t *updbversion; /* version we're working on */
 
        isc_timer_t *updatetimer;
        isc_event_t updateevent;
@@ -2084,12 +2086,18 @@ dns__catz_timer_cb(isc_task_t *task, isc_event_t *event) {
        LOCK(&catz->catzs->lock);
 
        INSIST(DNS_DB_VALID(catz->db));
-       INSIST(catz->dbversion != NULL);
+       INSIST(catz->updb == NULL);
+       INSIST(catz->updbversion == NULL);
 
        catz->updatepending = false;
        catz->updaterunning = true;
        catz->updateresult = ISC_R_UNSET;
 
+       dns_db_attach(catz->db, &catz->updb);
+       INSIST(catz->dbversion != NULL);
+       catz->updbversion = catz->dbversion;
+       catz->dbversion = NULL;
+
        dns_name_format(&catz->name, domain, DNS_NAME_FORMATSIZE);
        isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
                      ISC_LOG_INFO, "catz: %s: reload start", domain);
@@ -2213,14 +2221,14 @@ catz_rdatatype_is_processable(const dns_rdatatype_t type) {
 static void
 dns__catz_update_cb(void *data) {
        dns_catz_zone_t *catz = (dns_catz_zone_t *)data;
-       dns_db_t *db = NULL;
+       dns_db_t *updb = NULL;
        dns_catz_zones_t *catzs = NULL;
        dns_catz_zone_t *oldcatz = NULL, *newcatz = NULL;
        isc_result_t result;
        isc_region_t r;
        dns_dbnode_t *node = NULL;
        const dns_dbnode_t *vers_node = NULL;
-       dns_dbiterator_t *it = NULL;
+       dns_dbiterator_t *updbit = NULL;
        dns_fixedname_t fixname;
        dns_name_t *name;
        dns_rdatasetiter_t *rdsiter = NULL;
@@ -2235,7 +2243,7 @@ dns__catz_update_cb(void *data) {
        REQUIRE(DNS_DB_VALID(catz->db));
        REQUIRE(DNS_CATZ_ZONES_VALID(catz->catzs));
 
-       db = catz->db;
+       updb = catz->updb;
        catzs = catz->catzs;
 
        if (atomic_load(&catzs->shuttingdown)) {
@@ -2243,12 +2251,12 @@ dns__catz_update_cb(void *data) {
                goto exit;
        }
 
-       dns_name_format(&db->origin, bname, DNS_NAME_FORMATSIZE);
+       dns_name_format(&updb->origin, bname, DNS_NAME_FORMATSIZE);
 
        /*
         * Create a new catz in the same context as current catz.
         */
-       dns_name_toregion(&db->origin, &r);
+       dns_name_toregion(&updb->origin, &r);
        LOCK(&catzs->lock);
        result = isc_ht_find(catzs->zones, r.base, r.length, (void **)&oldcatz);
        UNLOCK(&catzs->lock);
@@ -2260,7 +2268,7 @@ dns__catz_update_cb(void *data) {
                goto exit;
        }
 
-       result = dns_db_getsoaserial(db, oldcatz->dbversion, &vers);
+       result = dns_db_getsoaserial(updb, oldcatz->updbversion, &vers);
        if (result != ISC_R_SUCCESS) {
                /* A zone without SOA record?!? */
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
@@ -2275,9 +2283,8 @@ dns__catz_update_cb(void *data) {
                      "catz: updating catalog zone '%s' with serial %" PRIu32,
                      bname, vers);
 
-       result = dns_catz_new_zone(catzs, &newcatz, &db->origin);
+       result = dns_catz_new_zone(catzs, &newcatz, &updb->origin);
        if (result != ISC_R_SUCCESS) {
-               dns_db_closeversion(db, &oldcatz->dbversion, false);
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                              DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
                              "catz: failed to create new zone - %s",
@@ -2285,10 +2292,9 @@ dns__catz_update_cb(void *data) {
                goto exit;
        }
 
-       result = dns_db_createiterator(db, DNS_DB_NONSEC3, &it);
+       result = dns_db_createiterator(updb, DNS_DB_NONSEC3, &updbit);
        if (result != ISC_R_SUCCESS) {
                dns_catz_detach_catz(&newcatz);
-               dns_db_closeversion(db, &oldcatz->dbversion, false);
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                              DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
                              "catz: failed to create DB iterator - %s",
@@ -2303,21 +2309,19 @@ dns__catz_update_cb(void *data) {
         * records might be processed differently depending on the version of
         * the catalog zone's schema.
         */
-       result = dns_name_fromstring2(name, "version", &db->origin, 0, NULL);
+       result = dns_name_fromstring2(name, "version", &updb->origin, 0, NULL);
        if (result != ISC_R_SUCCESS) {
-               dns_dbiterator_destroy(&it);
+               dns_dbiterator_destroy(&updbit);
                dns_catz_detach_catz(&newcatz);
-               dns_db_closeversion(db, &oldcatz->dbversion, false);
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                              DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
                              "catz: failed to create name from string - %s",
                              isc_result_totext(result));
                goto exit;
        }
-       result = dns_dbiterator_seek(it, name);
+       result = dns_dbiterator_seek(updbit, name);
        if (result != ISC_R_SUCCESS) {
-               dns_dbiterator_destroy(&it);
-               dns_db_closeversion(db, &oldcatz->dbversion, false);
+               dns_dbiterator_destroy(&updbit);
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                              DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
                              "catz: zone '%s' has no 'version' record (%s)",
@@ -2337,7 +2341,7 @@ dns__catz_update_cb(void *data) {
                        break;
                }
 
-               result = dns_dbiterator_current(it, &node, name);
+               result = dns_dbiterator_current(updbit, &node, name);
                if (result != ISC_R_SUCCESS) {
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                                      DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
@@ -2346,7 +2350,7 @@ dns__catz_update_cb(void *data) {
                        break;
                }
 
-               result = dns_dbiterator_pause(it);
+               result = dns_dbiterator_pause(updbit);
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
                if (!is_vers_processed) {
@@ -2354,19 +2358,19 @@ dns__catz_update_cb(void *data) {
                        vers_node = node;
                } else if (node == vers_node) {
                        /* Skip the already processed version node */
-                       dns_db_detachnode(db, &node);
-                       result = dns_dbiterator_next(it);
+                       dns_db_detachnode(updb, &node);
+                       result = dns_dbiterator_next(updbit);
                        continue;
                }
 
-               result = dns_db_allrdatasets(db, node, oldcatz->dbversion, 0, 0,
-                                            &rdsiter);
+               result = dns_db_allrdatasets(updb, node, oldcatz->updbversion,
+                                            0, 0, &rdsiter);
                if (result != ISC_R_SUCCESS) {
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
                                      DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
                                      "catz: failed to fetch rrdatasets - %s",
                                      isc_result_totext(result));
-                       dns_db_detachnode(db, &node);
+                       dns_db_detachnode(updb, &node);
                        break;
                }
 
@@ -2421,18 +2425,17 @@ dns__catz_update_cb(void *data) {
 
                dns_rdatasetiter_destroy(&rdsiter);
 
-               dns_db_detachnode(db, &node);
+               dns_db_detachnode(updb, &node);
 
                if (!is_vers_processed) {
                        is_vers_processed = true;
-                       result = dns_dbiterator_first(it);
+                       result = dns_dbiterator_first(updbit);
                } else {
-                       result = dns_dbiterator_next(it);
+                       result = dns_dbiterator_next(updbit);
                }
        }
 
-       dns_dbiterator_destroy(&it);
-       dns_db_closeversion(db, &oldcatz->dbversion, false);
+       dns_dbiterator_destroy(&updbit);
        isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
                      ISC_LOG_DEBUG(3),
                      "catz: update_from_db: iteration finished: %s",
@@ -2499,7 +2502,7 @@ final:
         */
        if (!oldcatz->db_registered) {
                result = dns_db_updatenotify_register(
-                       db, dns_catz_dbupdate_callback, oldcatz->catzs);
+                       updb, dns_catz_dbupdate_callback, oldcatz->catzs);
                if (result == ISC_R_SUCCESS) {
                        oldcatz->db_registered = true;
                }
@@ -2555,6 +2558,9 @@ dns__catz_done_cb(void *data, isc_result_t result) {
        }
 
 done:
+       dns_db_closeversion(catz->updb, &catz->updbversion, false);
+       dns_db_detach(&catz->updb);
+
        UNLOCK(&catz->catzs->lock);
 
        isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,