summaryrefslogtreecommitdiff
path: root/lib/dns/rbtdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/rbtdb.c')
-rw-r--r--lib/dns/rbtdb.c127
1 files changed, 66 insertions, 61 deletions
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index d5b5b5c8194f8..f841ebea5e943 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbtdb.c,v 1.270.12.6.10.2 2009/12/31 21:44:36 each Exp $ */
+/* $Id: rbtdb.c,v 1.270.12.16 2009/12/30 08:34:30 jinmei Exp $ */
/*! \file */
@@ -258,21 +258,8 @@ typedef struct rdatasetheader {
dns_rbtnode_t *node;
isc_stdtime_t last_used;
- ISC_LINK(struct rdatasetheader) lru_link;
- /*%<
- * Used for LRU-based cache management. We should probably make
- * these cache-DB specific. We might also make it a pointer and
- * ensure only the top header has a valid link to save memory.
- * The linked-list is locked by the rbtdb->lrulock.
- */
+ ISC_LINK(struct rdatasetheader) link;
- /*
- * It's possible this should not be here anymore, but instead
- * referenced from the bucket's heap directly.
- */
-#if 0
- isc_heap_t *heap;
-#endif
unsigned int heap_index;
/*%<
* Used for TTL-based cache cleaning.
@@ -396,7 +383,7 @@ typedef struct rbtdb_version {
isc_uint8_t flags;
isc_uint16_t iterations;
isc_uint8_t salt_length;
- unsigned char salt[NSEC3_MAX_HASH_LENGTH];
+ unsigned char salt[DNS_NSEC3_SALTSIZE];
} rbtdb_version_t;
typedef ISC_LIST(rbtdb_version_t) rbtdb_versionlist_t;
@@ -1227,7 +1214,7 @@ free_noqname(isc_mem_t *mctx, struct noqname **noqname) {
static inline void
init_rdataset(dns_rbtdb_t *rbtdb, rdatasetheader_t *h)
{
- ISC_LINK_INIT(h, lru_link);
+ ISC_LINK_INIT(h, link);
h->heap_index = 0;
#if TRACE_HEADER
@@ -1267,8 +1254,10 @@ free_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *rdataset)
}
idx = rdataset->node->locknum;
- if (ISC_LINK_LINKED(rdataset, lru_link))
- ISC_LIST_UNLINK(rbtdb->rdatasets[idx], rdataset, lru_link);
+ if (ISC_LINK_LINKED(rdataset, link)) {
+ INSIST(IS_CACHE(rbtdb));
+ ISC_LIST_UNLINK(rbtdb->rdatasets[idx], rdataset, link);
+ }
if (rdataset->heap_index != 0)
isc_heap_delete(rbtdb->heaps[idx], rdataset->heap_index);
rdataset->heap_index = 0;
@@ -2075,8 +2064,6 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version,
continue;
#endif
- INSIST(nsec3param.salt_length <=
- sizeof(version->salt));
memcpy(version->salt, nsec3param.salt,
nsec3param.salt_length);
version->hash = nsec3param.hash;
@@ -2284,17 +2271,18 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
for (header = HEAD(resigned_list);
header != NULL;
header = HEAD(resigned_list)) {
- ISC_LIST_UNLINK(resigned_list, header, lru_link);
- if (rollback) {
- nodelock_t *lock;
- lock = &rbtdb->node_locks[header->node->locknum].lock;
- NODE_LOCK(lock, isc_rwlocktype_write);
+ nodelock_t *lock;
+
+ ISC_LIST_UNLINK(resigned_list, header, link);
+
+ lock = &rbtdb->node_locks[header->node->locknum].lock;
+ NODE_LOCK(lock, isc_rwlocktype_write);
+ if (rollback)
resign_insert(rbtdb, header->node->locknum, header);
- NODE_UNLOCK(lock, isc_rwlocktype_write);
- }
decrement_reference(rbtdb, header->node, least_serial,
isc_rwlocktype_write, isc_rwlocktype_none,
ISC_FALSE);
+ NODE_UNLOCK(lock, isc_rwlocktype_write);
}
if (!EMPTY(cleanup_list)) {
@@ -3524,11 +3512,17 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
/*
* The node may be a zone cut itself. If it might be one,
* make sure we check for it later.
+ *
+ * DS records live above the zone cut in ordinary zone so
+ * we want to ignore any referral.
+ *
+ * Stub zones don't have anything "above" the delgation so
+ * we always return a referral.
*/
if (node->find_callback &&
- (node != search.rbtdb->origin_node ||
- IS_STUB(search.rbtdb)) &&
- !dns_rdatatype_atparent(type))
+ ((node != search.rbtdb->origin_node &&
+ !dns_rdatatype_atparent(type)) ||
+ IS_STUB(search.rbtdb)))
maybe_zonecut = ISC_TRUE;
}
@@ -3546,8 +3540,8 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* We now go looking for rdata...
*/
- NODE_LOCK(&(search.rbtdb->node_locks[node->locknum].lock),
- isc_rwlocktype_read);
+ lock = &search.rbtdb->node_locks[node->locknum].lock;
+ NODE_LOCK(lock, isc_rwlocktype_read);
found = NULL;
foundsig = NULL;
@@ -3625,8 +3619,10 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* we are using behave as if it isn't here.
*/
if (header->type == dns_rdatatype_nsec3 &&
- !matchparams(header, &search))
+ !matchparams(header, &search)) {
+ NODE_UNLOCK(lock, isc_rwlocktype_read);
goto partial_match;
+ }
/*
* If we found a type we were looking for,
* remember it.
@@ -3705,7 +3701,6 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* we really have a partial match.
*/
if (!wild) {
- lock = &search.rbtdb->node_locks[node->locknum].lock;
NODE_UNLOCK(lock, isc_rwlocktype_read);
goto partial_match;
}
@@ -3722,7 +3717,6 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
*
* Return the delegation.
*/
- lock = &search.rbtdb->node_locks[node->locknum].lock;
NODE_UNLOCK(lock, isc_rwlocktype_read);
result = setup_delegation(&search, nodep, foundname,
rdataset, sigrdataset);
@@ -3744,7 +3738,6 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
goto node_exit;
}
- lock = &search.rbtdb->node_locks[node->locknum].lock;
NODE_UNLOCK(lock, isc_rwlocktype_read);
result = find_closest_nsec(&search, nodep, foundname,
rdataset, sigrdataset,
@@ -3829,7 +3822,6 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
if (result == DNS_R_GLUE &&
(search.options & DNS_DBFIND_VALIDATEGLUE) != 0 &&
!valid_glue(&search, foundname, type, node)) {
- lock = &search.rbtdb->node_locks[node->locknum].lock;
NODE_UNLOCK(lock, isc_rwlocktype_read);
result = setup_delegation(&search, nodep, foundname,
rdataset, sigrdataset);
@@ -3861,8 +3853,7 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
foundname->attributes |= DNS_NAMEATTR_WILDCARD;
node_exit:
- NODE_UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock),
- isc_rwlocktype_read);
+ NODE_UNLOCK(lock, isc_rwlocktype_read);
tree_exit:
RWUNLOCK(&search.rbtdb->tree_lock, isc_rwlocktype_read);
@@ -5408,8 +5399,10 @@ static isc_result_t
resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader) {
isc_result_t result;
+ INSIST(!IS_CACHE(rbtdb));
INSIST(newheader->heap_index == 0);
- INSIST(!ISC_LINK_LINKED(newheader, lru_link));
+ INSIST(!ISC_LINK_LINKED(newheader, link));
+
result = isc_heap_insert(rbtdb->heaps[idx], newheader);
return (result);
}
@@ -5735,7 +5728,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
idx = newheader->node->locknum;
if (IS_CACHE(rbtdb)) {
ISC_LIST_PREPEND(rbtdb->rdatasets[idx],
- newheader, lru_link);
+ newheader, link);
/*
* XXXMLG We don't check the return value
* here. If it fails, we will not do TTL
@@ -5794,7 +5787,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
idx = newheader->node->locknum;
if (IS_CACHE(rbtdb)) {
ISC_LIST_PREPEND(rbtdb->rdatasets[idx],
- newheader, lru_link);
+ newheader, link);
isc_heap_insert(rbtdb->heaps[idx], newheader);
} else if (RESIGN(newheader)) {
resign_insert(rbtdb, idx, newheader);
@@ -6519,11 +6512,17 @@ static void
delete_callback(void *data, void *arg) {
dns_rbtdb_t *rbtdb = arg;
rdatasetheader_t *current, *next;
+ unsigned int locknum;
- for (current = data; current != NULL; current = next) {
+ current = data;
+ locknum = current->node->locknum;
+ NODE_LOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write);
+ while (current != NULL) {
next = current->next;
free_rdataset(rbtdb, rbtdb->common.mctx, current);
+ current = next;
}
+ NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write);
}
static isc_boolean_t
@@ -6642,8 +6641,8 @@ getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, dns_hash_t *hash,
if (rbtversion->havensec3) {
if (hash != NULL)
*hash = rbtversion->hash;
- if (salt != NULL && salt_length != 0) {
- REQUIRE(*salt_length > rbtversion->salt_length);
+ if (salt != NULL && salt_length != NULL) {
+ REQUIRE(*salt_length >= rbtversion->salt_length);
memcpy(salt, rbtversion->salt, rbtversion->salt_length);
}
if (salt_length != NULL)
@@ -6707,27 +6706,35 @@ getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
rdatasetheader_t *header = NULL, *this;
unsigned int i;
isc_result_t result = ISC_R_NOTFOUND;
+ unsigned int locknum;
REQUIRE(VALID_RBTDB(rbtdb));
RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
for (i = 0; i < rbtdb->node_lock_count; i++) {
+ NODE_LOCK(&rbtdb->node_locks[i].lock, isc_rwlocktype_read);
this = isc_heap_element(rbtdb->heaps[i], 1);
- if (this == NULL)
+ if (this == NULL) {
+ NODE_UNLOCK(&rbtdb->node_locks[i].lock,
+ isc_rwlocktype_read);
continue;
+ }
if (header == NULL)
header = this;
- else if (isc_serial_lt(this->resign, header->resign))
+ else if (isc_serial_lt(this->resign, header->resign)) {
+ locknum = header->node->locknum;
+ NODE_UNLOCK(&rbtdb->node_locks[locknum].lock,
+ isc_rwlocktype_read);
header = this;
+ } else
+ NODE_UNLOCK(&rbtdb->node_locks[i].lock,
+ isc_rwlocktype_read);
}
if (header == NULL)
goto unlock;
- NODE_LOCK(&rbtdb->node_locks[header->node->locknum].lock,
- isc_rwlocktype_read);
-
bind_rdataset(rbtdb, header->node, header, 0, rdataset);
if (foundname != NULL)
@@ -6761,7 +6768,7 @@ resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version)
header = rdataset->private3;
header--;
- RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
NODE_LOCK(&rbtdb->node_locks[node->locknum].lock,
isc_rwlocktype_write);
/*
@@ -6771,11 +6778,11 @@ resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version)
new_reference(rbtdb, node);
isc_heap_delete(rbtdb->heaps[node->locknum], header->heap_index);
header->heap_index = 0;
- ISC_LIST_APPEND(rbtversion->resigned_list, header, lru_link);
+ ISC_LIST_APPEND(rbtversion->resigned_list, header, link);
NODE_UNLOCK(&rbtdb->node_locks[node->locknum].lock,
isc_rwlocktype_write);
- RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read);
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
}
static dns_stats_t *
@@ -8497,13 +8504,11 @@ update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
INSIST(IS_CACHE(rbtdb));
/* To be checked: can we really assume this? XXXMLG */
- INSIST(ISC_LINK_LINKED(header, lru_link));
+ INSIST(ISC_LINK_LINKED(header, link));
- ISC_LIST_UNLINK(rbtdb->rdatasets[header->node->locknum],
- header, lru_link);
+ ISC_LIST_UNLINK(rbtdb->rdatasets[header->node->locknum], header, link);
header->last_used = now;
- ISC_LIST_PREPEND(rbtdb->rdatasets[header->node->locknum],
- header, lru_link);
+ ISC_LIST_PREPEND(rbtdb->rdatasets[header->node->locknum], header, link);
}
/*%
@@ -8539,7 +8544,7 @@ overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]);
header != NULL && purgecount > 0;
header = header_prev) {
- header_prev = ISC_LIST_PREV(header, lru_link);
+ header_prev = ISC_LIST_PREV(header, link);
/*
* Unlink the entry at this point to avoid checking it
* again even if it's currently used someone else and
@@ -8548,7 +8553,7 @@ overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
* TTL was reset to 0.
*/
ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header,
- lru_link);
+ link);
expire_header(rbtdb, header, tree_locked);
purgecount--;
}