mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
3131. [func] Improve scalability by allocating one zone task
per 100 zones at startup time, rather than using a fixed-size task table. [RT #24406]
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: server.c,v 1.612 2011/06/17 07:05:01 each Exp $ */
|
||||
/* $Id: server.c,v 1.613 2011/07/06 01:36:31 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -204,12 +204,14 @@ struct zonelistentry {
|
||||
|
||||
/*%
|
||||
* Configuration context to retain for each view that allows
|
||||
* new zones to be added at runtime
|
||||
* new zones to be added at runtime.
|
||||
*/
|
||||
struct cfg_context {
|
||||
isc_mem_t * mctx;
|
||||
cfg_obj_t * config;
|
||||
cfg_parser_t * parser;
|
||||
cfg_obj_t * config;
|
||||
cfg_parser_t * nzparser;
|
||||
cfg_obj_t * nzconfig;
|
||||
cfg_aclconfctx_t * actx;
|
||||
};
|
||||
|
||||
@@ -1545,8 +1547,7 @@ configure_rpz(dns_view_t *view, const cfg_listelt_t *element) {
|
||||
* global defaults in 'config' used exclusively.
|
||||
*/
|
||||
static isc_result_t
|
||||
configure_view(dns_view_t *view, cfg_parser_t* parser,
|
||||
cfg_obj_t *config, cfg_obj_t *vconfig,
|
||||
configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
|
||||
ns_cachelist_t *cachelist, const cfg_obj_t *bindkeys,
|
||||
isc_mem_t *mctx, cfg_aclconfctx_t *actx,
|
||||
isc_boolean_t need_hints)
|
||||
@@ -1601,10 +1602,9 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
|
||||
isc_boolean_t auto_root = ISC_FALSE;
|
||||
ns_cache_t *nsc;
|
||||
isc_boolean_t zero_no_soattl;
|
||||
cfg_parser_t *newzones_parser = NULL;
|
||||
cfg_obj_t *nzfconf = NULL;
|
||||
dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL;
|
||||
unsigned int query_timeout;
|
||||
struct cfg_context *nzctx;
|
||||
|
||||
REQUIRE(DNS_VIEW_VALID(view));
|
||||
|
||||
@@ -1710,6 +1710,10 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
|
||||
(void)cfg_map_get(voptions, "zone", &zonelist);
|
||||
else
|
||||
(void)cfg_map_get(config, "zone", &zonelist);
|
||||
|
||||
/*
|
||||
* Load zone configuration
|
||||
*/
|
||||
for (element = cfg_list_first(zonelist);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element))
|
||||
@@ -1719,58 +1723,29 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
|
||||
actx, ISC_FALSE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Are we allowing zones to be added and deleted dynamically?
|
||||
*/
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "allow-new-zones", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_boolean_t allow = cfg_obj_asboolean(obj);
|
||||
struct cfg_context *cfg = NULL;
|
||||
if (allow) {
|
||||
cfg = isc_mem_get(view->mctx, sizeof(*cfg));
|
||||
if (cfg == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
memset(cfg, 0, sizeof(*cfg));
|
||||
isc_mem_attach(view->mctx, &cfg->mctx);
|
||||
if (config != NULL)
|
||||
cfg_obj_attach(config, &cfg->config);
|
||||
cfg_parser_attach(parser, &cfg->parser);
|
||||
cfg_aclconfctx_attach(actx, &cfg->actx);
|
||||
}
|
||||
dns_view_setnewzones(view, allow, cfg, newzone_cfgctx_destroy);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're allowing added zones, then load zone configuration
|
||||
* from the newzone file for zones that were added during previous
|
||||
* runs.
|
||||
*/
|
||||
if (view->new_zone_file != NULL) {
|
||||
nzctx = view->new_zone_config;
|
||||
if (nzctx != NULL && nzctx->nzconfig != NULL) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_INFO,
|
||||
"loading additional zones for view '%s'",
|
||||
view->name);
|
||||
|
||||
CHECK(cfg_parser_create(view->mctx, ns_g_lctx,
|
||||
&newzones_parser));
|
||||
result = cfg_parse_file(newzones_parser, view->new_zone_file,
|
||||
&cfg_type_newzones, &nzfconf);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
zonelist = NULL;
|
||||
cfg_map_get(nzfconf, "zone", &zonelist);
|
||||
for (element = cfg_list_first(zonelist);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element))
|
||||
{
|
||||
const cfg_obj_t *zconfig =
|
||||
cfg_listelt_value(element);
|
||||
CHECK(configure_zone(config, zconfig, vconfig,
|
||||
mctx, view, actx,
|
||||
ISC_TRUE));
|
||||
}
|
||||
zonelist = NULL;
|
||||
cfg_map_get(nzctx->nzconfig, "zone", &zonelist);
|
||||
|
||||
for (element = cfg_list_first(zonelist);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element))
|
||||
{
|
||||
const cfg_obj_t *zconfig = cfg_listelt_value(element);
|
||||
CHECK(configure_zone(config, zconfig, vconfig,
|
||||
mctx, view, actx,
|
||||
ISC_TRUE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2904,8 +2879,8 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
|
||||
if (result == ISC_R_SUCCESS)
|
||||
cfg_map_get(obj, "zone", &zonelist);
|
||||
}
|
||||
if (zonelist != NULL) {
|
||||
|
||||
if (zonelist != NULL) {
|
||||
for (element = cfg_list_first(zonelist);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element)) {
|
||||
@@ -2947,12 +2922,6 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
|
||||
if (cache != NULL)
|
||||
dns_cache_detach(&cache);
|
||||
|
||||
if (newzones_parser != NULL) {
|
||||
if (nzfconf != NULL)
|
||||
cfg_obj_destroy(newzones_parser, &nzfconf);
|
||||
cfg_parser_destroy(&newzones_parser);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
@@ -3157,6 +3126,61 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
get_viewinfo(const cfg_obj_t *vconfig, const char **namep,
|
||||
dns_rdataclass_t *classp)
|
||||
{
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
const char *viewname;
|
||||
dns_rdataclass_t viewclass;
|
||||
|
||||
REQUIRE(namep != NULL && *namep == NULL);
|
||||
REQUIRE(classp != NULL);
|
||||
|
||||
if (vconfig != NULL) {
|
||||
const cfg_obj_t *classobj = NULL;
|
||||
|
||||
viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
|
||||
classobj = cfg_tuple_get(vconfig, "class");
|
||||
result = ns_config_getclass(classobj, dns_rdataclass_in,
|
||||
&viewclass);
|
||||
} else {
|
||||
viewname = "_default";
|
||||
viewclass = dns_rdataclass_in;
|
||||
}
|
||||
|
||||
*namep = viewname;
|
||||
*classp = viewclass;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a view based on its configuration info and attach to it.
|
||||
*
|
||||
* If 'vconfig' is NULL, attach to the default view.
|
||||
*/
|
||||
static isc_result_t
|
||||
find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
|
||||
dns_view_t **viewp)
|
||||
{
|
||||
isc_result_t result;
|
||||
const char *viewname = NULL;
|
||||
dns_rdataclass_t viewclass;
|
||||
dns_view_t *view = NULL;
|
||||
|
||||
result = get_viewinfo(vconfig, &viewname, &viewclass);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
*viewp = view;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new view and add it to the list.
|
||||
*
|
||||
@@ -3169,22 +3193,14 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
|
||||
dns_view_t **viewp)
|
||||
{
|
||||
isc_result_t result;
|
||||
const char *viewname;
|
||||
const char *viewname = NULL;
|
||||
dns_rdataclass_t viewclass;
|
||||
dns_view_t *view = NULL;
|
||||
|
||||
if (vconfig != NULL) {
|
||||
const cfg_obj_t *classobj = NULL;
|
||||
|
||||
viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
|
||||
classobj = cfg_tuple_get(vconfig, "class");
|
||||
result = ns_config_getclass(classobj, dns_rdataclass_in,
|
||||
&viewclass);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
} else {
|
||||
viewname = "_default";
|
||||
viewclass = dns_rdataclass_in;
|
||||
}
|
||||
result = get_viewinfo(vconfig, &viewname, &viewclass);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
return (ISC_R_EXISTS);
|
||||
@@ -4175,6 +4191,95 @@ configure_session_key(const cfg_obj_t **maps, ns_server_t *server,
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
|
||||
cfg_parser_t *parser, cfg_aclconfctx_t *actx)
|
||||
{
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_boolean_t allow = ISC_FALSE;
|
||||
struct cfg_context *nzcfg = NULL;
|
||||
cfg_parser_t *nzparser = NULL;
|
||||
cfg_obj_t *nzconfig = NULL;
|
||||
const cfg_obj_t *maps[4];
|
||||
const cfg_obj_t *options = NULL, *voptions = NULL;
|
||||
const cfg_obj_t *nz = NULL;
|
||||
int i = 0;
|
||||
|
||||
REQUIRE (config != NULL);
|
||||
|
||||
if (vconfig != NULL)
|
||||
voptions = cfg_tuple_get(vconfig, "options");
|
||||
if (voptions != NULL)
|
||||
maps[i++] = voptions;
|
||||
result = cfg_map_get(config, "options", &options);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
maps[i++] = options;
|
||||
maps[i++] = ns_g_defaults;
|
||||
maps[i] = NULL;
|
||||
|
||||
result = ns_config_get(maps, "allow-new-zones", &nz);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
allow = cfg_obj_asboolean(nz);
|
||||
|
||||
if (!allow) {
|
||||
dns_view_setnewzones(view, ISC_FALSE, NULL, NULL);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
nzcfg = isc_mem_get(view->mctx, sizeof(*nzcfg));
|
||||
if (nzcfg == NULL) {
|
||||
dns_view_setnewzones(view, ISC_FALSE, NULL, NULL);
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
|
||||
dns_view_setnewzones(view, allow, nzcfg, newzone_cfgctx_destroy);
|
||||
|
||||
memset(nzcfg, 0, sizeof(*nzcfg));
|
||||
isc_mem_attach(view->mctx, &nzcfg->mctx);
|
||||
cfg_obj_attach(config, &nzcfg->config);
|
||||
cfg_parser_attach(parser, &nzcfg->parser);
|
||||
cfg_aclconfctx_attach(actx, &nzcfg->actx);
|
||||
|
||||
/*
|
||||
* Attempt to create a parser and parse the newzones
|
||||
* file. If successful, preserve both; otherwise leave
|
||||
* them NULL.
|
||||
*/
|
||||
result = cfg_parser_create(view->mctx, ns_g_lctx, &nzparser);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
result = cfg_parse_file(nzparser, view->new_zone_file,
|
||||
&cfg_type_newzones, &nzconfig);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
cfg_parser_attach(nzparser, &nzcfg->nzparser);
|
||||
cfg_obj_attach(nzconfig, &nzcfg->nzconfig);
|
||||
}
|
||||
|
||||
if (nzparser != NULL) {
|
||||
if (nzconfig != NULL)
|
||||
cfg_obj_destroy(nzparser, &nzconfig);
|
||||
cfg_parser_destroy(&nzparser);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
count_zones(const cfg_obj_t *conf) {
|
||||
const cfg_obj_t *zonelist = NULL;
|
||||
const cfg_listelt_t *element;
|
||||
int n = 0;
|
||||
|
||||
REQUIRE(conf != NULL);
|
||||
|
||||
cfg_map_get(conf, "zone", &zonelist);
|
||||
for (element = cfg_list_first(zonelist);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element))
|
||||
n++;
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
load_configuration(const char *filename, ns_server_t *server,
|
||||
isc_boolean_t first_time)
|
||||
@@ -4206,6 +4311,8 @@ load_configuration(const char *filename, ns_server_t *server,
|
||||
ns_cachelist_t cachelist, tmpcachelist;
|
||||
unsigned int maxsocks;
|
||||
ns_cache_t *nsc;
|
||||
struct cfg_context *nzctx;
|
||||
int num_zones = 0;
|
||||
|
||||
ISC_LIST_INIT(viewlist);
|
||||
ISC_LIST_INIT(builtin_viewlist);
|
||||
@@ -4633,25 +4740,87 @@ load_configuration(const char *filename, ns_server_t *server,
|
||||
*/
|
||||
(void)configure_session_key(maps, server, ns_g_mctx);
|
||||
|
||||
/*
|
||||
* Configure and freeze all explicit views. Explicit
|
||||
* views that have zones were already created at parsing
|
||||
* time, but views with no zones must be created here.
|
||||
*/
|
||||
views = NULL;
|
||||
(void)cfg_map_get(config, "view", &views);
|
||||
|
||||
/*
|
||||
* Create the views and count all the configured zones in
|
||||
* order to correctly size the zone manager's task table.
|
||||
* (We only count zones for configured views; the built-in
|
||||
* "bind" view can be ignored as it only adds a negligible
|
||||
* number of zones.)
|
||||
*
|
||||
* If we're allowing new zones, we need to be able to find the
|
||||
* new zone file and count those as well. So we setup the new
|
||||
* zone configuration context, but otherwise view configuration
|
||||
* waits until after the zone manager's task list has been sized.
|
||||
*/
|
||||
for (element = cfg_list_first(views);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element))
|
||||
{
|
||||
cfg_obj_t *vconfig = cfg_listelt_value(element);
|
||||
const cfg_obj_t *voptions = cfg_tuple_get(vconfig, "options");
|
||||
view = NULL;
|
||||
|
||||
CHECK(create_view(vconfig, &viewlist, &view));
|
||||
INSIST(view != NULL);
|
||||
CHECK(configure_view(view, conf_parser, config, vconfig,
|
||||
&cachelist, bindkeys,
|
||||
ns_g_mctx, ns_g_aclconfctx, ISC_TRUE));
|
||||
|
||||
num_zones += count_zones(voptions);
|
||||
CHECK(setup_newzones(view, config, vconfig, conf_parser,
|
||||
ns_g_aclconfctx));
|
||||
|
||||
nzctx = view->new_zone_config;
|
||||
if (nzctx != NULL && nzctx->nzconfig != NULL)
|
||||
num_zones += count_zones(nzctx->nzconfig);
|
||||
|
||||
dns_view_detach(&view);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there were no explicit views then we do the default
|
||||
* view here.
|
||||
*/
|
||||
if (views == NULL) {
|
||||
CHECK(create_view(NULL, &viewlist, &view));
|
||||
INSIST(view != NULL);
|
||||
|
||||
num_zones = count_zones(config);
|
||||
|
||||
CHECK(setup_newzones(view, config, NULL, conf_parser,
|
||||
ns_g_aclconfctx));
|
||||
|
||||
nzctx = view->new_zone_config;
|
||||
if (nzctx != NULL && nzctx->nzconfig != NULL)
|
||||
num_zones += count_zones(nzctx->nzconfig);
|
||||
|
||||
dns_view_detach(&view);
|
||||
}
|
||||
|
||||
/*
|
||||
* Zones have been counted; set the zone manager task pool size.
|
||||
*/
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_INFO,
|
||||
"sizing zone task pool based on %d zones", num_zones);
|
||||
CHECK(dns_zonemgr_setsize(ns_g_server->zonemgr, num_zones));
|
||||
|
||||
/*
|
||||
* Configure and freeze all explicit views. Explicit
|
||||
* views that have zones were already created at parsing
|
||||
* time, but views with no zones must be created here.
|
||||
*/
|
||||
for (element = cfg_list_first(views);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element))
|
||||
{
|
||||
cfg_obj_t *vconfig = cfg_listelt_value(element);
|
||||
|
||||
view = NULL;
|
||||
CHECK(find_view(vconfig, &viewlist, &view));
|
||||
CHECK(configure_view(view, config, vconfig,
|
||||
&cachelist, bindkeys, ns_g_mctx,
|
||||
ns_g_aclconfctx, ISC_TRUE));
|
||||
dns_view_freeze(view);
|
||||
dns_view_detach(&view);
|
||||
}
|
||||
@@ -4661,14 +4830,9 @@ load_configuration(const char *filename, ns_server_t *server,
|
||||
* were no explicit views.
|
||||
*/
|
||||
if (views == NULL) {
|
||||
/*
|
||||
* No explicit views; there ought to be a default view.
|
||||
* There may already be one created as a side effect
|
||||
* of zone statements, or we may have to create one.
|
||||
* In either case, we need to configure and freeze it.
|
||||
*/
|
||||
CHECK(create_view(NULL, &viewlist, &view));
|
||||
CHECK(configure_view(view, conf_parser, config, NULL,
|
||||
view = NULL;
|
||||
CHECK(find_view(NULL, &viewlist, &view));
|
||||
CHECK(configure_view(view, config, NULL,
|
||||
&cachelist, bindkeys,
|
||||
ns_g_mctx, ns_g_aclconfctx, ISC_TRUE));
|
||||
dns_view_freeze(view);
|
||||
@@ -4688,7 +4852,7 @@ load_configuration(const char *filename, ns_server_t *server,
|
||||
cfg_obj_t *vconfig = cfg_listelt_value(element);
|
||||
|
||||
CHECK(create_view(vconfig, &builtin_viewlist, &view));
|
||||
CHECK(configure_view(view, conf_parser, config, vconfig,
|
||||
CHECK(configure_view(view, config, vconfig,
|
||||
&cachelist, bindkeys,
|
||||
ns_g_mctx, ns_g_aclconfctx, ISC_FALSE));
|
||||
dns_view_freeze(view);
|
||||
@@ -5311,6 +5475,8 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
|
||||
CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,
|
||||
ns_g_socketmgr, &server->zonemgr),
|
||||
"dns_zonemgr_create");
|
||||
CHECKFATAL(dns_zonemgr_setsize(server->zonemgr, 1000),
|
||||
"dns_zonemgr_setsize");
|
||||
|
||||
server->statsfile = isc_mem_strdup(server->mctx, "named.stats");
|
||||
CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
|
||||
@@ -5420,7 +5586,8 @@ ns_server_destroy(ns_server_t **serverp) {
|
||||
if (server->server_id != NULL)
|
||||
isc_mem_free(server->mctx, server->server_id);
|
||||
|
||||
dns_zonemgr_detach(&server->zonemgr);
|
||||
if (server->zonemgr != NULL)
|
||||
dns_zonemgr_detach(&server->zonemgr);
|
||||
|
||||
if (server->tkeyctx != NULL)
|
||||
dns_tkeyctx_destroy(&server->tkeyctx);
|
||||
@@ -7589,6 +7756,11 @@ newzone_cfgctx_destroy(void **cfgp) {
|
||||
cfg_obj_destroy(cfg->parser, &cfg->config);
|
||||
cfg_parser_destroy(&cfg->parser);
|
||||
}
|
||||
if (cfg->nzparser != NULL) {
|
||||
if (cfg->nzconfig != NULL)
|
||||
cfg_obj_destroy(cfg->nzparser, &cfg->nzconfig);
|
||||
cfg_parser_destroy(&cfg->nzparser);
|
||||
}
|
||||
|
||||
isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg));
|
||||
*cfgp = NULL;
|
||||
|
Reference in New Issue
Block a user