]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
backup: allow concurrent backup procedure...
authorLibor Peltan <libor.peltan@nic.cz>
Wed, 10 Feb 2021 17:54:36 +0000 (18:54 +0100)
committerLibor Peltan <libor.peltan@nic.cz>
Wed, 10 Feb 2021 17:54:36 +0000 (18:54 +0100)
...of distinct zones

src/knot/ctl/commands.c
src/knot/server/server.c
src/knot/server/server.h
src/knot/zone/backup.c
src/knot/zone/backup.h

index 7da288d62a73d526c408ebcf7eb966ee7f14fd5c..54c309f65aafceecbd7a045fc1fc44cd60d8257d 100644 (file)
@@ -431,27 +431,29 @@ static int init_backup(ctl_args_t *args, bool restore_mode)
        assert(ctx != NULL);
        ctx->backup_journal = MATCH_AND_FILTER(args, CTL_FILTER_PURGE_JOURNAL);
        ctx->backup_zonefile = !MATCH_AND_FILTER(args, CTL_FILTER_PURGE_ZONEFILE);
-       if (args->server->backup_ctx != NULL) {
-               log_warning("backup already in progress");
-               zone_backup_deinit(ctx);
-               return KNOT_EPROGRESS;
-       }
-       args->server->backup_ctx = ctx;
-       ctx->server_self_ptr = &args->server->backup_ctx;
+       zone_backups_add(&args->server->backup_ctxs, ctx);
 
        return ret;
 }
 
