From d2ecff3c4a0d961041b860515858d258d40462d7 Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Thu, 2 Mar 2023 08:52:25 +0000 Subject: [PATCH] catz: use two pairs of dns_db_t and dns_dbversion_t in a catalog zone 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 | 76 +++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/lib/dns/catz.c b/lib/dns/catz.c index 3a28fbcf0e..60f690fbe1 100644 --- a/lib/dns/catz.c +++ b/lib/dns/catz.c @@ -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,