]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1905. [bug] Recursive clients soft quota support wasn't working
authorMark Andrews <marka@isc.org>
Wed, 27 Jul 2005 02:29:01 +0000 (02:29 +0000)
committerMark Andrews <marka@isc.org>
Wed, 27 Jul 2005 02:29:01 +0000 (02:29 +0000)
                        as expected. [RT #15103]

CHANGES
bin/named/client.c
bin/named/include/named/client.h
bin/named/query.c
bin/named/server.c
lib/isc/include/isc/quota.h
lib/isc/quota.c

diff --git a/CHANGES b/CHANGES
index a743b9ecaf48867ea710bedd1a539268ed43e462..ee698f1ff1becde0da7afcaed31451b06dd5270b 100644 (file)
--- 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]
 
index 14009bf296776ec564764fc374dcbfb11e56b1a2..f999545beb8a0b41b303895e2d33a17055864e79 100644 (file)
@@ -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 <config.h>
 
@@ -181,26 +181,32 @@ 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;
+ns_client_recursing(ns_client_t *client) {
        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);
 }
 
+void
+ns_client_killoldestquery(ns_client_t *client) {
+       ns_client_t *oldest;
+       REQUIRE(NS_CLIENT_VALID(client));
+
+       LOCK(&client->manager->lock);
+       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;
+       }
+       UNLOCK(&client->manager->lock);
+}
+
 void
 ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
        isc_result_t result;
index 9b3c130a63c562959478acf231d328d52a4787f7..334c813cd3b70e13aae49bea0920894cc8abe8cf 100644 (file)
@@ -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
index ebb7b4a788c1e4eabaef713520819a4e2b47b984..b08e1a2dfb75c6f738bb380a8082d780c92b5973 100644 (file)
@@ -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)
+                       ns_client_killoldestquery(client);
+               }
+               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);
-                       return (result);
+                       }
                }
-               ns_client_recursing(client, killoldest);
+               if (result != ISC_R_SUCCESS)
+                       return (result);
+               ns_client_recursing(client);
        }
 
        /*
index b57d1dc580bf188db3a759cdbe6866d65228766b..39ff745f7453e5862e0a95691c52943c0bd3427e 100644 (file)
@@ -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);
index 69488312b27063b4fc8a781b18d3ecc712873d43..9b6544e48f6ebdfb80706a2bb80cf6a6d887e711 100644 (file)
@@ -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
index 099094d7d82a1531b424abb13ce34151b31bb428..41360fdbf9fe3bf043fc8d428f7b1c61722c9f73 100644 (file)
@@ -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(&quota->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(&quota->lock);
 }
 
 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;
+       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_quota_reserve(isc_quota_t *quota) {
        isc_result_t result;
        LOCK(&quota->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(&quota->lock);
        return (result);
 }