From 8abe06b25d245ab2955d81525bfe6bd29b80908e Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 27 Jul 2005 02:29:01 +0000 Subject: [PATCH] 1905. [bug] Recursive clients soft quota support wasn't working as expected. [RT #15103] --- CHANGES | 3 +++ bin/named/client.c | 32 ++++++++++++++----------- bin/named/include/named/client.h | 13 +++++++---- bin/named/query.c | 40 ++++++++++++++++++-------------- bin/named/server.c | 15 ++++++++---- lib/isc/include/isc/quota.h | 18 +++++++++----- lib/isc/quota.c | 37 +++++++++++++++++------------ 7 files changed, 97 insertions(+), 61 deletions(-) diff --git a/CHANGES b/CHANGES index a743b9ecaf..ee698f1ff1 100644 --- a/CHANGES +++ b/CHANGES @@ -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 the output character set too early. [RT #14666] diff --git a/bin/named/client.c b/bin/named/client.c index 14009bf296..f999545beb 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -15,7 +15,7 @@ * 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 @@ -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); 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; 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; - } + 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); } diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index 9b3c130a63..334c813cd3 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -15,7 +15,7 @@ * 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 #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("'/'")) 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 - * kill the oldest recursive client (list head). + * Add client to end of th recursing list. + */ + +void +ns_client_killoldestquery(ns_client_t *client); +/*% + * Kill the oldest recursive query (recursing list head). */ void diff --git a/bin/named/query.c b/bin/named/query.c index ebb7b4a788..b08e1a2dfb 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -15,7 +15,7 @@ * 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 */ @@ -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). */ if (client->recursionquota == NULL) { - isc_boolean_t killoldest = ISC_FALSE; result = isc_quota_attach(&ns_g_server->recursionquota, &client->recursionquota); - if (result == ISC_R_SOFTQUOTA) { + if (result == ISC_R_SOFTQUOTA) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, - "recursive-clients limit exceeded, " + "recursive-clients soft limit exceeded, " "aborting oldest query"); - killoldest = ISC_TRUE; - result = ISC_R_SUCCESS; - } - 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_killoldestquery(client); + result == ISC_R_SUCCESS; + } else if (result == ISC_R_QUOTA) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, "no more recursive clients: %s", isc_result_totext(result)); - if (client->recursionquota != NULL) - isc_quota_detach(&client->recursionquota); - return (result); + ns_client_killoldestquery(client); } - 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); } /* diff --git a/bin/named/server.c b/bin/named/server.c index b57d1dc580..39ff745f74 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * 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 */ @@ -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); 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, "recursive-clients", &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, 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); result = isc_quota_init(&server->recursionquota, 100); RUNTIME_CHECK(result == ISC_R_SUCCESS); - isc_quota_soft(&server->recursionquota, ISC_FALSE); result = dns_aclenv_init(mctx, &server->aclenv); 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" "soa queries in progress: %u\n" "query logging is %s\n" - "recursive clients: %d/%d\n" + "recursive clients: %d/%d/%d\n" "tcp clients: %d/%d\n" "server is up and running", zonecount, ns_g_debuglevel, xferrunning, xferdeferred, 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); if (n >= isc_buffer_availablelength(text)) return (ISC_R_NOSPACE); diff --git a/lib/isc/include/isc/quota.h b/lib/isc/include/isc/quota.h index 69488312b2..9b6544e48f 100644 --- a/lib/isc/include/isc/quota.h +++ b/lib/isc/include/isc/quota.h @@ -15,7 +15,7 @@ * 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 #define ISC_QUOTA_H 1 @@ -72,9 +72,15 @@ isc_quota_destroy(isc_quota_t *quota); */ 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 @@ -83,9 +89,9 @@ isc_quota_reserve(isc_quota_t *quota); * Attempt to reserve one unit of 'quota'. * * Returns: - *\li #ISC_R_SUCCESS Success - *\li #ISC_R_SOFTQUOTA Success soft quota reached - *\li #ISC_R_QUOTA Quota is full + * \li #ISC_R_SUCCESS Success + * \li #ISC_R_SOFTQUOTA Success soft quota reached + * \li #ISC_R_QUOTA Quota is full */ void diff --git a/lib/isc/quota.c b/lib/isc/quota.c index 099094d7d8..41360fdbf9 100644 --- a/lib/isc/quota.c +++ b/lib/isc/quota.c @@ -15,7 +15,7 @@ * 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 */ @@ -30,38 +30,45 @@ isc_result_t isc_quota_init(isc_quota_t *quota, int max) { quota->max = max; quota->used = 0; - quota->soft = ISC_FALSE; + quota->soft = 0; return (isc_mutex_init("a->lock)); } void isc_quota_destroy(isc_quota_t *quota) { INSIST(quota->used == 0); - quota->max = -1; - quota->used = -1; - quota->soft = ISC_FALSE; + quota->max = 0; + quota->used = 0; + quota->soft = 0; DESTROYLOCK("a->lock); } void -isc_quota_soft(isc_quota_t *quota, isc_boolean_t soft) { +isc_quota_soft(isc_quota_t *quota, int soft) { + LOCK("a->lock); quota->soft = soft; + UNLOCK("a->lock); +} + +void +isc_quota_max(isc_quota_t *quota, int max) { + LOCK("a->lock); + quota->max = max; + UNLOCK("a->lock); } isc_result_t isc_quota_reserve(isc_quota_t *quota) { isc_result_t result; LOCK("a->lock); - if (quota->used < quota->max) { - quota->used++; - result = ISC_R_SUCCESS; - } else { - if (quota->soft) { - quota->used++; + if (quota->max == 0 || quota->used < quota->max) { + if (quota->soft == 0 || quota->used < quota->soft) + result = ISC_R_SUCCESS; + else result = ISC_R_SOFTQUOTA; - } else - result = ISC_R_QUOTA; - } + quota->used++; + } else + result = ISC_R_QUOTA; UNLOCK("a->lock); return (result); }