From: Libor Peltan Date: Fri, 1 Mar 2019 12:09:32 +0000 (+0100) Subject: Revert "reverted implementation of zone-update RCU callbacks" X-Git-Tag: v2.9.0~286^2~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=00fa2fddd32eb6333c3699bea9f6f41ce6062993;p=thirdparty%2Fknot-dns.git Revert "reverted implementation of zone-update RCU callbacks" This reverts commit dbe6243d6372b4d388cda9246446d83ac4557480. This also revers the "check unified" mechanizm which basicly was just an assert. --- diff --git a/src/knot/updates/zone-update.c b/src/knot/updates/zone-update.c index 0aea0797e7..374c5d9bc9 100644 --- a/src/knot/updates/zone-update.c +++ b/src/knot/updates/zone-update.c @@ -680,14 +680,40 @@ static int commit_full(conf_t *conf, zone_update_t *update) return ret; } -static int check_unified(zone_node_t *node, void *data) +/*! \brief Routine for calling call_rcu() easier way. + * + * Consider moving elsewhere, as it has no direct relation to zone-update. + */ +typedef struct { + struct rcu_head rcuhead; + void (*callback)(void *); + void *ctx; + bool free_ctx; +} callrcu_wrapper_t; + +static void callrcu_wrapper_cb(struct rcu_head *param) { - (void)data; - zone_node_t *counter = binode_counterpart(node); - assert((node->flags ^ counter->flags) == NODE_FLAGS_SECOND); - assert(node->rrset_count == counter->rrset_count); - assert(node->rrs == counter->rrs); - return KNOT_EOK; + callrcu_wrapper_t *wrap = (callrcu_wrapper_t *)param; + wrap->callback(wrap->ctx); + if (wrap->free_ctx) { + free(wrap->ctx); + } + free(wrap); + + // Trim extra heap. + mem_trim(); +} + +/* NOTE: Does nothing if not enough memory. */ +static void callrcu_wrapper(void *ctx, void *callback, bool free_ctx) +{ + callrcu_wrapper_t *wrap = calloc(1, sizeof(callrcu_wrapper_t)); + if (wrap != NULL) { + wrap->callback = callback; + wrap->ctx = ctx; + wrap->free_ctx = free_ctx; + call_rcu((struct rcu_head *)wrap, callrcu_wrapper_cb); + } } int zone_update_commit(conf_t *conf, zone_update_t *update) @@ -740,26 +766,21 @@ int zone_update_commit(conf_t *conf, zone_update_t *update) old_contents = zone_switch_contents(update->zone, update->new_cont); /* Sync RCU. */ - synchronize_rcu(); if (update->flags & UPDATE_FULL) { assert(update->new_cont_deep_copy); - zone_contents_deep_free(old_contents); + callrcu_wrapper(old_contents, zone_contents_deep_free, false); } else if (update->flags & UPDATE_INCREMENTAL) { if (update->new_cont_deep_copy) { - zone_contents_deep_free(old_contents); + callrcu_wrapper(old_contents, zone_contents_deep_free, false); } else { - update_free_zone(old_contents); + callrcu_wrapper(old_contents, update_free_zone, false); } changeset_clear(&update->change); } - update_cleanup(update->a_ctx); - free(update->a_ctx); + callrcu_wrapper(update->a_ctx, update_cleanup, true); update->a_ctx = NULL; update->new_cont = NULL; - zone_contents_apply(update->zone->contents, check_unified, NULL); - zone_contents_nsec3_apply(update->zone->contents, check_unified, NULL); - /* Sync zonefile immediately if configured. */ val = conf_zone_get(conf, C_ZONEFILE_SYNC, update->zone->name); if (conf_int(&val) == 0) {