]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
zone/timers: only write to timerDB if modified
authorLibor Peltan <libor.peltan@nic.cz>
Fri, 14 Nov 2025 08:02:51 +0000 (09:02 +0100)
committerLibor Peltan <libor.peltan@nic.cz>
Mon, 24 Nov 2025 09:41:28 +0000 (10:41 +0100)
12 files changed:
src/knot/dnssec/zone-sign.c
src/knot/events/handlers/dnssec.c
src/knot/events/handlers/ds_check.c
src/knot/events/handlers/ds_push.c
src/knot/events/handlers/notify.c
src/knot/events/handlers/refresh.c
src/knot/zone/backup.c
src/knot/zone/timers.c
src/knot/zone/timers.h
src/knot/zone/zone.c
src/knot/zone/zonedb-load.c
tests/knot/test_zone_timers.c

index 856c089cf64ed8ba68179c612597ad3cd7d40246..7308ec4f9d2a97f462868f4fbe8229a5fa62b176 100644 (file)
@@ -887,6 +887,7 @@ int knot_zone_sign_update_dnskeys(zone_update_t *update,
        if (dnssec_ctx->policy->ds_push && node_rrtype_exists(ch.add->apex, KNOT_RRTYPE_CDS)) {
                // there is indeed a change to CDS
                update->zone->timers->next_ds_push = time(NULL) + dnssec_ctx->policy->propagation_delay;
+               update->zone->timers->flags |= TIMERS_MODIFIED;
                zone_events_schedule_at(update->zone, ZONE_EVENT_DS_PUSH, update->zone->timers->next_ds_push);
        }
 
index 0150bdd3b66c95de8fd6329049257f85f9a7a48d..d0367a76a624efb64a1d2b0baa604bb0971ceddc 100644 (file)
@@ -41,6 +41,7 @@ void event_dnssec_reschedule(conf_t *conf, zone_t *zone,
 
        if (refresh->plan_ds_check) {
                zone->timers->next_ds_check = now;
+               zone->timers->flags |= TIMERS_MODIFIED;
        }
 
        unsigned jitter = dnskey_sync_jitter(conf, zone);
index f4f8cae2b378d60badc750bd7b4b39c287b41a2b..eaf44f5b9e5e0b049faa62355e41f847b797fae0 100644 (file)
@@ -25,6 +25,8 @@ int event_ds_check(conf_t *conf, zone_t *zone)
                                   conf->cache.srv_tcp_remote_io_timeout);
 
        zone->timers->next_ds_check = 0;
+       zone->timers->flags |= TIMERS_MODIFIED;
+
        switch (ret) {
        case KNOT_NO_READY_KEY:
                break;
index deb6392050a59738bf86845d3299aac35f8a1a66..1f59d2fddc3e3a2173a2a7bf1fc505879ed9367a 100644 (file)
@@ -249,6 +249,7 @@ int event_ds_push(conf_t *conf, zone_t *zone)
                        zone_events_schedule_at(zone, ZONE_EVENT_DS_PUSH, next_push);
                        zone->timers->next_ds_push = next_push;
                }
+               zone->timers->flags |= TIMERS_MODIFIED;
 
                conf_mix_iter_next(&iter);
        }
index 1cb788cb537a2a22a92165457d539983ac7cad70..7728dc23a00f2dea3d19a9bee047894f78345135 100644 (file)
@@ -112,7 +112,7 @@ static int send_notify(conf_t *conf, zone_t *zone, const knot_rrset_t *soa,
                               requestor.layer.flags,
                               "%sserial %u", log_retry, knot_soa_serial(soa->rrs.rdata));
                zone->timers->last_notified_serial = knot_soa_serial(soa->rrs.rdata);
