summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib/dns/adb.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/lib/dns/adb.c')
-rw-r--r--contrib/bind9/lib/dns/adb.c64
1 files changed, 44 insertions, 20 deletions
diff --git a/contrib/bind9/lib/dns/adb.c b/contrib/bind9/lib/dns/adb.c
index c65c474..ae5dec8 100644
--- a/contrib/bind9/lib/dns/adb.c
+++ b/contrib/bind9/lib/dns/adb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,9 +15,9 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: adb.c,v 1.215.18.17 2007/09/11 02:23:26 marka Exp $ */
+/* $Id: adb.c,v 1.215.18.24 2008/10/17 03:35:14 marka Exp $ */
-/*! \file
+/*! \file
*
* \note
* In finds, if task == NULL, no events will be generated, and no events
@@ -71,7 +71,7 @@
#define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6')
#define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
-/*!
+/*!
* The number of buckets needs to be a prime (for good hashing).
*
* XXXRTH How many buckets do we need?
@@ -119,6 +119,7 @@ struct dns_adb {
isc_mutex_t lock;
isc_mutex_t reflock; /*%< Covers irefcnt, erefcnt */
+ isc_mutex_t overmemlock; /*%< Covers overmem */
isc_mem_t *mctx;
dns_view_t *view;
isc_timermgr_t *timermgr;
@@ -494,6 +495,7 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
isc_boolean_t new_addresses_added;
dns_rdatatype_t rdtype;
unsigned int findoptions;
+ dns_adbnamehooklist_t *hookhead;
INSIST(DNS_ADBNAME_VALID(adbname));
adb = adbname->adb;
@@ -518,10 +520,12 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
INSIST(rdata.length == 4);
memcpy(&ina.s_addr, rdata.data, 4);
isc_sockaddr_fromin(&sockaddr, &ina, 0);
+ hookhead = &adbname->v4;
} else {
INSIST(rdata.length == 16);
memcpy(in6a.s6_addr, rdata.data, 16);
isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
+ hookhead = &adbname->v6;
}
INSIST(nh == NULL);
@@ -550,7 +554,7 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
link_entry(adb, addr_bucket, entry);
} else {
- for (anh = ISC_LIST_HEAD(adbname->v4);
+ for (anh = ISC_LIST_HEAD(*hookhead);
anh != NULL;
anh = ISC_LIST_NEXT(anh, plink))
if (anh->entry == foundentry)
@@ -563,12 +567,8 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
}
new_addresses_added = ISC_TRUE;
- if (nh != NULL) {
- if (rdtype == dns_rdatatype_a)
- ISC_LIST_APPEND(adbname->v4, nh, plink);
- else
- ISC_LIST_APPEND(adbname->v6, nh, plink);
- }
+ if (nh != NULL)
+ ISC_LIST_APPEND(*hookhead, nh, plink);
nh = NULL;
result = dns_rdataset_next(rdataset);
}
@@ -1738,8 +1738,11 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
bucket = entry->lock_bucket;
LOCK(&adb->entrylocks[bucket]);
- if (entry_is_lame(adb, entry, qname, qtype, now))
+ if (!FIND_RETURNLAME(find)
+ && entry_is_lame(adb, entry, qname, qtype, now)) {
+ find->options |= DNS_ADBFIND_LAMEPRUNED;
goto nextv6;
+ }
addrinfo = new_adbaddrinfo(adb, entry, find->port);
if (addrinfo == NULL) {
find->partial_result |= DNS_ADBFIND_INET6;
@@ -1773,12 +1776,15 @@ shutdown_task(isc_task_t *task, isc_event_t *ev) {
INSIST(DNS_ADB_VALID(adb));
/*
+ * Wait for lock around check_exit() call to be released.
+ */
+ LOCK(&adb->lock);
+ /*
* Kill the timer, and then the ADB itself. Note that this implies
* that this task was the one scheduled to get timer events. If
* this is not true (and it is unfortunate there is no way to INSIST()
* this) badness will occur.
*/
- LOCK(&adb->lock);
isc_timer_detach(&adb->timer);
UNLOCK(&adb->lock);
isc_event_free(&ev);
@@ -1990,6 +1996,7 @@ destroy(dns_adb_t *adb) {
DESTROYLOCK(&adb->reflock);
DESTROYLOCK(&adb->lock);
DESTROYLOCK(&adb->mplock);
+ DESTROYLOCK(&adb->overmemlock);
isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
}
@@ -2060,6 +2067,10 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
if (result != ISC_R_SUCCESS)
goto fail0d;
+ result = isc_mutex_init(&adb->overmemlock);
+ if (result != ISC_R_SUCCESS)
+ goto fail0e;
+
/*
* Initialize the bucket locks for names and elements.
* May as well initialize the list heads, too.
@@ -2162,6 +2173,8 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
if (adb->afmp != NULL)
isc_mempool_destroy(&adb->afmp);
+ DESTROYLOCK(&adb->overmemlock);
+ fail0e:
DESTROYLOCK(&adb->reflock);
fail0d:
DESTROYLOCK(&adb->mplock);
@@ -3133,8 +3146,10 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
address_type = DNS_ADBFIND_INET6;
fetch = name->fetch_aaaa;
name->fetch_aaaa = NULL;
- }
- INSIST(address_type != 0);
+ } else
+ fetch = NULL;
+
+ INSIST(address_type != 0 && fetch != NULL);
dns_resolver_destroyfetch(&fetch->fetch);
dev->fetch = NULL;
@@ -3582,12 +3597,21 @@ water(void *arg, int mark) {
DP(ISC_LOG_DEBUG(1),
"adb reached %s water mark", overmem ? "high" : "low");
- adb->overmem = overmem;
- if (overmem) {
- isc_interval_set(&interval, 0, 1);
- (void)isc_timer_reset(adb->timer, isc_timertype_once, NULL,
- &interval, ISC_TRUE);
+ /*
+ * We can't use adb->lock as there is potential for water
+ * to be called when adb->lock is held.
+ */
+ LOCK(&adb->overmemlock);
+ if (adb->overmem != overmem) {
+ adb->overmem = overmem;
+ if (overmem) {
+ isc_interval_set(&interval, 0, 1);
+ (void)isc_timer_reset(adb->timer, isc_timertype_once,
+ NULL, &interval, ISC_TRUE);
+ }
+ isc_mem_waterack(adb->mctx, mark);
}
+ UNLOCK(&adb->overmemlock);
}
void
OpenPOWER on IntegriCloud