From: Ondřej Surý Date: Thu, 19 Feb 2026 09:03:45 +0000 (+0100) Subject: Refactor the 'max-cache-size' configuration handling X-Git-Tag: v9.21.21~3^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6fa415f71fd7f867c3b4d0071258bece0bc46b7b;p=thirdparty%2Fbind9.git Refactor the 'max-cache-size' configuration handling 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. --- diff --git a/bin/named/server.c b/bin/named/server.c index 6d6fabc707e..5d82a7ac349 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -18,14 +18,13 @@ #include #include #include +#include #include #include #include #include #include -#include - #ifdef HAVE_DNSTAP #include #endif @@ -60,6 +59,7 @@ #include #include +#include #include #include #include @@ -119,6 +119,7 @@ #include #include +#include #include #if defined(HAVE_GEOIP2) #include @@ -152,10 +153,6 @@ #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); } } } diff --git a/lib/dns/adb.c b/lib/dns/adb.c index 341f9c96cda..fbfcd8e446b 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -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; diff --git a/lib/dns/cache.c b/lib/dns/cache.c index ca3a6415742..04e7133f46d 100644 --- a/lib/dns/cache.c +++ b/lib/dns/cache.c @@ -48,12 +48,6 @@ #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 ***/ diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h index cce3970df55..2f88c9beca4 100644 --- a/lib/dns/include/dns/adb.h +++ b/lib/dns/include/dns/adb.h @@ -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 ***/ diff --git a/lib/dns/include/dns/cache.h b/lib/dns/include/dns/cache.h index c2f0ba7a47f..8949fce462e 100644 --- a/lib/dns/include/dns/cache.h +++ b/lib/dns/include/dns/cache.h @@ -52,6 +52,12 @@ #include +/* + * 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 ***/