mirror of
https://github.com/isc-projects/bind9.git
synced 2026-02-27 12:02:10 -05: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:
parent
81a26ce8b3
commit
176f7a135e
1 changed files with 11 additions and 19 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue