"all zones loaded");
}
+ /*
+ * Clear taskmgr privileged mode now that zones are loaded.
+ */
+ isc_taskmgr_setmode(dns_zonemgr_gettaskmgr(server->zonemgr),
+ isc_taskmgrmode_normal);
+
CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr),
"forcing zone maintenance");
}
static isc_result_t
-load_zones(named_server_t *server, bool reconfig) {
+load_zones(named_server_t *server, bool init, bool reconfig) {
isc_result_t result;
dns_view_t *view;
ns_zoneload_t *zl;
isc_mem_put(server->mctx, zl, sizeof(*zl));
}
+ /*
+ * If we're setting up the server for the first time,
+ * set the task manager into privileged mode; this ensures
+ * that no other tasks will begin to run until after
+ * zone loading is complete.
+ *
+ * We do *not* want to do this in the case of reload or
+ * reconfig, as loading a large zone could cause the server
+ * to be inactive for too long a time.
+ */
+ isc_taskmgr_setmode(named_g_taskmgr, init ? isc_taskmgrmode_privileged
+ : isc_taskmgrmode_normal);
+
isc_task_endexclusive(server->task);
return (result);
}
CHECKFATAL(load_configuration(named_g_conffile, server, true),
"loading configuration");
- CHECKFATAL(load_zones(server, false), "loading zones");
+ CHECKFATAL(load_zones(server, true, false), "loading zones");
#ifdef ENABLE_AFL
named_g_run_done = true;
#endif /* ifdef ENABLE_AFL */
CHECK(loadconfig(server));
- result = load_zones(server, false);
+ result = load_zones(server, false, false);
if (result == ISC_R_SUCCESS) {
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
CHECK(loadconfig(server));
- result = load_zones(server, true);
+ result = load_zones(server, false, true);
if (result == ISC_R_SUCCESS) {
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
*\li 'zone->zmgr' == NULL;
*/
+isc_taskmgr_t *
+dns_zonemgr_gettaskmgr(dns_zonemgr_t *zmgr);
+/*%
+ * Get the tasmkgr object attached to 'zmgr'.
+ */
+
void
dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value);
/*%<
*/
uint32_t
-dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr);
+dns_zonemgr_gettransfersin(dns_zonemgr_t *zmgr);
/*%<
* Return the maximum number of simultaneous transfers in allowed.
*
*/
uint32_t
-dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr);
+dns_zonemgr_gettransfersperns(dns_zonemgr_t *zmgr);
/*%<
* Return the number of transfers allowed per nameserver.
*
dns_zonemgr_getnotifyrate
dns_zonemgr_getserialqueryrate
dns_zonemgr_getstartupnotifyrate
-dns_zonemgr_getttransfersin
-dns_zonemgr_getttransfersperns
+dns_zonemgr_gettaskmgr
+dns_zonemgr_gettransfersin
+dns_zonemgr_gettransfersperns
dns_zonemgr_managezone
dns_zonemgr_releasezone
dns_zonemgr_resumexfrs
}
uint32_t
-dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
+dns_zonemgr_gettransfersin(dns_zonemgr_t *zmgr) {
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
return (zmgr->transfersin);
}
uint32_t
-dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
+dns_zonemgr_gettransfersperns(dns_zonemgr_t *zmgr) {
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
return (zmgr->transfersperns);
}
+isc_taskmgr_t *
+dns_zonemgr_gettaskmgr(dns_zonemgr_t *zmgr) {
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ return (zmgr->taskmgr);
+}
+
/*
* Try to start a new incoming zone transfer to fill a quota
* slot that was just vacated.
#pragma once
/*****
-***** Module Info
-*****/
+ ***** Module Info
+ *****/
/*! \file isc/task.h
* \brief The task system provides a lightweight execution context, which is
#define ISC_TASKEVENT_LASTEVENT (ISC_EVENTCLASS_TASK + 65535)
/*****
-***** Tasks.
-*****/
+ ***** Tasks.
+ *****/
ISC_LANG_BEGINDECLS
* but when the task manager has been set to privileged execution mode via
* isc_taskmgr_setmode(), only tasks with the flag set will be executed,
* and all other tasks will wait until they're done. Once all privileged
- * tasks have finished executing, the task manager will automatically
- * return to normal execution mode and nonprivileged task can resume.
+ * tasks have finished executing, the task manager resumes running
+ * non-privileged tasks.
*
* Requires:
*\li 'task' is a valid task.
*/
bool
-isc_task_privilege(isc_task_t *task);
+isc_task_getprivilege(isc_task_t *task);
/*%<
* Returns the current value of the task's privilege flag.
*
*\li 'task' is a valid task.
*/
+bool
+isc_task_privileged(isc_task_t *task);
+/*%<
+ * Returns true if the task's privilege flag is set *and* the task
+ * manager is currently in privileged mode.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ */
+
/*****
-***** Task Manager.
-*****/
+ ***** Task Manager.
+ *****/
void
isc_taskmgr_attach(isc_taskmgr_t *, isc_taskmgr_t **);
void
isc_taskmgr_detach(isc_taskmgr_t *);
+/*%<
+ * Attach/detach the task manager.
+ */
+
+void
+isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode);
+isc_taskmgrmode_t
+isc_taskmgr_mode(isc_taskmgr_t *manager);
+/*%<
+ * Set/get the operating mode of the task manager. Valid modes are:
+ *
+ *\li isc_taskmgrmode_normal
+ *\li isc_taskmgrmode_privileged
+ *
+ * In privileged execution mode, only tasks that have had the "privilege"
+ * flag set via isc_task_setprivilege() can be executed. When all such
+ * tasks are complete, non-privileged tasks resume running. The task calling
+ * this function should be in task-exclusive mode; the privileged tasks
+ * will be run after isc_task_endexclusive() is called.
+ *
+ * Requires:
+ *
+ *\li 'manager' is a valid task manager.
+ */
void
isc_taskmgr_setexcltask(isc_taskmgr_t *mgr, isc_task_t *task);
worker = &nm->workers[tid];
- if (isc_task_privilege(task)) {
+ if (isc_task_privileged(task)) {
event = (isc__netievent_t *)
isc__nm_get_netievent_privilegedtask(nm, task);
} else {
/* Locked by task manager lock. */
unsigned int default_quantum;
LIST(isc_task_t) tasks;
+ atomic_uint_fast32_t mode;
atomic_bool exclusive_req;
atomic_bool exiting;
INIT_LIST(manager->tasks);
atomic_init(&manager->exiting, false);
+ atomic_init(&manager->mode, isc_taskmgrmode_normal);
atomic_store_relaxed(&manager->exclusive_req, false);
isc_mem_attach(mctx, &manager->mctx);
}
}
+void
+isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode) {
+ atomic_store(&manager->mode, mode);
+}
+
+isc_taskmgrmode_t
+isc_taskmgr_mode(isc_taskmgr_t *manager) {
+ return (atomic_load(&manager->mode));
+}
+
void
isc_task_setprivilege(isc_task_t *task, bool priv) {
REQUIRE(VALID_TASK(task));
}
bool
-isc_task_privilege(isc_task_t *task) {
+isc_task_getprivilege(isc_task_t *task) {
REQUIRE(VALID_TASK(task));
return (TASK_PRIVILEGED(task));
}
+bool
+isc_task_privileged(isc_task_t *task) {
+ REQUIRE(VALID_TASK(task));
+
+ return (isc_taskmgr_mode(task->manager) && TASK_PRIVILEGED(task));
+}
+
bool
isc_task_exiting(isc_task_t *task) {
REQUIRE(VALID_TASK(task));
* queue without things happening while we do it.
*/
isc_nm_pause(netmgr);
+ isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged);
result = isc_task_create(taskmgr, 0, &task1);
assert_int_equal(result, ISC_R_SUCCESS);
isc_task_setname(task1, "privileged", NULL);
- assert_false(isc_task_privilege(task1));
+ assert_false(isc_task_getprivilege(task1));
isc_task_setprivilege(task1, true);
- assert_true(isc_task_privilege(task1));
+ assert_true(isc_task_getprivilege(task1));
result = isc_task_create(taskmgr, 0, &task2);
assert_int_equal(result, ISC_R_SUCCESS);
isc_task_setname(task2, "normal", NULL);
- assert_false(isc_task_privilege(task2));
+ assert_false(isc_task_getprivilege(task2));
/* First event: privileged */
event = isc_event_allocate(test_mctx, task1, ISC_TASKEVENT_TEST, set,
assert_int_equal(atomic_load(&counter), 6);
isc_task_setprivilege(task1, false);
- assert_false(isc_task_privilege(task1));
+ assert_false(isc_task_getprivilege(task1));
isc_task_destroy(&task1);
assert_null(task1);
* without things happening while we do it.
*/
isc_nm_pause(netmgr);
+ isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged);
result = isc_task_create(taskmgr, 0, &task1);
assert_int_equal(result, ISC_R_SUCCESS);
isc_task_setname(task1, "privileged", NULL);
- assert_false(isc_task_privilege(task1));
+ assert_false(isc_task_getprivilege(task1));
isc_task_setprivilege(task1, true);
- assert_true(isc_task_privilege(task1));
+ assert_true(isc_task_getprivilege(task1));
result = isc_task_create(taskmgr, 0, &task2);
assert_int_equal(result, ISC_R_SUCCESS);
isc_task_setname(task2, "normal", NULL);
- assert_false(isc_task_privilege(task2));
+ assert_false(isc_task_getprivilege(task2));
/* First event: privileged */
event = isc_event_allocate(test_mctx, task1, ISC_TASKEVENT_TEST,
assert_true(VALID_TASK(task2));
assert_true(VALID_TASK(task3));
- assert_true(isc_task_privilege(task1));
- assert_true(isc_task_privilege(task2));
- assert_true(isc_task_privilege(task3));
+ assert_true(isc_task_getprivilege(task1));
+ assert_true(isc_task_getprivilege(task2));
+ assert_true(isc_task_getprivilege(task3));
isc_task_destroy(&task1);
isc_task_destroy(&task2);
isc_task_exiting
isc_task_getcurrenttime
isc_task_getcurrenttimex
+isc_task_getprivilege
isc_task_onshutdown
isc_task_pause
-isc_task_privilege
+isc_task_privileged
isc_task_purge
isc_task_purgeevent
isc_task_purgerange
isc_task_unpause
isc_task_unsend
isc_taskmgr_excltask
+isc_taskmgr_mode
@IF NOTYET
isc_taskmgr_renderjson
@END NOTYET
isc_taskmgr_renderxml
@END LIBXML2
isc_taskmgr_setexcltask
+isc_taskmgr_setmode
isc_taskpool_create
isc_taskpool_destroy
isc_taskpool_expand