Compare commits
3 Commits
stable
...
ondrej-fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e756358ef4 | ||
|
|
82c0d2033a | ||
|
|
dd6f70a334 |
311
lib/dns/adb.c
311
lib/dns/adb.c
@@ -95,6 +95,8 @@ typedef struct dns_adblameinfo dns_adblameinfo_t;
|
||||
typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
|
||||
typedef struct dns_adbfetch dns_adbfetch_t;
|
||||
typedef struct dns_adbfetch6 dns_adbfetch6_t;
|
||||
typedef ISC_LIST(dns_adbnamebucket_t) dns_adbnamebucketlist_t;
|
||||
typedef ISC_LIST(dns_adbentrybucket_t) dns_adbentrybucketlist_t;
|
||||
|
||||
/*% dns adb structure */
|
||||
struct dns_adb {
|
||||
@@ -110,9 +112,11 @@ struct dns_adb {
|
||||
|
||||
isc_refcount_t references;
|
||||
|
||||
dns_adbnamebucketlist_t namebuckets_lru;
|
||||
isc_ht_t *namebuckets;
|
||||
isc_rwlock_t names_lock;
|
||||
|
||||
dns_adbentrybucketlist_t entrybuckets_lru;
|
||||
isc_ht_t *entrybuckets;
|
||||
isc_rwlock_t entries_lock;
|
||||
|
||||
@@ -167,9 +171,9 @@ struct dns_adbname {
|
||||
*/
|
||||
struct dns_adbnamebucket {
|
||||
dns_adbnamelist_t names;
|
||||
dns_adbnamelist_t deadnames;
|
||||
isc_mutex_t lock;
|
||||
isc_refcount_t references;
|
||||
ISC_LINK(dns_adbnamebucket_t) link;
|
||||
};
|
||||
|
||||
/*%
|
||||
@@ -272,9 +276,9 @@ struct dns_adbentry {
|
||||
*/
|
||||
struct dns_adbentrybucket {
|
||||
dns_adbentrylist_t entries;
|
||||
dns_adbentrylist_t deadentries;
|
||||
isc_mutex_t lock;
|
||||
isc_refcount_t references;
|
||||
ISC_LINK(dns_adbentrybucket_t) link;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -311,7 +315,10 @@ new_adbfetch(dns_adb_t *);
|
||||
static void
|
||||
free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
|
||||
static void
|
||||
get_namebucket(dns_adb_t *, const dns_name_t *, dns_adbnamebucket_t **);
|
||||
purge_stale_names(dns_adb_t *adb, isc_stdtime_t now);
|
||||
static void
|
||||
get_namebucket(dns_adb_t *, const dns_name_t *, isc_stdtime_t now,
|
||||
dns_adbnamebucket_t **);
|
||||
static dns_adbname_t *
|
||||
get_name(dns_adbnamebucket_t *, const dns_name_t *, unsigned int);
|
||||
static void
|
||||
@@ -384,12 +391,6 @@ log_quota(dns_adbentry_t *entry, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
|
||||
#define NAME_GLUEOK(n) (((n)->flags & NAME_GLUE_OK) != 0)
|
||||
#define NAME_HINTOK(n) (((n)->flags & NAME_HINT_OK) != 0)
|
||||
|
||||
/*
|
||||
* Private flag(s) for entries.
|
||||
* MUST NOT overlap FCTX_ADDRINFO_xxx and DNS_FETCHOPT_NOEDNS0.
|
||||
*/
|
||||
#define ENTRY_IS_DEAD 0x00400000
|
||||
|
||||
/*
|
||||
* To the name, address classes are all that really exist. If it has a
|
||||
* V6 address it doesn't care if it came from a AAAA query.
|
||||
@@ -580,13 +581,7 @@ _entry_detach(dns_adbentry_t **entryp, const char *func, const char *file,
|
||||
#endif /* ADB_TRACE */
|
||||
|
||||
if (refs == 1) {
|
||||
/*
|
||||
* If the entry is linked to a bucket, we need to
|
||||
* unlink it before destroying it.
|
||||
*/
|
||||
if (ISC_LINK_LINKED(entry, plink)) {
|
||||
unlink_entry(entry);
|
||||
}
|
||||
unlink_entry(entry);
|
||||
free_adbentry(&entry);
|
||||
}
|
||||
}
|
||||
@@ -782,9 +777,6 @@ expire_name(dns_adbname_t **n, isc_eventtype_t evtype) {
|
||||
* we'll clean it up later.
|
||||
*/
|
||||
if (!NAME_DEAD(adbname)) {
|
||||
dns_adbnamebucket_t *nbucket = adbname->bucket;
|
||||
ISC_LIST_UNLINK(nbucket->names, adbname, plink);
|
||||
ISC_LIST_APPEND(nbucket->deadnames, adbname, plink);
|
||||
adbname->flags |= NAME_IS_DEAD;
|
||||
}
|
||||
}
|
||||
@@ -866,11 +858,7 @@ unlink_name(dns_adbname_t *name) {
|
||||
|
||||
REQUIRE(nbucket != NULL);
|
||||
|
||||
if (NAME_DEAD(name)) {
|
||||
ISC_LIST_UNLINK(nbucket->deadnames, name, plink);
|
||||
} else {
|
||||
ISC_LIST_UNLINK(nbucket->names, name, plink);
|
||||
}
|
||||
ISC_LIST_UNLINK(nbucket->names, name, plink);
|
||||
|
||||
isc_refcount_decrement(&nbucket->references);
|
||||
}
|
||||
@@ -885,40 +873,6 @@ link_entry(dns_adbentrybucket_t *ebucket, dns_adbentry_t *entry) {
|
||||
|
||||
DP(DEF_LEVEL, "link ADB entry %p to bucket %p", entry, ebucket);
|
||||
|
||||
/*
|
||||
* If we're in the overmem condition, take this opportunity to
|
||||
* clean up the least-recently used entries in the bucket.
|
||||
*/
|
||||
if (isc_mem_isovermem(entry->adb->mctx)) {
|
||||
int i;
|
||||
|
||||
DP(ISC_LOG_DEBUG(1), "adb: overmem, cleaning bucket %p",
|
||||
ebucket);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
dns_adbentry_t *e = ISC_LIST_TAIL(ebucket->entries);
|
||||
if (e == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the only reference to an entry is from
|
||||
* the bucket itself, we can kill it. Otherwise
|
||||
* we move it to deadentries and kill it later.
|
||||
*/
|
||||
if (isc_refcount_current(&e->references) == 1) {
|
||||
unlink_entry(e);
|
||||
entry_detach(&e);
|
||||
continue;
|
||||
}
|
||||
|
||||
INSIST((e->flags & ENTRY_IS_DEAD) == 0);
|
||||
e->flags |= ENTRY_IS_DEAD;
|
||||
ISC_LIST_UNLINK(ebucket->entries, e, plink);
|
||||
ISC_LIST_PREPEND(ebucket->deadentries, e, plink);
|
||||
}
|
||||
}
|
||||
|
||||
entry->bucket = ebucket;
|
||||
ISC_LIST_PREPEND(ebucket->entries, entry, plink);
|
||||
isc_refcount_increment0(&ebucket->references);
|
||||
@@ -941,31 +895,20 @@ unlink_entry(dns_adbentry_t *entry) {
|
||||
|
||||
DP(DEF_LEVEL, "unlink ADB entry %p from bucket %p", entry, ebucket);
|
||||
|
||||
if ((entry->flags & ENTRY_IS_DEAD) != 0) {
|
||||
ISC_LIST_UNLINK(ebucket->deadentries, entry, plink);
|
||||
} else {
|
||||
ISC_LIST_UNLINK(ebucket->entries, entry, plink);
|
||||
}
|
||||
ISC_LIST_UNLINK(ebucket->entries, entry, plink);
|
||||
|
||||
isc_refcount_decrement(&ebucket->references);
|
||||
}
|
||||
|
||||
static void
|
||||
shutdown_names(dns_adb_t *adb) {
|
||||
isc_result_t result;
|
||||
isc_ht_iter_t *it = NULL;
|
||||
dns_adbnamebucket_t *nbucket = NULL;
|
||||
|
||||
RWLOCK(&adb->names_lock, isc_rwlocktype_read);
|
||||
isc_ht_iter_create(adb->namebuckets, &it);
|
||||
for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS;
|
||||
result = isc_ht_iter_next(it))
|
||||
for (nbucket = ISC_LIST_HEAD(adb->namebuckets_lru); nbucket != NULL;
|
||||
nbucket = ISC_LIST_NEXT(nbucket, link))
|
||||
{
|
||||
dns_adbnamebucket_t *nbucket = NULL;
|
||||
dns_adbname_t *name = NULL;
|
||||
dns_adbname_t *next_name = NULL;
|
||||
|
||||
isc_ht_iter_current(it, (void **)&nbucket);
|
||||
INSIST(nbucket != NULL);
|
||||
|
||||
LOCK(&nbucket->lock);
|
||||
/*
|
||||
@@ -976,56 +919,36 @@ shutdown_names(dns_adb_t *adb) {
|
||||
*/
|
||||
name = ISC_LIST_HEAD(nbucket->names);
|
||||
while (name != NULL) {
|
||||
next_name = ISC_LIST_NEXT(name, plink);
|
||||
dns_adbname_t *next_name = ISC_LIST_NEXT(name, plink);
|
||||
expire_name(&name, DNS_EVENT_ADBSHUTDOWN);
|
||||
name = next_name;
|
||||
}
|
||||
|
||||
UNLOCK(&nbucket->lock);
|
||||
}
|
||||
|
||||
isc_ht_iter_destroy(&it);
|
||||
RWUNLOCK(&adb->names_lock, isc_rwlocktype_read);
|
||||
}
|
||||
|
||||
static void
|
||||
shutdown_entries(dns_adb_t *adb) {
|
||||
isc_result_t result;
|
||||
isc_ht_iter_t *iter = NULL;
|
||||
dns_adbentrybucket_t *ebucket = NULL;
|
||||
|
||||
RWLOCK(&adb->entries_lock, isc_rwlocktype_read);
|
||||
isc_ht_iter_create(adb->entrybuckets, &iter);
|
||||
for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS;
|
||||
result = isc_ht_iter_next(iter))
|
||||
for (ebucket = ISC_LIST_HEAD(adb->entrybuckets_lru); ebucket != NULL;
|
||||
ebucket = ISC_LIST_NEXT(ebucket, link))
|
||||
{
|
||||
dns_adbentrybucket_t *ebucket = NULL;
|
||||
dns_adbentry_t *entry = NULL;
|
||||
dns_adbentry_t *next_entry = NULL;
|
||||
|
||||
isc_ht_iter_current(iter, (void **)&ebucket);
|
||||
INSIST(ebucket != NULL);
|
||||
|
||||
LOCK(&ebucket->lock);
|
||||
entry = ISC_LIST_HEAD(ebucket->entries);
|
||||
while (entry != NULL) {
|
||||
/*
|
||||
* Run through the list and clean up any
|
||||
* entries not in use.
|
||||
*/
|
||||
for (entry = ISC_LIST_HEAD(ebucket->entries); entry != NULL;
|
||||
entry = next_entry) {
|
||||
next_entry = ISC_LIST_NEXT(entry, plink);
|
||||
if (isc_refcount_current(&entry->references) == 1 &&
|
||||
entry->expires == 0) {
|
||||
unlink_entry(entry);
|
||||
}
|
||||
entry_detach(&entry);
|
||||
entry = next_entry;
|
||||
}
|
||||
|
||||
UNLOCK(&ebucket->lock);
|
||||
}
|
||||
RWUNLOCK(&adb->entries_lock, isc_rwlocktype_read);
|
||||
|
||||
isc_ht_iter_destroy(&iter);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1033,7 +956,6 @@ shutdown_entries(dns_adb_t *adb) {
|
||||
*/
|
||||
static void
|
||||
clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
|
||||
dns_adbentrybucket_t *ebucket = NULL;
|
||||
dns_adbnamehook_t *namehook = NULL;
|
||||
|
||||
namehook = ISC_LIST_HEAD(*namehooks);
|
||||
@@ -1044,27 +966,17 @@ clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
|
||||
* Clean up the entry if needed.
|
||||
*/
|
||||
if (namehook->entry != NULL) {
|
||||
dns_adbentrybucket_t *ebucket = NULL;
|
||||
|
||||
INSIST(DNS_ADBENTRY_VALID(namehook->entry));
|
||||
|
||||
/*
|
||||
* If entry bucket for the next address is
|
||||
* different from the previous one, then
|
||||
* unlock the old one, lock the new one, and
|
||||
* carry on. (This way we don't necessarily
|
||||
* have to lock and unlock for every list
|
||||
* member.)
|
||||
*/
|
||||
if (ebucket != namehook->entry->bucket) {
|
||||
if (ebucket != NULL) {
|
||||
UNLOCK(&ebucket->lock);
|
||||
}
|
||||
ebucket = namehook->entry->bucket;
|
||||
INSIST(ebucket != NULL);
|
||||
LOCK(&ebucket->lock);
|
||||
}
|
||||
ebucket = namehook->entry->bucket;
|
||||
INSIST(ebucket != NULL);
|
||||
|
||||
LOCK(&ebucket->lock);
|
||||
namehook->entry->nh--;
|
||||
entry_detach(&namehook->entry);
|
||||
UNLOCK(&ebucket->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1075,10 +987,6 @@ clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
|
||||
|
||||
namehook = ISC_LIST_HEAD(*namehooks);
|
||||
}
|
||||
|
||||
if (ebucket != NULL) {
|
||||
UNLOCK(&ebucket->lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1325,7 +1233,7 @@ new_adbnamebucket(dns_adb_t *adb) {
|
||||
};
|
||||
|
||||
ISC_LIST_INIT(nbucket->names);
|
||||
ISC_LIST_INIT(nbucket->deadnames);
|
||||
ISC_LINK_INIT(nbucket, link);
|
||||
|
||||
isc_mutex_init(&nbucket->lock);
|
||||
isc_refcount_init(&nbucket->references, 0);
|
||||
@@ -1466,7 +1374,7 @@ new_adbentrybucket(dns_adb_t *adb) {
|
||||
};
|
||||
|
||||
ISC_LIST_INIT(ebucket->entries);
|
||||
ISC_LIST_INIT(ebucket->deadentries);
|
||||
ISC_LINK_INIT(ebucket, link);
|
||||
|
||||
isc_mutex_init(&ebucket->lock);
|
||||
isc_refcount_init(&ebucket->references, 0);
|
||||
@@ -1598,7 +1506,7 @@ free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {
|
||||
* Search for the name bucket in the hash table.
|
||||
*/
|
||||
static void
|
||||
get_namebucket(dns_adb_t *adb, const dns_name_t *name,
|
||||
get_namebucket(dns_adb_t *adb, const dns_name_t *name, isc_stdtime_t now,
|
||||
dns_adbnamebucket_t **nbucketp) {
|
||||
isc_result_t result;
|
||||
dns_adbnamebucket_t *nbucket = NULL;
|
||||
@@ -1606,6 +1514,11 @@ get_namebucket(dns_adb_t *adb, const dns_name_t *name,
|
||||
REQUIRE(nbucketp != NULL && *nbucketp == NULL);
|
||||
|
||||
RWLOCK(&adb->names_lock, isc_rwlocktype_write);
|
||||
/*
|
||||
* First, see if there are stale names at the
|
||||
* end of the list, and purge them if so.
|
||||
*/
|
||||
purge_stale_names(adb, now);
|
||||
result = isc_ht_find(adb->namebuckets, name->ndata, name->length,
|
||||
(void **)&nbucket);
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
@@ -1615,7 +1528,10 @@ get_namebucket(dns_adb_t *adb, const dns_name_t *name,
|
||||
nbucket = new_adbnamebucket(adb);
|
||||
result = isc_ht_add(adb->namebuckets, name->ndata, name->length,
|
||||
nbucket);
|
||||
} else {
|
||||
ISC_LIST_UNLINK(adb->namebuckets_lru, nbucket, link);
|
||||
}
|
||||
ISC_LIST_PREPEND(adb->namebuckets_lru, nbucket, link);
|
||||
RWUNLOCK(&adb->names_lock, isc_rwlocktype_write);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
|
||||
@@ -1666,7 +1582,10 @@ get_entrybucket(dns_adb_t *adb, const isc_sockaddr_t *addr,
|
||||
result = isc_ht_add(adb->entrybuckets,
|
||||
(const unsigned char *)addr, sizeof(*addr),
|
||||
ebucket);
|
||||
} else {
|
||||
ISC_LIST_UNLINK(adb->entrybuckets_lru, ebucket, link);
|
||||
}
|
||||
ISC_LIST_PREPEND(adb->entrybuckets_lru, ebucket, link);
|
||||
RWUNLOCK(&adb->entries_lock, isc_rwlocktype_write);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
|
||||
@@ -1884,55 +1803,58 @@ maybe_expire_name(dns_adbname_t **namep, isc_stdtime_t now) {
|
||||
* is in the overmem condition, the tail and the next to tail entries
|
||||
* will be unconditionally removed (unless they have an outstanding fetch).
|
||||
* We don't care about a race on 'overmem' at the risk of causing some
|
||||
* collateral damage or a small delay in starting cleanup, so we don't bother
|
||||
* to lock ADB (if it's not locked).
|
||||
* collateral damage or a small delay in starting cleanup.
|
||||
*
|
||||
* Name bucket must be locked; adb may be locked; no other locks held.
|
||||
* adb->names_lock MUST be write locked
|
||||
*/
|
||||
static void
|
||||
purge_stale_names(dns_adb_t *adb, dns_adbnamebucket_t *nbucket,
|
||||
isc_stdtime_t now) {
|
||||
dns_adbname_t *adbname = NULL, *next_adbname = NULL;
|
||||
purge_stale_names(dns_adb_t *adb, isc_stdtime_t now) {
|
||||
dns_adbnamebucket_t *nbucket = NULL;
|
||||
bool overmem = isc_mem_isovermem(adb->mctx);
|
||||
int max_removed = overmem ? 2 : 1;
|
||||
int scans = 0, removed = 0;
|
||||
|
||||
REQUIRE(nbucket != NULL);
|
||||
|
||||
/*
|
||||
* We limit the number of scanned entries to 10 (arbitrary choice)
|
||||
* in order to avoid examining too many entries when there are many
|
||||
* tail entries that have fetches (this should be rare, but could
|
||||
* happen).
|
||||
*/
|
||||
for (adbname = ISC_LIST_TAIL(nbucket->names);
|
||||
adbname != NULL && removed < max_removed && scans < 10;
|
||||
adbname = next_adbname)
|
||||
{
|
||||
INSIST(!NAME_DEAD(adbname));
|
||||
|
||||
next_adbname = ISC_LIST_PREV(adbname, plink);
|
||||
for (nbucket = ISC_LIST_TAIL(adb->namebuckets_lru);
|
||||
nbucket != NULL && removed < max_removed && scans < 10;
|
||||
nbucket = ISC_LIST_PREV(nbucket, link))
|
||||
{
|
||||
dns_adbname_t *adbname = NULL;
|
||||
dns_adbname_t *next_adbname = NULL;
|
||||
|
||||
LOCK(&nbucket->lock);
|
||||
|
||||
scans++;
|
||||
|
||||
/*
|
||||
* Remove the name if it's expired or unused, has no
|
||||
* address data, and there are no active fetches.
|
||||
*/
|
||||
maybe_expire_name(&adbname, now);
|
||||
if (adbname == NULL) {
|
||||
removed++;
|
||||
if (overmem) {
|
||||
for (adbname = ISC_LIST_HEAD(nbucket->names); adbname != NULL;
|
||||
adbname = next_adbname)
|
||||
{
|
||||
next_adbname = ISC_LIST_PREV(adbname, plink);
|
||||
|
||||
/*
|
||||
* Remove the name if it's expired or unused,
|
||||
* has no address data.
|
||||
*/
|
||||
maybe_expire_namehooks(adbname, now);
|
||||
maybe_expire_name(&adbname, now);
|
||||
if (adbname == NULL) {
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!NAME_FETCH(adbname) &&
|
||||
(overmem || adbname->last_used + ADB_STALE_MARGIN <= now))
|
||||
{
|
||||
expire_name(&adbname, DNS_EVENT_ADBCANCELED);
|
||||
removed++;
|
||||
if (overmem ||
|
||||
adbname->last_used + ADB_STALE_MARGIN <= now) {
|
||||
expire_name(&adbname, DNS_EVENT_ADBCANCELED);
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
UNLOCK(&nbucket->lock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1961,7 +1883,6 @@ maybe_expire_entry(dns_adbentry_t **entryp, isc_stdtime_t now) {
|
||||
*entryp = NULL;
|
||||
DP(DEF_LEVEL, "killing entry %p", entry);
|
||||
INSIST(ISC_LINK_LINKED(entry, plink));
|
||||
unlink_entry(entry);
|
||||
entry_detach(&entry);
|
||||
}
|
||||
|
||||
@@ -2014,31 +1935,23 @@ cleanup_entries(dns_adbentrybucket_t *ebucket, isc_stdtime_t now) {
|
||||
|
||||
static void
|
||||
clean_hashes(dns_adb_t *adb, isc_stdtime_t now) {
|
||||
isc_result_t result;
|
||||
isc_ht_iter_t *it = NULL;
|
||||
dns_adbnamebucket_t *nbucket = NULL;
|
||||
dns_adbentrybucket_t *ebucket = NULL;
|
||||
|
||||
RWLOCK(&adb->names_lock, isc_rwlocktype_read);
|
||||
isc_ht_iter_create(adb->namebuckets, &it);
|
||||
for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS;
|
||||
result = isc_ht_iter_next(it))
|
||||
for (nbucket = ISC_LIST_HEAD(adb->namebuckets_lru); nbucket != NULL;
|
||||
nbucket = ISC_LIST_NEXT(nbucket, link))
|
||||
{
|
||||
dns_adbnamebucket_t *nbucket = NULL;
|
||||
isc_ht_iter_current(it, (void **)&nbucket);
|
||||
cleanup_names(nbucket, now);
|
||||
}
|
||||
isc_ht_iter_destroy(&it);
|
||||
RWUNLOCK(&adb->names_lock, isc_rwlocktype_read);
|
||||
|
||||
RWLOCK(&adb->entries_lock, isc_rwlocktype_read);
|
||||
isc_ht_iter_create(adb->entrybuckets, &it);
|
||||
for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS;
|
||||
result = isc_ht_iter_next(it))
|
||||
for (ebucket = ISC_LIST_HEAD(adb->entrybuckets_lru); ebucket != NULL;
|
||||
ebucket = ISC_LIST_NEXT(ebucket, link))
|
||||
{
|
||||
dns_adbentrybucket_t *ebucket = NULL;
|
||||
isc_ht_iter_current(it, (void **)&ebucket);
|
||||
cleanup_entries(ebucket, now);
|
||||
}
|
||||
isc_ht_iter_destroy(&it);
|
||||
RWUNLOCK(&adb->entries_lock, isc_rwlocktype_read);
|
||||
}
|
||||
|
||||
@@ -2061,6 +1974,7 @@ destroy(dns_adb_t *adb) {
|
||||
cleanup_names(nbucket, INT_MAX);
|
||||
isc_mutex_destroy(&nbucket->lock);
|
||||
isc_refcount_destroy(&nbucket->references);
|
||||
ISC_LIST_UNLINK(adb->namebuckets_lru, nbucket, link);
|
||||
isc_mem_put(adb->mctx, nbucket, sizeof(*nbucket));
|
||||
}
|
||||
isc_ht_iter_destroy(&it);
|
||||
@@ -2078,6 +1992,7 @@ destroy(dns_adb_t *adb) {
|
||||
cleanup_entries(ebucket, INT_MAX);
|
||||
isc_mutex_destroy(&ebucket->lock);
|
||||
isc_refcount_destroy(&ebucket->references);
|
||||
ISC_LIST_UNLINK(adb->entrybuckets_lru, ebucket, link);
|
||||
isc_mem_put(adb->mctx, ebucket, sizeof(*ebucket));
|
||||
}
|
||||
isc_ht_iter_destroy(&it);
|
||||
@@ -2124,9 +2039,11 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_taskmgr_t *taskmgr,
|
||||
dns_resolver_attach(view->resolver, &adb->res);
|
||||
isc_mem_attach(mem, &adb->mctx);
|
||||
|
||||
ISC_LIST_INIT(adb->namebuckets_lru);
|
||||
isc_ht_init(&adb->namebuckets, adb->mctx, 1, ISC_HT_CASE_INSENSITIVE);
|
||||
isc_rwlock_init(&adb->names_lock, 0, 0);
|
||||
|
||||
ISC_LIST_INIT(adb->entrybuckets_lru);
|
||||
isc_ht_init(&adb->entrybuckets, adb->mctx, 1, ISC_HT_CASE_SENSITIVE);
|
||||
isc_rwlock_init(&adb->entries_lock, 0, 0);
|
||||
|
||||
@@ -2166,9 +2083,11 @@ free_lock:
|
||||
|
||||
isc_rwlock_destroy(&adb->entries_lock);
|
||||
isc_ht_destroy(&adb->entrybuckets);
|
||||
INSIST(ISC_LIST_EMPTY(adb->entrybuckets_lru));
|
||||
|
||||
isc_rwlock_destroy(&adb->names_lock);
|
||||
isc_ht_destroy(&adb->namebuckets);
|
||||
INSIST(ISC_LIST_EMPTY(adb->namebuckets_lru));
|
||||
|
||||
dns_resolver_detach(&adb->res);
|
||||
dns_view_weakdetach(&adb->view);
|
||||
@@ -2316,17 +2235,15 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
/*
|
||||
* Try to see if we know anything about this name at all.
|
||||
*/
|
||||
get_namebucket(adb, name, &nbucket);
|
||||
get_namebucket(adb, name, now, &nbucket);
|
||||
INSIST(nbucket != NULL);
|
||||
LOCK(&nbucket->lock);
|
||||
adbname = get_name(nbucket, name, find->options);
|
||||
if (adbname == NULL) {
|
||||
/*
|
||||
* Nothing found. Allocate a new adbname structure for
|
||||
* this name. First, see if there are stale names at the
|
||||
* end of the list, and purge them if so.
|
||||
* this name.
|
||||
*/
|
||||
purge_stale_names(adb, nbucket, now);
|
||||
|
||||
adbname = new_adbname(adb, name);
|
||||
link_name(nbucket, adbname);
|
||||
@@ -2726,8 +2643,8 @@ 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, bool debug, isc_stdtime_t now) {
|
||||
isc_result_t result;
|
||||
isc_ht_iter_t *it = NULL;
|
||||
dns_adbnamebucket_t *nbucket = NULL;
|
||||
dns_adbentrybucket_t *ebucket = NULL;
|
||||
|
||||
fprintf(f, ";\n; Address database dump\n;\n");
|
||||
fprintf(f, "; [edns success/timeout]\n");
|
||||
@@ -2741,15 +2658,11 @@ dump_adb(dns_adb_t *adb, FILE *f, bool debug, isc_stdtime_t now) {
|
||||
* Ensure this operation is applied to both hash tables at once.
|
||||
*/
|
||||
RWLOCK(&adb->names_lock, isc_rwlocktype_read);
|
||||
|
||||
isc_ht_iter_create(adb->namebuckets, &it);
|
||||
for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS;
|
||||
result = isc_ht_iter_next(it))
|
||||
for (nbucket = ISC_LIST_HEAD(adb->namebuckets_lru); nbucket != NULL;
|
||||
nbucket = ISC_LIST_NEXT(nbucket, link))
|
||||
{
|
||||
dns_adbnamebucket_t *nbucket = NULL;
|
||||
dns_adbname_t *name = NULL;
|
||||
|
||||
isc_ht_iter_current(it, (void **)&nbucket);
|
||||
LOCK(&nbucket->lock);
|
||||
if (debug) {
|
||||
static int n = 0;
|
||||
@@ -2796,20 +2709,16 @@ dump_adb(dns_adb_t *adb, FILE *f, bool debug, isc_stdtime_t now) {
|
||||
}
|
||||
UNLOCK(&nbucket->lock);
|
||||
}
|
||||
isc_ht_iter_destroy(&it);
|
||||
RWUNLOCK(&adb->names_lock, isc_rwlocktype_read);
|
||||
|
||||
fprintf(f, ";\n; Unassociated entries\n;\n");
|
||||
|
||||
RWLOCK(&adb->entries_lock, isc_rwlocktype_read);
|
||||
isc_ht_iter_create(adb->entrybuckets, &it);
|
||||
for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS;
|
||||
result = isc_ht_iter_next(it))
|
||||
for (ebucket = ISC_LIST_HEAD(adb->entrybuckets_lru); ebucket != NULL;
|
||||
ebucket = ISC_LIST_NEXT(ebucket, link))
|
||||
{
|
||||
dns_adbentrybucket_t *ebucket = NULL;
|
||||
dns_adbentry_t *entry = NULL;
|
||||
|
||||
isc_ht_iter_current(it, (void **)&ebucket);
|
||||
LOCK(&ebucket->lock);
|
||||
|
||||
for (entry = ISC_LIST_HEAD(ebucket->entries); entry != NULL;
|
||||
@@ -2821,8 +2730,6 @@ dump_adb(dns_adb_t *adb, FILE *f, bool debug, isc_stdtime_t now) {
|
||||
}
|
||||
UNLOCK(&ebucket->lock);
|
||||
}
|
||||
isc_ht_iter_destroy(&it);
|
||||
|
||||
RWUNLOCK(&adb->entries_lock, isc_rwlocktype_read);
|
||||
}
|
||||
|
||||
@@ -2993,20 +2900,16 @@ putstr(isc_buffer_t **b, const char *str) {
|
||||
|
||||
isc_result_t
|
||||
dns_adb_dumpquota(dns_adb_t *adb, isc_buffer_t **buf) {
|
||||
isc_result_t result;
|
||||
isc_ht_iter_t *it = NULL;
|
||||
dns_adbentrybucket_t *ebucket = NULL;
|
||||
|
||||
REQUIRE(DNS_ADB_VALID(adb));
|
||||
|
||||
RWLOCK(&adb->entries_lock, isc_rwlocktype_read);
|
||||
isc_ht_iter_create(adb->entrybuckets, &it);
|
||||
for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS;
|
||||
result = isc_ht_iter_next(it))
|
||||
for (ebucket = ISC_LIST_HEAD(adb->entrybuckets_lru); ebucket != NULL;
|
||||
ebucket = ISC_LIST_NEXT(ebucket, link))
|
||||
{
|
||||
dns_adbentrybucket_t *ebucket = NULL;
|
||||
dns_adbentry_t *entry = NULL;
|
||||
|
||||
isc_ht_iter_current(it, (void **)&ebucket);
|
||||
LOCK(&ebucket->lock);
|
||||
for (entry = ISC_LIST_HEAD(ebucket->entries); entry != NULL;
|
||||
entry = ISC_LIST_NEXT(entry, plink))
|
||||
@@ -3031,12 +2934,8 @@ dns_adb_dumpquota(dns_adb_t *adb, isc_buffer_t **buf) {
|
||||
UNLOCK(&ebucket->lock);
|
||||
}
|
||||
RWUNLOCK(&adb->entries_lock, isc_rwlocktype_read);
|
||||
isc_ht_iter_destroy(&it);
|
||||
|
||||
if (result == ISC_R_NOMORE) {
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
return (result);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
@@ -3556,9 +3455,6 @@ dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int bits,
|
||||
REQUIRE(DNS_ADB_VALID(adb));
|
||||
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
||||
|
||||
REQUIRE((bits & ENTRY_IS_DEAD) == 0);
|
||||
REQUIRE((mask & ENTRY_IS_DEAD) == 0);
|
||||
|
||||
ebucket = addr->entry->bucket;
|
||||
LOCK(&ebucket->lock);
|
||||
|
||||
@@ -3942,8 +3838,7 @@ dns_adb_flushname(dns_adb_t *adb, const dns_name_t *name) {
|
||||
|
||||
void
|
||||
dns_adb_flushnames(dns_adb_t *adb, const dns_name_t *name) {
|
||||
isc_result_t result;
|
||||
isc_ht_iter_t *iter = NULL;
|
||||
dns_adbnamebucket_t *nbucket = NULL;
|
||||
|
||||
REQUIRE(DNS_ADB_VALID(adb));
|
||||
REQUIRE(name != NULL);
|
||||
@@ -3953,14 +3848,11 @@ dns_adb_flushnames(dns_adb_t *adb, const dns_name_t *name) {
|
||||
}
|
||||
|
||||
RWLOCK(&adb->names_lock, isc_rwlocktype_read);
|
||||
isc_ht_iter_create(adb->namebuckets, &iter);
|
||||
for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS;
|
||||
result = isc_ht_iter_next(iter))
|
||||
for (nbucket = ISC_LIST_HEAD(adb->namebuckets_lru); nbucket != NULL;
|
||||
nbucket = ISC_LIST_NEXT(nbucket, link))
|
||||
{
|
||||
dns_adbnamebucket_t *nbucket = NULL;
|
||||
dns_adbname_t *adbname = NULL, *nextname = NULL;
|
||||
|
||||
isc_ht_iter_current(iter, (void **)&nbucket);
|
||||
LOCK(&nbucket->lock);
|
||||
adbname = ISC_LIST_HEAD(nbucket->names);
|
||||
while (adbname != NULL) {
|
||||
@@ -3973,7 +3865,6 @@ dns_adb_flushnames(dns_adb_t *adb, const dns_name_t *name) {
|
||||
}
|
||||
UNLOCK(&nbucket->lock);
|
||||
}
|
||||
isc_ht_iter_destroy(&iter);
|
||||
RWUNLOCK(&adb->names_lock, isc_rwlocktype_read);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user