]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Refactor the 'max-cache-size' configuration handling
authorOndřej Surý <ondrej@isc.org>
Thu, 19 Feb 2026 09:03:45 +0000 (10:03 +0100)
committerOndřej Surý <ondrej@isc.org>
Mon, 30 Mar 2026 19:46:44 +0000 (21:46 +0200)
Extract the inline max-cache-size logic from configure_view() into
reusable helpers: configure_max_cache_size(), default_max_cache_size(),
max_cache_size_as_percent(), and sanitized_max_cache_size().

Move DNS_CACHE_MINSIZE and DNS_ADB_MINADBSIZE to public headers and
remove the SIZE_AS_PERCENT sentinel.

bin/named/server.c
lib/dns/adb.c
lib/dns/cache.c
lib/dns/include/dns/adb.h
lib/dns/include/dns/cache.h

index 6d6fabc707ed07ed62c38e30bb5c6dd429b3326c..5d82a7ac349025d70e3f409858591f33a4e36afb 100644 (file)
 #include <limits.h>
 #include <signal.h>
 #include <stdbool.h>
+#include <stddef.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <dns/acl.h>
-
 #ifdef HAVE_DNSTAP
 #include <fstrm.h>
 #endif
@@ -60,6 +59,7 @@
 #include <isc/timer.h>
 #include <isc/util.h>
 
+#include <dns/acl.h>
 #include <dns/adb.h>
 #include <dns/badcache.h>
 #include <dns/cache.h>
 
 #include <named/config.h>
 #include <named/control.h>
+#include <named/globals.h>
 #include <named/nzd.h>
 #if defined(HAVE_GEOIP2)
 #include <named/geoip.h>
 #define SIZE_MAX ((size_t)(-1))
 #endif /* ifndef SIZE_MAX */
 
