diff options
author | Daniel Salzman <daniel.salzman@nic.cz> | 2022-11-24 20:31:34 +0100 |
---|---|---|
committer | Daniel Salzman <daniel.salzman@nic.cz> | 2022-12-05 15:14:43 +0100 |
commit | 089cbd1023f4cb7b7495362152f1583fd615ff71 (patch) | |
tree | 5582dbdad5db85044e0b44079174b99bb3a0ebf4 | |
parent | doc/reference: make effect of missing ACL "address" and "key" items clear (diff) | |
download | knot-089cbd1023f4cb7b7495362152f1583fd615ff71.tar.xz knot-089cbd1023f4cb7b7495362152f1583fd615ff71.zip |
zonedb: reload changed catalog members only (reuse otherwise), refactoring
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/knot/catalog/catalog_update.c | 3 | ||||
-rw-r--r-- | src/knot/ctl/commands.c | 4 | ||||
-rw-r--r-- | src/knot/server/server.c | 8 | ||||
-rw-r--r-- | src/knot/server/server.h | 28 | ||||
-rw-r--r-- | src/knot/updates/zone-update.c | 10 | ||||
-rw-r--r-- | src/knot/zone/zonedb-load.c | 62 | ||||
-rw-r--r-- | src/knot/zone/zonedb-load.h | 9 | ||||
-rw-r--r-- | src/utils/knotd/main.c | 8 | ||||
-rw-r--r-- | tests-extra/tests/catalog/multi/test.py | 6 |
10 files changed, 86 insertions, 54 deletions
diff --git a/configure.ac b/configure.ac index 43b8b8217..8fecd828a 100644 --- a/configure.ac +++ b/configure.ac @@ -712,7 +712,7 @@ LIBS="$save_LIBS" # Checks for header files. AC_HEADER_RESOLV -AC_CHECK_HEADERS_ONCE([pthread_np.h sys/uio.h bsd/string.h]) +AC_CHECK_HEADERS_ONCE([pthread_np.h stdatomic.h sys/uio.h bsd/string.h]) # Checks for optional library functions. AC_CHECK_FUNCS([accept4 clock_gettime fgetln getline initgroups malloc_trim \ diff --git a/src/knot/catalog/catalog_update.c b/src/knot/catalog/catalog_update.c index faed011f3..50f38cbc2 100644 --- a/src/knot/catalog/catalog_update.c +++ b/src/knot/catalog/catalog_update.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -398,6 +398,7 @@ int catalog_zone_purge(server_t *server, conf_t *conf, const knot_dname_t *zone) int ret = catalog_update_del_all(&server->catalog_upd, &server->catalog, zone, &members); if (ret == KNOT_EOK && members > 0) { log_zone_info(zone, "catalog zone purged, %zd member zones deconfigured", members); + server->catalog_upd_signal = true; if (kill(getpid(), SIGUSR1) != 0) { ret = knot_map_errno(); } diff --git a/src/knot/ctl/commands.c b/src/knot/ctl/commands.c index 8d502e29c..8a4dbe993 100644 --- a/src/knot/ctl/commands.c +++ b/src/knot/ctl/commands.c @@ -1839,7 +1839,7 @@ static int ctl_server(ctl_args_t *args, ctl_cmd_t cmd) ret = KNOT_CTL_ESTOP; break; case CTL_RELOAD: - ret = server_reload(args->server); + ret = server_reload(args->server, RELOAD_FULL); if (ret != KNOT_EOK) { send_error(args, knot_strerror(ret)); } @@ -2059,7 +2059,7 @@ static int ctl_conf_txn(ctl_args_t *args, ctl_cmd_t cmd) break; } - ret = server_reload(args->server); + ret = server_reload(args->server, RELOAD_COMMIT); break; default: assert(0); diff --git a/src/knot/server/server.c b/src/knot/server/server.c index c4fa12ae1..616a8d93f 100644 --- a/src/knot/server/server.c +++ b/src/knot/server/server.c @@ -1047,7 +1047,7 @@ static void warn_server_reconfigure(conf_t *conf, server_t *server) } } -int server_reload(server_t *server) +int server_reload(server_t *server, reload_t mode) { if (server == NULL) { return KNOT_EINVAL; @@ -1109,7 +1109,7 @@ int server_reload(server_t *server) stats_reconfigure(conf(), server); } if (full || (flags & (CONF_IO_FRLD_ZONES | CONF_IO_FRLD_ZONE))) { - server_update_zones(conf(), server); + server_update_zones(conf(), server, mode); } /* Free old config needed for module unload in zone reload. */ @@ -1303,7 +1303,7 @@ int server_reconfigure(conf_t *conf, server_t *server) return KNOT_EOK; } -void server_update_zones(conf_t *conf, server_t *server) +void server_update_zones(conf_t *conf, server_t *server, reload_t mode) { if (conf == NULL || server == NULL) { return; @@ -1319,7 +1319,7 @@ void server_update_zones(conf_t *conf, server_t *server) worker_pool_wait(server->workers); /* Reload zone database and free old zones. */ - zonedb_reload(conf, server); + zonedb_reload(conf, server, mode); /* Trim extra heap. */ mem_trim(); diff --git a/src/knot/server/server.h b/src/knot/server/server.h index 98f28f0ac..5adafdb6a 100644 --- a/src/knot/server/server.h +++ b/src/knot/server/server.h @@ -16,6 +16,8 @@ #pragma once +#include <stdatomic.h> + #include "knot/conf/conf.h" #include "knot/catalog/catalog_update.h" #include "knot/common/evsched.h" @@ -49,6 +51,17 @@ typedef enum { } server_state_t; /*! + * \brief Server reload kinds. + */ +typedef enum { + RELOAD_NONE = 0, + RELOAD_FULL = 1 << 0, /*!< Reload the server and all zones. */ + RELOAD_COMMIT = 1 << 1, /*!< Process changes from dynamic configuration. */ + RELOAD_ZONES = 1 << 2, /*!< Reload all zones. */ + RELOAD_CATALOG = 1 << 3, /*!< Process catalog zone changes. */ +} reload_t; + +/*! * \brief Server interface structure. */ typedef struct { @@ -103,8 +116,9 @@ typedef struct server { iface_t *ifaces; size_t n_ifaces; - /*! \brief Pending changes to catalog member zones. */ + /*! \brief Pending changes to catalog member zones, update indication. */ catalog_update_t catalog_upd; + atomic_bool catalog_upd_signal; /*! \brief Context of pending zones' backup. */ zone_backup_ctxs_t backup_ctxs; @@ -152,10 +166,11 @@ void server_wait(server_t *server); * \brief Reload server configuration. * * \param server Server instance. + * \param mode Reload mode. * * \return Error code, KNOT_EOK if success. */ -int server_reload(server_t *server); +int server_reload(server_t *server, reload_t mode); /*! * \brief Requests server to stop. @@ -169,6 +184,9 @@ void server_stop(server_t *server); * * Routine for dynamic server reconfiguration. * + * \param conf Configuration. + * \param server Server instance. + * * \return Error code, KNOT_EOK if success. */ int server_reconfigure(conf_t *conf, server_t *server); @@ -177,5 +195,9 @@ int server_reconfigure(conf_t *conf, server_t *server); * \brief Reconfigure zone database. * * Routine for dynamic server zones reconfiguration. + * + * \param conf Configuration. + * \param server Server instance. + * \param mode Reload mode. */ -void server_update_zones(conf_t *conf, server_t *server); +void server_update_zones(conf_t *conf, server_t *server, reload_t mode); diff --git a/src/knot/updates/zone-update.c b/src/knot/updates/zone-update.c index f857be269..952db4809 100644 --- a/src/knot/updates/zone-update.c +++ b/src/knot/updates/zone-update.c @@ -14,10 +14,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ +#include <signal.h> +#include <unistd.h> +#include <urcu.h> + #include "knot/catalog/interpret.h" #include "knot/common/log.h" #include "knot/common/systemd.h" #include "knot/dnssec/zone-events.h" +#include "knot/server/server.h" #include "knot/updates/zone-update.h" #include "knot/zone/adds_tree.h" #include "knot/zone/adjust.h" @@ -28,10 +33,6 @@ #include "contrib/trim.h" #include "contrib/ucw/lists.h" -#include <signal.h> -#include <unistd.h> -#include <urcu.h> - // Call mem_trim() whenever accumulated size of updated zones reaches this size. #define UPDATE_MEMTRIM_AT (10 * 1024 * 1024) @@ -783,6 +784,7 @@ static int update_catalog(conf_t *conf, zone_update_t *update) if (ret == KNOT_EOK) { log_zone_info(update->zone->name, "catalog reloaded, %zd updates", upd_count); + update->zone->server->catalog_upd_signal = true; if (kill(getpid(), SIGUSR1) != 0) { ret = knot_map_errno(); } diff --git a/src/knot/zone/zonedb-load.c b/src/knot/zone/zonedb-load.c index 842258a20..cedf83378 100644 --- a/src/knot/zone/zonedb-load.c +++ b/src/knot/zone/zonedb-load.c @@ -32,9 +32,6 @@ #include "knot/zone/zonefile.h" #include "libknot/libknot.h" -#define FULL(conf) (!((conf)->io.flags & CONF_IO_FACTIVE) || \ - ((conf)->io.flags & CONF_IO_FRLD_ZONES)) - static bool zone_file_updated(conf_t *conf, const zone_t *old_zone, const knot_dname_t *zone_name) { @@ -278,14 +275,12 @@ static bool check_open_catalog(catalog_t *cat) } static zone_t *reuse_member_zone(zone_t *zone, server_t *server, conf_t *conf, - list_t *expired_contents) + reload_t mode, list_t *expired_contents) { if (!zone_get_flag(zone, ZONE_IS_CAT_MEMBER, false)) { return NULL; } - bool full = FULL(conf); - catalog_upd_val_t *upd = catalog_update_get(&server->catalog_upd, zone->name); if (upd != NULL) { switch (upd->type) { @@ -295,10 +290,12 @@ static zone_t *reuse_member_zone(zone_t *zone, server_t *server, conf_t *conf, ptrlist_add(expired_contents, zone_expire(zone), NULL); knot_sem_post(&zone->cow_lock); // FALLTHROUGH - case CAT_UPD_INVALID: - case CAT_UPD_MINOR: case CAT_UPD_PROP: + zone->change_type = CONF_IO_TRELOAD; break; // reload the member zone + case CAT_UPD_INVALID: + case CAT_UPD_MINOR: + return zone; // reuse the member zone case CAT_UPD_REM: return NULL; // remove the member zone case CAT_UPD_ADD: // cannot add existing member @@ -306,9 +303,7 @@ static zone_t *reuse_member_zone(zone_t *zone, server_t *server, conf_t *conf, assert(0); return NULL; } - } - - if (!full && (upd == NULL || upd->type != CAT_UPD_UNIQ)) { + } else if (mode & (RELOAD_COMMIT | RELOAD_CATALOG)) { return zone; // reuse the member zone } @@ -400,11 +395,13 @@ static zone_t *add_member_zone(catalog_upd_val_t *val, knot_zonedb_t *check, * * \param conf New server configuration. * \param server Server instance. + * \param mode Reload mode. * \param expired_contents Out: ptrlist of zone_contents_t to be deep freed after sync RCU. * * \return New zone database. */ -static knot_zonedb_t *create_zonedb(conf_t *conf, server_t *server, list_t *expired_contents) +static knot_zonedb_t *create_zonedb(conf_t *conf, server_t *server, reload_t mode, + list_t *expired_contents) { assert(conf); assert(server); @@ -415,10 +412,8 @@ static knot_zonedb_t *create_zonedb(conf_t *conf, server_t *server, list_t *expi return NULL; } - bool full = FULL(conf); - - /* Mark changed zones. */ - if (!full) { + /* Mark changed zones during dynamic configuration. */ + if (mode == RELOAD_COMMIT) { mark_changed_zones(db_old, conf->io.zones); } @@ -429,7 +424,7 @@ static knot_zonedb_t *create_zonedb(conf_t *conf, server_t *server, list_t *expi const knot_dname_t *name = conf_dname(&id); zone_t *old_zone = knot_zonedb_find(db_old, name); - if (old_zone != NULL && !full) { + if (old_zone != NULL && (mode & (RELOAD_COMMIT | RELOAD_CATALOG))) { /* Reuse unchanged zone. */ if (!(old_zone->change_type & CONF_IO_TRELOAD)) { knot_zonedb_insert(db_new, old_zone); @@ -449,13 +444,14 @@ static knot_zonedb_t *create_zonedb(conf_t *conf, server_t *server, list_t *expi knot_zonedb_insert(db_new, zone); } - /* Remove deleted cataloged zones from conf before catalog removals are commited. */ + /* Purge decataloged zones before catalog removals are commited. */ catalog_it_t *cat_it = catalog_it_begin(&server->catalog_upd); while (!catalog_it_finished(cat_it)) { catalog_upd_val_t *upd = catalog_it_val(cat_it); if (upd->type == CAT_UPD_REM) { zone_t *zone = knot_zonedb_find(db_old, upd->member); if (zone != NULL) { + zone->change_type = CONF_IO_TUNSET; zone_purge(conf, zone); } } @@ -474,7 +470,8 @@ static knot_zonedb_t *create_zonedb(conf_t *conf, server_t *server, list_t *expi knot_zonedb_iter_t *it = knot_zonedb_iter_begin(db_old); while (!knot_zonedb_iter_finished(it)) { zone_t *newzone = reuse_member_zone(knot_zonedb_iter_val(it), - server, conf, expired_contents); + server, conf, mode, + expired_contents); if (newzone != NULL) { knot_zonedb_insert(db_new, newzone); } @@ -536,14 +533,12 @@ static knot_zonedb_t *create_zonedb(conf_t *conf, server_t *server, list_t *expi * \param server Server context. */ static void remove_old_zonedb(conf_t *conf, knot_zonedb_t *db_old, - server_t *server) + server_t *server, reload_t mode) { catalog_commit_cleanup(&server->catalog); knot_zonedb_t *db_new = server->zone_db; - bool full = FULL(conf); - if (db_old == NULL) { goto catalog_only; } @@ -551,7 +546,7 @@ static void remove_old_zonedb(conf_t *conf, knot_zonedb_t *db_old, knot_zonedb_iter_t *it = knot_zonedb_iter_begin(db_old); while (!knot_zonedb_iter_finished(it)) { zone_t *zone = knot_zonedb_iter_val(it); - if (full) { + if (mode & (RELOAD_FULL | RELOAD_ZONES)) { /* Check if reloaded (reused contents). */ zone_t *new_zone = knot_zonedb_find(db_new, zone->name); if (new_zone != NULL) { @@ -565,7 +560,6 @@ static void remove_old_zonedb(conf_t *conf, knot_zonedb_t *db_old, zone_t *new_zone = knot_zonedb_find(db_new, zone->name); assert(new_zone); replan_events(conf, new_zone, zone); - zone->contents = NULL; zone_free(&zone); /* Check if removed (drop also contents). */ @@ -584,27 +578,37 @@ catalog_only: * thread while all zone events are paused. */ catalog_update_clear(&server->catalog_upd); - if (full) { + if (mode & (RELOAD_FULL | RELOAD_ZONES)) { knot_zonedb_deep_free(&db_old, false); } else { knot_zonedb_free(&db_old); } } -void zonedb_reload(conf_t *conf, server_t *server) +void zonedb_reload(conf_t *conf, server_t *server, reload_t mode) { if (conf == NULL || server == NULL) { return; } + if (mode == RELOAD_COMMIT) { + assert(conf->io.flags & CONF_IO_FACTIVE); + if (conf->io.flags & CONF_IO_FRLD_ZONES) { + mode = RELOAD_ZONES; + } + } + list_t contents_tofree; init_list(&contents_tofree); catalog_update_finalize(&server->catalog_upd, &server->catalog, conf); - log_info("catalog, updating, %zu changes", trie_weight(server->catalog_upd.upd)); + size_t cat_upd_size = trie_weight(server->catalog_upd.upd); + if (cat_upd_size > 0) { + log_info("catalog, updating, %zu changes", cat_upd_size); + } /* Insert all required zones to the new zone DB. */ - knot_zonedb_t *db_new = create_zonedb(conf, server, &contents_tofree); + knot_zonedb_t *db_new = create_zonedb(conf, server, mode, &contents_tofree); if (db_new == NULL) { log_error("failed to create new zone database"); return; @@ -622,7 +626,7 @@ void zonedb_reload(conf_t *conf, server_t *server) ptrlist_free_custom(&contents_tofree, NULL, (ptrlist_free_cb)zone_contents_deep_free); /* Remove old zone DB. */ - remove_old_zonedb(conf, db_old, server); + remove_old_zonedb(conf, db_old, server, mode); } int zone_reload_modules(conf_t *conf, server_t *server, const knot_dname_t *zone_name) diff --git a/src/knot/zone/zonedb-load.h b/src/knot/zone/zonedb-load.h index 1a0ea3268..c69b831d9 100644 --- a/src/knot/zone/zonedb-load.h +++ b/src/knot/zone/zonedb-load.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,10 +22,11 @@ /*! * \brief Update zone database according to configuration. * - * \param[in] conf Configuration. - * \param[in] server Server instance. + * \param conf Configuration. + * \param server Server instance. + * \param mode Reload mode. */ -void zonedb_reload(conf_t *conf, server_t *server); +void zonedb_reload(conf_t *conf, server_t *server, reload_t mode); /*! * \brief Re-create zone_t struct in zoneDB so that the zone is reloaded incl modules. diff --git a/src/utils/knotd/main.c b/src/utils/knotd/main.c index 3f8ce4b5a..34990288f 100644 --- a/src/utils/knotd/main.c +++ b/src/utils/knotd/main.c @@ -259,11 +259,13 @@ static void event_loop(server_t *server, const char *socket) /* Interrupts. */ if (sig_req_reload && !sig_req_stop) { sig_req_reload = false; - server_reload(server); + server_reload(server, RELOAD_FULL); } if (sig_req_zones_reload && !sig_req_stop) { sig_req_zones_reload = false; - server_update_zones(conf(), server); + reload_t mode = server->catalog_upd_signal ? RELOAD_CATALOG : RELOAD_ZONES; + server->catalog_upd_signal = false; + server_update_zones(conf(), server, mode); } if (sig_req_stop) { break; @@ -571,7 +573,7 @@ int main(int argc, char **argv) /* Populate zone database. */ log_info("loading %zu zones", conf_id_count(conf(), C_ZONE)); - server_update_zones(conf(), &server); + server_update_zones(conf(), &server, RELOAD_ZONES); /* Check number of loaded zones. */ if (knot_zonedb_size(server.zone_db) == 0) { diff --git a/tests-extra/tests/catalog/multi/test.py b/tests-extra/tests/catalog/multi/test.py index 0858fe6d8..1d5b1948e 100644 --- a/tests-extra/tests/catalog/multi/test.py +++ b/tests-extra/tests/catalog/multi/test.py @@ -58,14 +58,14 @@ master.ctl("zone-reload %s" % zone[1].name) t.sleep(5) check_exists(master, "member1.example.", True, "First") -check_exists(master, "member2.example.", True, "First") -check_exists(master, "member3.example.", True, "First") +check_exists(master, "member2.example.", False, "First") +check_exists(master, "member3.example.", False, "First") master.ctl("zone-reload %s" % zone[2].name) t.sleep(5) check_exists(master, "member1.example.", True, "Second") check_exists(master, "member2.example.", True, "Second") -check_exists(master, "member3.example.", True, "Second") +check_exists(master, "member3.example.", False, "Second") t.end() |