mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
Reduce the number of clientmgr objects created
Previously, as a way of reducing the contention between threads a clientmgr object would be created for each interface/IP address. We tasks being more strictly bound to netmgr workers, this is no longer needed and we can just create clientmgr object per worker queue (ncpus). Each clientmgr object than would have a single task and single memory context.
This commit is contained in:
168
lib/ns/client.c
168
lib/ns/client.c
@@ -132,8 +132,6 @@ ns_client_dumpmessage(ns_client_t *client, const char *reason);
|
||||
static void
|
||||
compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
|
||||
const unsigned char *secret, isc_buffer_t *buf);
|
||||
static void
|
||||
get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp);
|
||||
|
||||
void
|
||||
ns_client_recursing(ns_client_t *client) {
|
||||
@@ -321,10 +319,10 @@ client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
|
||||
void
|
||||
ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
|
||||
isc_result_t result;
|
||||
unsigned char *data;
|
||||
unsigned char *data = NULL;
|
||||
isc_buffer_t buffer;
|
||||
isc_region_t r;
|
||||
isc_region_t *mr;
|
||||
isc_region_t *mr = NULL;
|
||||
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
|
||||
@@ -387,7 +385,7 @@ done:
|
||||
void
|
||||
ns_client_send(ns_client_t *client) {
|
||||
isc_result_t result;
|
||||
unsigned char *data;
|
||||
unsigned char *data = NULL;
|
||||
isc_buffer_t buffer = { .magic = 0 };
|
||||
isc_region_t r;
|
||||
dns_compress_t cctx;
|
||||
@@ -396,7 +394,7 @@ ns_client_send(ns_client_t *client) {
|
||||
unsigned int preferred_glue;
|
||||
bool opt_included = false;
|
||||
size_t respsize;
|
||||
dns_aclenv_t *env;
|
||||
dns_aclenv_t *env = NULL;
|
||||
#ifdef HAVE_DNSTAP
|
||||
unsigned char zone[DNS_NAME_MAXWIRE];
|
||||
dns_dtmsgtype_t dtmsgtype;
|
||||
@@ -414,7 +412,7 @@ ns_client_send(ns_client_t *client) {
|
||||
* Delay the response according to the -T delay option
|
||||
*/
|
||||
|
||||
env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
|
||||
env = client->manager->aclenv;
|
||||
|
||||
CTRACE("send");
|
||||
|
||||
@@ -876,24 +874,24 @@ isc_result_t
|
||||
ns_client_addopt(ns_client_t *client, dns_message_t *message,
|
||||
dns_rdataset_t **opt) {
|
||||
unsigned char ecs[ECS_SIZE];
|
||||
char nsid[BUFSIZ], *nsidp;
|
||||
char nsid[BUFSIZ], *nsidp = NULL;
|
||||
unsigned char cookie[COOKIE_SIZE];
|
||||
isc_result_t result;
|
||||
dns_view_t *view;
|
||||
dns_resolver_t *resolver;
|
||||
dns_view_t *view = NULL;
|
||||
dns_resolver_t *resolver = NULL;
|
||||
uint16_t udpsize;
|
||||
dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
|
||||
int count = 0;
|
||||
unsigned int flags;
|
||||
unsigned char expire[4];
|
||||
unsigned char advtimo[2];
|
||||
dns_aclenv_t *env;
|
||||
dns_aclenv_t *env = NULL;
|
||||
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
REQUIRE(opt != NULL && *opt == NULL);
|
||||
REQUIRE(message != NULL);
|
||||
|
||||
env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
|
||||
env = client->manager->aclenv;
|
||||
view = client->view;
|
||||
resolver = (view != NULL) ? view->resolver : NULL;
|
||||
if (resolver != NULL) {
|
||||
@@ -1569,10 +1567,6 @@ ns__client_put_cb(void *client0) {
|
||||
client->magic = 0;
|
||||
client->shuttingdown = true;
|
||||
|
||||
if (client->manager != NULL) {
|
||||
clientmgr_detach(&client->manager);
|
||||
}
|
||||
|
||||
isc_mem_put(client->mctx, client->sendbuf, NS_CLIENT_SEND_BUFFER_SIZE);
|
||||
if (client->opt != NULL) {
|
||||
INSIST(dns_rdataset_isassociated(client->opt));
|
||||
@@ -1582,6 +1576,10 @@ ns__client_put_cb(void *client0) {
|
||||
|
||||
dns_message_detach(&client->message);
|
||||
|
||||
if (client->manager != NULL) {
|
||||
clientmgr_detach(&client->manager);
|
||||
}
|
||||
|
||||
/*
|
||||
* Detaching the task must be done after unlinking from
|
||||
* the manager's lists because the manager accesses
|
||||
@@ -1601,9 +1599,7 @@ ns__client_put_cb(void *client0) {
|
||||
ns_server_detach(&client->sctx);
|
||||
}
|
||||
|
||||
if (client->mctx != NULL) {
|
||||
isc_mem_detach(&client->mctx);
|
||||
}
|
||||
isc_mem_detach(&client->mctx);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1628,6 +1624,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
bool notimp;
|
||||
size_t reqsize;
|
||||
dns_aclenv_t *env = NULL;
|
||||
isc_sockaddr_t sockaddr;
|
||||
#ifdef HAVE_DNSTAP
|
||||
dns_dtmsgtype_t dtmsgtype;
|
||||
#endif /* ifdef HAVE_DNSTAP */
|
||||
@@ -1639,12 +1636,14 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
client = isc_nmhandle_getdata(handle);
|
||||
if (client == NULL) {
|
||||
ns_interface_t *ifp = (ns_interface_t *)arg;
|
||||
ns_clientmgr_t *clientmgr =
|
||||
ns_interfacemgr_getclientmgr(ifp->mgr);
|
||||
|
||||
INSIST(VALID_MANAGER(ifp->clientmgr));
|
||||
INSIST(VALID_MANAGER(clientmgr));
|
||||
|
||||
client = isc_nmhandle_getextra(handle);
|
||||
|
||||
result = ns__client_setup(client, ifp->clientmgr, true);
|
||||
result = ns__client_setup(client, clientmgr, true);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
@@ -1705,7 +1704,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
}
|
||||
#endif /* if NS_CLIENT_DROPPORT */
|
||||
|
||||
env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
|
||||
env = client->manager->aclenv;
|
||||
if (client->sctx->blackholeacl != NULL &&
|
||||
(dns_acl_match(&netaddr, NULL, client->sctx->blackholeacl, env,
|
||||
&match, NULL) == ISC_R_SUCCESS) &&
|
||||
@@ -1921,26 +1920,8 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the destination address. If the receiving interface is
|
||||
* bound to a specific address, we simply use it regardless of the
|
||||
* address family. All IPv4 queries should fall into this case.
|
||||
* Otherwise, if this is a TCP query, get the address from the
|
||||
* receiving socket (this needs a system call and can be heavy).
|
||||
* For IPv6 UDP queries, we get this from the pktinfo structure (if
|
||||
* supported).
|
||||
*
|
||||
* If all the attempts fail (this can happen due to memory shortage,
|
||||
* etc), we regard this as an error for safety.
|
||||
*/
|
||||
if ((client->manager->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
|
||||
{
|
||||
isc_netaddr_fromsockaddr(&client->destaddr,
|
||||
&client->manager->interface->addr);
|
||||
} else {
|
||||
isc_sockaddr_t sockaddr = isc_nmhandle_localaddr(handle);
|
||||
isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
|
||||
}
|
||||
sockaddr = isc_nmhandle_localaddr(handle);
|
||||
isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
|
||||
|
||||
isc_sockaddr_fromnetaddr(&client->destsockaddr, &client->destaddr, 0);
|
||||
|
||||
@@ -2202,17 +2183,6 @@ ns__client_tcpconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp) {
|
||||
MTRACE("clienttask");
|
||||
|
||||
int tid = isc_nm_tid();
|
||||
REQUIRE(tid >= 0);
|
||||
REQUIRE(tid < manager->ncpus);
|
||||
|
||||
isc_task_attach(manager->taskpool[tid], taskp);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
isc_result_t result;
|
||||
@@ -2225,16 +2195,17 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
* The caller is responsible for that.
|
||||
*/
|
||||
|
||||
REQUIRE(NS_CLIENT_VALID(client) || (new &&client != NULL));
|
||||
REQUIRE(VALID_MANAGER(mgr) || !new);
|
||||
|
||||
if (new) {
|
||||
*client = (ns_client_t){ .magic = 0 };
|
||||
REQUIRE(VALID_MANAGER(mgr));
|
||||
REQUIRE(client != NULL);
|
||||
REQUIRE(mgr->tid == isc_nm_tid());
|
||||
|
||||
*client = (ns_client_t){ .magic = 0, .tid = mgr->tid };
|
||||
|
||||
isc_mem_attach(mgr->mctx, &client->mctx);
|
||||
clientmgr_attach(mgr, &client->manager);
|
||||
ns_server_attach(mgr->sctx, &client->sctx);
|
||||
get_clienttask(mgr, &client->task);
|
||||
isc_task_attach(mgr->task, &client->task);
|
||||
|
||||
dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
|
||||
&client->message);
|
||||
@@ -2251,6 +2222,9 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
REQUIRE(client->tid == isc_nm_tid());
|
||||
|
||||
ns_clientmgr_t *oldmgr = client->manager;
|
||||
ns_server_t *sctx = client->sctx;
|
||||
isc_task_t *task = client->task;
|
||||
@@ -2258,6 +2232,7 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
dns_message_t *message = client->message;
|
||||
isc_mem_t *oldmctx = client->mctx;
|
||||
ns_query_t query = client->query;
|
||||
int tid = client->tid;
|
||||
|
||||
/*
|
||||
* Retain these values from the existing client, but
|
||||
@@ -2270,7 +2245,8 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
.task = task,
|
||||
.sendbuf = sendbuf,
|
||||
.message = message,
|
||||
.query = query };
|
||||
.query = query,
|
||||
.tid = tid };
|
||||
}
|
||||
|
||||
client->query.attributes &= ~NS_QUERYATTR_ANSWERED;
|
||||
@@ -2308,9 +2284,7 @@ cleanup:
|
||||
if (client->manager != NULL) {
|
||||
clientmgr_detach(&client->manager);
|
||||
}
|
||||
if (client->mctx != NULL) {
|
||||
isc_mem_detach(&client->mctx);
|
||||
}
|
||||
isc_mem_detach(&client->mctx);
|
||||
if (client->sctx != NULL) {
|
||||
ns_server_detach(&client->sctx);
|
||||
}
|
||||
@@ -2359,16 +2333,12 @@ clientmgr_detach(ns_clientmgr_t **mp) {
|
||||
|
||||
static void
|
||||
clientmgr_destroy(ns_clientmgr_t *manager) {
|
||||
int i;
|
||||
|
||||
MTRACE("clientmgr_destroy");
|
||||
|
||||
isc_refcount_destroy(&manager->references);
|
||||
manager->magic = 0;
|
||||
|
||||
if (manager->interface != NULL) {
|
||||
ns_interface_detach(&manager->interface);
|
||||
}
|
||||
dns_aclenv_detach(&manager->aclenv);
|
||||
|
||||
isc_mutex_destroy(&manager->lock);
|
||||
isc_mutex_destroy(&manager->reclock);
|
||||
@@ -2377,54 +2347,45 @@ clientmgr_destroy(ns_clientmgr_t *manager) {
|
||||
isc_task_detach(&manager->excl);
|
||||
}
|
||||
|
||||
for (i = 0; i < manager->ncpus; i++) {
|
||||
if (manager->taskpool[i] != NULL) {
|
||||
isc_task_detach(&manager->taskpool[i]);
|
||||
}
|
||||
}
|
||||
isc_mem_put(manager->mctx, manager->taskpool,
|
||||
manager->ncpus * sizeof(manager->taskpool[0]));
|
||||
isc_task_detach(&manager->task);
|
||||
ns_server_detach(&manager->sctx);
|
||||
|
||||
isc_mem_put(manager->mctx, manager, sizeof(*manager));
|
||||
isc_mem_putanddetach(&manager->mctx, manager, sizeof(*manager));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr,
|
||||
isc_timermgr_t *timermgr, ns_interface_t *interface,
|
||||
int ncpus, ns_clientmgr_t **managerp) {
|
||||
ns_clientmgr_t *manager;
|
||||
ns_clientmgr_create(ns_server_t *sctx, isc_taskmgr_t *taskmgr,
|
||||
isc_timermgr_t *timermgr, dns_aclenv_t *aclenv, int tid,
|
||||
ns_clientmgr_t **managerp) {
|
||||
ns_clientmgr_t *manager = NULL;
|
||||
isc_mem_t *mctx = NULL;
|
||||
isc_result_t result;
|
||||
int i;
|
||||
|
||||
isc_mem_create(&mctx);
|
||||
|
||||
manager = isc_mem_get(mctx, sizeof(*manager));
|
||||
*manager = (ns_clientmgr_t){ .magic = 0 };
|
||||
*manager = (ns_clientmgr_t){ .magic = 0, .mctx = mctx };
|
||||
|
||||
result = isc_taskmgr_excltask(taskmgr, &manager->excl);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(mctx, manager, sizeof(*manager));
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_mutex_init(&manager->lock);
|
||||
isc_mutex_init(&manager->reclock);
|
||||
|
||||
manager->excl = NULL;
|
||||
result = isc_taskmgr_excltask(taskmgr, &manager->excl);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_reclock;
|
||||
}
|
||||
|
||||
manager->mctx = mctx;
|
||||
manager->taskmgr = taskmgr;
|
||||
manager->timermgr = timermgr;
|
||||
manager->ncpus = ncpus;
|
||||
manager->tid = tid;
|
||||
|
||||
ns_interface_attach(interface, &manager->interface);
|
||||
dns_aclenv_attach(aclenv, &manager->aclenv);
|
||||
|
||||
manager->exiting = false;
|
||||
manager->taskpool = isc_mem_get(
|
||||
mctx, manager->ncpus * sizeof(manager->taskpool[0]));
|
||||
for (i = 0; i < manager->ncpus; i++) {
|
||||
manager->taskpool[i] = NULL;
|
||||
result = isc_task_create_bound(manager->taskmgr, 20,
|
||||
&manager->taskpool[i], i);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
}
|
||||
result = isc_task_create_bound(manager->taskmgr, 20, &manager->task,
|
||||
manager->tid);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
isc_refcount_init(&manager->references, 1);
|
||||
manager->sctx = NULL;
|
||||
ns_server_attach(sctx, &manager->sctx);
|
||||
@@ -2438,14 +2399,6 @@ ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr,
|
||||
*managerp = manager;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup_reclock:
|
||||
isc_mutex_destroy(&manager->reclock);
|
||||
isc_mutex_destroy(&manager->lock);
|
||||
|
||||
isc_mem_put(mctx, manager, sizeof(*manager));
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2496,8 +2449,7 @@ isc_result_t
|
||||
ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
|
||||
dns_acl_t *acl, bool default_allow) {
|
||||
isc_result_t result;
|
||||
dns_aclenv_t *env =
|
||||
ns_interfacemgr_getaclenv(client->manager->interface->mgr);
|
||||
dns_aclenv_t *env = client->manager->aclenv;
|
||||
isc_netaddr_t tmpnetaddr;
|
||||
int match;
|
||||
|
||||
|
Reference in New Issue
Block a user