]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
zone: use a mutex for access to zone->flags
authorLibor Peltan <libor.peltan@nic.cz>
Fri, 6 Nov 2020 16:51:10 +0000 (17:51 +0100)
committerDaniel Salzman <daniel.salzman@nic.cz>
Sun, 8 Nov 2020 17:40:30 +0000 (18:40 +0100)
src/knot/ctl/commands.c
src/knot/events/handlers/dnssec.c
src/knot/events/handlers/refresh.c
src/knot/nameserver/process_query.c
src/knot/updates/zone-update.c
src/knot/zone/zone.c
src/knot/zone/zone.h
src/knot/zone/zonedb-load.c

index 9c7a8027dc8eb90c5749b1b21763b4b9484fc029..0f801694a93f917d43a0df8fef03141ee6afcc96 100644 (file)
@@ -349,7 +349,7 @@ static int zone_retransfer(zone_t *zone, ctl_args_t *args)
                return KNOT_ENOTSUP;
        }
 
-       zone->flags |= ZONE_FORCE_AXFR;
+       zone_set_flag(zone, ZONE_FORCE_AXFR);
        schedule_trigger(zone, args, ZONE_EVENT_REFRESH, true);
 
        return KNOT_EOK;
@@ -379,7 +379,7 @@ static int zone_flush(zone_t *zone, ctl_args_t *args)
        }
 
        if (ctl_has_flag(args->data[KNOT_CTL_IDX_FLAGS], CTL_FLAG_FORCE)) {
-               zone->flags |= ZONE_FORCE_FLUSH;
+               zone_set_flag(zone, ZONE_FORCE_FLUSH);
        }
 
        schedule_trigger(zone, args, ZONE_EVENT_FLUSH, true);
@@ -460,7 +460,7 @@ static int zone_sign(zone_t *zone, ctl_args_t *args)
                return KNOT_ENOTSUP;
        }
 
-       zone->flags |= ZONE_FORCE_RESIGN;
+       zone_set_flag(zone, ZONE_FORCE_RESIGN);
        schedule_trigger(zone, args, ZONE_EVENT_DNSSEC, true);
 
        return KNOT_EOK;
@@ -475,9 +475,9 @@ static int zone_key_roll(zone_t *zone, ctl_args_t *args)
 
        const char *key_type = args->data[KNOT_CTL_IDX_TYPE];
        if (strncasecmp(key_type, "ksk", 3) == 0) {
-               zone->flags |= ZONE_FORCE_KSK_ROLL;
+               zone_set_flag(zone, ZONE_FORCE_KSK_ROLL);
        } else if (strncasecmp(key_type, "zsk", 3) == 0) {
-               zone->flags |= ZONE_FORCE_ZSK_ROLL;
+               zone_set_flag(zone, ZONE_FORCE_ZSK_ROLL);
        } else {
                return KNOT_EINVAL;
        }
index dfbe6993bb86745530918f9baed11ed2effbab60..ace19118db6a0670ffc894ed1bd36f3bfe02b4d9 100644 (file)
@@ -75,22 +75,19 @@ int event_dnssec(conf_t *conf, zone_t *zone)
        int sign_flags = 0;
        bool zone_changed = false;
 
