2881. [bug] Reduce the amount of time the rbtdb write lock
is held when closing a version. [RT #21198]
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -1,3 +1,6 @@
|
||||
2881. [bug] Reduce the amount of time the rbtdb write lock
|
||||
is held when closing a version. [RT #21198]
|
||||
|
||||
2880. [cleanup] Make the output of dnssec-keygen and dnssec-revoke
|
||||
consistent. [RT #21078]
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: events.h,v 1.53 2009/09/01 00:22:26 jinmei Exp $ */
|
||||
/* $Id: events.h,v 1.54 2010/05/10 01:39:03 marka Exp $ */
|
||||
|
||||
#ifndef DNS_EVENTS_H
|
||||
#define DNS_EVENTS_H 1
|
||||
@@ -58,7 +58,7 @@
|
||||
#define DNS_EVENT_MASTERNEXTZONE (ISC_EVENTCLASS_DNS + 28)
|
||||
#define DNS_EVENT_IOREADY (ISC_EVENTCLASS_DNS + 29)
|
||||
#define DNS_EVENT_LOOKUPDONE (ISC_EVENTCLASS_DNS + 30)
|
||||
/* #define DNS_EVENT_unused (ISC_EVENTCLASS_DNS + 31) */
|
||||
#define DNS_EVENT_RBTDEADNODES (ISC_EVENTCLASS_DNS + 31)
|
||||
#define DNS_EVENT_DISPATCHCONTROL (ISC_EVENTCLASS_DNS + 32)
|
||||
#define DNS_EVENT_REQUESTCONTROL (ISC_EVENTCLASS_DNS + 33)
|
||||
#define DNS_EVENT_DUMPQUANTUM (ISC_EVENTCLASS_DNS + 34)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: rbtdb.c,v 1.300 2010/02/26 00:18:06 marka Exp $ */
|
||||
/* $Id: rbtdb.c,v 1.301 2010/05/10 01:39:03 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -2109,6 +2109,34 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
cleanup_dead_nodes_callback(isc_task_t *task, isc_event_t *event) {
|
||||
dns_rbtdb_t *rbtdb = event->ev_arg;
|
||||
isc_boolean_t again = ISC_FALSE;
|
||||
unsigned int locknum;
|
||||
unsigned int refs;
|
||||
|
||||
RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
|
||||
for (locknum = 0; locknum < rbtdb->node_lock_count; locknum++) {
|
||||
NODE_LOCK(&rbtdb->node_locks[locknum].lock,
|
||||
isc_rwlocktype_write);
|
||||
cleanup_dead_nodes(rbtdb, locknum);
|
||||
if (ISC_LIST_HEAD(rbtdb->deadnodes[locknum]) != NULL)
|
||||
again = ISC_TRUE;
|
||||
NODE_UNLOCK(&rbtdb->node_locks[locknum].lock,
|
||||
isc_rwlocktype_write);
|
||||
}
|
||||
RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
|
||||
if (again)
|
||||
isc_task_send(task, &event);
|
||||
else {
|
||||
isc_event_free(&event);
|
||||
isc_refcount_decrement(&rbtdb->references, &refs);
|
||||
if (refs == 0)
|
||||
maybe_free_rbtdb(rbtdb);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
@@ -2309,15 +2337,28 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
|
||||
}
|
||||
|
||||
if (!EMPTY(cleanup_list)) {
|
||||
/*
|
||||
* We acquire a tree write lock here in order to make sure
|
||||
* that stale nodes will be removed in decrement_reference().
|
||||
* If we didn't have the lock, those nodes could miss the
|
||||
* chance to be removed until the server stops. The write lock
|
||||
* is expensive, but this event should be rare enough to justify
|
||||
* the cost.
|
||||
*/
|
||||
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
|
||||
isc_event_t *event = NULL;
|
||||
isc_rwlocktype_t tlock = isc_rwlocktype_none;
|
||||
|
||||
if (rbtdb->task != NULL)
|
||||
event = isc_event_allocate(rbtdb->common.mctx, NULL,
|
||||
DNS_EVENT_RBTDEADNODES,
|
||||
cleanup_dead_nodes_callback,
|
||||
rbtdb, sizeof(isc_event_t));
|
||||
if (event == NULL) {
|
||||
/*
|
||||
* We acquire a tree write lock here in order to make
|
||||
* sure that stale nodes will be removed in
|
||||
* decrement_reference(). If we didn't have the lock,
|
||||
* those nodes could miss the chance to be removed
|
||||
* until the server stops. The write lock is
|
||||
* expensive, but this event should be rare enough
|
||||
* to justify the cost.
|
||||
*/
|
||||
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
|
||||
tlock = isc_rwlocktype_write;
|
||||
}
|
||||
|
||||
for (changed = HEAD(cleanup_list);
|
||||
changed != NULL;
|
||||
changed = next_changed) {
|
||||
@@ -2332,20 +2373,25 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
|
||||
* This is a good opportunity to purge any dead nodes,
|
||||
* so use it.
|
||||
*/
|
||||
cleanup_dead_nodes(rbtdb, rbtnode->locknum);
|
||||
if (event == NULL)
|
||||
cleanup_dead_nodes(rbtdb, rbtnode->locknum);
|
||||
|
||||
if (rollback)
|
||||
rollback_node(rbtnode, serial);
|
||||
decrement_reference(rbtdb, rbtnode, least_serial,
|
||||
isc_rwlocktype_write,
|
||||
isc_rwlocktype_write, ISC_FALSE);
|
||||
isc_rwlocktype_write, tlock,
|
||||
ISC_FALSE);
|
||||
|
||||
NODE_UNLOCK(lock, isc_rwlocktype_write);
|
||||
|
||||
isc_mem_put(rbtdb->common.mctx, changed,
|
||||
sizeof(*changed));
|
||||
}
|
||||
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
|
||||
if (event != NULL) {
|
||||
isc_refcount_increment(&rbtdb->references, NULL);
|
||||
isc_task_send(rbtdb->task, &event);
|
||||
} else
|
||||
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
Reference in New Issue
Block a user