3334. [bug] Hold a zone table reference while performing a
asyncronous load of a zone. [RT #28326]
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -1,3 +1,6 @@
|
||||
3334. [bug] Hold a zone table reference while performing a
|
||||
asyncronous load of a zone. [RT #28326]
|
||||
|
||||
3333. [bug] Setting resolver-query-timeout too low can cause
|
||||
named to not recover if it looses connectivity.
|
||||
[RT #29623]
|
||||
|
||||
47
lib/dns/zt.c
47
lib/dns/zt.c
@@ -46,6 +46,7 @@ struct dns_zt {
|
||||
dns_zt_allloaded_t loaddone;
|
||||
void * loaddone_arg;
|
||||
/* Locked by lock. */
|
||||
isc_boolean_t flush;
|
||||
isc_uint32_t references;
|
||||
unsigned int loads_pending;
|
||||
dns_rbt_t *table;
|
||||
@@ -93,8 +94,10 @@ dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp)
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_rbt;
|
||||
|
||||
zt->mctx = mctx;
|
||||
zt->mctx = NULL;
|
||||
isc_mem_attach(mctx, &zt->mctx);
|
||||
zt->references = 1;
|
||||
zt->flush = ISC_FALSE;
|
||||
zt->rdclass = rdclass;
|
||||
zt->magic = ZTMAGIC;
|
||||
zt->loaddone = NULL;
|
||||
@@ -200,6 +203,16 @@ flush(dns_zone_t *zone, void *uap) {
|
||||
return (dns_zone_flush(zone));
|
||||
}
|
||||
|
||||
static void
|
||||
zt_destroy(dns_zt_t *zt) {
|
||||
if (zt->flush)
|
||||
(void)dns_zt_apply(zt, ISC_FALSE, flush, NULL);
|
||||
dns_rbt_destroy(&zt->table);
|
||||
isc_rwlock_destroy(&zt->rwlock);
|
||||
zt->magic = 0;
|
||||
isc_mem_putanddetach(&zt->mctx, zt, sizeof(*zt));
|
||||
}
|
||||
|
||||
static void
|
||||
zt_flushanddetach(dns_zt_t **ztp, isc_boolean_t need_flush) {
|
||||
isc_boolean_t destroy = ISC_FALSE;
|
||||
@@ -215,17 +228,13 @@ zt_flushanddetach(dns_zt_t **ztp, isc_boolean_t need_flush) {
|
||||
zt->references--;
|
||||
if (zt->references == 0)
|
||||
destroy = ISC_TRUE;
|
||||
if (need_flush)
|
||||
zt->flush = ISC_TRUE;
|
||||
|
||||
RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
|
||||
|
||||
if (destroy) {
|
||||
if (need_flush)
|
||||
(void)dns_zt_apply(zt, ISC_FALSE, flush, NULL);
|
||||
dns_rbt_destroy(&zt->table);
|
||||
isc_rwlock_destroy(&zt->rwlock);
|
||||
zt->magic = 0;
|
||||
isc_mem_put(zt->mctx, zt, sizeof(*zt));
|
||||
}
|
||||
if (destroy)
|
||||
zt_destroy(zt);
|
||||
|
||||
*ztp = NULL;
|
||||
}
|
||||
@@ -272,10 +281,9 @@ dns_zt_asyncload(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg) {
|
||||
|
||||
REQUIRE(VALID_ZT(zt));
|
||||
|
||||
RWLOCK(&zt->rwlock, isc_rwlocktype_read);
|
||||
RWLOCK(&zt->rwlock, isc_rwlocktype_write);
|
||||
|
||||
INSIST(zt->loads_pending == 0);
|
||||
|
||||
result = dns_zt_apply2(zt, ISC_FALSE, NULL, asyncload, &dl);
|
||||
|
||||
pending = zt->loads_pending;
|
||||
@@ -284,7 +292,7 @@ dns_zt_asyncload(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg) {
|
||||
zt->loaddone_arg = arg;
|
||||
}
|
||||
|
||||
RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
|
||||
RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
|
||||
|
||||
if (pending == 0)
|
||||
alldone(arg);
|
||||
@@ -305,10 +313,15 @@ asyncload(dns_zone_t *zone, void *callback) {
|
||||
|
||||
REQUIRE(zone != NULL);
|
||||
zt = dns_zone_getview(zone)->zonetable;
|
||||
INSIST(VALID_ZT(zt));
|
||||
|
||||
result = dns_zone_asyncload(zone, *loaded, zt);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
INSIST(zt->references > 0);
|
||||
zt->references++;
|
||||
INSIST(zt->references != 0);
|
||||
zt->loads_pending++;
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -479,6 +492,7 @@ dns_zt_apply2(dns_zt_t *zt, isc_boolean_t stop, isc_result_t *sub,
|
||||
*/
|
||||
static isc_result_t
|
||||
doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) {
|
||||
isc_boolean_t destroy = ISC_FALSE;
|
||||
dns_zt_allloaded_t alldone = NULL;
|
||||
void *arg = NULL;
|
||||
|
||||
@@ -489,6 +503,10 @@ doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) {
|
||||
|
||||
RWLOCK(&zt->rwlock, isc_rwlocktype_write);
|
||||
INSIST(zt->loads_pending != 0);
|
||||
INSIST(zt->references != 0);
|
||||
zt->references--;
|
||||
if (zt->references == 0)
|
||||
destroy = ISC_TRUE;
|
||||
zt->loads_pending--;
|
||||
if (zt->loads_pending == 0) {
|
||||
alldone = zt->loaddone;
|
||||
@@ -501,6 +519,9 @@ doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) {
|
||||
if (alldone != NULL)
|
||||
alldone(arg);
|
||||
|
||||
if (destroy)
|
||||
zt_destroy(zt);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user