From: Mark Andrews Date: Sat, 11 Jul 2009 04:23:54 +0000 (+0000) Subject: 2920. [bug] Delay thawing the zone until the reload of it has X-Git-Tag: v9.6.1-P1^2^5~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a4169935438c4ae1ef83c7e4b5aa18537c500d08;p=thirdparty%2Fbind9.git 2920. [bug] Delay thawing the zone until the reload of it has completed successfully. [RT #19750] --- diff --git a/CHANGES b/CHANGES index f2e254c6126..bb3f1c83a63 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,8 @@ 2621. [doc] Made copyright boilterplate consistent. [RT #19833] +2920. [bug] Delay thawing the zone until the reload of it has + completed successfully. [RT #19750] + 2618. [bug] The sdb and sdlz db_interator_seek() methods could loop infinitely. [RT #19847] diff --git a/bin/named/control.c b/bin/named/control.c index 8bd8f6ce361..b6b7c73be4e 100644 --- a/bin/named/control.c +++ b/bin/named/control.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: control.c,v 1.33 2007/09/13 04:45:18 each Exp $ */ +/* $Id: control.c,v 1.33.266.1 2009/07/11 04:23:52 marka Exp $ */ /*! \file */ @@ -170,10 +170,12 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { } else if (command_compare(command, NS_COMMAND_TSIGDELETE)) { result = ns_server_tsigdelete(ns_g_server, command, text); } else if (command_compare(command, NS_COMMAND_FREEZE)) { - result = ns_server_freeze(ns_g_server, ISC_TRUE, command); + result = ns_server_freeze(ns_g_server, ISC_TRUE, command, + text); } else if (command_compare(command, NS_COMMAND_UNFREEZE) || command_compare(command, NS_COMMAND_THAW)) { - result = ns_server_freeze(ns_g_server, ISC_FALSE, command); + result = ns_server_freeze(ns_g_server, ISC_FALSE, command, + text); } else if (command_compare(command, NS_COMMAND_RECURSING)) { result = ns_server_dumprecursing(ns_g_server); } else if (command_compare(command, NS_COMMAND_TIMERPOKE)) { diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index 43eccc4a63d..1a3f746f3fb 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.h,v 1.93.120.2 2009/01/29 23:47:44 tbox Exp $ */ +/* $Id: server.h,v 1.93.120.3 2009/07/11 04:23:53 marka Exp $ */ #ifndef NAMED_SERVER_H #define NAMED_SERVER_H 1 @@ -276,7 +276,8 @@ ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text); * Enable or disable updates for a zone. */ isc_result_t -ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args); +ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, + isc_buffer_t *text); /*% * Dump the current recursive queries. diff --git a/bin/named/server.c b/bin/named/server.c index e685e18dc33..026bcbeb42b 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.520.12.7 2009/01/30 03:53:38 marka Exp $ */ +/* $Id: server.c,v 1.520.12.8 2009/07/11 04:23:52 marka Exp $ */ /*! \file */ @@ -5401,7 +5401,9 @@ ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) { * Act on a "freeze" or "thaw" command from the command channel. */ isc_result_t -ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) { +ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, + isc_buffer_t *text) +{ isc_result_t result, tresult; dns_zone_t *zone = NULL; dns_zonetype_t type; @@ -5411,6 +5413,7 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) { char *journal; const char *vname, *sep; isc_boolean_t frozen; + const char *msg = NULL; result = zone_from_args(server, args, &zone); if (result != ISC_R_SUCCESS) @@ -5443,25 +5446,47 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) { frozen = dns_zone_getupdatedisabled(zone); if (freeze) { - if (frozen) + if (frozen) { + msg = "WARNING: The zone was already frozen.\n" + "Someone else may be editing it or " + "it may still be re-loading."; result = DNS_R_FROZEN; - if (result == ISC_R_SUCCESS) + } + if (result == ISC_R_SUCCESS) { result = dns_zone_flush(zone); + if (result != ISC_R_SUCCESS) + msg = "Flushing the zone updates to " + "disk failed."; + } if (result == ISC_R_SUCCESS) { journal = dns_zone_getjournal(zone); if (journal != NULL) (void)isc_file_remove(journal); } + if (result == ISC_R_SUCCESS) + dns_zone_setupdatedisabled(zone, freeze); } else { if (frozen) { - result = dns_zone_load(zone); - if (result == DNS_R_CONTINUE || - result == DNS_R_UPTODATE) + result = dns_zone_loadandthaw(zone); + switch (result) { + case ISC_R_SUCCESS: + case DNS_R_UPTODATE: + msg = "The zone reload and thaw was " + "successful."; + result = ISC_R_SUCCESS; + break; + case DNS_R_CONTINUE: + msg = "A zone reload and thaw was started.\n" + "Check the logs to see the result."; result = ISC_R_SUCCESS; + break; + } } } - if (result == ISC_R_SUCCESS) - dns_zone_setupdatedisabled(zone, freeze); + + if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text)) + isc_buffer_putmem(text, (const unsigned char *)msg, + strlen(msg) + 1); view = dns_zone_getview(zone); if (strcmp(view->name, "_bind") == 0 || diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index e2859ae5bbb..a7919fab7cc 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.160.50.4 2009/01/29 22:40:35 jinmei Exp $ */ +/* $Id: zone.h,v 1.160.50.5 2009/07/11 04:23:53 marka Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -256,6 +256,9 @@ dns_zone_load(dns_zone_t *zone); isc_result_t dns_zone_loadnew(dns_zone_t *zone); + +isc_result_t +dns_zone_loadandthaw(dns_zone_t *zone); /*%< * Cause the database to be loaded from its backing store. * Confirm that the minimum requirements for the zone type are @@ -264,6 +267,8 @@ dns_zone_loadnew(dns_zone_t *zone); * dns_zone_loadnew() only loads zones that are not yet loaded. * dns_zone_load() also loads zones that are already loaded and * and whose master file has changed since the last load. + * dns_zone_loadandthaw() is similar to dns_zone_load() but will + * also re-enable DNS UPDATEs when the load completes. * * Require: *\li 'zone' to be a valid zone. diff --git a/lib/dns/win32/libdns.def b/lib/dns/win32/libdns.def index 55228120ba2..b697c8ff314 100644 --- a/lib/dns/win32/libdns.def +++ b/lib/dns/win32/libdns.def @@ -717,6 +717,7 @@ dns_zone_iattach dns_zone_idetach dns_zone_isforced dns_zone_load +dns_zone_loadandthaw dns_zone_log dns_zone_maintenance dns_zone_markdirty diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 5a4fab3654c..712ee8a4dfa 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.483.36.7 2009/06/17 04:53:57 marka Exp $ */ +/* $Id: zone.c,v 1.483.36.8 2009/07/11 04:23:53 marka Exp $ */ /*! \file */ @@ -351,11 +351,15 @@ struct dns_zone { #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U +#define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */ +#define DNS_ZONEFLG_THAW 0x08000000U #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0) /* Flags for zone_load() */ #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */ +#define DNS_ZONELOADFLAG_THAW 0x00000002U /* Thaw the zone on successful + load. */ #define UNREACH_CHACHE_SIZE 10U #define UNREACH_HOLD_TIME 600 /* 10 minutes */ @@ -1314,7 +1318,9 @@ zone_load(dns_zone_t *zone, unsigned int flags) { INSIST(zone->type != dns_zone_none); if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) { - result = ISC_R_SUCCESS; + if ((flags & DNS_ZONELOADFLAG_THAW) != 0) + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW); + result = DNS_R_CONTINUE; goto cleanup; } @@ -1448,6 +1454,8 @@ zone_load(dns_zone_t *zone, unsigned int flags) { if (result == DNS_R_CONTINUE) { DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING); + if ((flags & DNS_ZONELOADFLAG_THAW) != 0) + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW); goto cleanup; } @@ -1470,6 +1478,30 @@ dns_zone_loadnew(dns_zone_t *zone) { return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT)); } +isc_result_t +dns_zone_loadandthaw(dns_zone_t *zone) { + isc_result_t result; + + result = zone_load(zone, DNS_ZONELOADFLAG_THAW); + switch (result) { + case DNS_R_CONTINUE: + /* Deferred thaw. */ + break; + case ISC_R_SUCCESS: + case DNS_R_UPTODATE: + case DNS_R_SEENINCLUDE: + zone->update_disabled = ISC_FALSE; + break; + case DNS_R_NOMASTERFILE: + zone->update_disabled = ISC_FALSE; + break; + default: + /* Error, remain in disabled state. */ + break; + } + return (result); +} + static unsigned int get_master_options(dns_zone_t *zone) { unsigned int options; @@ -9875,6 +9907,13 @@ zone_loaddone(void *arg, isc_result_t result) { (void)zone_postload(load->zone, load->db, load->loadtime, result); zonemgr_putio(&load->zone->readio); DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING); + /* + * Leave the zone frozen if the reload fails. + */ + if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) && + DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW)) + zone->update_disabled = ISC_FALSE; + DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW); UNLOCK_ZONE(load->zone); load->magic = 0;