+static zone_backup_ctx_t *latest_backup_ctx(ctl_args_t *args)
+{
+       // no need to mutex in this case
+       return (zone_backup_ctx_t *)TAIL(args->server->backup_ctxs.ctxs);
+}
+
 static void deinit_backup(ctl_args_t *args)
 {
-       zone_backup_ctx_t *ctx = args->server->backup_ctx;
-       zone_backup_deinit(ctx);
+       zone_backup_deinit(latest_backup_ctx(args));
 }
 
 static int zone_backup_cmd(zone_t *zone, ctl_args_t *args)
 {
-       zone_backup_ctx_t *ctx = args->server->backup_ctx;
-       assert(zone->backup_ctx == NULL);
+       zone_backup_ctx_t *ctx = latest_backup_ctx(args);
+       if (zone->backup_ctx != NULL) {
+               log_zone_warning(zone->name, "zone backup already in progress, skipping zone");
+               return KNOT_EOK;
+       }
        zone->backup_ctx = ctx;
        pthread_mutex_lock(&ctx->readers_mutex);
        ctx->readers++;
@@ -490,7 +492,7 @@ static int zones_apply_backup(ctl_args_t *args, bool restore_mode)
 
        /* Global catalog zones backup. */
        if (args->data[KNOT_CTL_IDX_ZONE] == NULL) {
-               zone_backup_ctx_t *ctx = args->server->backup_ctx;
+               zone_backup_ctx_t *ctx = latest_backup_ctx(args);
                ctx->backup_global = true;
                ret = global_backup(ctx, &args->server->catalog, NULL);
                if (ret != KNOT_EOK) {
index 04f5faeefe95efb67c6cca701e18f40b5c05eca5..6dcb7676429bbd562e4c958a82154ae02cb37c7f 100644 (file)
@@ -602,6 +602,8 @@ int server_init(server_t *server, int bg_workers)
                return ret;
        }
 
+       zone_backups_init(&server->backup_ctxs);
+
        char *catalog_dir = conf_db(conf(), C_CATALOG_DB);
        conf_val_t catalog_size = conf_db_param(conf(), C_CATALOG_DB_MAX_SIZE, NULL);
        catalog_init(&server->catalog, catalog_dir, conf_int(&catalog_size));
@@ -630,11 +632,7 @@ void server_deinit(server_t *server)
                return;
        }
 
-       if (server->backup_ctx != NULL) {
-               log_warning("backup in progress, terminating, will be incomplete");
-               server->backup_ctx->readers = 1; // ensure complete deinit
-               zone_backup_deinit(server->backup_ctx);
-       }
+       zone_backups_deinit(&server->backup_ctxs);
 
        /* Save zone timers. */
        if (server->zone_db != NULL) {
index 8418df93e062f381702f77d3a09b9c6bff1f853d..56dd3cd383e3df4eba4dbec052745c6dd45dabcd 100644 (file)
@@ -106,7 +106,7 @@ typedef struct server {
        catalog_update_t catalog_upd;
 
        /*! \brief Context of pending zones' backup. */
-       zone_backup_ctx_t *backup_ctx;
+       zone_backup_ctxs_t backup_ctxs;
 } server_t;
 
 /*!
index 008ace5316430971beb992ec14252505a16da345..348de17dc5e6fc50d219fac7f2b52f8a2dc5d437 100644 (file)
@@ -67,7 +67,6 @@ int zone_backup_init(bool restore_mode, const char *backup_dir,
        ctx->restore_mode = restore_mode;
        ctx->backup_global = false;
        ctx->readers = 1;
-       ctx->server_self_ptr = NULL;
        ctx->backup_dir = (char *)(ctx + 1);
        memcpy(ctx->backup_dir, backup_dir, backup_dir_len);
 
@@ -124,14 +123,53 @@ void zone_backup_deinit(zone_backup_ctx_t *ctx)
                BACKUP_LOCKFILE(ctx, lockfile);
                unlink(lockfile);
 
-               if (ctx->server_self_ptr != NULL) {
-                       *ctx->server_self_ptr = NULL;
-               }
+               zone_backups_rem(ctx);
 
                free(ctx);
        }
 }
 
+void zone_backups_init(zone_backup_ctxs_t *ctxs)
+{
+       init_list(&ctxs->ctxs);
+       pthread_mutex_init(&ctxs->mutex, NULL);
+}
+
+void zone_backups_deinit(zone_backup_ctxs_t *ctxs)
+{
+       zone_backup_ctx_t *ctx, *nxt;
+       WALK_LIST_DELSAFE(ctx, nxt, ctxs->ctxs) {
+               log_warning("backup in progress, terminating, will be incomplete");
+               ctx->readers = 1; // ensure full deinit
+               zone_backup_deinit(ctx);
+       }
+       pthread_mutex_destroy(&ctxs->mutex);
+}
+
+void zone_backups_add(zone_backup_ctxs_t *ctxs, zone_backup_ctx_t *ctx)
+{
+       pthread_mutex_lock(&ctxs->mutex);
+       add_tail(&ctxs->ctxs, (node_t *)ctx);
+       pthread_mutex_unlock(&ctxs->mutex);
+}
+
+static zone_backup_ctxs_t *get_ctxs_trick(zone_backup_ctx_t *ctx)
+{
+       node_t *n = (node_t *)ctx;
+       while (n->prev != NULL) {
+               n = n->prev;
+       }
+       return (zone_backup_ctxs_t *)n;
+}
+
+void zone_backups_rem(zone_backup_ctx_t *ctx)
+{
+       zone_backup_ctxs_t *ctxs = get_ctxs_trick(ctx);
+       pthread_mutex_lock(&ctxs->mutex);
+       rem_node((node_t *)ctx);
+       pthread_mutex_unlock(&ctxs->mutex);
+}
+
 static char *dir_file(const char *dir_name, const char *file_name)
 {
        const char *basename = strrchr(file_name, '/');
index b826a8e55e1bb305438d394649b5d333a07abaed..73670bfada461970ce01f2f6db32cae035acde9b 100644 (file)
@@ -23,6 +23,7 @@
 #include "knot/zone/zone.h"
 
 typedef struct zone_backup_ctx {
+       node_t n;                           // ability to be put into list_t
        bool restore_mode;                  // if true, this is not a backup, but restore
        bool backup_journal;                // if true, also backup journal
        bool backup_zonefile;               // if true, also backup zone contents to a zonefile (default on)
@@ -35,9 +36,13 @@ typedef struct zone_backup_ctx {
        knot_lmdb_db_t bck_journal;         // backup journal DB
        knot_lmdb_db_t bck_catalog;         // backup catalog DB
        int lock_file;                      // lock file preventing simultaneous backups to same directory
-       struct zone_backup_ctx **server_self_ptr; // pointer on pointer on this structure itself in server_t
 } zone_backup_ctx_t;
 
+typedef struct {
+       list_t ctxs;
+       pthread_mutex_t mutex;
+} zone_backup_ctxs_t;
+
 int zone_backup_init(bool restore_mode, const char *backup_dir,
                      size_t kasp_db_size, size_t timer_db_size, size_t journal_db_size,
                      size_t catalog_db_size, zone_backup_ctx_t **out_ctx);
@@ -48,3 +53,8 @@ int zone_backup(conf_t *conf, zone_t *zone);
 
 int global_backup(zone_backup_ctx_t *ctx, catalog_t *catalog,
                   const knot_dname_t *zone_only);
+
+void zone_backups_init(zone_backup_ctxs_t *ctxs);
+void zone_backups_deinit(zone_backup_ctxs_t *ctxs);
+void zone_backups_add(zone_backup_ctxs_t *ctxs, zone_backup_ctx_t *ctx);
+void zone_backups_rem(zone_backup_ctx_t *ctx);