diff -up bind-9.5.0b1/lib/dns/rbtdb.c.segv bind-9.5.0b1/lib/dns/rbtdb.c
--- bind-9.5.0b1/lib/dns/rbtdb.c.segv 2008-02-04 12:30:36.000000000 +0100
+++ bind-9.5.0b1/lib/dns/rbtdb.c 2008-02-04 13:46:48.000000000 +0100
@@ -763,23 +763,17 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boole
isc_mem_put(rbtdb->common.mctx, rbtdb->current_version,
sizeof(rbtdb_version_t));
}
- if (IS_CACHE(rbtdb)) {
- /*
- * We assume the number of remaining dead nodes is reasonably
- * small; the overhead of unlinking all nodes here should be
- * negligible.
- */
- for (i = 0; i < rbtdb->node_lock_count; i++) {
- dns_rbtnode_t *node;
-
- node = ISC_LIST_HEAD(rbtdb->deadnodes[i]);
- while (node != NULL) {
- ISC_LIST_UNLINK(rbtdb->deadnodes[i], node,
- deadlink);
- node = ISC_LIST_HEAD(rbtdb->deadnodes[i]);
- }
+
+ for (i = 0; i < rbtdb->node_lock_count; i++) {
+ dns_rbtnode_t *node;
+
+ node = ISC_LIST_HEAD(rbtdb->deadnodes[i]);
+ while (node != NULL) {
+ ISC_LIST_UNLINK(rbtdb->deadnodes[i], node, deadlink);
+ node = ISC_LIST_HEAD(rbtdb->deadnodes[i]);
}
}
+
if (event == NULL)
rbtdb->quantum = (rbtdb->task != NULL) ? 100 : 0;
again:
@@ -1912,6 +1906,7 @@ closeversion(dns_db_t *db, dns_dbversion
}
if (!EMPTY(cleanup_list)) {
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
for (changed = HEAD(cleanup_list);
changed != NULL;
changed = next_changed) {
@@ -1922,16 +1917,18 @@ closeversion(dns_db_t *db, dns_dbversion
lock = &rbtdb->node_locks[rbtnode->locknum].lock;
NODE_LOCK(lock, isc_rwlocktype_write);
+ cleanup_dead_nodes(rbtdb, rbtnode->locknum);
if (rollback)
rollback_node(rbtnode, serial);
decrement_reference(rbtdb, rbtnode, least_serial,
isc_rwlocktype_write,
- isc_rwlocktype_none);
+ isc_rwlocktype_write);
NODE_UNLOCK(lock, isc_rwlocktype_write);
isc_mem_put(rbtdb->common.mctx, changed,
sizeof(*changed));
}
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
}
end:
@@ -2009,6 +2006,7 @@ findnode(dns_db_t *db, dns_name_t *name,
dns_name_t nodename;
isc_result_t result;
isc_rwlocktype_t locktype = isc_rwlocktype_read;
+ isc_boolean_t need_relock;
REQUIRE(VALID_RBTDB(rbtdb));
@@ -2064,29 +2062,27 @@ findnode(dns_db_t *db, dns_name_t *name,
* happen to hold a write lock on the tree, it's a good chance to purge
* dead nodes.
*/
- if (IS_CACHE(rbtdb)) {
- isc_boolean_t need_relock = ISC_FALSE;
+ need_relock = ISC_FALSE;
+ NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_read);
+ if (ISC_LINK_LINKED(node, deadlink) && isc_rwlocktype_write)
+ need_relock = ISC_TRUE;
+ else if (!ISC_LIST_EMPTY(rbtdb->deadnodes[node->locknum]) &&
+ locktype == isc_rwlocktype_write)
+ need_relock = ISC_TRUE;
+ NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_read);
+ if (need_relock) {
NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock,
- isc_rwlocktype_read);
- if (ISC_LINK_LINKED(node, deadlink) && isc_rwlocktype_write)
- need_relock = ISC_TRUE;
- else if (!ISC_LIST_EMPTY(rbtdb->deadnodes[node->locknum]) &&
- locktype == isc_rwlocktype_write)
- need_relock = ISC_TRUE;
+ isc_rwlocktype_write);
+ if (ISC_LINK_LINKED(node, deadlink))
+ ISC_LIST_UNLINK(rbtdb->deadnodes[node->locknum],
+ node, deadlink);
+ if (locktype == isc_rwlocktype_write)
+ cleanup_dead_nodes(rbtdb, node->locknum);
NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock,
- isc_rwlocktype_read);
- if (need_relock) {
- NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock,
- isc_rwlocktype_write);
- if (ISC_LINK_LINKED(node, deadlink))
- ISC_LIST_UNLINK(rbtdb->deadnodes[node->locknum],
- node, deadlink);
- if (locktype == isc_rwlocktype_write)
- cleanup_dead_nodes(rbtdb, node->locknum);
- NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock,
- isc_rwlocktype_write);
- }
+ isc_rwlocktype_write);
}
NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
@@ -6149,15 +6145,6 @@ dns_rbtdb_create
for (i = 0; i < (int)rbtdb->node_lock_count; i++)
ISC_LIST_INIT(rbtdb->rdatasets[i]);
- rbtdb->deadnodes = isc_mem_get(mctx, rbtdb->node_lock_count *
- sizeof(rbtnodelist_t));
- if (rbtdb->deadnodes == NULL) {
- result = ISC_R_NOMEMORY;
- goto cleanup_rdatasets;
- }
- for (i = 0; i < (int)rbtdb->node_lock_count; i++)
- ISC_LIST_INIT(rbtdb->deadnodes[i]);
-
/*
* Create the heaps.
*/
@@ -6165,7 +6152,7 @@ dns_rbtdb_create
sizeof(isc_heap_t *));
if (rbtdb->heaps == NULL) {
result = ISC_R_NOMEMORY;
- goto cleanup_deadnodes;
+ goto cleanup_rdatasets;
}
for (i = 0; i < (int)rbtdb->node_lock_count; i++)
rbtdb->heaps[i] = NULL;
@@ -6178,10 +6165,18 @@ dns_rbtdb_create
}
} else {
rbtdb->rdatasets = NULL;
- rbtdb->deadnodes = NULL;
rbtdb->heaps = NULL;
}
+ rbtdb->deadnodes = isc_mem_get(mctx, rbtdb->node_lock_count *
+ sizeof(rbtnodelist_t));
+ if (rbtdb->deadnodes == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_heaps;
+ }
+ for (i = 0; i < (int)rbtdb->node_lock_count; i++)
+ ISC_LIST_INIT(rbtdb->deadnodes[i]);
+
rbtdb->active = rbtdb->node_lock_count;
for (i = 0; i < (int)(rbtdb->node_lock_count); i++) {
@@ -6197,7 +6192,7 @@ dns_rbtdb_create
isc_refcount_decrement(&rbtdb->node_locks[i].references, NULL);
isc_refcount_destroy(&rbtdb->node_locks[i].references);
}
- goto cleanup_heaps;
+ goto cleanup_deadnodes;
}
rbtdb->node_locks[i].exiting = ISC_FALSE;
}
@@ -6310,6 +6305,10 @@ dns_rbtdb_create
return (ISC_R_SUCCESS);
+ cleanup_deadnodes:
+ isc_mem_put(mctx, rbtdb->deadnodes,
+ rbtdb->node_lock_count * sizeof(rbtnodelist_t));
+
cleanup_heaps:
if (rbtdb->heaps != NULL) {
for (i = 0 ; i < (int)rbtdb->node_lock_count ; i++)
@@ -6319,11 +6318,6 @@ dns_rbtdb_create
rbtdb->node_lock_count * sizeof(isc_heap_t *));
}
- cleanup_deadnodes:
- if (rbtdb->deadnodes != NULL)
- isc_mem_put(mctx, rbtdb->deadnodes,
- rbtdb->node_lock_count * sizeof(rbtnodelist_t));
-
cleanup_rdatasets:
if (rbtdb->rdatasets != NULL)
isc_mem_put(mctx, rbtdb->rdatasets, rbtdb->node_lock_count *