diff --git a/bin/named/server.c b/bin/named/server.c index e3da808bbb..9569ee9b5d 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -8738,7 +8738,7 @@ load_zones(ns_server_t *server, bool init, bool reconfig) { * zones. */ isc_refcount_increment(&zl->refs, NULL); - CHECK(dns_view_asyncload(view, view_loaded, zl)); + CHECK(dns_view_asyncload2(view, view_loaded, zl, reconfig)); } cleanup: diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index ee9f6e3685..8e21298c03 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -808,6 +808,10 @@ dns_view_loadnew(dns_view_t *view, bool stop); isc_result_t dns_view_asyncload(dns_view_t *view, dns_zt_allloaded_t callback, void *arg); + +isc_result_t +dns_view_asyncload2(dns_view_t *view, dns_zt_allloaded_t callback, void *arg, + bool newonly); /*%< * Load zones attached to this view. dns_view_load() loads * all zones whose master file has changed since the last diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index b61d7a2b7d..c059ce29e7 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -404,6 +404,10 @@ dns_zone_loadandthaw(dns_zone_t *zone); isc_result_t dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg); + +isc_result_t +dns_zone_asyncload2(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg, + bool newonly); /*%< * Cause the database to be loaded from its backing store asynchronously. * Other zone maintenance functions are suspended until this is complete. diff --git a/lib/dns/include/dns/zt.h b/lib/dns/include/dns/zt.h index dabd56787a..84ca8eaad1 100644 --- a/lib/dns/include/dns/zt.h +++ b/lib/dns/include/dns/zt.h @@ -147,6 +147,10 @@ dns_zt_loadnew(dns_zt_t *zt, bool stop); isc_result_t dns_zt_asyncload(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg); + +isc_result_t +dns_zt_asyncload2(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg, + bool newonly); /*%< * Load all zones in the table. If 'stop' is true, * stop on the first error and return it. If 'stop' diff --git a/lib/dns/tests/zt_test.c b/lib/dns/tests/zt_test.c index 0548ce7626..8b506d2eb3 100644 --- a/lib/dns/tests/zt_test.c +++ b/lib/dns/tests/zt_test.c @@ -34,6 +34,7 @@ struct args { void *arg1; void *arg2; + bool arg3; }; /* @@ -77,7 +78,7 @@ start_zt_asyncload(isc_task_t *task, isc_event_t *event) { UNUSED(task); - dns_zt_asyncload(args->arg1, all_done, args->arg2); + dns_zt_asyncload2(args->arg1, all_done, args->arg2, false); isc_event_free(&event); } @@ -88,7 +89,7 @@ start_zone_asyncload(isc_task_t *task, isc_event_t *event) { UNUSED(task); - dns_zone_asyncload(args->arg1, load_done, args->arg2); + dns_zone_asyncload2(args->arg1, load_done, args->arg2, args->arg3); isc_event_free(&event); } @@ -142,9 +143,12 @@ ATF_TC_HEAD(asyncload_zone, tc) { } ATF_TC_BODY(asyncload_zone, tc) { isc_result_t result; + int n; dns_zone_t *zone = NULL; dns_view_t *view = NULL; dns_db_t *db = NULL; + FILE* zonefile, *origfile; + char buf[4096]; bool done = false; int i = 0; struct args args; @@ -167,20 +171,66 @@ ATF_TC_BODY(asyncload_zone, tc) { ATF_CHECK(!dns__zone_loadpending(zone)); ATF_CHECK(!done); - dns_zone_setfile(zone, "testdata/zt/zone1.db"); + zonefile = fopen("./zone.data", "wb"); + ATF_CHECK(zonefile != NULL); + origfile = fopen("./testdata/zt/zone1.db", "r+b"); + ATF_CHECK(origfile != NULL); + n = fread(buf, 1, 4096, origfile); + fwrite(buf, 1, n, zonefile); + fflush(zonefile); + + dns_zone_setfile(zone, "./zone.data"); args.arg1 = zone; args.arg2 = &done; + args.arg3 = false; isc_app_onrun(mctx, maintask, start_zone_asyncload, &args); isc_app_run(); while (dns__zone_loadpending(zone) && i++ < 5000) dns_test_nap(1000); ATF_CHECK(done); - /* The zone should now be loaded; test it */ result = dns_zone_getdb(zone, &db); ATF_CHECK_EQ(result, ISC_R_SUCCESS); + dns_db_detach(&db); + /* + * Add something to zone file, reload zone with newonly - it should + * not be reloaded. + */ + fprintf(zonefile, "\nb in b 1.2.3.4\n"); + fflush(zonefile); + + args.arg1 = zone; + args.arg2 = &done; + args.arg3 = false; + isc_app_onrun(mctx, maintask, start_zone_asyncload, &args); + + isc_app_run(); + + while (dns__zone_loadpending(zone) && i++ < 5000) + dns_test_nap(1000); + ATF_CHECK(done); + /* The zone should now be loaded; test it */ + result = dns_zone_getdb(zone, &db); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + dns_db_detach(&db); + + /* Now reload it without newonly - it should be reloaded */ + args.arg1 = zone; + args.arg2 = &done; + args.arg3 = false; + isc_app_onrun(mctx, maintask, start_zone_asyncload, &args); + + isc_app_run(); + + while (dns__zone_loadpending(zone) && i++ < 5000) + dns_test_nap(1000); + ATF_CHECK(done); + /* The zone should now be loaded; test it */ + result = dns_zone_getdb(zone, &db); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + ATF_CHECK(db != NULL); if (db != NULL) dns_db_detach(&db); diff --git a/lib/dns/view.c b/lib/dns/view.c index 4fb3e3b0c4..ea6e43149f 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -1557,10 +1557,16 @@ dns_view_loadnew(dns_view_t *view, bool stop) { isc_result_t dns_view_asyncload(dns_view_t *view, dns_zt_allloaded_t callback, void *arg) { + return (dns_view_asyncload2(view, callback, arg, false)); +} + +isc_result_t +dns_view_asyncload2(dns_view_t *view, dns_zt_allloaded_t callback, void *arg, + bool newonly) { REQUIRE(DNS_VIEW_VALID(view)); REQUIRE(view->zonetable != NULL); - return (dns_zt_asyncload(view->zonetable, callback, arg)); + return (dns_zt_asyncload2(view->zonetable, callback, arg, newonly)); } isc_result_t diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index d48eeb2822..62a156ce64 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -1081,6 +1081,7 @@ dns_validator_send dns_view_adddelegationonly dns_view_addzone dns_view_asyncload +dns_view_asyncload2 dns_view_attach dns_view_checksig dns_view_create @@ -1153,6 +1154,7 @@ dns_xfrin_detach dns_xfrin_shutdown dns_zone_addnsec3chain dns_zone_asyncload +dns_zone_asyncload2 dns_zone_attach dns_zone_catz_enable dns_zone_catz_enable_db @@ -1389,6 +1391,7 @@ dns_zonemgr_unreachabledel dns_zt_apply dns_zt_apply2 dns_zt_asyncload +dns_zt_asyncload2 dns_zt_attach dns_zt_create dns_zt_detach diff --git a/lib/dns/zone.c b/lib/dns/zone.c index a25d0cc158..c20caf70f1 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -713,6 +713,7 @@ struct dns_asyncload { dns_zone_t *zone; dns_zt_zoneloaded_t loaded; void *loaded_arg; + bool newonly; }; /*% @@ -2223,7 +2224,8 @@ zone_asyncload(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); LOCK_ZONE(zone); - result = zone_load(zone, 0, true); + result = zone_load(zone, asl->newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, + true); if (result != DNS_R_CONTINUE) { DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING); } @@ -2239,6 +2241,13 @@ zone_asyncload(isc_task_t *task, isc_event_t *event) { isc_result_t dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) { + return (dns_zone_asyncload2(zone, done, arg, false)); +} + +isc_result_t +dns_zone_asyncload2(dns_zone_t *zone, dns_zt_zoneloaded_t done, void * arg, + bool newonly) +{ isc_event_t *e; dns_asyncload_t *asl = NULL; isc_result_t result = ISC_R_SUCCESS; @@ -2262,6 +2271,7 @@ dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) { asl->zone = NULL; asl->loaded = done; asl->loaded_arg = arg; + asl->newonly = newonly; e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr, DNS_EVENT_ZONELOAD, diff --git a/lib/dns/zt.c b/lib/dns/zt.c index 7572498cc4..c84da2fd01 100644 --- a/lib/dns/zt.c +++ b/lib/dns/zt.c @@ -51,6 +51,12 @@ struct dns_zt { #define ZTMAGIC ISC_MAGIC('Z', 'T', 'b', 'l') #define VALID_ZT(zt) ISC_MAGIC_VALID(zt, ZTMAGIC) +struct zt_load_params { + dns_zt_zoneloaded_t dl; + bool newonly; + struct dns_zt* zt; +}; + static void auto_detach(void *, void *); @@ -270,8 +276,18 @@ load(dns_zone_t *zone, void *uap) { isc_result_t dns_zt_asyncload(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg) { + return (dns_zt_asyncload2(zt, alldone, arg, false)); +} + +isc_result_t +dns_zt_asyncload2(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg, + bool newonly) +{ isc_result_t result; - static dns_zt_zoneloaded_t dl = doneloading; + struct zt_load_params params; + params.dl = doneloading; + params.newonly = newonly; + params.zt = zt; int pending; REQUIRE(VALID_ZT(zt)); @@ -279,7 +295,7 @@ dns_zt_asyncload(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg) { RWLOCK(&zt->rwlock, isc_rwlocktype_write); INSIST(zt->loads_pending == 0); - result = dns_zt_apply2(zt, false, NULL, asyncload, &dl); + result = dns_zt_apply2(zt, false, NULL, asyncload, ¶ms); pending = zt->loads_pending; if (pending != 0) { @@ -301,10 +317,11 @@ dns_zt_asyncload(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg) { * the zone loading is complete. */ static isc_result_t -asyncload(dns_zone_t *zone, void *callback) { +asyncload(dns_zone_t *zone, void *paramsv) { isc_result_t result; - dns_zt_zoneloaded_t *loaded = callback; - dns_zt_t *zt; + struct zt_load_params * params = (struct zt_load_params*) paramsv; + + dns_zt_t *zt = params->zt; REQUIRE(zone != NULL); zt = dns_zone_getview(zone)->zonetable; @@ -314,7 +331,7 @@ asyncload(dns_zone_t *zone, void *callback) { zt->references++; zt->loads_pending++; - result = dns_zone_asyncload(zone, *loaded, zt); + result = dns_zone_asyncload2(zone, *params->dl, zt, params->newonly); if (result != ISC_R_SUCCESS) { zt->references--; zt->loads_pending--;