-       if (zone->flags & ZONE_FORCE_RESIGN) {
+       if (zone_get_flag(zone, ZONE_FORCE_RESIGN, true)) {
                log_zone_info(zone->name, "DNSSEC, dropping previous "
                              "signatures, re-signing zone");
-               zone->flags &= ~ZONE_FORCE_RESIGN;
                sign_flags = ZONE_SIGN_DROP_SIGNATURES;
        } else {
                log_zone_info(zone->name, "DNSSEC, signing zone");
                sign_flags = 0;
        }
 
-       if (zone->flags & ZONE_FORCE_KSK_ROLL) {
-               zone->flags &= ~ZONE_FORCE_KSK_ROLL;
+       if (zone_get_flag(zone, ZONE_FORCE_KSK_ROLL, true)) {
                r_flags |= KEY_ROLL_FORCE_KSK_ROLL;
        }
-       if (zone->flags & ZONE_FORCE_ZSK_ROLL) {
-               zone->flags &= ~ZONE_FORCE_ZSK_ROLL;
+       if (zone_get_flag(zone, ZONE_FORCE_ZSK_ROLL, true)) {
                r_flags |= KEY_ROLL_FORCE_ZSK_ROLL;
        }
 
index 78cfbbb04321ec761d4f9eaf2d995139b50fa15b..646caf55b0995563595194f695df9abe51710c12 100644 (file)
@@ -1263,8 +1263,7 @@ int event_refresh(conf_t *conf, zone_t *zone)
        try_refresh_ctx_t trctx = { 0 };
 
        // TODO: Flag on zone is ugly. Event specific parameters would be nice.
-       if (zone->flags & ZONE_FORCE_AXFR) {
-               zone->flags &= ~ZONE_FORCE_AXFR;
+       if (zone_get_flag(zone, ZONE_FORCE_AXFR, true)) {
                trctx.force_axfr = true;
                zone->zonefile.retransfer = true;
        }
index 089184520938dc9207152284935306c5389b684f..4c4a62999d20eb57587a3f917d13c97ac55a1ec0 100644 (file)
@@ -424,7 +424,7 @@ static int prepare_answer(knot_pkt_t *query, knot_pkt_t *resp, knot_layer_t *ctx
        }
 
        /* Allow normal queries to catalog only over TCP and if allowed by ACL. */
-       if (qdata->extra->zone != NULL && (qdata->extra->zone->flags & ZONE_IS_CATALOG) &&
+       if (qdata->extra->zone != NULL && qdata->extra->zone->is_catalog_flag &&
            query_type(query) == KNOTD_QUERY_TYPE_NORMAL) {
                if ((qdata->params->flags & KNOTD_QUERY_FLAG_LIMIT_SIZE) ||
                    !process_query_acl_check(conf(), ACL_ACTION_TRANSFER, qdata)) {
index 1973bd7e52eec3ed17d63f5a87bf674951106079..6927bbb9a3c010f55e24a3ecf16d0360ffb13609 100644 (file)
@@ -713,7 +713,7 @@ static int update_catalog(conf_t *conf, zone_update_t *update)
                return (val.code == KNOT_ENOENT || val.code == KNOT_YP_EINVAL_ID) ? KNOT_EOK : val.code;
        }
 
-       update->zone->flags |= ZONE_IS_CATALOG;
+       zone_set_flag(update->zone, ZONE_IS_CATALOG);
 
        int ret = KNOT_EOK;
        if ((update->flags & UPDATE_INCREMENTAL)) {
index 7998d10cb1c0c63583c7c60ae68aabd1973137e6..5e608f28afa46b0bf6e86cf228e52af893ba43d4 100644 (file)
@@ -65,8 +65,7 @@ static int flush_journal(conf_t *conf, zone_t *zone, bool allow_empty_zone, bool
        int ret = KNOT_EOK;
        zone_journal_t j = zone_journal(zone);
 
-       bool force = zone->flags & ZONE_FORCE_FLUSH;
-       zone->flags &= ~ZONE_FORCE_FLUSH;
+       bool force = zone_get_flag(zone, ZONE_FORCE_FLUSH, true);
 
        conf_val_t val = conf_zone_get(conf, C_ZONEFILE_SYNC, zone->name);
        int64_t sync_timeout = conf_int(&val);
@@ -357,6 +356,38 @@ void zone_clear_preferred_master(zone_t *zone)
        pthread_mutex_unlock(&zone->preferred_lock);
 }
 
+void zone_set_flag(zone_t *zone, zone_flag_t flag)
+{
+       if (zone == NULL) {
+               return;
+       }
+
+       pthread_mutex_lock(&zone->preferred_lock); // this mutex seems OK to be reused for this
+       zone->flags |= flag;
+       pthread_mutex_unlock(&zone->preferred_lock);
+
+       if (flag & ZONE_IS_CATALOG) {
+               zone->is_catalog_flag = true;
+       }
+}
+
+zone_flag_t zone_get_flag(zone_t *zone, zone_flag_t flag, bool clear)
+{
+       if (zone == NULL) {
+               return 0;
+       }
+
+       pthread_mutex_lock(&zone->preferred_lock);
+       zone_flag_t res = (zone->flags & flag);
+       if (clear && res) {
+               zone->flags &= ~flag;
+       }
+       assert(((bool)(zone->flags & ZONE_IS_CATALOG)) == zone->is_catalog_flag);
+       pthread_mutex_unlock(&zone->preferred_lock);
+
+       return res;
+}
+
 const knot_rdataset_t *zone_soa(const zone_t *zone)
 {
        if (!zone || zone_contents_is_empty(zone->contents)) {
index 1154e80dc7ed5892edbcc1f1d00ce26cf7b3df08..db2e88904751438a9507f0c0000b3b729f9dfea6 100644 (file)
@@ -34,7 +34,7 @@ struct zone_backup_ctx;
 /*!
  * \brief Zone flags.
  */
-typedef enum zone_flag_t {
+typedef enum {
        ZONE_FORCE_AXFR     = 1 << 0, /*!< Force AXFR as next transfer. */
        ZONE_FORCE_RESIGN   = 1 << 1, /*!< Force zone re-sign. */
        ZONE_FORCE_FLUSH    = 1 << 2, /*!< Force zone flush. */
@@ -52,6 +52,7 @@ typedef struct zone
        knot_dname_t *name;
        zone_contents_t *contents;
        zone_flag_t flags;
+       bool is_catalog_flag; //!< Lock-less indication of ZONE_IS_CATALOG flag.
 
        /*! \brief Dynamic configuration zone change type. */
        conf_io_type_t change_type;
@@ -93,7 +94,7 @@ typedef struct zone
        catalog_t *catalog;
        catalog_update_t *catalog_upd;
 
-       /*! \brief Preferred master lock. */
+       /*! \brief Preferred master lock. Also used for flags access. */
        pthread_mutex_t preferred_lock;
        /*! \brief Preferred master for remote operation. */
        struct sockaddr_storage *preferred_master;
@@ -165,6 +166,12 @@ void zone_set_preferred_master(zone_t *zone, const struct sockaddr_storage *addr
 /*! \brief Clears the current preferred master address. */
 void zone_clear_preferred_master(zone_t *zone);
 
+/*! \brief Sets a zone flag. */
+void zone_set_flag(zone_t *zone, zone_flag_t flag);
+
+/*! \brief Returns if a flag is set (and optionally clears it). */
+zone_flag_t zone_get_flag(zone_t *zone, zone_flag_t flag, bool clear);
+
 /*! \brief Get zone SOA RR. */
 const knot_rdataset_t *zone_soa(const zone_t *zone);
 
index aba2b76ae78b5fc3d18e22f945cb04224f177fb2..e7b0bf09f73a85017ecb3c2952740d7b63b32812 100644 (file)
@@ -127,7 +127,7 @@ static zone_t *create_zone_reload(conf_t *conf, const knot_dname_t *name,
        }
 
        zone->contents = old_zone->contents;
-       zone->flags = (old_zone->flags & (ZONE_IS_CATALOG | ZONE_IS_CAT_MEMBER));
+       zone_set_flag(zone, zone_get_flag(old_zone, ZONE_IS_CATALOG | ZONE_IS_CAT_MEMBER, false));
 
        zone->timers = old_zone->timers;
        timers_sanitize(conf, zone);
@@ -263,7 +263,7 @@ 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)
 {
-       if (!(zone->flags & ZONE_IS_CAT_MEMBER)) {
+       if (!zone_get_flag(zone, ZONE_IS_CAT_MEMBER, false)) {
                return NULL;
        }
 
@@ -283,7 +283,7 @@ static zone_t *reuse_member_zone(zone_t *zone, server_t *server, conf_t *conf,
        if (newzone == NULL) {
                log_zone_error(zone->name, "zone cannot be created");
        } else {
-               assert(newzone->flags & ZONE_IS_CAT_MEMBER);
+               assert(zone_get_flag(newzone, ZONE_IS_CAT_MEMBER, false));
                conf_activate_modules(conf, server, newzone->name, &newzone->query_modules,
                                      &newzone->query_plan);
        }
@@ -302,7 +302,7 @@ static zone_t *reuse_cold_zone(const knot_dname_t *zname, server_t *server, conf
        if (zone == NULL) {
                log_zone_error(zname, "zone cannot be created");
        } else {
-               zone->flags |= ZONE_IS_CAT_MEMBER;
+               zone_set_flag(zone, ZONE_IS_CAT_MEMBER);
                conf_activate_modules(conf, server, zone->name, &zone->query_modules,
                                      &zone->query_plan);
        }
@@ -326,7 +326,7 @@ static zone_t *add_member_zone(catalog_upd_val_t *val, knot_zonedb_t *check,
                log_zone_error(val->member, "zone cannot be created");
                catalog_del2(conf->catalog, val);
        } else {
-               zone->flags |= ZONE_IS_CAT_MEMBER;
+               zone_set_flag(zone, ZONE_IS_CAT_MEMBER);
                conf_activate_modules(conf, server, zone->name, &zone->query_modules,
                                      &zone->query_plan);
                log_zone_info(val->member, "zone added from catalog");