Merge branch '4093-use-rcu-for-view-zonetable' into 'main'

Use RCU for view->zonetable

Closes #4093

See merge request isc-projects/bind9!7990
This commit is contained in:
Mark Andrews 2023-06-02 00:39:07 +00:00
commit c26d66604b
17 changed files with 281 additions and 84 deletions

View file

@ -1,3 +1,6 @@
6187. [bug] Address view shutdown INSIST when accessing the
zonetable. [GL #4093]
6186. [bug] Fix a 'clients-per-query' miscalculation bug. When the
'stale-answer-enable' options was enabled and the
'stale-answer-client-timeout' option was enabled and

View file

@ -2708,7 +2708,7 @@ catz_addmodzone_cb(void *arg) {
goto cleanup;
}
result = dns_view_findzone(cz->view, name, &zone);
result = dns_view_findzone(cz->view, name, DNS_ZTFIND_EXACT, &zone);
if (cz->mod) {
dns_catz_zone_t *parentcatz;
@ -2834,7 +2834,7 @@ catz_addmodzone_cb(void *arg) {
}
/* Is it there yet? */
CHECK(dns_view_findzone(cz->view, name, &zone));
CHECK(dns_view_findzone(cz->view, name, DNS_ZTFIND_EXACT, &zone));
/*
* Load the zone from the master file. If this fails, we'll
@ -2856,7 +2856,7 @@ catz_addmodzone_cb(void *arg) {
}
/* Remove the zone from the zone table */
dns_zt_unmount(cz->view->zonetable, zone);
dns_view_delzone(cz->view, zone);
goto cleanup;
}
@ -2891,7 +2891,7 @@ catz_delzone_cb(void *arg) {
dns_name_format(dns_catz_entry_getname(cz->entry), cname,
DNS_NAME_FORMATSIZE);
result = dns_view_findzone(cz->view, dns_catz_entry_getname(cz->entry),
&zone);
DNS_ZTFIND_EXACT, &zone);
if (result != ISC_R_SUCCESS) {
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
@ -2925,7 +2925,7 @@ catz_delzone_cb(void *arg) {
dns_zone_unload(zone);
}
CHECK(dns_zt_unmount(cz->view->zonetable, zone));
CHECK(dns_view_delzone(cz->view, zone));
file = dns_zone_getfile(zone);
if (file != NULL) {
isc_file_remove(file);
@ -3068,7 +3068,8 @@ configure_catz_zone(dns_view_t *view, dns_view_t *pview,
isc_ht_iter_current(it, (void **)&entry);
name = dns_catz_entry_getname(entry);
tresult = dns_view_findzone(pview, name, &dnszone);
tresult = dns_view_findzone(pview, name,
DNS_ZTFIND_EXACT, &dnszone);
if (tresult != ISC_R_SUCCESS) {
continue;
}
@ -5036,7 +5037,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
*/
if (view->hints == NULL) {
dns_zone_t *rootzone = NULL;
(void)dns_view_findzone(view, dns_rootname, &rootzone);
(void)dns_view_findzone(view, dns_rootname, DNS_ZTFIND_EXACT,
&rootzone);
if (rootzone != NULL) {
dns_zone_detach(&rootzone);
need_hints = false;
@ -5768,7 +5770,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
/*
* This zone already exists.
*/
(void)dns_view_findzone(view, name, &zone);
(void)dns_view_findzone(view, name, DNS_ZTFIND_EXACT,
&zone);
if (zone != NULL) {
dns_zone_detach(&zone);
continue;
@ -5799,7 +5802,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
}
if (pview != NULL) {
(void)dns_view_findzone(pview, name, &zone);
(void)dns_view_findzone(
pview, name, DNS_ZTFIND_EXACT, &zone);
dns_view_detach(&pview);
}
@ -5858,7 +5862,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
CHECK(dns_name_fromstring(
name, zones[ipv4only_zone].name, 0, NULL));
(void)dns_view_findzone(view, name, &zone);
(void)dns_view_findzone(view, name, DNS_ZTFIND_EXACT,
&zone);
if (zone != NULL) {
dns_zone_detach(&zone);
continue;
@ -5888,7 +5893,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
}
if (pview != NULL) {
(void)dns_view_findzone(pview, name, &zone);
(void)dns_view_findzone(
pview, name, DNS_ZTFIND_EXACT, &zone);
dns_view_detach(&pview);
}
@ -6574,7 +6580,8 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
goto cleanup;
}
result = dns_view_findzone(otherview, origin, &zone);
result = dns_view_findzone(otherview, origin, DNS_ZTFIND_EXACT,
&zone);
dns_view_detach(&otherview);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
@ -6693,7 +6700,8 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
/*
* Check for duplicates in the new zone table.
*/
result = dns_view_findzone(view, origin, &dupzone);
result = dns_view_findzone(view, origin, DNS_ZTFIND_EXACT,
&dupzone);
if (result == ISC_R_SUCCESS) {
/*
* We already have this zone!
@ -6749,7 +6757,8 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
goto cleanup;
}
if (pview != NULL) {
result = dns_view_findzone(pview, origin, &zone);
result = dns_view_findzone(pview, origin, DNS_ZTFIND_EXACT,
&zone);
}
if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) {
goto cleanup;
@ -7815,7 +7824,7 @@ configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig,
return;
}
result2 = dns_view_findzone(pview, origin, &zone);
result2 = dns_view_findzone(pview, origin, DNS_ZTFIND_EXACT, &zone);
if (result2 != ISC_R_SUCCESS) {
dns_view_detach(&pview);
return;
@ -9740,8 +9749,7 @@ cleanup_viewlist:
if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0)
{
dns_view_setviewrevert(view);
(void)dns_zt_apply(view->zonetable, false, NULL,
removed, view);
(void)dns_view_apply(view, false, NULL, removed, view);
}
dns_view_detach(&view);
}
@ -10572,7 +10580,8 @@ zone_from_args(named_server_t *server, isc_lex_t *lex, const char *zonetxt,
result = ISC_R_NOTFOUND;
}
} else {
result = dns_view_findzone(view, name, zonep);
result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT,
zonep);
}
if (result != ISC_R_SUCCESS) {
snprintf(problem, sizeof(problem),
@ -11311,8 +11320,8 @@ add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
ISC_LIST_INIT(vle->zonelist);
ISC_LIST_APPEND(dctx->viewlist, vle, link);
if (dctx->dumpzones) {
result = dns_zt_apply(view->zonetable, true, NULL,
add_zone_tolist, dctx);
result = dns_view_apply(view, true, NULL, add_zone_tolist,
dctx);
}
return (result);
}
@ -12409,8 +12418,8 @@ named_server_sync(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) {
for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
view = ISC_LIST_NEXT(view, link))
{
result = dns_zt_apply(view->zonetable, false, NULL,
synczone, &cleanup);
result = dns_view_apply(view, false, NULL, synczone,
&cleanup);
if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS)
{
tresult = result;
@ -13439,7 +13448,7 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
result = (view->redirect == NULL) ? ISC_R_NOTFOUND
: ISC_R_EXISTS;
} else {
result = dns_view_findzone(view, name, &zone);
result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone);
if (result == ISC_R_SUCCESS) {
result = ISC_R_EXISTS;
}
@ -13503,7 +13512,7 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
}
dns_zone_attach(view->redirect, &zone);
} else {
result = dns_view_findzone(view, name, &zone);
result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone);
if (result != ISC_R_SUCCESS) {
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
@ -13551,7 +13560,7 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
}
/* Remove the zone from the zone table */
dns_zt_unmount(view->zonetable, zone);
dns_view_delzone(view, zone);
goto cleanup;
}
@ -13619,7 +13628,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
result = ISC_R_NOTFOUND;
}
} else {
result = dns_view_findzone(view, name, &zone);
result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone);
}
if (result != ISC_R_SUCCESS) {
goto cleanup;
@ -13688,7 +13697,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
}
dns_zone_attach(view->redirect, &zone);
} else {
CHECK(dns_view_findzone(view, name, &zone));
CHECK(dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone));
}
#ifndef HAVE_LMDB
@ -13759,7 +13768,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
}
/* Remove the zone from the zone table */
dns_zt_unmount(view->zonetable, zone);
dns_view_delzone(view, zone);
goto cleanup;
}
@ -14147,7 +14156,7 @@ named_server_delzone(named_server_t *server, isc_lex_t *lex,
if (dns_zone_gettype(zone) == dns_zone_redirect) {
dns_zone_detach(&view->redirect);
} else {
CHECK(dns_zt_unmount(view->zonetable, zone));
CHECK(dns_view_delzone(view, zone));
}
/* Send cleanup event */

View file

@ -1780,8 +1780,8 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
if ((flags & STATS_XML_ZONES) != 0) {
TRY0(xmlTextWriterStartElement(writer,
ISC_XMLCHAR "zones"));
CHECK(dns_zt_apply(view->zonetable, true, NULL,
zone_xmlrender, writer));
CHECK(dns_view_apply(view, true, NULL, zone_xmlrender,
writer));
TRY0(xmlTextWriterEndElement(writer)); /* /zones */
}
@ -2494,8 +2494,8 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
CHECKMEM(za);
if ((flags & STATS_JSON_ZONES) != 0) {
CHECK(dns_zt_apply(view->zonetable, true, NULL,
zone_jsonrender, za));
CHECK(dns_view_apply(view, true, NULL,
zone_jsonrender, za));
}
if (json_object_array_length(za) != 0) {

View file

@ -166,7 +166,7 @@ syncptr_find_zone(sample_instance_t *inst, dns_rdata_t *rdata, dns_name_t *name,
}
/* Find a zone containing owner name of the PTR record. */
result = dns_zt_find(inst->view->zonetable, name, 0, zone);
result = dns_view_findzone(inst->view, name, 0, zone);
if (result == DNS_R_PARTIALMATCH) {
result = ISC_R_SUCCESS;
} else if (result != ISC_R_SUCCESS) {

View file

@ -139,7 +139,7 @@ publish_zone(sample_instance_t *inst, dns_zone_t *zone) {
/* Return success if the zone is already in the view as expected. */
result = dns_view_findzone(inst->view, dns_zone_getorigin(zone),
&zone_in_view);
DNS_ZTFIND_EXACT, &zone_in_view);
if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
goto cleanup;
}

View file

@ -247,6 +247,19 @@ AC_DEFINE_UNQUOTED([RCU_VERSION], ["$RCU_VERSION"], [Compile-time Userspace-RCU
CFLAGS="$CFLAGS $LIBURCU_CFLAGS"
LIBS="$LIBS $LIBURCU_LIBS"
#
# Userspace-RCU inlining doesn't work for rcu_deference() with some combination
# of C compiler and library version.
#
AC_MSG_CHECKING([whether we can inline small liburcu functions])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#define URCU_INLINE_SMALL_FUNCTIONS 1
#include <urcu.h>]],
[[struct opaque *a; struct opaque *b = rcu_dereference(a);]])],
[AC_MSG_RESULT([yes])
AC_DEFINE([URCU_INLINE_SMALL_FUNCTIONS], [1], [Inline small (less than 10 lines) functions])],
[AC_MSG_RESULT([no])])
# Fuzzing is not included in pairwise testing as fuzzing tools are
# not present in the relevant Docker image.
#

View file

@ -561,7 +561,7 @@ dns__catz_zones_merge(dns_catz_zone_t *catz, dns_catz_zone_t *newcatz) {
/* Try to find the zone in the view */
find_result = dns_view_findzone(catz->catzs->view,
dns_catz_entry_getname(nentry),
&zone);
DNS_ZTFIND_EXACT, &zone);
if (find_result == ISC_R_SUCCESS) {
dns_catz_coo_t *coo = NULL;
char pczname[DNS_NAME_FORMATSIZE];

View file

@ -441,7 +441,7 @@ dns_dlz_writeablezone(dns_view_t *view, dns_dlzdb_t *dlzdb,
}
/* See if the zone already exists */
result = dns_view_findzone(view, origin, &dupzone);
result = dns_view_findzone(view, origin, DNS_ZTFIND_EXACT, &dupzone);
if (result == ISC_R_SUCCESS) {
dns_zone_detach(&dupzone);
result = ISC_R_EXISTS;

View file

@ -493,6 +493,16 @@ dns_view_addzone(dns_view_t *view, dns_zone_t *zone);
*\li 'zone' is a valid zone.
*/
isc_result_t
dns_view_delzone(dns_view_t *view, dns_zone_t *zone);
/*%<
* Removes zone 'zone' from 'view'.
*
* Requires:
*
*\li 'zone' is a valid zone.
*/
void
dns_view_freeze(dns_view_t *view);
/*%<
@ -751,11 +761,11 @@ dns_viewlist_findzone(dns_viewlist_t *list, const dns_name_t *name,
*/
isc_result_t
dns_view_findzone(dns_view_t *view, const dns_name_t *name, dns_zone_t **zonep);
dns_view_findzone(dns_view_t *view, const dns_name_t *name,
unsigned int options, dns_zone_t **zonep);
/*%<
* Search for the zone 'name' in the zone table of 'view'.
* If found, 'zonep' is (strongly) attached to it. There
* are no partial matches.
* If found, 'zonep' is (strongly) attached to it.
*
* Requires:
*
@ -1281,4 +1291,20 @@ dns_view_addtrustedkey(dns_view_t *view, dns_rdatatype_t rdtype,
*
*\li Anything else Failure.
*/
isc_result_t
dns_view_apply(dns_view_t *view, bool stop, isc_result_t *sub,
isc_result_t (*action)(dns_zone_t *, void *), void *uap);
/*%<
* Call dns_zt_apply on the view's zonetable.
*
* Returns:
* \li ISC_R_SUCCESS if action was applied to all nodes. If 'stop' is
* false and 'sub' is non NULL then the first error (if any)
* reported by 'action' is returned in '*sub'. If 'stop' is true,
* the first error code from 'action' is returned.
*
* \li ISC_R_SHUTTINGDOWN if the view is in the process of shutting down.
*/
ISC_LANG_ENDDECLS

View file

@ -6593,7 +6593,7 @@ name_external(const dns_name_t *name, dns_rdatatype_t type, fetchctx_t *fctx) {
* then don't cache.
*/
dns_ztfind_t options = DNS_ZTFIND_NOEXACT | DNS_ZTFIND_MIRROR;
result = dns_zt_find(fctx->res->view->zonetable, name, options, &zone);
result = dns_view_findzone(fctx->res->view, name, options, &zone);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
dns_name_t *zname = dns_zone_getorigin(zone);
dns_namereln_t reln = dns_name_fullcompare(

View file

@ -30,6 +30,7 @@
#include <isc/result.h>
#include <isc/stats.h>
#include <isc/string.h>
#include <isc/urcu.h>
#include <isc/util.h>
#include <dns/acl.h>
@ -133,7 +134,6 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, const char *name,
isc_rwlock_init(&view->sfd_lock);
view->zonetable = NULL;
dns_zt_create(mctx, view, &view->zonetable);
result = dns_fwdtable_create(mctx, &view->fwdtable);
@ -460,7 +460,7 @@ dns_view_detach(dns_view_t **viewp) {
if (isc_refcount_decrement(&view->references) == 1) {
dns_zone_t *mkzone = NULL, *rdzone = NULL;
dns_zt_t *zt = NULL;
dns_zt_t *zonetable = NULL;
dns_resolver_t *resolver = NULL;
dns_adb_t *adb = NULL;
dns_requestmgr_t *requestmgr = NULL;
@ -481,6 +481,15 @@ dns_view_detach(dns_view_t **viewp) {
/* Swap the pointers under the lock */
LOCK(&view->lock);
rcu_read_lock();
zonetable = rcu_xchg_pointer(&view->zonetable, NULL);
if (zonetable != NULL) {
if (view->flush) {
dns_zt_flush(zonetable);
}
}
rcu_read_unlock();
if (view->resolver != NULL) {
resolver = view->resolver;
view->resolver = NULL;
@ -495,14 +504,6 @@ dns_view_detach(dns_view_t **viewp) {
requestmgr = view->requestmgr;
view->requestmgr = NULL;
}
if (view->zonetable != NULL) {
zt = view->zonetable;
view->zonetable = NULL;
if (view->flush) {
dns_zt_flush(zt);
}
}
if (view->managed_keys != NULL) {
mkzone = view->managed_keys;
view->managed_keys = NULL;
@ -537,8 +538,9 @@ dns_view_detach(dns_view_t **viewp) {
dns_requestmgr_detach(&requestmgr);
}
if (zt != NULL) {
dns_zt_detach(&zt);
if (zonetable != NULL) {
synchronize_rcu();
dns_zt_detach(&zonetable);
}
if (mkzone != NULL) {
dns_zone_detach(&mkzone);
@ -560,10 +562,16 @@ dialup(dns_zone_t *zone, void *dummy) {
void
dns_view_dialup(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->zonetable != NULL);
dns_zt_t *zonetable = NULL;
(void)dns_zt_apply(view->zonetable, false, NULL, dialup, NULL);
REQUIRE(DNS_VIEW_VALID(view));
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
(void)dns_zt_apply(zonetable, false, NULL, dialup, NULL);
}
rcu_read_unlock();
}
void
@ -762,21 +770,60 @@ dns_view_thaw(dns_view_t *view) {
isc_result_t
dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
isc_result_t result;
dns_zt_t *zonetable = NULL;
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
result = dns_zt_mount(view->zonetable, zone);
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
result = dns_zt_mount(zonetable, zone);
} else {
result = ISC_R_SHUTTINGDOWN;
}
rcu_read_unlock();
return (result);
}
isc_result_t
dns_view_delzone(dns_view_t *view, dns_zone_t *zone) {
isc_result_t result;
dns_zt_t *zonetable = NULL;
REQUIRE(DNS_VIEW_VALID(view));
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
result = dns_zt_unmount(zonetable, zone);
} else {
result = ISC_R_SUCCESS;
}
rcu_read_unlock();
return (result);
}
isc_result_t
dns_view_findzone(dns_view_t *view, const dns_name_t *name,
dns_zone_t **zonep) {
unsigned int options, dns_zone_t **zonep) {
isc_result_t result;
dns_zt_t *zonetable = NULL;
REQUIRE(DNS_VIEW_VALID(view));
return (dns_zt_find(view->zonetable, name, DNS_ZTFIND_EXACT, zonep));
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
result = dns_zt_find(zonetable, name, options, zonep);
} else {
result = ISC_R_NOTFOUND;
}
rcu_read_unlock();
return (result);
}
isc_result_t
@ -791,6 +838,7 @@ dns_view_find(dns_view_t *view, const dns_name_t *name, dns_rdatatype_t type,
bool is_cache, is_staticstub_zone;
dns_rdataset_t zrdataset, zsigrdataset;
dns_zone_t *zone = NULL;
dns_zt_t *zonetable = NULL;
/*
* Find an rdataset whose owner name is 'name', and whose type is
@ -813,7 +861,14 @@ dns_view_find(dns_view_t *view, const dns_name_t *name, dns_rdatatype_t type,
* Find a database to answer the query.
*/
is_staticstub_zone = false;
result = dns_zt_find(view->zonetable, name, DNS_ZTFIND_MIRROR, &zone);
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
result = dns_zt_find(zonetable, name, DNS_ZTFIND_MIRROR, &zone);
} else {
result = ISC_R_SHUTTINGDOWN;
}
rcu_read_unlock();
if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub &&
!use_static_stub)
{
@ -1067,6 +1122,7 @@ dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
bool is_cache, use_zone = false, try_hints = false;
dns_zone_t *zone = NULL;
dns_name_t *zfname = NULL;
dns_zt_t *zonetable = NULL;
dns_rdataset_t zrdataset, zsigrdataset;
dns_fixedname_t zfixedname;
unsigned int ztoptions = DNS_ZTFIND_MIRROR;
@ -1087,7 +1143,14 @@ dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
if ((options & DNS_DBFIND_NOEXACT) != 0) {
ztoptions |= DNS_ZTFIND_NOEXACT;
}
result = dns_zt_find(view->zonetable, name, ztoptions, &zone);
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
result = dns_zt_find(zonetable, name, ztoptions, &zone);
} else {
result = ISC_R_SHUTTINGDOWN;
}
rcu_read_unlock();
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
result = dns_zone_getdb(zone, &db);
}
@ -1287,11 +1350,19 @@ dns_viewlist_findzone(dns_viewlist_t *list, const dns_name_t *name,
for (view = ISC_LIST_HEAD(*list); view != NULL;
view = ISC_LIST_NEXT(view, link))
{
dns_zt_t *zonetable = NULL;
if (!allclasses && view->rdclass != rdclass) {
continue;
}
result = dns_zt_find(view->zonetable, name, DNS_ZTFIND_EXACT,
(zone1 == NULL) ? &zone1 : &zone2);
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
result = dns_zt_find(zonetable, name, DNS_ZTFIND_EXACT,
(zone1 == NULL) ? &zone1 : &zone2);
} else {
result = ISC_R_NOTFOUND;
}
rcu_read_unlock();
INSIST(result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND);
if (zone2 != NULL) {
dns_zone_detach(&zone1);
@ -1311,15 +1382,39 @@ dns_viewlist_findzone(dns_viewlist_t *list, const dns_name_t *name,
isc_result_t
dns_view_load(dns_view_t *view, bool stop, bool newonly) {
isc_result_t result;
dns_zt_t *zonetable = NULL;
REQUIRE(DNS_VIEW_VALID(view));
return (dns_zt_load(view->zonetable, stop, newonly));
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
result = dns_zt_load(zonetable, stop, newonly);
} else {
result = ISC_R_SUCCESS;
}
rcu_read_unlock();
return (result);
}
isc_result_t
dns_view_asyncload(dns_view_t *view, bool newonly, dns_zt_callback_t *callback,
void *arg) {
isc_result_t result;
dns_zt_t *zonetable = NULL;
REQUIRE(DNS_VIEW_VALID(view));
return (dns_zt_asyncload(view->zonetable, newonly, callback, arg));
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
result = dns_zt_asyncload(zonetable, newonly, callback, arg);
} else {
result = ISC_R_SUCCESS;
}
rcu_read_unlock();
return (result);
}
isc_result_t
@ -1455,10 +1550,21 @@ dns_view_flushnode(dns_view_t *view, const dns_name_t *name, bool tree) {
isc_result_t
dns_view_freezezones(dns_view_t *view, bool value) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->zonetable != NULL);
isc_result_t result;
dns_zt_t *zonetable = NULL;
return (dns_zt_freezezones(view->zonetable, view, value));
REQUIRE(DNS_VIEW_VALID(view));
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
result = dns_zt_freezezones(zonetable, view, value);
} else {
result = ISC_R_SUCCESS;
}
rcu_read_unlock();
return (result);
}
isc_result_t
@ -2119,6 +2225,7 @@ cleanup:
void
dns_view_setviewcommit(dns_view_t *view) {
dns_zone_t *redirect = NULL, *managed_keys = NULL;
dns_zt_t *zonetable = NULL;
REQUIRE(DNS_VIEW_VALID(view));
@ -2133,9 +2240,13 @@ dns_view_setviewcommit(dns_view_t *view) {
UNLOCK(&view->lock);
if (view->zonetable != NULL) {
dns_zt_setviewcommit(view->zonetable);
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
dns_zt_setviewcommit(zonetable);
}
rcu_read_unlock();
if (redirect != NULL) {
dns_zone_setviewcommit(redirect);
dns_zone_detach(&redirect);
@ -2149,7 +2260,7 @@ dns_view_setviewcommit(dns_view_t *view) {
void
dns_view_setviewrevert(dns_view_t *view) {
dns_zone_t *redirect = NULL, *managed_keys = NULL;
dns_zt_t *zonetable;
dns_zt_t *zonetable = NULL;
REQUIRE(DNS_VIEW_VALID(view));
@ -2164,7 +2275,6 @@ dns_view_setviewrevert(dns_view_t *view) {
if (view->managed_keys != NULL) {
dns_zone_attach(view->managed_keys, &managed_keys);
}
zonetable = view->zonetable;
UNLOCK(&view->lock);
if (redirect != NULL) {
@ -2175,9 +2285,12 @@ dns_view_setviewrevert(dns_view_t *view) {
dns_zone_setviewrevert(managed_keys);
dns_zone_detach(&managed_keys);
}
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
dns_zt_setviewrevert(zonetable);
}
rcu_read_unlock();
}
bool
@ -2361,3 +2474,22 @@ dns_view_addtrustedkey(dns_view_t *view, dns_rdatatype_t rdtype,
cleanup:
return (result);
}
isc_result_t
dns_view_apply(dns_view_t *view, bool stop, isc_result_t *sub,
isc_result_t (*action)(dns_zone_t *, void *), void *uap) {
isc_result_t result;
dns_zt_t *zonetable = NULL;
REQUIRE(DNS_VIEW_VALID(view));
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);
if (zonetable != NULL) {
result = dns_zt_apply(zonetable, stop, sub, action, uap);
} else {
result = ISC_R_SHUTTINGDOWN;
}
rcu_read_unlock();
return (result);
}

View file

@ -19,9 +19,6 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
/* Inline small (less than 10 lines) functions */
#define URCU_INLINE_SMALL_FUNCTIONS
#if defined(RCU_MEMBARRIER) || defined(RCU_MB) || defined(RCU_SIGNAL)
#include <urcu.h>
#elif defined(RCU_QSBR)

View file

@ -146,7 +146,8 @@ ns_notify_start(ns_client_t *client, isc_nmhandle_t *handle) {
}
dns_name_format(zonename, namebuf, sizeof(namebuf));
result = dns_view_findzone(client->view, zonename, &zone);
result = dns_view_findzone(client->view, zonename, DNS_ZTFIND_EXACT,
&zone);
if (result == ISC_R_SUCCESS) {
dns_zonetype_t zonetype = dns_zone_gettype(zone);

View file

@ -1116,7 +1116,7 @@ query_getzonedb(ns_client_t *client, const dns_name_t *name,
ztoptions |= DNS_ZTFIND_NOEXACT;
}
result = dns_zt_find(client->view->zonetable, name, ztoptions, &zone);
result = dns_view_findzone(client->view, name, ztoptions, &zone);
if (result == DNS_R_PARTIALMATCH) {
partial = true;

View file

@ -1987,7 +1987,8 @@ ns_update_start(ns_client_t *client, isc_nmhandle_t *handle,
"RRs");
}
result = dns_view_findzone(client->view, zonename, &zone);
result = dns_view_findzone(client->view, zonename, DNS_ZTFIND_EXACT,
&zone);
if (result != ISC_R_SUCCESS) {
FAILN(DNS_R_NOTAUTH, zonename,
"not authoritative for update zone");

View file

@ -795,7 +795,8 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
FAILC(DNS_R_FORMERR, "multiple questions");
}
result = dns_view_findzone(client->view, question_name, &zone);
result = dns_view_findzone(client->view, question_name,
DNS_ZTFIND_EXACT, &zone);
if (result != ISC_R_SUCCESS || dns_zone_gettype(zone) == dns_zone_dlz) {
/*
* The normal zone table does not have a match, or this is

View file

@ -28,6 +28,7 @@
#include <isc/buffer.h>
#include <isc/loop.h>
#include <isc/timer.h>
#include <isc/urcu.h>
#include <isc/util.h>
#include <dns/db.h>
@ -56,17 +57,21 @@ count_zone(dns_zone_t *zone, void *uap) {
ISC_LOOP_TEST_IMPL(apply) {
isc_result_t result;
dns_zone_t *zone = NULL;
dns_zt_t *zt = NULL;
int nzones = 0;
result = dns_test_makezone("foo", &zone, NULL, true);
assert_int_equal(result, ISC_R_SUCCESS);
view = dns_zone_getview(zone);
assert_non_null(view->zonetable);
rcu_read_lock();
zt = rcu_dereference(view->zonetable);
rcu_read_unlock();
assert_non_null(zt);
assert_int_equal(nzones, 0);
result = dns_zt_apply(view->zonetable, false, NULL, count_zone,
&nzones);
result = dns_view_apply(view, false, NULL, count_zone, &nzones);
assert_int_equal(result, ISC_R_SUCCESS);
assert_int_equal(nzones, 1);
@ -151,6 +156,7 @@ ISC_LOOP_TEST_IMPL(asyncload_zone) {
isc_result_t result;
int n;
dns_zone_t *zone = NULL;
dns_zt_t *zt = NULL;
char buf[4096];
result = dns_test_makezone("foo", &zone, NULL, true);
@ -161,7 +167,10 @@ ISC_LOOP_TEST_IMPL(asyncload_zone) {
assert_int_equal(result, ISC_R_SUCCESS);
view = dns_zone_getview(zone);
assert_non_null(view->zonetable);
rcu_read_lock();
zt = rcu_dereference(view->zonetable);
rcu_read_unlock();
assert_non_null(zt);
assert_false(dns__zone_loadpending(zone));
zonefile = fopen("./zone.data", "wb");
@ -239,7 +248,9 @@ ISC_LOOP_TEST_IMPL(asyncload_zt) {
dns_zone_setfile(zone3, TESTS_DIR "/testdata/zt/nonexistent.db",
dns_masterformat_text, &dns_master_style_default);
zt = view->zonetable;
rcu_read_lock();
zt = rcu_dereference(view->zonetable);
rcu_read_unlock();
assert_non_null(zt);
dns_test_setupzonemgr();
@ -254,7 +265,10 @@ ISC_LOOP_TEST_IMPL(asyncload_zt) {
assert_false(dns__zone_loadpending(zone2));
assert_false(atomic_load(&done));
rcu_read_lock();
zt = rcu_dereference(view->zonetable);
dns_zt_asyncload(zt, false, all_done, NULL);
rcu_read_unlock();
}
ISC_TEST_LIST_START