-               zone->timers->flags |= LAST_NOTIFIED_SERIAL_VALID;
+               zone->timers->flags |= LAST_NOTIFIED_SERIAL_VALID | TIMERS_MODIFIED;
        } else if (knot_pkt_ext_rcode(req->resp) == 0) {
                NOTIFY_OUT_LOG(LOG_WARNING, zone->name, slave,
                               requestor.layer.flags,
index fc5f2fbf19c04abeec18724b8b0eb6ecdc37d8cb..46f7834564cb1e3d77d8ccfa9bfd6db1922b552c 100644 (file)
@@ -219,7 +219,7 @@ static void finalize_timers_base(struct refresh_data *data, bool also_expire)
        limit_timer(conf, zone->name, &soa_refresh, "refresh",
                    C_REFRESH_MIN_INTERVAL, C_REFRESH_MAX_INTERVAL);
        zone->timers->next_refresh = now + soa_refresh;
-       zone->timers->flags |= LAST_REFRESH_OK;
+       zone->timers->flags |= LAST_REFRESH_OK | TIMERS_MODIFIED;
 
        if (zone->is_catalog_flag) {
                // It's already zero in most cases.
@@ -1083,6 +1083,7 @@ static bool wait4pinned_master(struct refresh_data *data)
        // Starting countdown for master transition.
        if (data->zone->timers->master_pin_hit == 0) {
                data->zone->timers->master_pin_hit = now;
+               data->zone->timers->flags |= TIMERS_MODIFIED;
                zone_events_schedule_at(data->zone, ZONE_EVENT_REFRESH, now + data->fallback->pin_tol);
        // Switch to a new master.
        } else if (data->zone->timers->master_pin_hit + data->fallback->pin_tol <= now) {
@@ -1507,6 +1508,7 @@ int event_refresh(conf_t *conf, zone_t *zone)
                time_t now = time(NULL);
                zone->timers->next_refresh = now + next;
                zone->timers->flags &= ~LAST_REFRESH_OK;
+               zone->timers->flags |= TIMERS_MODIFIED;
 
                char time_str[64] = { 0 };
                struct tm time_gm = { 0 };
index 8ffe1441cba7dd3c79dabef5cb6592cb5daea09d..73ec28c50f6f87cbbe2f2e77ca36f63538027d7d 100644 (file)
@@ -498,6 +498,7 @@ int zone_backup(conf_t *conf, zone_t *zone)
                        zone_timers_sanitize(conf, zone);
                        zone->zonefile.bootstrap_cnt = 0;
                } else {
+                       zone->timers->flags |= TIMERS_MODIFIED; // otherwise the write is skipped!
                        ret = zone_timers_write(&ctx->bck_timer_db, zone->name, zone->timers);
                }
                if (ret != KNOT_EOK) {
index 4e591ee9684dab6999f6fe7c0444f9bcd64b46fd..e920f11d128894779e6de6251c85abc8610909b6 100644 (file)
@@ -117,8 +117,11 @@ static int deserialize_timers(zone_timers_t *timers_ptr,
 }
 
 static void txn_write_timers(knot_lmdb_txn_t *txn, const knot_dname_t *zone,
-                             const zone_timers_t *timers)
+                             zone_timers_t *timers)
 {
+       if (!(timers->flags & TIMERS_MODIFIED)) { // TODO move this conditional to txn_zone_write, as it is also in zone_timers_write. Here temporarily to avoid git conflicts.
+               return;
+       }
        const char *format = (timers->last_master.sin6_family == AF_INET ||
                              timers->last_master.sin6_family == AF_INET6) ?
                             "TTTTTTTTTTBD" :
@@ -139,6 +142,10 @@ static void txn_write_timers(knot_lmdb_txn_t *txn, const knot_dname_t *zone,
                TIMER_LAST_MASTER,   &timers->last_master, sizeof(timers->last_master));
        knot_lmdb_insert(txn, &k, &v);
        free(v.mv_data);
+
+       if (txn->ret == KNOT_EOK) {
+               timers->flags &= ~TIMERS_MODIFIED;
+       }
 }
 
 
@@ -186,10 +193,10 @@ int zone_timers_read(knot_lmdb_db_t *db, const knot_dname_t *zone,
 }
 
 int zone_timers_write(knot_lmdb_db_t *db, const knot_dname_t *zone,
-                      const zone_timers_t *timers)
+                      zone_timers_t *timers)
 {
        int ret = knot_lmdb_open(db);
-       if (ret != KNOT_EOK) {
+       if (ret != KNOT_EOK || !(timers->flags & TIMERS_MODIFIED)) {
                return ret;
        }
        knot_lmdb_txn_t txn = { 0 };
index 17bf72e3061a58b03174745c6e44d28fda63fdfa..e992c9fde99d2456f22cf3634ef0998b21a3960a 100644 (file)
@@ -12,6 +12,7 @@
 #include "libknot/dname.h"
 #include "knot/journal/knot_lmdb.h"
 
+#define TIMERS_MODIFIED            (1 << 0)
 #define LAST_SIGNED_SERIAL_FOUND   (1 << 1)
 #define LAST_SIGNED_SERIAL_VALID   (1 << 2)
 #define LAST_NOTIFIED_SERIAL_VALID (1 << 3)
@@ -64,7 +65,7 @@ int zone_timers_read(knot_lmdb_db_t *db, const knot_dname_t *zone,
  * \return KNOT_E*
  */
 int zone_timers_write(knot_lmdb_db_t *db, const knot_dname_t *zone,
-                      const zone_timers_t *timers);
+                      zone_timers_t *timers);
 
 /*!
  * \brief Write timers for all zones.
index 3312483af4a146b4a17995df6880ae8fbe5c47a4..01e03f83d5dd0164325a80d70038574d4e9503b7 100644 (file)
@@ -141,6 +141,7 @@ static int flush_journal(conf_t *conf, zone_t *zone, bool allow_empty_zone, bool
 flush_journal_replan:
        /* Plan next journal flush after proper period. */
        zone->timers->last_flush = time(NULL);
+       zone->timers->flags |= TIMERS_MODIFIED;
        if (sync_timeout > 0) {
                time_t next_flush = zone->timers->last_flush + sync_timeout;
                zone_events_schedule_at(zone, ZONE_EVENT_FLUSH, (time_t)0,
@@ -309,6 +310,7 @@ int selective_zone_purge(conf_t *conf, zone_t *zone, purge_flag_t params)
                time_t member = (zone->catalog_gen != NULL ? zone->timers->catalog_member : 0);
                memset(zone->timers, 0, sizeof(*zone->timers));
                zone->timers->catalog_member = member;
+               zone->timers->flags |= TIMERS_MODIFIED;
 
                if (member) {
                        ret = zone_timers_write(&zone->server->timerdb, zone->name,
@@ -390,6 +392,7 @@ void zone_perform_expire(conf_t *conf, zone_t *zone)
 
        zone->timers->next_expire = time(NULL);
        zone->timers->next_refresh = zone->timers->next_expire;
+       zone->timers->flags |= TIMERS_MODIFIED;
        replan_from_timers(conf, zone);
 }
 
@@ -599,6 +602,7 @@ void zone_set_last_master(zone_t *zone, const struct sockaddr_storage *addr)
                memcpy(&zone->timers->last_master, addr, sizeof(zone->timers->last_master));
        }
        zone->timers->master_pin_hit = 0;
+       zone->timers->flags |= TIMERS_MODIFIED;
 }
 
 static void set_flag(zone_t *zone, zone_flag_t flag, bool remove)
@@ -682,6 +686,7 @@ void zone_timers_sanitize(conf_t *conf, zone_t *zone)
        assert(zone);
 
        time_t now = time(NULL);
+       zone_timers_t prev = *zone->timers;
 
        // assume now if we don't know when we flushed
        time_set_default(&zone->timers->last_flush, now);
@@ -698,6 +703,10 @@ void zone_timers_sanitize(conf_t *conf, zone_t *zone)
                zone->timers->flags &= ~LAST_REFRESH_OK;
                zone->timers->next_expire = 0;
        }
+
+       if (memcmp(&prev, zone->timers, sizeof(prev)) != 0) {
+               zone->timers->flags |= TIMERS_MODIFIED;
+       }
 }
 
 int zone_timers_begin(zone_t *zone)
@@ -966,7 +975,7 @@ void zone_set_lastsigned_serial(zone_t *zone, uint32_t serial)
 {
        bool extra_txn = (zone->control_update != NULL && zone->timers == zone->timers_static && zone_timers_begin(zone) == KNOT_EOK); // zone_update_commit() is not within a zone event in case of control_update
        zone->timers->last_signed_serial = serial;
-       zone->timers->flags |= LAST_SIGNED_SERIAL_FOUND | LAST_SIGNED_SERIAL_VALID;
+       zone->timers->flags |= LAST_SIGNED_SERIAL_FOUND | LAST_SIGNED_SERIAL_VALID | TIMERS_MODIFIED;
        if (extra_txn) {
                zone_timers_commit(zone);
        }
index 91d137b9ff1581aa4dc78ee78c2d69f2d0e8b0f3..d00f76cb35d359f4f7ee96ea5cb5c0c73f537767 100644 (file)
@@ -146,6 +146,7 @@ static zone_t *create_zone_new(conf_t *conf, const knot_dname_t *name,
                zone->catalog_gen = knot_dname_copy(conf_dname(&catz), NULL);
                if (zone->timers->catalog_member == 0) {
                        zone->timers->catalog_member = time(NULL);
+                       zone->timers->flags |= TIMERS_MODIFIED;
                        ret = zone_timers_write(&zone->server->timerdb, zone->name,
                                                zone->timers);
                }
@@ -231,6 +232,7 @@ static zone_contents_t *zone_expire(zone_t *zone, bool zonedb_cow)
                zone_timers_begin(zone);
                zone->timers->next_expire = time(NULL);
                zone->timers->next_refresh = zone->timers->next_expire;
+               zone->timers->flags |= TIMERS_MODIFIED;
                zone_timers_commit(zone);
        }
        return zone_switch_contents(zone, NULL);
index 6fcddc18b2fbeed2601d8e7b1be88ba8f8009998..e0d93f4ce04ad6bcb3fc28aabbe91ee51f2cb821 100644 (file)
@@ -15,7 +15,7 @@
 #include "libknot/error.h"
 
 static const zone_timers_t MOCK_TIMERS = {
-       .flags = LAST_SIGNED_SERIAL_FOUND | LAST_SIGNED_SERIAL_VALID,
+       .flags = LAST_SIGNED_SERIAL_FOUND | LAST_SIGNED_SERIAL_VALID | TIMERS_MODIFIED,
        .last_flush     = 1474559960,
        .next_refresh   = 1474559961,
        .last_notified_serial = 123456,
@@ -65,7 +65,7 @@ int main(int argc, char *argv[])
        }
 
        const knot_dname_t *zone = (uint8_t *)"\x7""example""\x3""com";
-       struct zone_timers timers = MOCK_TIMERS;
+       struct zone_timers timers = MOCK_TIMERS, timers2 = { 0 };
 
        // Create database
        knot_lmdb_db_t _db = { 0 }, *db = &_db;
@@ -82,21 +82,20 @@ int main(int argc, char *argv[])
        is_int(KNOT_EOK, ret, "zone_timers_write()");
 
        // Read timers
-       memset(&timers, 0, sizeof(timers));
-       ret = zone_timers_read(db, zone, &timers);
+       ret = zone_timers_read(db, zone, &timers2);
        ok(ret == KNOT_EOK, "zone_timers_read()");
-       ok(timers_eq(&timers, &MOCK_TIMERS), "inconsistent timers");
+       ok(timers_eq(&timers2, &timers), "inconsistent timers");
 
        // Sweep none
        ret = zone_timers_sweep(db, keep_all, NULL);
        is_int(KNOT_EOK, ret, "zone_timers_sweep() none");
-       ret = zone_timers_read(db, zone, &timers);
+       ret = zone_timers_read(db, zone, &timers2);
        is_int(KNOT_EOK, ret, "zone_timers_read()");
 
        // Sweep all
        ret = zone_timers_sweep(db, remove_all, NULL);
        is_int(KNOT_EOK, ret, "zone_timers_sweep() all");
-       ret = zone_timers_read(db, zone, &timers);
+       ret = zone_timers_read(db, zone, &timers2);
        is_int(KNOT_ENOENT, ret, "zone_timers_read() nonexistent");
 
        // Clean up.