2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 22:15:20 +00:00

1069. [func] Kill oldest recursive query when recursive query

quota is exhausted.
This commit is contained in:
Mark Andrews
2001-10-24 03:10:18 +00:00
parent 897f762e3c
commit b19619260f
6 changed files with 88 additions and 17 deletions

View File

@@ -1,3 +1,5 @@
1069. [func] Kill oldest recursive query when recursive query quota is exhausted.
1068. [bug] errno could be overwritten by catgets(). [RT #1921]
1067. [func] Allow quotas to be soft, isc_quota_soft().

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: client.c,v 1.189 2001/10/13 01:10:26 gson Exp $ */
/* $Id: client.c,v 1.190 2001/10/24 03:10:13 marka Exp $ */
#include <config.h>
@@ -95,6 +95,7 @@ struct ns_clientmgr {
/* Locked by lock. */
isc_boolean_t exiting;
client_list_t active; /* Active clients */
client_list_t recursing; /* Recursing clients */
client_list_t inactive; /* To be recycled */
};
@@ -173,6 +174,27 @@ static void client_start(isc_task_t *task, isc_event_t *event);
static void client_request(isc_task_t *task, isc_event_t *event);
static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
void
ns_client_recursing(ns_client_t *client, isc_boolean_t killoldest) {
ns_client_t *oldest;
REQUIRE(NS_CLIENT_VALID(client));
LOCK(&client->manager->lock);
if (killoldest) {
oldest = ISC_LIST_HEAD(client->manager->recursing);
if (oldest != NULL) {
ns_query_cancel(oldest);
ISC_LIST_UNLINK(*oldest->list, oldest, link);
ISC_LIST_APPEND(client->manager->active, oldest, link);
oldest->list = &client->manager->active;
}
}
ISC_LIST_UNLINK(*client->list, client, link);
ISC_LIST_APPEND(client->manager->recursing, client, link);
client->list = &client->manager->recursing;
UNLOCK(&client->manager->lock);
}
/*
* Enter the inactive state.
*
@@ -201,7 +223,7 @@ client_deactivate(ns_client_t *client) {
client->mortal = ISC_FALSE;
LOCK(&client->manager->lock);
ISC_LIST_UNLINK(client->manager->active, client, link);
ISC_LIST_UNLINK(*client->list, client, link);
ISC_LIST_APPEND(client->manager->inactive, client, link);
client->list = &client->manager->inactive;
UNLOCK(&client->manager->lock);
@@ -251,7 +273,8 @@ client_free(ns_client_t *client) {
client->list = NULL;
if (manager->exiting &&
ISC_LIST_EMPTY(manager->active) &&
ISC_LIST_EMPTY(manager->inactive))
ISC_LIST_EMPTY(manager->inactive) &&
ISC_LIST_EMPTY(manager->recursing))
need_clientmgr_destroy = ISC_TRUE;
UNLOCK(&manager->lock);
}
@@ -506,7 +529,6 @@ client_shutdown(isc_task_t *task, isc_event_t *event) {
(void)exit_check(client);
}
static void
ns_client_endrequest(ns_client_t *client) {
INSIST(client->naccepts == 0);
@@ -1860,6 +1882,7 @@ static void
clientmgr_destroy(ns_clientmgr_t *manager) {
REQUIRE(ISC_LIST_EMPTY(manager->active));
REQUIRE(ISC_LIST_EMPTY(manager->inactive));
REQUIRE(ISC_LIST_EMPTY(manager->recursing));
MTRACE("clientmgr_destroy");
@@ -1889,6 +1912,7 @@ ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
manager->exiting = ISC_FALSE;
ISC_LIST_INIT(manager->active);
ISC_LIST_INIT(manager->inactive);
ISC_LIST_INIT(manager->recursing);
manager->magic = MANAGER_MAGIC;
MTRACE("create");
@@ -1919,6 +1943,11 @@ ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
manager->exiting = ISC_TRUE;
for (client = ISC_LIST_HEAD(manager->recursing);
client != NULL;
client = ISC_LIST_NEXT(client, link))
isc_task_shutdown(client->task);
for (client = ISC_LIST_HEAD(manager->active);
client != NULL;
client = ISC_LIST_NEXT(client, link))
@@ -1930,7 +1959,8 @@ ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
isc_task_shutdown(client->task);
if (ISC_LIST_EMPTY(manager->active) &&
ISC_LIST_EMPTY(manager->inactive))
ISC_LIST_EMPTY(manager->inactive) &&
ISC_LIST_EMPTY(manager->recursing))
need_destroy = ISC_TRUE;
UNLOCK(&manager->lock);

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: client.h,v 1.61 2001/10/01 18:53:58 gson Exp $ */
/* $Id: client.h,v 1.62 2001/10/24 03:10:17 marka Exp $ */
#ifndef NAMED_CLIENT_H
#define NAMED_CLIENT_H 1
@@ -306,4 +306,11 @@ void
ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdataclass_t rdclass,
char *buf, size_t len);
void
ns_client_recursing(ns_client_t *client, isc_boolean_t killoldest);
/*
* Add client to end of recursing list. If 'killoldest' is true
* kill the oldest recursive client (list head).
*/
#endif /* NAMED_CLIENT_H */

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.h,v 1.30 2001/09/21 19:08:06 gson Exp $ */
/* $Id: query.h,v 1.31 2001/10/24 03:10:18 marka Exp $ */
#ifndef NAMED_QUERY_H
#define NAMED_QUERY_H 1
@@ -49,6 +49,7 @@ struct ns_query {
dns_zone_t * authzone;
isc_boolean_t authdbset;
isc_boolean_t isreferral;
isc_mutex_t fetchlock;
dns_fetch_t * fetch;
dns_a6context_t a6ctx;
isc_bufferlist_t namebufs;
@@ -84,4 +85,7 @@ ns_query_free(ns_client_t *client);
void
ns_query_start(ns_client_t *client);
void
ns_query_cancel(ns_client_t *client);
#endif /* NAMED_QUERY_H */

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.c,v 1.205 2001/10/23 06:04:37 marka Exp $ */
/* $Id: query.c,v 1.206 2001/10/24 03:10:14 marka Exp $ */
#include <config.h>
@@ -204,6 +204,17 @@ query_maybeputqname(ns_client_t *client) {
}
}
void
ns_query_cancel(ns_client_t *client) {
LOCK(&client->query.fetchlock);
if (client->query.fetch != NULL) {
dns_resolver_cancelfetch(client->query.fetch);
client->query.fetch = NULL;
}
UNLOCK(&client->query.fetchlock);
}
static inline void
query_reset(ns_client_t *client, isc_boolean_t everything) {
isc_buffer_t *dbuf, *dbuf_next;
@@ -217,11 +228,7 @@ query_reset(ns_client_t *client, isc_boolean_t everything) {
/*
* Cancel the fetch if it's running.
*/
if (client->query.fetch != NULL) {
dns_resolver_cancelfetch(client->query.fetch);
client->query.fetch = NULL;
}
ns_query_cancel(client);
/*
* Cleanup any active versions.
@@ -509,6 +516,9 @@ ns_query_init(ns_client_t *client) {
client->query.restarts = 0;
client->query.timerset = ISC_FALSE;
client->query.qname = NULL;
result = isc_mutex_init(&client->query.fetchlock);
if (result != ISC_R_SUCCESS)
return (result);
client->query.fetch = NULL;
client->query.authdb = NULL;
client->query.authzone = NULL;
@@ -516,13 +526,16 @@ ns_query_init(ns_client_t *client) {
client->query.isreferral = ISC_FALSE;
query_reset(client, ISC_FALSE);
result = query_newdbversion(client, 3);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
DESTROYLOCK(&client->query.fetchlock);
return (result);
}
dns_a6_init(&client->query.a6ctx, query_simplefind, query_adda6rrset,
NULL, NULL, client);
result = query_newnamebuf(client);
if (result != ISC_R_SUCCESS) {
ns_dbversion_t *dbversion;
DESTROYLOCK(&client->query.fetchlock);
for (dbversion = ISC_LIST_HEAD(client->query.freeversions);
dbversion != NULL;
dbversion = ISC_LIST_HEAD(client->query.freeversions)) {
@@ -2043,6 +2056,7 @@ query_resume(isc_task_t *task, isc_event_t *event) {
REQUIRE(task == client->task);
REQUIRE(RECURSING(client));
LOCK(&client->query.fetchlock);
if (client->query.fetch != NULL) {
/*
* This is the fetch we've been waiting for.
@@ -2061,6 +2075,7 @@ query_resume(isc_task_t *task, isc_event_t *event) {
*/
fetch_cancelled = ISC_TRUE;
}
UNLOCK(&client->query.fetchlock);
INSIST(client->query.fetch == NULL);
client->query.attributes &= ~NS_QUERYATTR_RECURSING;
@@ -2080,7 +2095,10 @@ query_resume(isc_task_t *task, isc_event_t *event) {
if (devent->sigrdataset != NULL)
query_putrdataset(client, &devent->sigrdataset);
isc_event_free(&event);
query_next(client, ISC_R_CANCELED);
if (fetch_cancelled)
query_error(client, DNS_R_SERVFAIL);
else
query_next(client, ISC_R_CANCELED);
/*
* This may destroy the client.
*/
@@ -2109,9 +2127,17 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
* response.
*/
if (! client->mortal) {
isc_boolean_t killoldest = ISC_FALSE;
result = isc_quota_attach(&ns_g_server->recursionquota,
&client->recursionquota);
if (result == ISC_R_SUCCESS)
if (result == ISC_R_SOFTQUOTA) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
"killing oldest recursive client: %s",
isc_result_totext(result));
killoldest = ISC_TRUE;
}
if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA)
result = ns_client_replace(client);
if (result != ISC_R_SUCCESS) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
@@ -2120,6 +2146,7 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
isc_result_totext(result));
return (result);
}
ns_client_recursing(client, killoldest);
}
/*

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.352 2001/10/17 19:34:07 gson Exp $ */
/* $Id: server.c,v 1.353 2001/10/24 03:10:15 marka Exp $ */
#include <config.h>
@@ -2387,6 +2387,7 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = isc_quota_init(&server->recursionquota, 100);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
isc_quota_soft(&server->recursionquota, ISC_TRUE);
result = dns_aclenv_init(mctx, &server->aclenv);
RUNTIME_CHECK(result == ISC_R_SUCCESS);