From: Alessio Podda Date: Thu, 4 Jun 2026 12:05:08 +0000 (+0200) Subject: Split inline sync state into a separate struct X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c2e2776b86d38ce30a318bb10a9cc129ffac3a80;p=thirdparty%2Fbind9.git Split inline sync state into a separate struct The inline sync state is only needed when there is a raw-to-secure sync in progress, and should be handled "atomically". This commit creates a separate structure that holds all the inline sync state to streamline the creation and cleanup. --- diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 0bfff8e33f..2fe411c222 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -615,9 +615,8 @@ dns__zone_free(dns_zone_t *zone) { isc_mem_put(zone->mctx, include, sizeof *include); } - if (zone->rss_state != NULL) { - dns_update_state_clear(&zone->rss_state); - } + zone_clear_inline_sync(zone); + INSIST(zone->iss == NULL); if (zone->masterfile != NULL) { isc_mem_free(zone->mctx, zone->masterfile); @@ -4019,8 +4018,7 @@ static bool zone_maintenance_request_pending(dns_zone_t *zone) { REQUIRE(LOCKED_ZONE(zone)); - return zone->rss_zone == NULL && - DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) && + return zone->iss == NULL && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) && !ISC_LIST_EMPTY(zone->maintenance_queue); } @@ -9878,12 +9876,12 @@ zone_inline_sync_action(dns_zone_t *zone) { zone->inline_sync_phase = inline_sync_idle; /* * A full rebuild replaces any parked incremental sync state; - * zone_maintenance() cancels rss_* before bootstrapping. + * zone_maintenance() cancels zone->iss before bootstrapping. */ return inline_sync_bootstrap; } - if (zone->rss_zone != NULL) { + if (zone->iss != NULL) { return inline_sync_incremental_continue; } @@ -9909,9 +9907,10 @@ static bool zone_inline_sync_pending(dns_zone_t *zone) { REQUIRE(LOCKED_ZONE(zone)); - return zone->rss_zone != NULL || - zone->inline_sync_phase == inline_sync_incremental || - zone->inline_sync_phase == inline_sync_full; + return dns__zone_inline_secure(zone) && + (zone->iss != NULL || + zone->inline_sync_phase == inline_sync_incremental || + zone->inline_sync_phase == inline_sync_full); } static void @@ -14381,53 +14380,130 @@ zone_get_raw_serial(dns_zone_t *raw, uint32_t *serialp) { return result; } -static void -zone_clear_inline_sync(dns_zone_t *zone) { - dns_zone_t *rss_zone = NULL; - dns_zone_t *rss_raw = NULL; - dns_db_t *rss_db = NULL; - dns_dbversion_t *rss_oldver = NULL; - dns_dbversion_t *rss_newver = NULL; - dns_update_state_t *rss_state = NULL; +static zone_inline_sync_t * +inline_sync_pop(dns_zone_t *zone) { + zone_inline_sync_t *iss = NULL; REQUIRE(DNS_ZONE_VALID(zone)); LOCK_ZONE(zone); - if (zone->rss_zone == NULL && zone->rss_state == NULL) { - UNLOCK_ZONE(zone); + if (zone->iss != NULL) { + /* + * inline_sync_run() is only called from zone maintenance, so + * zone->iss can only be parked between maintenance passes here. + */ + iss = MOVE_OWNERSHIP(zone->iss); + } + UNLOCK_ZONE(zone); + + return iss; +} + +static void +inline_sync_destroy(zone_inline_sync_t **issp) { + zone_inline_sync_t *iss = NULL; + + REQUIRE(issp != NULL); + + iss = *issp; + if (iss == NULL) { return; } + *issp = NULL; - /* - * inline_sync_run() is only called from zone maintenance, so rss_* - * state can only be parked between maintenance passes here. - */ - rss_zone = MOVE_OWNERSHIP(zone->rss_zone); - rss_raw = MOVE_OWNERSHIP(zone->rss_raw); - rss_db = MOVE_OWNERSHIP(zone->rss_db); - rss_oldver = MOVE_OWNERSHIP(zone->rss_oldver); - rss_newver = MOVE_OWNERSHIP(zone->rss_newver); - rss_state = MOVE_OWNERSHIP(zone->rss_state); - zone->rss_end = 0; - dns_diff_clear(&zone->rss_diff); - UNLOCK_ZONE(zone); + INSIST(iss->mctx != NULL); - dns_update_state_clear(&rss_state); - if (rss_db != NULL) { - if (rss_oldver != NULL) { - dns_db_closeversion(rss_db, &rss_oldver, false); + dns_diff_clear(&iss->diff); + dns_update_state_clear(&iss->state); + if (iss->db != NULL) { + if (iss->oldver != NULL) { + dns_db_closeversion(iss->db, &iss->oldver, false); } - if (rss_newver != NULL) { - dns_db_closeversion(rss_db, &rss_newver, false); + if (iss->newver != NULL) { + dns_db_closeversion(iss->db, &iss->newver, false); } - dns_db_detach(&rss_db); + dns_db_detach(&iss->db); + } + if (iss->raw != NULL) { + dns_zone_detach(&iss->raw); + } + isc_mem_putanddetach(&iss->mctx, iss, sizeof(*iss)); +} + +static isc_result_t +inline_sync_create(dns_zone_t *zone, uint32_t *endp, + zone_inline_sync_t **issp) { + isc_result_t result = ISC_R_SUCCESS; + zone_inline_sync_t *iss = NULL; + uint32_t end = 0; + + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(endp != NULL); + REQUIRE(issp != NULL && *issp == NULL); + + iss = isc_mem_cget(zone->mctx, 1, sizeof(*iss)); + isc_mem_attach(zone->mctx, &iss->mctx); + + LOCK_ZONE(zone); + + /* + * The inline_sync_run() is loop-serialized for the zone. Install the + * transaction while attaching its resources so zone->iss stays the + * single marker for sync-in-flight. + */ + INSIST(zone->iss == NULL); + zone->iss = iss; + dns_diff_init(iss->mctx, &iss->diff); + + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); + if (zone->db != NULL) { + dns_db_attach(zone->db, &iss->db); + } else { + result = ISC_R_FAILURE; } - if (rss_raw != NULL) { - dns_zone_detach(&rss_raw); + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + + if (zone->raw != NULL) { + dns_zone_attach(zone->raw, &iss->raw); + } else { + result = ISC_R_FAILURE; } - if (rss_zone != NULL) { - dns_zone_idetach(&rss_zone); + + UNLOCK_ZONE(zone); + + CHECK(result); + CHECK(zone_get_raw_serial(iss->raw, &end)); + + LOCK_ZONE(zone); + if (zone->sourceserialset && end == zone->sourceserial) { + UNLOCK_ZONE(zone); + result = DNS_R_UNCHANGED; + goto cleanup; } + iss->end = end; + UNLOCK_ZONE(zone); + + dns_db_currentversion(iss->db, &iss->oldver); + CHECK(dns_db_newversion(iss->db, &iss->newver)); + + *endp = end; + *issp = iss; + return ISC_R_SUCCESS; + +cleanup: + iss = inline_sync_pop(zone); + inline_sync_destroy(&iss); + return result; +} + +static void +zone_clear_inline_sync(dns_zone_t *zone) { + zone_inline_sync_t *iss = NULL; + + REQUIRE(DNS_ZONE_VALID(zone)); + + iss = inline_sync_pop(zone); + inline_sync_destroy(&iss); } static void @@ -14485,17 +14561,20 @@ inline_sync_finalize(dns_zone_t *zone, uint32_t newserial, uint32_t desired) { isc_result_t result = ISC_R_SUCCESS; dns_journal_t *rjournal = NULL; dns_update_log_t log = { update_log_cb, NULL }; + zone_inline_sync_t *iss = NULL; uint32_t end = 0; ENTER; LOCK_ZONE(zone); - end = zone->rss_end; + iss = zone->iss; + INSIST(iss != NULL); + end = iss->end; UNLOCK_ZONE(zone); result = dns_update_signaturesinc( - &log, zone, zone->rss_db, zone->rss_oldver, zone->rss_newver, - &zone->rss_diff, zone->sigvalidityinterval, &zone->rss_state); + &log, zone, iss->db, iss->oldver, iss->newver, &iss->diff, + zone->sigvalidityinterval, &iss->state); if (result == DNS_R_CONTINUE) { LOCK_ZONE(zone); zone_schedule_inline_sync(zone, inline_sync_idle); @@ -14511,13 +14590,13 @@ inline_sync_finalize(dns_zone_t *zone, uint32_t newserial, uint32_t desired) { * created for it), commence applying raw zone deltas to it so that * contents of the raw zone and the secure zone are kept in sync. */ - if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) { + if (result != ISC_R_SUCCESS && dns_db_issecure(iss->db)) { goto cleanup; } - CHECK(dns_journal_open(zone->rss_raw->mctx, zone->rss_raw->journal, + CHECK(dns_journal_open(iss->raw->mctx, iss->raw->journal, DNS_JOURNAL_WRITE, &rjournal)); - CHECK(zone_journal(zone, &zone->rss_diff, &end, "inline_sync")); + CHECK(zone_journal(zone, &iss->diff, &end, "inline_sync")); dns_journal_set_sourceserial(rjournal, end); dns_journal_commit(rjournal); @@ -14537,8 +14616,8 @@ inline_sync_finalize(dns_zone_t *zone, uint32_t newserial, uint32_t desired) { dns__zone_settimer(zone, isc_time_now()); UNLOCK_ZONE(zone); - dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false); - dns_db_closeversion(zone->rss_db, &zone->rss_newver, true); + dns_db_closeversion(iss->db, &iss->oldver, false); + dns_db_closeversion(iss->db, &iss->newver, true); if (newserial != 0) { dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)", @@ -14561,45 +14640,11 @@ inline_sync_run(dns_zone_t *zone) { uint32_t start = 0, end = 0; dns_difftuple_t *tuple = NULL, *soatuple = NULL; uint32_t newserial = 0, desired = 0; + zone_inline_sync_t *iss = NULL; ENTER; - LOCK_ZONE(zone); - - /* - * The inline_sync_run() is loop-serialized for the zone. - * Make sure there's no processing currently running. - */ - INSIST(zone->rss_zone == NULL); - zone_iattach(zone, &zone->rss_zone); - dns_diff_init(zone->mctx, &zone->rss_diff); - - ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); - if (zone->db != NULL) { - dns_db_attach(zone->db, &zone->rss_db); - } else { - result = ISC_R_FAILURE; - } - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); - - if (zone->raw != NULL) { - dns_zone_attach(zone->raw, &zone->rss_raw); - } else { - result = ISC_R_FAILURE; - } - - UNLOCK_ZONE(zone); - - CHECK(result); - CHECK(zone_get_raw_serial(zone->rss_raw, &end)); - LOCK_ZONE(zone); - if (zone->sourceserialset && end == zone->sourceserial) { - UNLOCK_ZONE(zone); - result = DNS_R_UNCHANGED; - goto cleanup; - } - zone->rss_end = end; - UNLOCK_ZONE(zone); + CHECK(inline_sync_create(zone, &end, &iss)); /* * We first attempt to sync the raw zone to the secure zone by using the @@ -14610,7 +14655,7 @@ inline_sync_run(dns_zone_t *zone) { * If that fails, then we'll fall back to a direct comparison between * raw and secure zones. */ - CHECK(dns_journal_open(zone->rss_raw->mctx, zone->rss_raw->journal, + CHECK(dns_journal_open(iss->raw->mctx, iss->raw->journal, DNS_JOURNAL_WRITE, &rjournal)); result = dns_journal_open(zone->mctx, zone->journal, DNS_JOURNAL_READ, @@ -14637,15 +14682,12 @@ inline_sync_run(dns_zone_t *zone) { dns_journal_destroy(&sjournal); } - dns_db_currentversion(zone->rss_db, &zone->rss_oldver); - CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver)); - /* * Try to apply diffs from the raw zone's journal to the secure zone. If * that fails, we recover by syncing up the databases directly. */ - result = sync_secure_journal(zone, zone->rss_raw, rjournal, start, end, - &soatuple, &zone->rss_diff); + result = sync_secure_journal(zone, iss->raw, rjournal, start, end, + &soatuple, &iss->diff); if (result == DNS_R_UNCHANGED) { LOCK_ZONE(zone); zone->sourceserial = end; @@ -14654,9 +14696,8 @@ inline_sync_run(dns_zone_t *zone) { goto cleanup; } else if (result != ISC_R_SUCCESS) { - result = sync_secure_db(zone, zone->rss_raw, zone->rss_db, - zone->rss_oldver, &soatuple, - &zone->rss_diff); + result = sync_secure_db(zone, iss->raw, iss->db, iss->oldver, + &soatuple, &iss->diff); if (result == DNS_R_UNCHANGED) { LOCK_ZONE(zone); zone->sourceserial = end; @@ -14668,13 +14709,13 @@ inline_sync_run(dns_zone_t *zone) { CHECK(result); } - CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db, zone->rss_newver)); + CHECK(dns_diff_apply(&iss->diff, iss->db, iss->newver)); if (soatuple != NULL) { uint32_t oldserial; - CHECK(dns_db_createsoatuple(zone->rss_db, zone->rss_oldver, - zone->rss_diff.mctx, DNS_DIFFOP_DEL, + CHECK(dns_db_createsoatuple(iss->db, iss->oldver, + iss->diff.mctx, DNS_DIFFOP_DEL, &tuple)); oldserial = dns_soa_getserial(&tuple->rdata); newserial = desired = dns_soa_getserial(&soatuple->rdata); @@ -14685,14 +14726,12 @@ inline_sync_run(dns_zone_t *zone) { } dns_soa_setserial(newserial, &soatuple->rdata); } - CHECK(do_one_tuple(&tuple, zone->rss_db, zone->rss_newver, - &zone->rss_diff)); - CHECK(do_one_tuple(&soatuple, zone->rss_db, zone->rss_newver, - &zone->rss_diff)); + CHECK(do_one_tuple(&tuple, iss->db, iss->newver, &iss->diff)); + CHECK(do_one_tuple(&soatuple, iss->db, iss->newver, + &iss->diff)); } else { - CHECK(update_soa_serial(zone, zone->rss_db, zone->rss_newver, - &zone->rss_diff, zone->mctx, - zone->updatemethod)); + CHECK(update_soa_serial(zone, iss->db, iss->newver, &iss->diff, + zone->mctx, zone->updatemethod)); } cleanup: @@ -14735,7 +14774,7 @@ inline_sync_resume(dns_zone_t *zone) { ENTER; LOCK_ZONE(zone); - INSIST(zone->rss_zone != NULL); + INSIST(zone->iss != NULL); UNLOCK_ZONE(zone); result = inline_sync_finalize(zone, 0, 0); diff --git a/lib/dns/zone_p.h b/lib/dns/zone_p.h index 3647369c8d..d7cc14d65f 100644 --- a/lib/dns/zone_p.h +++ b/lib/dns/zone_p.h @@ -188,8 +188,8 @@ typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t; typedef struct dns_include dns_include_t; /* - * Pending inline-signing sync request for the secure zone. Active - * incremental signing continuation state is owned separately by rss_* fields. + * Pending inline-signing sync request for the secure zone. Active incremental + * signing continuation state is owned separately by zone_inline_sync_t. */ typedef enum inline_sync_phase { inline_sync_idle = 0, /*%< No inline sync request is queued. */ @@ -197,6 +197,21 @@ typedef enum inline_sync_phase { inline_sync_full = 2, /*%< Full rebuild is queued. */ } inline_sync_phase_t; +/* + * In-flight inline-signing sync transaction. Pointed to by zone->iss; NULL + * means no sync is running. + */ +typedef struct zone_inline_sync { + isc_mem_t *mctx; + dns_zone_t *raw; + dns_db_t *db; + dns_dbversion_t *oldver; + dns_dbversion_t *newver; + dns_diff_t diff; + dns_update_state_t *state; + uint32_t end; +} zone_inline_sync_t; + /*% * Hold checkds state. */ @@ -586,14 +601,7 @@ struct dns_zone { * Inline zone signing state. */ inline_sync_phase_t inline_sync_phase; - dns_diff_t rss_diff; - dns_dbversion_t *rss_newver; - dns_dbversion_t *rss_oldver; - dns_db_t *rss_db; - dns_zone_t *rss_raw; - uint32_t rss_end; - dns_zone_t *rss_zone; - dns_update_state_t *rss_state; + zone_inline_sync_t *iss; isc_stats_t *gluecachestats;