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.c581
1 files changed, 527 insertions, 54 deletions
diff --git a/contrib/bind9/lib/dns/adb.c b/contrib/bind9/lib/dns/adb.c
index cd9cadf..fcc2dd8 100644
--- a/contrib/bind9/lib/dns/adb.c
+++ b/contrib/bind9/lib/dns/adb.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: adb.c,v 1.243.42.6 2010-08-11 23:45:49 tbox Exp $ */
+/* $Id: adb.c,v 1.254 2010-12-21 23:47:08 tbox Exp $ */
/*! \file
*
@@ -66,13 +66,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?
- */
-#define NBUCKETS 1009 /*%< how many buckets for names/addrs */
-
-/*!
* For type 3 negative cache entries, we will remember that the address is
* broken for this long. XXXMLG This is also used for actual addresses, too.
* The intent is to keep us from constantly asking about A/AAAA records
@@ -139,30 +132,37 @@ struct dns_adb {
*
* XXXRTH Have a per-bucket structure that contains all of these?
*/
- dns_adbnamelist_t names[NBUCKETS];
- dns_adbnamelist_t deadnames[NBUCKETS];
- /*% See dns_adbnamelist_t */
- isc_mutex_t namelocks[NBUCKETS];
- /*% See dns_adbnamelist_t */
- isc_boolean_t name_sd[NBUCKETS];
- /*% See dns_adbnamelist_t */
- unsigned int name_refcnt[NBUCKETS];
+ unsigned int nnames;
+ isc_mutex_t namescntlock;
+ unsigned int namescnt;
+ dns_adbnamelist_t *names;
+ dns_adbnamelist_t *deadnames;
+ isc_mutex_t *namelocks;
+ isc_boolean_t *name_sd;
+ unsigned int *name_refcnt;
/*!
- * Bucketized locks for entries.
+ * Bucketized locks and lists for entries.
*
* XXXRTH Have a per-bucket structure that contains all of these?
*/
- dns_adbentrylist_t entries[NBUCKETS];
- dns_adbentrylist_t deadentries[NBUCKETS];
- isc_mutex_t entrylocks[NBUCKETS];
- isc_boolean_t entry_sd[NBUCKETS]; /*%< shutting down */
- unsigned int entry_refcnt[NBUCKETS];
+ unsigned int nentries;
+ isc_mutex_t entriescntlock;
+ unsigned int entriescnt;
+ dns_adbentrylist_t *entries;
+ dns_adbentrylist_t *deadentries;
+ isc_mutex_t *entrylocks;
+ isc_boolean_t *entry_sd; /*%< shutting down */
+ unsigned int *entry_refcnt;
isc_event_t cevent;
isc_boolean_t cevent_sent;
isc_boolean_t shutting_down;
isc_eventlist_t whenshutdown;
+ isc_event_t growentries;
+ isc_boolean_t growentries_sent;
+ isc_event_t grownames;
+ isc_boolean_t grownames_sent;
};
/*
@@ -484,6 +484,322 @@ ttlclamp(dns_ttl_t ttl) {
}
/*
+ * Hashing is most efficient if the number of buckets is prime.
+ * The sequence below is the closest previous primes to 2^n and
+ * 1.5 * 2^n, for values of n from 10 to 28. (The tables will
+ * no longer grow beyond 2^28 entries.)
+ */
+static const unsigned nbuckets[] = { 1021, 1531, 2039, 3067, 4093, 6143,
+ 8191, 12281, 16381, 24571, 32749,
+ 49193, 65521, 98299, 131071, 199603,
+ 262139, 393209, 524287, 768431, 1048573,
+ 1572853, 2097143, 3145721, 4194301,
+ 6291449, 8388593, 12582893, 16777213,
+ 25165813, 33554393, 50331599, 67108859,
+ 100663291, 134217689, 201326557,
+ 268535431, 0 };
+
+static void
+grow_entries(isc_task_t *task, isc_event_t *ev) {
+ dns_adb_t *adb;
+ dns_adbentry_t *e;
+ dns_adbentrylist_t *newdeadentries = NULL;
+ dns_adbentrylist_t *newentries = NULL;
+ isc_boolean_t *newentry_sd = NULL;
+ isc_mutex_t *newentrylocks = NULL;
+ isc_result_t result;
+ unsigned int *newentry_refcnt = NULL;
+ unsigned int i, n, bucket;
+
+ adb = ev->ev_arg;
+ INSIST(DNS_ADB_VALID(adb));
+
+ isc_event_free(&ev);
+
+ isc_task_beginexclusive(task);
+
+ i = 0;
+ while (nbuckets[i] != 0 && adb->nentries >= nbuckets[i])
+ i++;
+ if (nbuckets[i] != 0)
+ n = nbuckets[i];
+ else
+ goto done;
+
+ DP(ISC_LOG_INFO, "adb: grow_entries to %u starting", n);
+
+ /*
+ * Are we shutting down?
+ */
+ for (i = 0; i < adb->nentries; i++)
+ if (adb->entry_sd[i])
+ goto cleanup;
+
+ /*
+ * Grab all the resources we need.
+ */
+ newentries = isc_mem_get(adb->mctx, sizeof(*newentries) * n);
+ newdeadentries = isc_mem_get(adb->mctx, sizeof(*newdeadentries) * n);
+ newentrylocks = isc_mem_get(adb->mctx, sizeof(*newentrylocks) * n);
+ newentry_sd = isc_mem_get(adb->mctx, sizeof(*newentry_sd) * n);
+ newentry_refcnt = isc_mem_get(adb->mctx, sizeof(*newentry_refcnt) * n);
+ if (newentries == NULL || newdeadentries == NULL ||
+ newentrylocks == NULL || newentry_sd == NULL ||
+ newentry_refcnt == NULL)
+ goto cleanup;
+
+ /*
+ * Initialise the new resources.
+ */
+ result = isc_mutexblock_init(newentrylocks, n);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ for (i = 0; i < n; i++) {
+ ISC_LIST_INIT(newentries[i]);
+ ISC_LIST_INIT(newdeadentries[i]);
+ newentry_sd[i] = ISC_FALSE;
+ newentry_refcnt[i] = 0;
+ adb->irefcnt++;
+ }
+
+ /*
+ * Move entries to new arrays.
+ */
+ for (i = 0; i < adb->nentries; i++) {
+ e = ISC_LIST_HEAD(adb->entries[i]);
+ while (e != NULL) {
+ ISC_LIST_UNLINK(adb->entries[i], e, plink);
+ bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
+ e->lock_bucket = bucket;
+ ISC_LIST_APPEND(newentries[bucket], e, plink);
+ INSIST(adb->entry_refcnt[i] > 0);
+ adb->entry_refcnt[i]--;
+ newentry_refcnt[bucket]++;
+ e = ISC_LIST_HEAD(adb->entries[i]);
+ }
+ e = ISC_LIST_HEAD(adb->deadentries[i]);
+ while (e != NULL) {
+ ISC_LIST_UNLINK(adb->deadentries[i], e, plink);
+ bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
+ e->lock_bucket = bucket;
+ ISC_LIST_APPEND(newdeadentries[bucket], e, plink);
+ INSIST(adb->entry_refcnt[i] > 0);
+ adb->entry_refcnt[i]--;
+ newentry_refcnt[bucket]++;
+ e = ISC_LIST_HEAD(adb->deadentries[i]);
+ }
+ INSIST(adb->entry_refcnt[i] == 0);
+ adb->irefcnt--;
+ }
+
+ /*
+ * Cleanup old resources.
+ */
+ DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
+ isc_mem_put(adb->mctx, adb->entries,
+ sizeof(*adb->entries) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->deadentries,
+ sizeof(*adb->deadentries) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->entrylocks,
+ sizeof(*adb->entrylocks) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->entry_sd,
+ sizeof(*adb->entry_sd) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->entry_refcnt,
+ sizeof(*adb->entry_refcnt) * adb->nentries);
+
+ /*
+ * Install new resources.
+ */
+ adb->entries = newentries;
+ adb->deadentries = newdeadentries;
+ adb->entrylocks = newentrylocks;
+ adb->entry_sd = newentry_sd;
+ adb->entry_refcnt = newentry_refcnt;
+ adb->nentries = n;
+
+ /*
+ * Only on success do we set adb->growentries_sent to ISC_FALSE.
+ * This will prevent us being continuously being called on error.
+ */
+ adb->growentries_sent = ISC_FALSE;
+ goto done;
+
+ cleanup:
+ if (newentries != NULL)
+ isc_mem_put(adb->mctx, newentries,
+ sizeof(*newentries) * n);
+ if (newdeadentries != NULL)
+ isc_mem_put(adb->mctx, newdeadentries,
+ sizeof(*newdeadentries) * n);
+ if (newentrylocks != NULL)
+ isc_mem_put(adb->mctx, newentrylocks,
+ sizeof(*newentrylocks) * n);
+ if (newentry_sd != NULL)
+ isc_mem_put(adb->mctx, newentry_sd,
+ sizeof(*newentry_sd) * n);
+ if (newentry_refcnt != NULL)
+ isc_mem_put(adb->mctx, newentry_refcnt,
+ sizeof(*newentry_refcnt) * n);
+ done:
+ isc_task_endexclusive(task);
+
+ LOCK(&adb->lock);
+ if (dec_adb_irefcnt(adb))
+ check_exit(adb);
+ UNLOCK(&adb->lock);
+ DP(ISC_LOG_INFO, "adb: grow_entries finished");
+}
+
+static void
+grow_names(isc_task_t *task, isc_event_t *ev) {
+ dns_adb_t *adb;
+ dns_adbname_t *name;
+ dns_adbnamelist_t *newdeadnames = NULL;
+ dns_adbnamelist_t *newnames = NULL;
+ isc_boolean_t *newname_sd = NULL;
+ isc_mutex_t *newnamelocks = NULL;
+ isc_result_t result;
+ unsigned int *newname_refcnt = NULL;
+ unsigned int i, n, bucket;
+
+ adb = ev->ev_arg;
+ INSIST(DNS_ADB_VALID(adb));
+
+ isc_event_free(&ev);
+
+ isc_task_beginexclusive(task);
+
+ i = 0;
+ while (nbuckets[i] != 0 && adb->nnames >= nbuckets[i])
+ i++;
+ if (nbuckets[i] != 0)
+ n = nbuckets[i];
+ else
+ goto done;
+
+ DP(ISC_LOG_INFO, "adb: grow_names to %u starting", n);
+
+ /*
+ * Are we shutting down?
+ */
+ for (i = 0; i < adb->nnames; i++)
+ if (adb->name_sd[i])
+ goto cleanup;
+
+ /*
+ * Grab all the resources we need.
+ */
+ newnames = isc_mem_get(adb->mctx, sizeof(*newnames) * n);
+ newdeadnames = isc_mem_get(adb->mctx, sizeof(*newdeadnames) * n);
+ newnamelocks = isc_mem_get(adb->mctx, sizeof(*newnamelocks) * n);
+ newname_sd = isc_mem_get(adb->mctx, sizeof(*newname_sd) * n);
+ newname_refcnt = isc_mem_get(adb->mctx, sizeof(*newname_refcnt) * n);
+ if (newnames == NULL || newdeadnames == NULL ||
+ newnamelocks == NULL || newname_sd == NULL ||
+ newname_refcnt == NULL)
+ goto cleanup;
+
+ /*
+ * Initialise the new resources.
+ */
+ result = isc_mutexblock_init(newnamelocks, n);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ for (i = 0; i < n; i++) {
+ ISC_LIST_INIT(newnames[i]);
+ ISC_LIST_INIT(newdeadnames[i]);
+ newname_sd[i] = ISC_FALSE;
+ newname_refcnt[i] = 0;
+ adb->irefcnt++;
+ }
+
+ /*
+ * Move names to new arrays.
+ */
+ for (i = 0; i < adb->nnames; i++) {
+ name = ISC_LIST_HEAD(adb->names[i]);
+ while (name != NULL) {
+ ISC_LIST_UNLINK(adb->names[i], name, plink);
+ bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
+ name->lock_bucket = bucket;
+ ISC_LIST_APPEND(newnames[bucket], name, plink);
+ INSIST(adb->name_refcnt[i] > 0);
+ adb->name_refcnt[i]--;
+ newname_refcnt[bucket]++;
+ name = ISC_LIST_HEAD(adb->names[i]);
+ }
+ name = ISC_LIST_HEAD(adb->deadnames[i]);
+ while (name != NULL) {
+ ISC_LIST_UNLINK(adb->deadnames[i], name, plink);
+ bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
+ name->lock_bucket = bucket;
+ ISC_LIST_APPEND(newdeadnames[bucket], name, plink);
+ INSIST(adb->name_refcnt[i] > 0);
+ adb->name_refcnt[i]--;
+ newname_refcnt[bucket]++;
+ name = ISC_LIST_HEAD(adb->deadnames[i]);
+ }
+ INSIST(adb->name_refcnt[i] == 0);
+ adb->irefcnt--;
+ }
+
+ /*
+ * Cleanup old resources.
+ */
+ DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
+ isc_mem_put(adb->mctx, adb->names,
+ sizeof(*adb->names) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->deadnames,
+ sizeof(*adb->deadnames) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->namelocks,
+ sizeof(*adb->namelocks) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->name_sd,
+ sizeof(*adb->name_sd) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->name_refcnt,
+ sizeof(*adb->name_refcnt) * adb->nnames);
+
+ /*
+ * Install new resources.
+ */
+ adb->names = newnames;
+ adb->deadnames = newdeadnames;
+ adb->namelocks = newnamelocks;
+ adb->name_sd = newname_sd;
+ adb->name_refcnt = newname_refcnt;
+ adb->nnames = n;
+
+ /*
+ * Only on success do we set adb->grownames_sent to ISC_FALSE.
+ * This will prevent us being continuously being called on error.
+ */
+ adb->grownames_sent = ISC_FALSE;
+ goto done;
+
+ cleanup:
+ if (newnames != NULL)
+ isc_mem_put(adb->mctx, newnames, sizeof(*newnames) * n);
+ if (newdeadnames != NULL)
+ isc_mem_put(adb->mctx, newdeadnames, sizeof(*newdeadnames) * n);
+ if (newnamelocks != NULL)
+ isc_mem_put(adb->mctx, newnamelocks, sizeof(*newnamelocks) * n);
+ if (newname_sd != NULL)
+ isc_mem_put(adb->mctx, newname_sd, sizeof(*newname_sd) * n);
+ if (newname_refcnt != NULL)
+ isc_mem_put(adb->mctx, newname_refcnt,
+ sizeof(*newname_refcnt) * n);
+ done:
+ isc_task_endexclusive(task);
+
+ LOCK(&adb->lock);
+ if (dec_adb_irefcnt(adb))
+ check_exit(adb);
+ UNLOCK(&adb->lock);
+ DP(ISC_LOG_INFO, "adb: grow_names finished");
+}
+
+/*
* Requires the adbname bucket be locked and that no entry buckets be locked.
*
* This code handles A and AAAA rdatasets only.
@@ -836,12 +1152,12 @@ violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) {
*/
static isc_boolean_t
shutdown_names(dns_adb_t *adb) {
- int bucket;
+ unsigned int bucket;
isc_boolean_t result = ISC_FALSE;
dns_adbname_t *name;
dns_adbname_t *next_name;
- for (bucket = 0; bucket < NBUCKETS; bucket++) {
+ for (bucket = 0; bucket < adb->nnames; bucket++) {
LOCK(&adb->namelocks[bucket]);
adb->name_sd[bucket] = ISC_TRUE;
@@ -881,12 +1197,12 @@ shutdown_names(dns_adb_t *adb) {
*/
static isc_boolean_t
shutdown_entries(dns_adb_t *adb) {
- int bucket;
+ unsigned int bucket;
isc_boolean_t result = ISC_FALSE;
dns_adbentry_t *entry;
dns_adbentry_t *next_entry;
- for (bucket = 0; bucket < NBUCKETS; bucket++) {
+ for (bucket = 0; bucket < adb->nentries; bucket++) {
LOCK(&adb->entrylocks[bucket]);
adb->entry_sd[bucket] = ISC_TRUE;
@@ -1306,6 +1622,16 @@ new_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
ISC_LIST_INIT(name->finds);
ISC_LINK_INIT(name, plink);
+ LOCK(&adb->namescntlock);
+ adb->namescnt++;
+ if (!adb->grownames_sent && adb->namescnt > (adb->nnames * 8)) {
+ isc_event_t *event = &adb->grownames;
+ inc_adb_irefcnt(adb);
+ isc_task_send(adb->task, &event);
+ adb->grownames_sent = ISC_TRUE;
+ }
+ UNLOCK(&adb->namescntlock);
+
return (name);
}
@@ -1329,6 +1655,9 @@ free_adbname(dns_adb_t *adb, dns_adbname_t **name) {
dns_name_free(&n->name, adb->mctx);
isc_mempool_put(adb->nmp, n);
+ LOCK(&adb->namescntlock);
+ adb->namescnt--;
+ UNLOCK(&adb->namescntlock);
}
static inline dns_adbnamehook_t *
@@ -1417,6 +1746,16 @@ new_adbentry(dns_adb_t *adb) {
e->expires = 0;
ISC_LIST_INIT(e->lameinfo);
ISC_LINK_INIT(e, plink);
+ LOCK(&adb->entriescntlock);
+ adb->entriescnt++;
+ if (!adb->growentries_sent &&
+ adb->entriescnt > (adb->nentries * 8)) {
+ isc_event_t *event = &adb->growentries;
+ inc_adb_irefcnt(adb);
+ isc_task_send(adb->task, &event);
+ adb->growentries_sent = ISC_TRUE;
+ }
+ UNLOCK(&adb->entriescntlock);
return (e);
}
@@ -1444,6 +1783,9 @@ free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) {
}
isc_mempool_put(adb->emp, e);
+ LOCK(&adb->entriescntlock);
+ adb->entriescnt--;
+ UNLOCK(&adb->entriescntlock);
}
static inline dns_adbfind_t *
@@ -1597,7 +1939,7 @@ find_name_and_lock(dns_adb_t *adb, dns_name_t *name,
dns_adbname_t *adbname;
int bucket;
- bucket = dns_name_fullhash(name, ISC_FALSE) % NBUCKETS;
+ bucket = dns_name_fullhash(name, ISC_FALSE) % adb->nnames;
if (*bucketp == DNS_ADB_INVALIDBUCKET) {
LOCK(&adb->namelocks[bucket]);
@@ -1639,7 +1981,7 @@ find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp,
dns_adbentry_t *entry, *entry_next;
int bucket;
- bucket = isc_sockaddr_hash(addr, ISC_TRUE) % NBUCKETS;
+ bucket = isc_sockaddr_hash(addr, ISC_TRUE) % adb->nentries;
if (*bucketp == DNS_ADB_INVALIDBUCKET) {
LOCK(&adb->entrylocks[bucket]);
@@ -1992,13 +2334,36 @@ destroy(dns_adb_t *adb) {
isc_mempool_destroy(&adb->aimp);
isc_mempool_destroy(&adb->afmp);
- DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS);
- DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS);
+ DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
+ isc_mem_put(adb->mctx, adb->entries,
+ sizeof(*adb->entries) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->deadentries,
+ sizeof(*adb->deadentries) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->entrylocks,
+ sizeof(*adb->entrylocks) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->entry_sd,
+ sizeof(*adb->entry_sd) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->entry_refcnt,
+ sizeof(*adb->entry_refcnt) * adb->nentries);
+
+ DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
+ isc_mem_put(adb->mctx, adb->names,
+ sizeof(*adb->names) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->deadnames,
+ sizeof(*adb->deadnames) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->namelocks,
+ sizeof(*adb->namelocks) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->name_sd,
+ sizeof(*adb->name_sd) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->name_refcnt,
+ sizeof(*adb->name_refcnt) * adb->nnames);
DESTROYLOCK(&adb->reflock);
DESTROYLOCK(&adb->lock);
DESTROYLOCK(&adb->mplock);
DESTROYLOCK(&adb->overmemlock);
+ DESTROYLOCK(&adb->entriescntlock);
+ DESTROYLOCK(&adb->namescntlock);
isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
}
@@ -2014,7 +2379,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
{
dns_adb_t *adb;
isc_result_t result;
- int i;
+ unsigned int i;
REQUIRE(mem != NULL);
REQUIRE(view != NULL);
@@ -2054,6 +2419,30 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb->shutting_down = ISC_FALSE;
ISC_LIST_INIT(adb->whenshutdown);
+ adb->nentries = nbuckets[0];
+ adb->entriescnt = 0;
+ adb->entries = NULL;
+ adb->deadentries = NULL;
+ adb->entry_sd = NULL;
+ adb->entry_refcnt = NULL;
+ adb->entrylocks = NULL;
+ ISC_EVENT_INIT(&adb->growentries, sizeof(adb->growentries), 0, NULL,
+ DNS_EVENT_ADBGROWENTRIES, grow_entries, adb,
+ adb, NULL, NULL);
+ adb->growentries_sent = ISC_FALSE;
+
+ adb->nnames = nbuckets[0];
+ adb->namescnt = 0;
+ adb->names = NULL;
+ adb->deadnames = NULL;
+ adb->name_sd = NULL;
+ adb->name_refcnt = NULL;
+ adb->namelocks = NULL;
+ ISC_EVENT_INIT(&adb->grownames, sizeof(adb->grownames), 0, NULL,
+ DNS_EVENT_ADBGROWNAMES, grow_names, adb,
+ adb, NULL, NULL);
+ adb->grownames_sent = ISC_FALSE;
+
isc_mem_attach(mem, &adb->mctx);
result = isc_mutex_init(&adb->lock);
@@ -2072,28 +2461,68 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
if (result != ISC_R_SUCCESS)
goto fail0e;
+ result = isc_mutex_init(&adb->entriescntlock);
+ if (result != ISC_R_SUCCESS)
+ goto fail0f;
+
+ result = isc_mutex_init(&adb->namescntlock);
+ if (result != ISC_R_SUCCESS)
+ goto fail0g;
+
+#define ALLOCENTRY(adb, el) \
+ do { \
+ (adb)->el = isc_mem_get((adb)->mctx, \
+ sizeof(*(adb)->el) * (adb)->nentries); \
+ if ((adb)->el == NULL) { \
+ result = ISC_R_NOMEMORY; \
+ goto fail1; \
+ }\
+ } while (0)
+ ALLOCENTRY(adb, entries);
+ ALLOCENTRY(adb, deadentries);
+ ALLOCENTRY(adb, entrylocks);
+ ALLOCENTRY(adb, entry_sd);
+ ALLOCENTRY(adb, entry_refcnt);
+#undef ALLOCENTRY
+
+#define ALLOCNAME(adb, el) \
+ do { \
+ (adb)->el = isc_mem_get((adb)->mctx, \
+ sizeof(*(adb)->el) * (adb)->nnames); \
+ if ((adb)->el == NULL) { \
+ result = ISC_R_NOMEMORY; \
+ goto fail1; \
+ }\
+ } while (0)
+ ALLOCNAME(adb, names);
+ ALLOCNAME(adb, deadnames);
+ ALLOCNAME(adb, namelocks);
+ ALLOCNAME(adb, name_sd);
+ ALLOCNAME(adb, name_refcnt);
+#undef ALLOCNAME
+
/*
* Initialize the bucket locks for names and elements.
* May as well initialize the list heads, too.
*/
- result = isc_mutexblock_init(adb->namelocks, NBUCKETS);
+ result = isc_mutexblock_init(adb->namelocks, adb->nnames);
if (result != ISC_R_SUCCESS)
goto fail1;
- for (i = 0; i < NBUCKETS; i++) {
+ for (i = 0; i < adb->nnames; i++) {
ISC_LIST_INIT(adb->names[i]);
ISC_LIST_INIT(adb->deadnames[i]);
adb->name_sd[i] = ISC_FALSE;
adb->name_refcnt[i] = 0;
adb->irefcnt++;
}
- for (i = 0; i < NBUCKETS; i++) {
+ for (i = 0; i < adb->nentries; i++) {
ISC_LIST_INIT(adb->entries[i]);
ISC_LIST_INIT(adb->deadentries[i]);
adb->entry_sd[i] = ISC_FALSE;
adb->entry_refcnt[i] = 0;
adb->irefcnt++;
}
- result = isc_mutexblock_init(adb->entrylocks, NBUCKETS);
+ result = isc_mutexblock_init(adb->entrylocks, adb->nentries);
if (result != ISC_R_SUCCESS)
goto fail2;
@@ -2140,12 +2569,42 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
isc_task_detach(&adb->task);
/* clean up entrylocks */
- DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS);
+ DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
fail2: /* clean up namelocks */
- DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS);
+ DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
fail1: /* clean up only allocated memory */
+ if (adb->entries != NULL)
+ isc_mem_put(adb->mctx, adb->entries,
+ sizeof(*adb->entries) * adb->nentries);
+ if (adb->deadentries != NULL)
+ isc_mem_put(adb->mctx, adb->deadentries,
+ sizeof(*adb->deadentries) * adb->nentries);
+ if (adb->entrylocks != NULL)
+ isc_mem_put(adb->mctx, adb->entrylocks,
+ sizeof(*adb->entrylocks) * adb->nentries);
+ if (adb->entry_sd != NULL)
+ isc_mem_put(adb->mctx, adb->entry_sd,
+ sizeof(*adb->entry_sd) * adb->nentries);
+ if (adb->entry_refcnt != NULL)
+ isc_mem_put(adb->mctx, adb->entry_refcnt,
+ sizeof(*adb->entry_refcnt) * adb->nentries);
+ if (adb->names != NULL)
+ isc_mem_put(adb->mctx, adb->names,
+ sizeof(*adb->names) * adb->nnames);
+ if (adb->deadnames != NULL)
+ isc_mem_put(adb->mctx, adb->deadnames,
+ sizeof(*adb->deadnames) * adb->nnames);
+ if (adb->namelocks != NULL)
+ isc_mem_put(adb->mctx, adb->namelocks,
+ sizeof(*adb->namelocks) * adb->nnames);
+ if (adb->name_sd != NULL)
+ isc_mem_put(adb->mctx, adb->name_sd,
+ sizeof(*adb->name_sd) * adb->nnames);
+ if (adb->name_refcnt != NULL)
+ isc_mem_put(adb->mctx, adb->name_refcnt,
+ sizeof(*adb->name_refcnt) * adb->nnames);
if (adb->nmp != NULL)
isc_mempool_destroy(&adb->nmp);
if (adb->nhmp != NULL)
@@ -2161,6 +2620,10 @@ 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->namescntlock);
+ fail0g:
+ DESTROYLOCK(&adb->entriescntlock);
+ fail0f:
DESTROYLOCK(&adb->overmemlock);
fail0e:
DESTROYLOCK(&adb->reflock);
@@ -2728,7 +3191,7 @@ dns_adb_cancelfind(dns_adbfind_t *find) {
void
dns_adb_dump(dns_adb_t *adb, FILE *f) {
- int i;
+ unsigned int i;
isc_stdtime_t now;
REQUIRE(DNS_ADB_VALID(adb));
@@ -2744,9 +3207,9 @@ dns_adb_dump(dns_adb_t *adb, FILE *f) {
LOCK(&adb->lock);
isc_stdtime_get(&now);
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nnames; i++)
RUNTIME_CHECK(cleanup_names(adb, i, now) == ISC_FALSE);
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nentries; i++)
RUNTIME_CHECK(cleanup_entries(adb, i, now) == ISC_FALSE);
dump_adb(adb, f, ISC_FALSE, now);
@@ -2762,7 +3225,7 @@ dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) {
static void
dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
- int i;
+ unsigned int i;
dns_adbname_t *name;
dns_adbentry_t *entry;
@@ -2772,15 +3235,15 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
adb, adb->erefcnt, adb->irefcnt,
isc_mempool_getallocated(adb->nhmp));
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nnames; i++)
LOCK(&adb->namelocks[i]);
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nentries; i++)
LOCK(&adb->entrylocks[i]);
/*
* Dump the names
*/
- for (i = 0; i < NBUCKETS; i++) {
+ for (i = 0; i < adb->nnames; i++) {
name = ISC_LIST_HEAD(adb->names[i]);
if (name == NULL)
continue;
@@ -2824,7 +3287,7 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
fprintf(f, ";\n; Unassociated entries\n;\n");
- for (i = 0; i < NBUCKETS; i++) {
+ for (i = 0; i < adb->nentries; i++) {
entry = ISC_LIST_HEAD(adb->entries[i]);
while (entry != NULL) {
if (entry->refcnt == 0)
@@ -2836,9 +3299,9 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
/*
* Unlock everything
*/
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nentries; i++)
UNLOCK(&adb->entrylocks[i]);
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nnames; i++)
UNLOCK(&adb->namelocks[i]);
}
@@ -2999,10 +3462,20 @@ dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype)
else
adbname->fetch6_err = FIND_ERR_UNEXPECTED;
- result = dns_view_find(adb->view, &adbname->name, rdtype, now,
- NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0,
- ISC_TF(NAME_HINTOK(adbname)),
- NULL, NULL, fname, &rdataset, NULL);
+ /*
+ * We need to specify whether to search static-stub zones (if
+ * configured) depending on whether this is a "start at zone" lookup,
+ * i.e., whether it's a "bailiwick" glue. If it's bailiwick (in which
+ * case NAME_STARTATZONE is set) we need to stop the search at any
+ * matching static-stub zone without looking into the cache to honor
+ * the configuration on which server we should send queries to.
+ */
+ result = dns_view_find2(adb->view, &adbname->name, rdtype, now,
+ NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0,
+ ISC_TF(NAME_HINTOK(adbname)),
+ (adbname->flags & NAME_STARTATZONE) != 0 ?
+ ISC_TRUE : ISC_FALSE,
+ NULL, NULL, fname, &rdataset, NULL);
/* XXXVIX this switch statement is too sparse to gen a jump table. */
switch (result) {
@@ -3557,9 +4030,9 @@ dns_adb_flush(dns_adb_t *adb) {
/*
* Call our cleanup routines.
*/
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nnames; i++)
RUNTIME_CHECK(cleanup_names(adb, i, INT_MAX) == ISC_FALSE);
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nentries; i++)
RUNTIME_CHECK(cleanup_entries(adb, i, INT_MAX) == ISC_FALSE);
#ifdef DUMP_ADB_AFTER_CLEANING
@@ -3578,7 +4051,7 @@ dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) {
INSIST(DNS_ADB_VALID(adb));
LOCK(&adb->lock);
- bucket = dns_name_hash(name, ISC_FALSE) % NBUCKETS;
+ bucket = dns_name_hash(name, ISC_FALSE) % adb->nnames;
LOCK(&adb->namelocks[bucket]);
adbname = ISC_LIST_HEAD(adb->names[bucket]);
while (adbname != NULL) {
OpenPOWER on IntegriCloud