2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

1905. [bug] Recursive clients soft quota support wasn't working

as expected. [RT #15103]
This commit is contained in:
Mark Andrews
2005-07-27 02:29:01 +00:00
parent 0992797c70
commit 8abe06b25d
7 changed files with 97 additions and 61 deletions

View File

@@ -1,3 +1,6 @@
1905. [bug] Recursive clients soft quota support wasn't working
as expected. [RT #15103]
1904. [bug] A escaped character is, potentially, converted to 1904. [bug] A escaped character is, potentially, converted to
the output character set too early. [RT #14666] the output character set too early. [RT #14666]

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: client.c,v 1.228 2005/06/07 00:15:59 marka Exp $ */ /* $Id: client.c,v 1.229 2005/07/27 02:28:58 marka Exp $ */
#include <config.h> #include <config.h>
@@ -181,23 +181,29 @@ static void client_request(isc_task_t *task, isc_event_t *event);
static void ns_client_dumpmessage(ns_client_t *client, const char *reason); static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
void void
ns_client_recursing(ns_client_t *client, isc_boolean_t killoldest) { ns_client_recursing(ns_client_t *client) {
REQUIRE(NS_CLIENT_VALID(client));
LOCK(&client->manager->lock);
ISC_LIST_UNLINK(*client->list, client, link);
ISC_LIST_APPEND(client->manager->recursing, client, link);
client->list = &client->manager->recursing;
UNLOCK(&client->manager->lock);
}
void
ns_client_killoldestquery(ns_client_t *client) {
ns_client_t *oldest; ns_client_t *oldest;
REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(NS_CLIENT_VALID(client));
LOCK(&client->manager->lock); LOCK(&client->manager->lock);
if (killoldest) { oldest = ISC_LIST_HEAD(client->manager->recursing);
oldest = ISC_LIST_HEAD(client->manager->recursing); if (oldest != NULL) {
if (oldest != NULL) { ns_query_cancel(oldest);
ns_query_cancel(oldest); ISC_LIST_UNLINK(*oldest->list, oldest, link);
ISC_LIST_UNLINK(*oldest->list, oldest, link); ISC_LIST_APPEND(client->manager->active, oldest, link);
ISC_LIST_APPEND(client->manager->active, oldest, link); oldest->list = &client->manager->active;
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); UNLOCK(&client->manager->lock);
} }

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: client.h,v 1.75 2005/07/18 05:58:57 marka Exp $ */ /* $Id: client.h,v 1.76 2005/07/27 02:28:59 marka Exp $ */
#ifndef NAMED_CLIENT_H #ifndef NAMED_CLIENT_H
#define NAMED_CLIENT_H 1 #define NAMED_CLIENT_H 1
@@ -326,10 +326,15 @@ ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
DNS_RDATACLASS_FORMATSIZE + sizeof(x) + sizeof("'/'")) DNS_RDATACLASS_FORMATSIZE + sizeof(x) + sizeof("'/'"))
void void
ns_client_recursing(ns_client_t *client, isc_boolean_t killoldest); ns_client_recursing(ns_client_t *client);
/*% /*%
* Add client to end of recursing list. If 'killoldest' is true * Add client to end of th recursing list.
* kill the oldest recursive client (list head). */
void
ns_client_killoldestquery(ns_client_t *client);
/*%
* Kill the oldest recursive query (recursing list head).
*/ */
void void

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: query.c,v 1.268 2005/06/27 00:15:42 marka Exp $ */ /* $Id: query.c,v 1.269 2005/07/27 02:28:58 marka Exp $ */
/*! \file */ /*! \file */
@@ -2701,33 +2701,37 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
* connection was accepted (if allowed by the TCP quota). * connection was accepted (if allowed by the TCP quota).
*/ */
if (client->recursionquota == NULL) { if (client->recursionquota == NULL) {
isc_boolean_t killoldest = ISC_FALSE;
result = isc_quota_attach(&ns_g_server->recursionquota, result = isc_quota_attach(&ns_g_server->recursionquota,
&client->recursionquota); &client->recursionquota);
if (result == ISC_R_SOFTQUOTA) { if (result == ISC_R_SOFTQUOTA) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT, ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_QUERY, ISC_LOG_WARNING, NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
"recursive-clients limit exceeded, " "recursive-clients soft limit exceeded, "
"aborting oldest query"); "aborting oldest query");
killoldest = ISC_TRUE; ns_client_killoldestquery(client);
result = ISC_R_SUCCESS; result == ISC_R_SUCCESS;
} } else if (result == ISC_R_QUOTA) {
if (dns_resolver_nrunning(client->view->resolver) >
(unsigned int)ns_g_server->recursionquota.max)
result = ISC_R_QUOTA;
if (result == ISC_R_SUCCESS && !client->mortal &&
(client->attributes & NS_CLIENTATTR_TCP) == 0)
result = ns_client_replace(client);
if (result != ISC_R_SUCCESS) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT, ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_QUERY, ISC_LOG_WARNING, NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
"no more recursive clients: %s", "no more recursive clients: %s",
isc_result_totext(result)); isc_result_totext(result));
if (client->recursionquota != NULL) ns_client_killoldestquery(client);
isc_quota_detach(&client->recursionquota);
return (result);
} }
ns_client_recursing(client, killoldest); if (result == ISC_R_SUCCESS && !client->mortal &&
(client->attributes & NS_CLIENTATTR_TCP) == 0) {
result = ns_client_replace(client);
if (result != ISC_R_SUCCESS) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_QUERY,
ISC_LOG_WARNING,
"ns_client_replace() failed: %s",
isc_result_totext(result));
isc_quota_detach(&client->recursionquota);
}
}
if (result != ISC_R_SUCCESS)
return (result);
ns_client_recursing(client);
} }
/* /*

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: server.c,v 1.445 2005/06/27 00:15:42 marka Exp $ */ /* $Id: server.c,v 1.446 2005/07/27 02:28:58 marka Exp $ */
/*! \file */ /*! \file */
@@ -1882,7 +1882,7 @@ configure_server_quota(cfg_obj_t **maps, const char *name, isc_quota_t *quota)
result = ns_config_get(maps, name, &obj); result = ns_config_get(maps, name, &obj);
INSIST(result == ISC_R_SUCCESS); INSIST(result == ISC_R_SUCCESS);
quota->max = cfg_obj_asuint32(obj); isc_quota_max(quota, cfg_obj_asuint32(obj));
} }
/* /*
@@ -2309,6 +2309,11 @@ load_configuration(const char *filename, ns_server_t *server,
configure_server_quota(maps, "tcp-clients", &server->tcpquota); configure_server_quota(maps, "tcp-clients", &server->tcpquota);
configure_server_quota(maps, "recursive-clients", configure_server_quota(maps, "recursive-clients",
&server->recursionquota); &server->recursionquota);
if (server->recursionquota.max > 1000)
isc_quota_soft(&server->recursionquota,
server->recursionquota.max - 100);
else
isc_quota_soft(&server->recursionquota, 0);
CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx, CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx,
ns_g_mctx, &server->blackholeacl)); ns_g_mctx, &server->blackholeacl));
@@ -3036,7 +3041,6 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
RUNTIME_CHECK(result == ISC_R_SUCCESS); RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = isc_quota_init(&server->recursionquota, 100); result = isc_quota_init(&server->recursionquota, 100);
RUNTIME_CHECK(result == ISC_R_SUCCESS); RUNTIME_CHECK(result == ISC_R_SUCCESS);
isc_quota_soft(&server->recursionquota, ISC_FALSE);
result = dns_aclenv_init(mctx, &server->aclenv); result = dns_aclenv_init(mctx, &server->aclenv);
RUNTIME_CHECK(result == ISC_R_SUCCESS); RUNTIME_CHECK(result == ISC_R_SUCCESS);
@@ -4147,12 +4151,13 @@ ns_server_status(ns_server_t *server, isc_buffer_t *text) {
"xfers deferred: %u\n" "xfers deferred: %u\n"
"soa queries in progress: %u\n" "soa queries in progress: %u\n"
"query logging is %s\n" "query logging is %s\n"
"recursive clients: %d/%d\n" "recursive clients: %d/%d/%d\n"
"tcp clients: %d/%d\n" "tcp clients: %d/%d\n"
"server is up and running", "server is up and running",
zonecount, ns_g_debuglevel, xferrunning, xferdeferred, zonecount, ns_g_debuglevel, xferrunning, xferdeferred,
soaqueries, server->log_queries ? "ON" : "OFF", soaqueries, server->log_queries ? "ON" : "OFF",
server->recursionquota.used, server->recursionquota.max, server->recursionquota.used, server->recursionquota.soft,
server->recursionquota.max,
server->tcpquota.used, server->tcpquota.max); server->tcpquota.used, server->tcpquota.max);
if (n >= isc_buffer_availablelength(text)) if (n >= isc_buffer_availablelength(text))
return (ISC_R_NOSPACE); return (ISC_R_NOSPACE);

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: quota.h,v 1.12 2005/04/29 00:23:42 marka Exp $ */ /* $Id: quota.h,v 1.13 2005/07/27 02:29:01 marka Exp $ */
#ifndef ISC_QUOTA_H #ifndef ISC_QUOTA_H
#define ISC_QUOTA_H 1 #define ISC_QUOTA_H 1
@@ -72,9 +72,15 @@ isc_quota_destroy(isc_quota_t *quota);
*/ */
void void
isc_quota_soft(isc_quota_t *quota, isc_boolean_t soft); isc_quota_soft(isc_quota_t *quota, int soft);
/*%< /*%<
* Turn on/off soft quotas. * Set a soft quota.
*/
void
isc_quota_max(isc_quota_t *quota, int max);
/*%<
* Re-set a maximum quota.
*/ */
isc_result_t isc_result_t
@@ -83,9 +89,9 @@ isc_quota_reserve(isc_quota_t *quota);
* Attempt to reserve one unit of 'quota'. * Attempt to reserve one unit of 'quota'.
* *
* Returns: * Returns:
*\li #ISC_R_SUCCESS Success * \li #ISC_R_SUCCESS Success
*\li #ISC_R_SOFTQUOTA Success soft quota reached * \li #ISC_R_SOFTQUOTA Success soft quota reached
*\li #ISC_R_QUOTA Quota is full * \li #ISC_R_QUOTA Quota is full
*/ */
void void

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: quota.c,v 1.15 2005/04/29 00:23:29 marka Exp $ */ /* $Id: quota.c,v 1.16 2005/07/27 02:29:00 marka Exp $ */
/*! \file */ /*! \file */
@@ -30,38 +30,45 @@ isc_result_t
isc_quota_init(isc_quota_t *quota, int max) { isc_quota_init(isc_quota_t *quota, int max) {
quota->max = max; quota->max = max;
quota->used = 0; quota->used = 0;
quota->soft = ISC_FALSE; quota->soft = 0;
return (isc_mutex_init(&quota->lock)); return (isc_mutex_init(&quota->lock));
} }
void void
isc_quota_destroy(isc_quota_t *quota) { isc_quota_destroy(isc_quota_t *quota) {
INSIST(quota->used == 0); INSIST(quota->used == 0);
quota->max = -1; quota->max = 0;
quota->used = -1; quota->used = 0;
quota->soft = ISC_FALSE; quota->soft = 0;
DESTROYLOCK(&quota->lock); DESTROYLOCK(&quota->lock);
} }
void void
isc_quota_soft(isc_quota_t *quota, isc_boolean_t soft) { isc_quota_soft(isc_quota_t *quota, int soft) {
LOCK(&quota->lock);
quota->soft = soft; quota->soft = soft;
UNLOCK(&quota->lock);
}
void
isc_quota_max(isc_quota_t *quota, int max) {
LOCK(&quota->lock);
quota->max = max;
UNLOCK(&quota->lock);
} }
isc_result_t isc_result_t
isc_quota_reserve(isc_quota_t *quota) { isc_quota_reserve(isc_quota_t *quota) {
isc_result_t result; isc_result_t result;
LOCK(&quota->lock); LOCK(&quota->lock);
if (quota->used < quota->max) { if (quota->max == 0 || quota->used < quota->max) {
quota->used++; if (quota->soft == 0 || quota->used < quota->soft)
result = ISC_R_SUCCESS; result = ISC_R_SUCCESS;
} else { else
if (quota->soft) {
quota->used++;
result = ISC_R_SOFTQUOTA; result = ISC_R_SOFTQUOTA;
} else quota->used++;
result = ISC_R_QUOTA; } else
} result = ISC_R_QUOTA;
UNLOCK(&quota->lock); UNLOCK(&quota->lock);
return (result); return (result);
} }