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:
2
CHANGES
2
CHANGES
@@ -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().
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user