]> 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 17:39:43 +0000 (17:39 +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.

lib/dns/catz.c

index 3a28fbcf0e2f816dc1e1bf0b79567691e57f7002..60f690fbe145b2678e22e55a933539fa9d72f191 100644 (file)
@@ -88,11 +88,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;
 
@@ -2094,12 +2096,18 @@ dns__catz_timer_cb(void *arg) {
        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);
@@ -2193,14 +2201,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 = NULL;
        dns_rdatasetiter_t *rdsiter = NULL;
@@ -2215,7 +2223,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)) {
@@ -2223,12 +2231,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);
@@ -2240,7 +2248,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,
@@ -2255,9 +2263,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",
@@ -2265,10 +2272,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",
@@ -2283,21 +2289,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)",
@@ -2317,7 +2321,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,
@@ -2326,7 +2330,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) {
@@ -2334,19 +2338,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;
                }
 
@@ -2401,18 +2405,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",
@@ -2479,7 +2482,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;
                }
@@ -2506,6 +2509,9 @@ dns__catz_done_cb(void *data) {
                dns__catz_timer_start(catz);
        }
 
+       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,