198 lines
8.5 KiB
Diff
198 lines
8.5 KiB
Diff
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 *
|