-#ifndef SIZE_AS_PERCENT
-#define SIZE_AS_PERCENT ((size_t)(-2))
-#endif /* ifndef SIZE_AS_PERCENT */
-
 /* RFC7828 defines timeout as 16-bit value specified in units of 100
  * milliseconds, so the maximum and minimum advertised and keepalive
  * timeouts are capped by the data type (it's ~109 minutes)
@@ -3575,6 +3572,117 @@ named_register_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj,
        return result;
 }
 
+static size_t
+sanitized_max_cache_size(const cfg_obj_t *obj, uint64_t value);
+
+static size_t
+max_cache_size_as_percent(const cfg_obj_t *obj, uint32_t percent) {
+       uint64_t totalphys = isc_meminfo_totalphys();
+
+       if (totalphys == 0) {
+               cfg_obj_log(obj, ISC_LOG_ERROR,
+                           "Unable to determine amount of physical "
+                           "memory, setting 'max-cache-size' to the "
+                           "minimum value");
+               return DNS_CACHE_MINSIZE;
+       }
+
+       uint64_t max_cache_size = totalphys * percent / 100;
+
+       cfg_obj_log(obj, ISC_LOG_INFO,
+                   "'max-cache-size %d%%' "
+                   "- setting to %" PRIu64 "MB "
+                   "(out of %" PRIu64 "MB)",
+                   percent, (uint64_t)(max_cache_size / (1024 * 1024)),
+                   totalphys / (1024 * 1024));
+
+       return sanitized_max_cache_size(obj, max_cache_size);
+}
+
+static size_t
+default_max_cache_size(const dns_view_t *view, const cfg_obj_t *obj) {
+       if (view->recursion) {
+               return max_cache_size_as_percent(obj, 90);
+       } else {
+               return DNS_CACHE_MINSIZE;
+       }
+}
+
+static size_t
+sanitized_max_cache_size(const cfg_obj_t *obj, uint64_t value) {
+       if (value >= DNS_CACHE_MINSIZE && value <= SIZE_MAX) {
+               return value;
+       }
+
+       if (value > SIZE_MAX) {
+               cfg_obj_log(obj, ISC_LOG_WARNING,
+                           "'max-cache-size %" PRIu64 "' "
+                           "is too large for this system; reducing to %lu",
+                           value, (unsigned long)SIZE_MAX);
+               return SIZE_MAX;
+       }
+
+       if (value < DNS_CACHE_MINSIZE) {
+               cfg_obj_log(obj, ISC_LOG_WARNING,
+                           "'max-cache-size' can't be less than %" PRIu64 "; "
+                           "setting 'max-cache-size' to the minimum value",
+                           DNS_CACHE_MINSIZE);
+               return DNS_CACHE_MINSIZE;
+       }
+
+       UNREACHABLE();
+}
+
+static size_t
+configure_max_cache_size(dns_view_t *view, const cfg_obj_t *maps[4]) {
+       isc_result_t result;
+       const cfg_obj_t *obj = NULL;
+       const char *str = NULL;
+
+       if (named_g_maxcachesize != 0) {
+               /*
+                * If "-T maxcachesize=..." is in effect, it overrides any
+                * other "max-cache-size" setting found in configuration,
+                * either implicit or explicit.  For simplicity, the value
+                * passed to that command line option is always treated as
+                * the number of bytes to set "max-cache-size" to.
+                */
+               return named_g_maxcachesize;
+       }
+
+       obj = NULL;
+       result = named_config_get(maps, "max-cache-size", &obj);
+       INSIST(result == ISC_R_SUCCESS);
+       if (cfg_obj_isstring(obj) &&
+           strcasecmp(cfg_obj_asstring(obj), "default") == 0)
+       {
+               /*
+                * The default for a view with recursion
+                * is 90% of memory. With no recursion,
+                * it's the minimum cache size allowed by
+                * dns_cache_setcachesize().
+                */
+               return default_max_cache_size(view, obj);
+       } else if (cfg_obj_isstring(obj)) {
+               str = cfg_obj_asstring(obj);
+               INSIST(strcasecmp(str, "unlimited") == 0);
+
+               cfg_obj_log(obj, ISC_LOG_WARNING,
+                           "'max-cache-size' can't be unlimited; "
+                           "falling back to default");
+
+               return default_max_cache_size(view, obj);
+       } else if (cfg_obj_ispercentage(obj)) {
+               return max_cache_size_as_percent(obj,
+                                                cfg_obj_aspercentage(obj));
+       } else if (cfg_obj_isuint64(obj)) {
+               uint64_t value = cfg_obj_asuint64(obj);
+               return sanitized_max_cache_size(obj, value);
+       } else {
+               UNREACHABLE();
+       }
+}
+
 static const char *const response_synonyms[] = { "response", NULL };
 
 /*
@@ -3613,7 +3721,6 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
        dns_cache_t *cache = NULL;
        isc_result_t result;
        size_t max_cache_size;
-       uint32_t max_cache_size_percent = 0;
        size_t max_adb_size;
        uint32_t lame_ttl, fail_ttl;
        uint32_t max_stale_ttl = 0;
@@ -3820,88 +3927,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
        INSIST(result == ISC_R_SUCCESS);
        view->recursion = cfg_obj_asboolean(obj);
 
-       if (named_g_maxcachesize != 0) {
-               /*
-                * If "-T maxcachesize=..." is in effect, it overrides any
-                * other "max-cache-size" setting found in configuration,
-                * either implicit or explicit.  For simplicity, the value
-                * passed to that command line option is always treated as
-                * the number of bytes to set "max-cache-size" to.
-                */
-               max_cache_size = named_g_maxcachesize;
-       } else {
-               obj = NULL;
-               result = named_config_get(maps, "max-cache-size", &obj);
-               INSIST(result == ISC_R_SUCCESS);
-               if (cfg_obj_isstring(obj) &&
-                   strcasecmp(cfg_obj_asstring(obj), "default") == 0)
-               {
-                       /*
-                        * The default for a view with recursion
-                        * is 90% of memory. With no recursion,
-                        * it's the minimum cache size allowed by
-                        * dns_cache_setcachesize().
-                        */
-                       if (view->recursion) {
-                               max_cache_size = SIZE_AS_PERCENT;
-                               max_cache_size_percent = 90;
-                       } else {
-                               max_cache_size = 1;
-                       }
-               } else if (cfg_obj_isstring(obj)) {
-                       str = cfg_obj_asstring(obj);
-                       INSIST(strcasecmp(str, "unlimited") == 0);
-                       max_cache_size = 0;
-               } else if (cfg_obj_ispercentage(obj)) {
-                       max_cache_size = SIZE_AS_PERCENT;
-                       max_cache_size_percent = cfg_obj_aspercentage(obj);
-               } else if (cfg_obj_isuint64(obj)) {
-                       uint64_t value = cfg_obj_asuint64(obj);
-                       if (value > SIZE_MAX) {
-                               cfg_obj_log(obj, ISC_LOG_WARNING,
-                                           "'max-cache-size "
-                                           "%" PRIu64 "' "
-                                           "is too large for this "
-                                           "system; reducing to %lu",
-                                           value, (unsigned long)SIZE_MAX);
-                               value = SIZE_MAX;
-                       }
-                       max_cache_size = (size_t)value;
-               } else {
-                       UNREACHABLE();
-               }
-       }
-
-       if (max_cache_size == 0) {
-               cfg_obj_log(obj, ISC_LOG_WARNING,
-                           "'max-cache-size' can't be zero or unlimited; "
-                           "falling back to default");
-               max_cache_size = SIZE_AS_PERCENT;
-               max_cache_size_percent = 90;
-       }
-
-       if (max_cache_size == SIZE_AS_PERCENT) {
-               uint64_t totalphys = isc_meminfo_totalphys();
-
-               if (totalphys == 0) {
-                       cfg_obj_log(obj, ISC_LOG_ERROR,
-                                   "Unable to determine amount of physical "
-                                   "memory, setting 'max-cache-size' to the "
-                                   "minimum value");
-                       max_cache_size = 1;
-               } else {
-                       max_cache_size = (size_t)(totalphys *
-                                                 max_cache_size_percent / 100);
-
-                       cfg_obj_log(obj, ISC_LOG_INFO,
-                                   "'max-cache-size %d%%' "
-                                   "- setting to %" PRIu64 "MB "
-                                   "(out of %" PRIu64 "MB)",
-                                   max_cache_size_percent,
-                                   (uint64_t)(max_cache_size / (1024 * 1024)),
-                                   totalphys / (1024 * 1024));
-               }
-       }
+       max_cache_size = configure_max_cache_size(view, maps);
 
        /*
         * Since both the delegation DB and ADB uses 1/8 of the
@@ -4339,25 +4365,21 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
         * Set the ADB cache size to 1/8th of the max-cache-size or
         * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared.
         */
