mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
lock find when unlinking adbname->finds in dns_adb_cancelfind()
In dns_adb_cancelfind(), we need to release the find lock and then acquire the bucket and find locks in that order, for consistency with locking hierarchy elsehwere. Previously we were only acquiring the bucket lock. Also rewrote the function for better readability.
This commit is contained in:
parent
227b488418
commit
a1e9a59e2b
1 changed files with 47 additions and 35 deletions
|
|
@ -2662,41 +2662,15 @@ dns_adb_destroyfind(dns_adbfind_t **findp) {
|
|||
free_adbfind(&find);
|
||||
}
|
||||
|
||||
void
|
||||
dns_adb_cancelfind(dns_adbfind_t *find) {
|
||||
isc_event_t *ev = NULL;
|
||||
isc_task_t *task = NULL;
|
||||
dns_adb_t *adb = NULL;
|
||||
dns_adbname_t *adbname = NULL;
|
||||
dns_adbnamebucket_t *nbucket = NULL;
|
||||
|
||||
LOCK(&find->lock);
|
||||
|
||||
DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
|
||||
|
||||
adb = find->adb;
|
||||
REQUIRE(DNS_ADB_VALID(adb));
|
||||
|
||||
REQUIRE(!FIND_EVENTFREED(find));
|
||||
REQUIRE(FIND_WANTEVENT(find));
|
||||
|
||||
if (find->adbname == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
adbname = find->adbname;
|
||||
find->adbname = NULL;
|
||||
nbucket = adbname->bucket;
|
||||
|
||||
UNLOCK(&find->lock);
|
||||
LOCK(&nbucket->lock);
|
||||
ISC_LIST_UNLINK(adbname->finds, find, plink);
|
||||
UNLOCK(&nbucket->lock);
|
||||
LOCK(&find->lock);
|
||||
|
||||
cleanup:
|
||||
/*
|
||||
* Caller must hold find lock.
|
||||
*/
|
||||
static void
|
||||
find_sendevent(dns_adbfind_t *find) {
|
||||
if (!FIND_EVENTSENT(find)) {
|
||||
ev = &find->event;
|
||||
task = ev->ev_sender;
|
||||
isc_event_t *ev = &find->event;
|
||||
isc_task_t *task = ev->ev_sender;
|
||||
|
||||
ev->ev_sender = find;
|
||||
ev->ev_type = DNS_EVENT_ADBCANCELED;
|
||||
ev->ev_destroy = event_freefind;
|
||||
|
|
@ -2709,7 +2683,45 @@ cleanup:
|
|||
|
||||
isc_task_sendanddetach(&task, (isc_event_t **)&ev);
|
||||
}
|
||||
UNLOCK(&find->lock);
|
||||
}
|
||||
|
||||
void
|
||||
dns_adb_cancelfind(dns_adbfind_t *find) {
|
||||
dns_adbname_t *adbname = NULL;
|
||||
|
||||
DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
|
||||
|
||||
REQUIRE(DNS_ADBFIND_VALID(find));
|
||||
REQUIRE(DNS_ADB_VALID(find->adb));
|
||||
|
||||
LOCK(&find->lock);
|
||||
REQUIRE(!FIND_EVENTFREED(find));
|
||||
REQUIRE(FIND_WANTEVENT(find));
|
||||
|
||||
adbname = find->adbname;
|
||||
|
||||
if (adbname == NULL) {
|
||||
find_sendevent(find);
|
||||
UNLOCK(&find->lock);
|
||||
} else {
|
||||
/*
|
||||
* Release the find lock, then acquire the bucket and find
|
||||
* locks in that order, to match locking hierarchy
|
||||
* elsewhere.
|
||||
*/
|
||||
UNLOCK(&find->lock);
|
||||
LOCK(&adbname->bucket->lock);
|
||||
LOCK(&find->lock);
|
||||
|
||||
if (find->adbname != NULL) {
|
||||
ISC_LIST_UNLINK(adbname->finds, find, plink);
|
||||
find->adbname = NULL;
|
||||
}
|
||||
find_sendevent(find);
|
||||
|
||||
UNLOCK(&find->lock);
|
||||
UNLOCK(&adbname->bucket->lock);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
Loading…
Reference in a new issue