2
0
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:
Evan Hunt
2011-07-06 01:36:32 +00:00
parent 007eafcd07
commit 42cf2ff7ba
17 changed files with 799 additions and 415 deletions

View File

@@ -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;