-       max_adb_size = 0;
-       if (cache_size_slice != 0U) {
-               max_adb_size = cache_size_slice;
-               if (max_adb_size == 0U) {
-                       max_adb_size = 1; /* Force minimum. */
-               }
-               if (view != nsc->primaryview &&
-                   max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE)
-               {
-                       max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE;
-                       if (!nsc->adbsizeadjusted) {
-                               dns_view_getadb(nsc->primaryview, &adb);
-                               if (adb != NULL) {
-                                       dns_adb_setadbsize(
-                                               adb,
-                                               MAX_ADB_SIZE_FOR_CACHESHARE);
-                                       nsc->adbsizeadjusted = true;
-                                       dns_adb_detach(&adb);
-                               }
+       max_adb_size = cache_size_slice;
+       if (max_adb_size < DNS_ADB_MINADBSIZE) {
+               max_adb_size = DNS_ADB_MINADBSIZE; /* Force minimum. */
+       }
+       if (view != nsc->primaryview &&
+           max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE)
+       {
+               max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE;
+               if (!nsc->adbsizeadjusted) {
+                       dns_view_getadb(nsc->primaryview, &adb);
+                       if (adb != NULL) {
+                               dns_adb_setadbsize(adb,
+                                                  MAX_ADB_SIZE_FOR_CACHESHARE);
+                               nsc->adbsizeadjusted = true;
+                               dns_adb_detach(&adb);
                        }
                }
        }
index 341f9c96cdacea86d1648d8fdd7a04d4dbb38103..fbfcd8e446b1be5c84c544ab67dab3885bb21265 100644 (file)
@@ -77,8 +77,6 @@
 #define ADB_STALE_MARGIN 1800
 #endif /* ifndef ADB_STALE_MARGIN */
 
-#define DNS_ADB_MINADBSIZE (1024U * 1024U) /*%< 1 Megabyte */
-
 typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
 typedef struct dns_adbnamehook dns_adbnamehook_t;
 typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
index ca3a641574271f44f96e8787c15ebf98eb32052f..04e7133f46d4447a8e47d1247379f93f0eaace83 100644 (file)
 #define CACHE_MAGIC       ISC_MAGIC('$', '$', '$', '$')
 #define VALID_CACHE(cache) ISC_MAGIC_VALID(cache, CACHE_MAGIC)
 
-/*
- * DNS_CACHE_MINSIZE is how many bytes is the floor for
- * dns_cache_setcachesize().
- */
-#define DNS_CACHE_MINSIZE 2097152U /*%< Bytes.  2097152 = 2 MB */
-
 /***
  ***   Types
  ***/
index cce3970df55a3843ef8d8934380ab8eab94a633b..2f88c9beca4873e044c6d02cb53167db7eccf498 100644 (file)
@@ -83,6 +83,8 @@
 #define DNS_ADBADDRINFO_MAGIC   ISC_MAGIC('a', 'd', 'A', 'I')
 #define DNS_ADBADDRINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBADDRINFO_MAGIC)
 
+#define DNS_ADB_MINADBSIZE (1024U * 1024U) /*%< 1 Megabyte */
+
 /***
  *** TYPES
  ***/
index c2f0ba7a47f470f0ce58ca52d06f2797ff0eb0c6..8949fce462e147d808e52784bc545dce44d21656 100644 (file)
 
 #include <dns/types.h>
 
+/*
+ * DNS_CACHE_MINSIZE is how many bytes is the floor for
+ * dns_cache_setcachesize().
+ */
+#define DNS_CACHE_MINSIZE UINT64_C(2097152) /*%< Bytes.  2097152 = 2 MB */
+
 /***
  ***   Functions
  ***/