diff options
Diffstat (limited to 'lib/dns/rbtdb.c')
-rw-r--r-- | lib/dns/rbtdb.c | 127 |
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--; } |