mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-09 03:02:05 -04:00
Convert rwlock in dns_acl to RCU
The dns_aclenv_t contains two dns_acl_t - localhost and localnets that can be swapped with a different ACLs as we configure BIND 9. Instead of protecting those two pointers with heavyweight read-write lock, use RCU mechanism to dereference and swap the pointers.
This commit is contained in:
parent
546c327349
commit
96bbf95b83
4 changed files with 65 additions and 60 deletions
|
|
@ -19,6 +19,7 @@
|
|||
#include <isc/mem.h>
|
||||
#include <isc/once.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/urcu.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/acl.h>
|
||||
|
|
@ -47,6 +48,7 @@ dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
|
|||
};
|
||||
|
||||
isc_mem_attach(mctx, &acl->mctx);
|
||||
dns_iptable_create(acl->mctx, &acl->iptable);
|
||||
|
||||
*target = acl;
|
||||
}
|
||||
|
|
@ -401,26 +403,18 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr, const dns_name_t *reqsigner,
|
|||
if (env == NULL) {
|
||||
return (false);
|
||||
}
|
||||
RWLOCK(&env->rwlock, isc_rwlocktype_read);
|
||||
if (env->localhost == NULL) {
|
||||
RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
|
||||
return (false);
|
||||
}
|
||||
dns_acl_attach(env->localhost, &inner);
|
||||
RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
|
||||
rcu_read_lock();
|
||||
dns_acl_attach(rcu_dereference(env->localhost), &inner);
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
|
||||
case dns_aclelementtype_localnets:
|
||||
if (env == NULL) {
|
||||
return (false);
|
||||
}
|
||||
RWLOCK(&env->rwlock, isc_rwlocktype_read);
|
||||
if (env->localnets == NULL) {
|
||||
RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
|
||||
return (false);
|
||||
}
|
||||
dns_acl_attach(env->localnets, &inner);
|
||||
RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
|
||||
rcu_read_lock();
|
||||
dns_acl_attach(rcu_dereference(env->localnets), &inner);
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
|
||||
#if defined(HAVE_GEOIP2)
|
||||
|
|
@ -652,7 +646,6 @@ dns_aclenv_create(isc_mem_t *mctx, dns_aclenv_t **envp) {
|
|||
|
||||
isc_mem_attach(mctx, &env->mctx);
|
||||
isc_refcount_init(&env->references, 1);
|
||||
isc_rwlock_init(&env->rwlock);
|
||||
|
||||
dns_acl_create(mctx, 0, &env->localhost);
|
||||
dns_acl_create(mctx, 0, &env->localnets);
|
||||
|
|
@ -663,34 +656,45 @@ dns_aclenv_create(isc_mem_t *mctx, dns_aclenv_t **envp) {
|
|||
void
|
||||
dns_aclenv_set(dns_aclenv_t *env, dns_acl_t *localhost, dns_acl_t *localnets) {
|
||||
REQUIRE(VALID_ACLENV(env));
|
||||
REQUIRE(DNS_ACL_VALID(localhost));
|
||||
REQUIRE(DNS_ACL_VALID(localnets));
|
||||
|
||||
RWLOCK(&env->rwlock, isc_rwlocktype_write);
|
||||
dns_acl_detach(&env->localhost);
|
||||
dns_acl_attach(localhost, &env->localhost);
|
||||
dns_acl_detach(&env->localnets);
|
||||
dns_acl_attach(localnets, &env->localnets);
|
||||
RWUNLOCK(&env->rwlock, isc_rwlocktype_write);
|
||||
rcu_read_lock();
|
||||
localhost = rcu_xchg_pointer(&env->localhost, dns_acl_ref(localhost));
|
||||
localnets = rcu_xchg_pointer(&env->localnets, dns_acl_ref(localnets));
|
||||
rcu_read_unlock();
|
||||
|
||||
dns_acl_detach(&localhost);
|
||||
dns_acl_detach(&localnets);
|
||||
}
|
||||
|
||||
void
|
||||
dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s) {
|
||||
REQUIRE(VALID_ACLENV(s));
|
||||
REQUIRE(VALID_ACLENV(t));
|
||||
dns_aclenv_copy(dns_aclenv_t *target, dns_aclenv_t *source) {
|
||||
REQUIRE(VALID_ACLENV(source));
|
||||
REQUIRE(VALID_ACLENV(target));
|
||||
|
||||
RWLOCK(&t->rwlock, isc_rwlocktype_write);
|
||||
RWLOCK(&s->rwlock, isc_rwlocktype_read);
|
||||
dns_acl_detach(&t->localhost);
|
||||
dns_acl_attach(s->localhost, &t->localhost);
|
||||
dns_acl_detach(&t->localnets);
|
||||
dns_acl_attach(s->localnets, &t->localnets);
|
||||
rcu_read_lock();
|
||||
|
||||
t->match_mapped = s->match_mapped;
|
||||
dns_acl_t *localhost = rcu_dereference(source->localhost);
|
||||
INSIST(DNS_ACL_VALID(localhost));
|
||||
|
||||
dns_acl_t *localnets = rcu_dereference(source->localnets);
|
||||
INSIST(DNS_ACL_VALID(localnets));
|
||||
|
||||
localhost = rcu_xchg_pointer(&target->localhost,
|
||||
dns_acl_ref(localhost));
|
||||
localnets = rcu_xchg_pointer(&target->localnets,
|
||||
dns_acl_ref(localnets));
|
||||
|
||||
target->match_mapped = source->match_mapped;
|
||||
#if defined(HAVE_GEOIP2)
|
||||
t->geoip = s->geoip;
|
||||
target->geoip = source->geoip;
|
||||
#endif /* if defined(HAVE_GEOIP2) */
|
||||
|
||||
RWUNLOCK(&s->rwlock, isc_rwlocktype_read);
|
||||
RWUNLOCK(&t->rwlock, isc_rwlocktype_write);
|
||||
rcu_read_unlock();
|
||||
|
||||
dns_acl_detach(&localhost);
|
||||
dns_acl_detach(&localnets);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -699,10 +703,17 @@ dns__aclenv_destroy(dns_aclenv_t *aclenv) {
|
|||
|
||||
aclenv->magic = 0;
|
||||
|
||||
isc_refcount_destroy(&aclenv->references);
|
||||
dns_acl_detach(&aclenv->localhost);
|
||||
dns_acl_detach(&aclenv->localnets);
|
||||
isc_rwlock_destroy(&aclenv->rwlock);
|
||||
rcu_read_lock();
|
||||
dns_acl_t *localhost = rcu_xchg_pointer(&aclenv->localhost, NULL);
|
||||
INSIST(DNS_ACL_VALID(localhost));
|
||||
|
||||
dns_acl_t *localnets = rcu_xchg_pointer(&aclenv->localnets, NULL);
|
||||
INSIST(DNS_ACL_VALID(localnets));
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
dns_acl_detach(&localhost);
|
||||
dns_acl_detach(&localnets);
|
||||
|
||||
isc_mem_putanddetach(&aclenv->mctx, aclenv, sizeof(*aclenv));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include <isc/magic.h>
|
||||
#include <isc/netaddr.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/rwlock.h>
|
||||
|
||||
#include <dns/geoip.h>
|
||||
#include <dns/iptable.h>
|
||||
|
|
@ -103,9 +102,8 @@ struct dns_aclenv {
|
|||
isc_mem_t *mctx;
|
||||
isc_refcount_t references;
|
||||
|
||||
isc_rwlock_t rwlock; /*%< Locks localhost and localnets */
|
||||
dns_acl_t *localhost;
|
||||
dns_acl_t *localnets;
|
||||
dns_acl_t *localhost;
|
||||
dns_acl_t *localnets;
|
||||
|
||||
bool match_mapped;
|
||||
#if defined(HAVE_GEOIP2)
|
||||
|
|
|
|||
|
|
@ -367,10 +367,11 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
|
|||
if (!dns_name_issubdomain(name, rule->name)) {
|
||||
continue;
|
||||
}
|
||||
RWLOCK(&env->rwlock, isc_rwlocktype_read);
|
||||
dns_acl_match(addr, NULL, env->localhost, NULL, &match,
|
||||
rcu_read_lock();
|
||||
dns_acl_t *localhost = rcu_dereference(env->localhost);
|
||||
dns_acl_match(addr, NULL, localhost, NULL, &match,
|
||||
NULL);
|
||||
RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
|
||||
rcu_read_unlock();
|
||||
if (match == 0) {
|
||||
if (signer != NULL) {
|
||||
isc_log_write(dns_lctx,
|
||||
|
|
|
|||
|
|
@ -84,30 +84,25 @@ ns_sortlist_setup(dns_acl_t *acl, dns_aclenv_t *env, isc_netaddr_t *clientaddr,
|
|||
}
|
||||
|
||||
if (order_elt->type == dns_aclelementtype_localhost) {
|
||||
dns_acl_t *inner = NULL;
|
||||
RWLOCK(&env->rwlock, isc_rwlocktype_read);
|
||||
if (env->localhost != NULL) {
|
||||
dns_acl_attach(env->localhost, &inner);
|
||||
}
|
||||
RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
|
||||
|
||||
rcu_read_lock();
|
||||
dns_acl_t *inner = rcu_dereference(env->localhost);
|
||||
if (inner != NULL) {
|
||||
*argp = inner;
|
||||
*argp = dns_acl_ref(inner);
|
||||
rcu_read_unlock();
|
||||
return (NS_SORTLISTTYPE_2ELEMENT);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
if (order_elt->type == dns_aclelementtype_localnets) {
|
||||
dns_acl_t *inner = NULL;
|
||||
RWLOCK(&env->rwlock, isc_rwlocktype_read);
|
||||
if (env->localnets != NULL) {
|
||||
dns_acl_attach(env->localnets, &inner);
|
||||
}
|
||||
RWUNLOCK(&env->rwlock, isc_rwlocktype_read);
|
||||
rcu_read_lock();
|
||||
dns_acl_t *inner = rcu_dereference(env->localhost);
|
||||
if (inner != NULL) {
|
||||
*argp = inner;
|
||||
*argp = dns_acl_ref(inner);
|
||||
rcu_read_unlock();
|
||||
return (NS_SORTLISTTYPE_2ELEMENT);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue