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:
@@ -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;
|
||||
|
Reference in New Issue
Block a user