From 176f7a135eee8b3ab2d3ed87d63126fbd2efd87b Mon Sep 17 00:00:00 2001 From: Bob Halley Date: Wed, 11 Aug 1999 22:06:21 +0000 Subject: [PATCH] findnode() had design legacies from an older version of the RBT API. It also failed to handle the case where it had discovered that a node didn't exist, had unlocked and relocked the tree (into write mode), and then had attempted to add the node and got DNS_R_EXISTS as the result. (I.e. someone beat us in the race to create the node.) In this case, an error would have been returned. The correct behavior is to succeed (being sure to increment the node reference count). --- lib/dns/rbtdb.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 08524ba601..bfba158ed1 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -912,42 +912,34 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, RWLOCK(&rbtdb->tree_lock, locktype); result = dns_rbt_findnode(rbtdb->tree, name, NULL, &node, NULL, ISC_TRUE, NULL, NULL); - again: - if (result == DNS_R_SUCCESS) { - locknum = node->locknum; - LOCK(&rbtdb->node_locks[locknum].lock); - new_reference(rbtdb, node); - UNLOCK(&rbtdb->node_locks[locknum].lock); - } else { + if (result != DNS_R_SUCCESS) { RWUNLOCK(&rbtdb->tree_lock, locktype); if (!create) { if (result == DNS_R_PARTIALMATCH) result = DNS_R_NOTFOUND; return (result); } - locktype = isc_rwlocktype_write; /* * It would be nice to try to upgrade the lock instead of * unlocking then relocking. */ + locktype = isc_rwlocktype_write; RWLOCK(&rbtdb->tree_lock, locktype); node = NULL; result = dns_rbt_addnode(rbtdb->tree, name, &node); - if (result != DNS_R_SUCCESS && result != DNS_R_EXISTS) { + if (result == DNS_R_SUCCESS) { + dns_rbt_namefromnode(node, &nodename); + node->locknum = dns_name_hash(&nodename, ISC_TRUE) % + rbtdb->node_lock_count; + } else if (result != DNS_R_EXISTS) { RWUNLOCK(&rbtdb->tree_lock, locktype); return (result); } - dns_rbt_namefromnode(node, &nodename); - node->locknum = dns_name_hash(&nodename, ISC_TRUE) % - rbtdb->node_lock_count; - /* - * Turning off creation mode ensures that we can 'goto again' - * only once. If we didn't do this and dns_rbt_findnode() - * was always failing, then we could loop forever. - */ - create = ISC_FALSE; - goto again; } + locknum = node->locknum; + LOCK(&rbtdb->node_locks[locknum].lock); + new_reference(rbtdb, node); + UNLOCK(&rbtdb->node_locks[locknum].lock); RWUNLOCK(&rbtdb->tree_lock, locktype); *nodep = (dns_dbnode_t *)node;