2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

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).
This commit is contained in:
Bob Halley
1999-08-11 22:06:21 +00:00
parent 81a26ce8b3
commit 176f7a135e

View File

@@ -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;