diff --git a/daemon/remote.c b/daemon/remote.c index 8877cd194..9fc649562 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -2754,7 +2754,6 @@ do_auth_zone_reload(RES* ssl, struct worker* worker, char* arg) if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) return; if(az) { - lock_rw_rdlock(&az->lock); z = auth_zone_find(az, nm, nmlen, LDNS_RR_CLASS_IN); if(z) { lock_rw_wrlock(&z->lock); @@ -2763,7 +2762,6 @@ do_auth_zone_reload(RES* ssl, struct worker* worker, char* arg) if(xfr) { lock_basic_lock(&xfr->lock); } - lock_rw_unlock(&az->lock); } free(nm); if(!z) { @@ -2950,7 +2948,6 @@ do_list_auth_zones(RES* ssl, struct auth_zones* az) { struct auth_zone* z; char buf[257], buf2[256]; - lock_rw_rdlock(&az->lock); RBTREE_FOR(z, struct auth_zone*, &az->ztree) { lock_rw_rdlock(&z->lock); dname_str(z->name, buf); @@ -2966,12 +2963,10 @@ do_list_auth_zones(RES* ssl, struct auth_zones* az) if(!ssl_printf(ssl, "%s\t%s\n", buf, buf2)) { /* failure to print */ lock_rw_unlock(&z->lock); - lock_rw_unlock(&az->lock); return; } lock_rw_unlock(&z->lock); } - lock_rw_unlock(&az->lock); } /** do the list_local_zones command */ @@ -3168,12 +3163,10 @@ do_rpz_enable_disable(RES* ssl, struct worker* worker, char* arg, int enable) { if (!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) return; if (az) { - lock_rw_rdlock(&az->lock); z = auth_zone_find(az, nm, nmlen, LDNS_RR_CLASS_IN); if (z) { lock_rw_wrlock(&z->lock); } - lock_rw_unlock(&az->lock); } free(nm); if (!z) { diff --git a/daemon/stats.c b/daemon/stats.c index 0e17300a1..f7b7cc4a0 100644 --- a/daemon/stats.c +++ b/daemon/stats.c @@ -325,20 +325,11 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset) s->svr.num_query_dnscrypt_replay = 0; #endif /* USE_DNSCRYPT */ if(worker->env.auth_zones) { - if(reset && !worker->env.cfg->stat_cumulative) { - lock_rw_wrlock(&worker->env.auth_zones->lock); - } else { - lock_rw_rdlock(&worker->env.auth_zones->lock); - } - s->svr.num_query_authzone_up = (long long)worker->env. - auth_zones->num_query_up; - s->svr.num_query_authzone_down = (long long)worker->env. - auth_zones->num_query_down; - if(reset && !worker->env.cfg->stat_cumulative) { - worker->env.auth_zones->num_query_up = 0; - worker->env.auth_zones->num_query_down = 0; - } - lock_rw_unlock(&worker->env.auth_zones->lock); + s->svr.num_query_authzone_up = (long long)worker->stats.num_query_authzone_up; + s->svr.num_query_authzone_down = (long long)worker->stats.num_query_authzone_down; + } else { + s->svr.num_query_authzone_up = 0; + s->svr.num_query_authzone_down = 0; } s->svr.mem_stream_wait = (long long)tcp_req_info_get_stream_buffer_size(); @@ -454,6 +445,8 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a) total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache; total->svr.num_queries_prefetch += a->svr.num_queries_prefetch; total->svr.num_queries_timed_out += a->svr.num_queries_timed_out; + total->svr.num_query_authzone_up += a->svr.num_query_authzone_up; + total->svr.num_query_authzone_down += a->svr.num_query_authzone_down; if (total->svr.max_query_time_us < a->svr.max_query_time_us) total->svr.max_query_time_us = a->svr.max_query_time_us; total->svr.sum_query_list_size += a->svr.sum_query_list_size; diff --git a/daemon/worker.c b/daemon/worker.c index 713de3163..000e51b0a 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -2230,6 +2230,7 @@ worker_init(struct worker* worker, struct config_file *cfg, worker->env = *worker->daemon->env; comm_base_timept(worker->base, &worker->env.now, &worker->env.now_tv); worker->env.worker = worker; + worker->env.stats = &worker->stats; worker->env.worker_base = worker->base; worker->env.send_query = &worker_send_query; worker->env.alloc = worker->alloc; diff --git a/iterator/iterator.c b/iterator/iterator.c index 59e4b36ce..315c90398 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1076,15 +1076,12 @@ auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq, delname = iq->qchase.qname; delnamelen = iq->qchase.qname_len; } - lock_rw_rdlock(&qstate->env->auth_zones->lock); z = auth_zones_find_zone(qstate->env->auth_zones, delname, delnamelen, qstate->qinfo.qclass); if(!z) { - lock_rw_unlock(&qstate->env->auth_zones->lock); return 1; } lock_rw_rdlock(&z->lock); - lock_rw_unlock(&qstate->env->auth_zones->lock); if(z->for_upstream) { if(iq->dp && query_dname_compare(z->name, iq->dp->name) == 0 && iq->dp->auth_dp && qstate->blacklist && @@ -2741,9 +2738,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, if((iq->chase_flags&BIT_RD) && !(iq->response->rep->flags&BIT_AA)) { verbose(VERB_ALGO, "forwarder, ignoring referral from auth zone"); } else { - lock_rw_wrlock(&qstate->env->auth_zones->lock); - qstate->env->auth_zones->num_query_up++; - lock_rw_unlock(&qstate->env->auth_zones->lock); + qstate->env->stats->num_query_authzone_up++; iq->num_current_queries++; iq->chase_to_rd = 0; iq->dnssec_lame_query = 0; diff --git a/services/authzone.c b/services/authzone.c index 6f6c55d43..5fbaff84e 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -300,9 +300,6 @@ struct auth_zones* auth_zones_create(void) } rbtree_init(&az->ztree, &auth_zone_cmp); rbtree_init(&az->xtree, &auth_xfer_cmp); - lock_rw_init(&az->lock); - lock_protect(&az->lock, &az->ztree, sizeof(az->ztree)); - lock_protect(&az->lock, &az->xtree, sizeof(az->xtree)); /* also lock protects the rbnode's in struct auth_zone, auth_xfer */ lock_rw_init(&az->rpz_lock); lock_protect(&az->rpz_lock, &az->rpz_first, sizeof(az->rpz_first)); @@ -1787,19 +1784,16 @@ auth_zones_read_zones(struct auth_zones* az, struct config_file* cfg, struct module_env* env, struct module_stack* mods) { struct auth_zone* z; - lock_rw_wrlock(&az->lock); RBTREE_FOR(z, struct auth_zone*, &az->ztree) { lock_rw_wrlock(&z->lock); if(!auth_zone_read_zonefile(z, cfg)) { lock_rw_unlock(&z->lock); - lock_rw_unlock(&az->lock); return 0; } if(z->zonefile && z->zonefile[0]!=0 && env) zonemd_offline_verify(z, env, mods); lock_rw_unlock(&z->lock); } - lock_rw_unlock(&az->lock); return 1; } @@ -2065,7 +2059,6 @@ auth_zones_setup_zones(struct auth_zones* az) { struct auth_zone* z; struct auth_xfer* x; - lock_rw_wrlock(&az->lock); RBTREE_FOR(z, struct auth_zone*, &az->ztree) { lock_rw_wrlock(&z->lock); x = auth_xfer_find(az, z->name, z->namelen, z->dclass); @@ -2077,7 +2070,6 @@ auth_zones_setup_zones(struct auth_zones* az) lock_basic_unlock(&x->lock); } lock_rw_unlock(&z->lock); - lock_rw_unlock(&az->lock); return 0; } if(x) { @@ -2085,7 +2077,6 @@ auth_zones_setup_zones(struct auth_zones* az) } lock_rw_unlock(&z->lock); } - lock_rw_unlock(&az->lock); return 1; } @@ -2102,9 +2093,7 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c) * locks to avoid a lock dependency cycle */ lock_rw_wrlock(&az->rpz_lock); } - lock_rw_wrlock(&az->lock); if(!(z=auth_zones_find_or_add_zone(az, c->name))) { - lock_rw_unlock(&az->lock); if(c->isrpz) { lock_rw_unlock(&az->rpz_lock); } @@ -2112,7 +2101,6 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c) } if(c->masters || c->urls) { if(!(x=auth_zones_find_or_add_xfer(az, z))) { - lock_rw_unlock(&az->lock); lock_rw_unlock(&z->lock); if(c->isrpz) { lock_rw_unlock(&az->rpz_lock); @@ -2122,7 +2110,6 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c) } if(c->for_downstream) az->have_downstream = 1; - lock_rw_unlock(&az->lock); /* set options */ z->zone_deleted = 0; @@ -2195,13 +2182,11 @@ static void az_setall_deleted(struct auth_zones* az) { struct auth_zone* z; - lock_rw_wrlock(&az->lock); RBTREE_FOR(z, struct auth_zone*, &az->ztree) { lock_rw_wrlock(&z->lock); z->zone_deleted = 1; lock_rw_unlock(&z->lock); } - lock_rw_unlock(&az->lock); } /** find zones that are marked deleted and delete them. @@ -2213,7 +2198,6 @@ az_delete_deleted_zones(struct auth_zones* az) struct auth_zone* z; struct auth_zone* delete_list = NULL, *next; struct auth_xfer* xfr; - lock_rw_wrlock(&az->lock); RBTREE_FOR(z, struct auth_zone*, &az->ztree) { lock_rw_wrlock(&z->lock); if(z->zone_deleted) { @@ -2239,7 +2223,6 @@ az_delete_deleted_zones(struct auth_zones* az) auth_zone_delete(z, az); z = next; } - lock_rw_unlock(&az->lock); } int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg, @@ -2368,7 +2351,6 @@ auth_xfer_del(rbnode_type* n, void* ATTR_UNUSED(arg)) void auth_zones_delete(struct auth_zones* az) { if(!az) return; - lock_rw_destroy(&az->lock); lock_rw_destroy(&az->rpz_lock); traverse_postorder(&az->ztree, auth_zone_del, NULL); traverse_postorder(&az->xtree, auth_xfer_del, NULL); @@ -3495,16 +3477,13 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo, int r; struct auth_zone* z; /* find the zone that should contain the answer. */ - lock_rw_rdlock(&az->lock); z = auth_zone_find(az, dp_nm, dp_nmlen, qinfo->qclass); if(!z) { - lock_rw_unlock(&az->lock); /* no auth zone, fallback to internet */ *fallback = 1; return 0; } lock_rw_rdlock(&z->lock); - lock_rw_unlock(&az->lock); /* if not for upstream queries, fallback */ if(!z->for_upstream) { @@ -3577,10 +3556,8 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env, int r; int fallback = 0; - lock_rw_rdlock(&az->lock); if(!az->have_downstream) { /* no downstream auth zones */ - lock_rw_unlock(&az->lock); return 0; } if(qinfo->qtype == LDNS_RR_TYPE_DS) { @@ -3595,11 +3572,9 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env, } if(!z) { /* no zone above it */ - lock_rw_unlock(&az->lock); return 0; } lock_rw_rdlock(&z->lock); - lock_rw_unlock(&az->lock); if(!z->for_downstream) { lock_rw_unlock(&z->lock); return 0; @@ -3610,9 +3585,7 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env, return 0; } lock_rw_unlock(&z->lock); - lock_rw_wrlock(&az->lock); - az->num_query_down++; - lock_rw_unlock(&az->lock); + env->stats->num_query_authzone_down++; auth_error_encode(qinfo, env, edns, repinfo, buf, temp, LDNS_RCODE_SERVFAIL); return 1; @@ -3625,9 +3598,7 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env, /* fallback to regular answering (recursive) */ return 0; } - lock_rw_wrlock(&az->lock); - az->num_query_down++; - lock_rw_unlock(&az->lock); + env->stats->num_query_authzone_down++; /* encode answer */ if(!r) @@ -3643,15 +3614,12 @@ int auth_zones_can_fallback(struct auth_zones* az, uint8_t* nm, size_t nmlen, { int r; struct auth_zone* z; - lock_rw_rdlock(&az->lock); z = auth_zone_find(az, nm, nmlen, dclass); if(!z) { - lock_rw_unlock(&az->lock); /* no such auth zone, fallback */ return 1; } lock_rw_rdlock(&z->lock); - lock_rw_unlock(&az->lock); r = z->fallback_enabled || (!z->for_upstream); lock_rw_unlock(&z->lock); return r; @@ -3840,16 +3808,13 @@ int auth_zones_notify(struct auth_zones* az, struct module_env* env, struct auth_xfer* xfr; struct auth_master* fromhost = NULL; /* see which zone this is */ - lock_rw_rdlock(&az->lock); xfr = auth_xfer_find(az, nm, nmlen, dclass); if(!xfr) { - lock_rw_unlock(&az->lock); /* no such zone, refuse the notify */ *refused = 1; return 0; } lock_basic_lock(&xfr->lock); - lock_rw_unlock(&az->lock); /* check access list for notifies */ if(!az_xfr_allowed_notify(xfr, addr, addrlen, &fromhost)) { @@ -3868,14 +3833,11 @@ int auth_zones_startprobesequence(struct auth_zones* az, struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t dclass) { struct auth_xfer* xfr; - lock_rw_rdlock(&az->lock); xfr = auth_xfer_find(az, nm, nmlen, dclass); if(!xfr) { - lock_rw_unlock(&az->lock); return 0; } lock_basic_lock(&xfr->lock); - lock_rw_unlock(&az->lock); xfr_process_notify(xfr, env, 0, 0, NULL); return 1; @@ -3894,15 +3856,12 @@ auth_xfer_set_expired(struct auth_xfer* xfr, struct module_env* env, lock_basic_unlock(&xfr->lock); /* find auth_zone */ - lock_rw_rdlock(&env->auth_zones->lock); z = auth_zone_find(env->auth_zones, xfr->name, xfr->namelen, xfr->dclass); if(!z) { - lock_rw_unlock(&env->auth_zones->lock); return; } lock_rw_wrlock(&z->lock); - lock_rw_unlock(&env->auth_zones->lock); /* expire auth_zone */ z->zone_expired = expired; @@ -5208,18 +5167,15 @@ xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env) /* get lock again, so it is a readlock and concurrently queries * can be answered */ - lock_rw_rdlock(&env->auth_zones->lock); z = auth_zone_find(env->auth_zones, xfr->name, xfr->namelen, xfr->dclass); if(!z) { - lock_rw_unlock(&env->auth_zones->lock); /* the zone is gone, ignore xfr results */ lock_basic_lock(&xfr->lock); return; } lock_rw_rdlock(&z->lock); lock_basic_lock(&xfr->lock); - lock_rw_unlock(&env->auth_zones->lock); if(z->zonefile == NULL || z->zonefile[0] == 0) { lock_rw_unlock(&z->lock); @@ -5277,18 +5233,15 @@ static int xfr_process_reacquire_locks(struct auth_xfer* xfr, { /* release xfr lock, then, while holding az->lock grab both * z->lock and xfr->lock */ - lock_rw_rdlock(&env->auth_zones->lock); *z = auth_zone_find(env->auth_zones, xfr->name, xfr->namelen, xfr->dclass); if(!*z) { - lock_rw_unlock(&env->auth_zones->lock); lock_basic_lock(&xfr->lock); *z = NULL; return 0; } lock_rw_wrlock(&(*z)->lock); lock_basic_lock(&xfr->lock); - lock_rw_unlock(&env->auth_zones->lock); return 1; } @@ -7015,7 +6968,6 @@ void auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env) { struct auth_xfer* x; - lock_rw_wrlock(&az->lock); RBTREE_FOR(x, struct auth_xfer*, &az->xtree) { lock_basic_lock(&x->lock); /* set lease_time, because we now have timestamp in env, @@ -7028,13 +6980,11 @@ auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env) } lock_basic_unlock(&x->lock); } - lock_rw_unlock(&az->lock); } void auth_zones_cleanup(struct auth_zones* az) { struct auth_xfer* x; - lock_rw_wrlock(&az->lock); RBTREE_FOR(x, struct auth_xfer*, &az->xtree) { lock_basic_lock(&x->lock); if(x->task_nextprobe && x->task_nextprobe->worker != NULL) { @@ -7049,7 +6999,6 @@ void auth_zones_cleanup(struct auth_zones* az) } lock_basic_unlock(&x->lock); } - lock_rw_unlock(&az->lock); } /** @@ -8553,7 +8502,6 @@ void auth_zones_pickup_zonemd_verify(struct auth_zones* az, size_t savezname_len; struct auth_zone* z; key.node.key = &key; - lock_rw_rdlock(&az->lock); RBTREE_FOR(z, struct auth_zone*, &az->ztree) { lock_rw_wrlock(&z->lock); if(!z->zonemd_check) { @@ -8569,10 +8517,8 @@ void auth_zones_pickup_zonemd_verify(struct auth_zones* az, } savezname_len = z->namelen; memmove(savezname, z->name, z->namelen); - lock_rw_unlock(&az->lock); auth_zone_verify_zonemd(z, env, &env->mesh->mods, NULL, 0, 1); lock_rw_unlock(&z->lock); - lock_rw_rdlock(&az->lock); /* find the zone we had before, it is not deleted, * because we have a flag for that that is processed at * apply_cfg time */ @@ -8582,5 +8528,4 @@ void auth_zones_pickup_zonemd_verify(struct auth_zones* az, if(!z) break; } - lock_rw_unlock(&az->lock); } diff --git a/services/authzone.h b/services/authzone.h index 07614ed82..892d9c558 100644 --- a/services/authzone.h +++ b/services/authzone.h @@ -70,18 +70,12 @@ struct auth_chunk; * Authoritative zones, shared. */ struct auth_zones { - /** lock on the authzone trees */ - lock_rw_type lock; /** rbtree of struct auth_zone */ rbtree_type ztree; /** rbtree of struct auth_xfer */ rbtree_type xtree; /** do we have downstream enabled */ int have_downstream; - /** number of queries upstream */ - size_t num_query_up; - /** number of queries downstream */ - size_t num_query_down; /** first auth zone containing rpz item in linked list */ struct auth_zone* rpz_first; /** rw lock for rpz linked list, needed when iterating or editing linked @@ -190,7 +184,7 @@ struct auth_rrset { /** * Authoritative zone transfer structure. - * Create and destroy needs the auth_zones* biglock. + * Create and destroy operations are not thread-safe. * The structure consists of different tasks. Each can be unowned (-1) or * owner by a worker (worker-num). A worker can pick up a task and then do * it. This means the events (timeouts, sockets) are for that worker. @@ -206,9 +200,8 @@ struct auth_xfer { rbnode_type node; /** lock on this structure, and on the workernum elements of the - * tasks. First hold the tree-lock in auth_zones, find the auth_xfer, - * lock this lock. Then a worker can reassign itself to fill up - * one of the tasks. + * tasks. First lock this lock, then a worker can reassign itself + * to fill up one of the tasks. * Once it has the task assigned to it, the worker can access the * other elements of the task structure without a lock, because that * is necessary for the eventloop and callbacks from that. */ @@ -576,8 +569,8 @@ struct auth_zone* auth_zone_find(struct auth_zones* az, uint8_t* nm, struct auth_xfer* auth_xfer_find(struct auth_zones* az, uint8_t* nm, size_t nmlen, uint16_t dclass); -/** create an auth zone. returns wrlocked zone. caller must have wrlock - * on az. returns NULL on malloc failure */ +/** create an auth zone. returns wrlocked zone, it is not thread-safe. + * returns NULL on malloc failure */ struct auth_zone* auth_zone_create(struct auth_zones* az, uint8_t* nm, size_t nmlen, uint16_t dclass); @@ -654,8 +647,7 @@ int auth_data_cmp(const void* z1, const void* z2); /** compare auth_xfer for sorted rbtree */ int auth_xfer_cmp(const void* z1, const void* z2); -/** Create auth_xfer structure. - * Caller must have wrlock on az. Returns locked xfer zone. +/** Create auth_xfer structure. Note that it is not thread-safe. * @param az: zones structure. * @param z: zone with name and class * @return xfer zone or NULL diff --git a/testcode/unitauth.c b/testcode/unitauth.c index 23c57e095..4dd3c7889 100644 --- a/testcode/unitauth.c +++ b/testcode/unitauth.c @@ -663,9 +663,7 @@ authtest_addzone(struct auth_zones* az, const char* name, char* fname) uint8_t* nm = sldns_str2wire_dname(name, &nmlen); struct config_file* cfg; if(!nm) fatal_exit("out of memory"); - lock_rw_wrlock(&az->lock); z = auth_zone_create(az, nm, nmlen, LDNS_RR_CLASS_IN); - lock_rw_unlock(&az->lock); if(!z) fatal_exit("cannot find zone"); auth_zone_set_zonefile(z, fname); z->for_upstream = 1; diff --git a/util/module.h b/util/module.h index abad3c8dd..a50683aa6 100644 --- a/util/module.h +++ b/util/module.h @@ -153,6 +153,8 @@ #ifndef UTIL_MODULE_H #define UTIL_MODULE_H +/* stats struct */ +#include "libunbound/unbound.h" #include "util/storage/lruhash.h" #include "util/data/msgreply.h" #include "util/data/msgparse.h" @@ -484,6 +486,8 @@ struct module_env { struct sldns_buffer* scratch_buffer; /** internal data for daemon - worker thread. */ struct worker* worker; + /** worker's per thread statistics */ + struct ub_server_stats* stats; /** the worker event base */ struct comm_base* worker_base; /** the outside network */