From: Ondřej Surý Date: Sun, 13 Nov 2022 10:04:30 +0000 (+0100) Subject: Remove isc_resource API and set limits directly in named_os unit X-Git-Tag: v9.19.8~9^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e2262c2112dd59b9dd756911d49ac9ccb05bba36;p=thirdparty%2Fbind9.git Remove isc_resource API and set limits directly in named_os unit The only function left in the isc_resource API was setting the file limit. Replace the whole unit with a simple getrlimit to check the maximum value of RLIMIT_NOFILE and set the maximum back to rlimit_cur. This is more compatible than trying to set RLIMIT_UNLIMITED on the RLIMIT_NOFILE as it doesn't work on Linux (see man 5 proc on /proc/sys/fs/nr_open), neither it does on Darwin kernel (see man 2 getrlimit). The only place where the maximum value could be raised under privileged user would be BSDs, but the `named_os_adjustnofile()` were not called there before. We would apply the increased limits only on Linux and Sun platforms. --- diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index de223496789..6d46f12589a 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -106,11 +106,6 @@ EXTERN dns_name_t named_g_sessionkeyname; EXTERN bool named_g_conffileset INIT(false); EXTERN cfg_aclconfctx_t *named_g_aclconfctx INIT(NULL); -/* - * Initial resource limits. - */ -EXTERN isc_resourcevalue_t named_g_initopenfiles INIT(0); - /* * Misc. */ diff --git a/bin/named/main.c b/bin/named/main.c index 59706f1f241..a75bbdb6e56 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -1043,7 +1042,6 @@ create_managers(void) { static void setup(void) { isc_result_t result; - isc_resourcevalue_t old_openfiles; ns_server_t *sctx; #ifdef HAVE_LIBSCF char *instance = NULL; @@ -1216,30 +1214,11 @@ setup(void) { NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "----------------------------------------------------"); - /* - * Get the initial resource limits. - */ - RUNTIME_CHECK(isc_resource_getlimit(isc_resource_openfiles, - &named_g_initopenfiles) == - ISC_R_SUCCESS); - /* * System resources cannot effectively be tuned on some systems. * Raise the limit in such cases for safety. */ - old_openfiles = named_g_initopenfiles; named_os_adjustnofile(); - RUNTIME_CHECK(isc_resource_getlimit(isc_resource_openfiles, - &named_g_initopenfiles) == - ISC_R_SUCCESS); - if (old_openfiles != named_g_initopenfiles) { - isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, - NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, - "adjusted limit on open files from " - "%" PRIu64 " to " - "%" PRIu64, - old_openfiles, named_g_initopenfiles); - } /* * If the named configuration filename is relative, prepend the current diff --git a/bin/named/os.c b/bin/named/os.c index 3506a5e605c..699ca2f2569 100644 --- a/bin/named/os.c +++ b/bin/named/os.c @@ -14,6 +14,7 @@ /*! \file */ #include #include +#include #include #include /* dev_t FreeBSD 2.1 */ #ifdef HAVE_UNAME @@ -37,13 +38,13 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include #ifdef HAVE_LIBSCF @@ -615,23 +616,47 @@ ns_os_uid(void) { void named_os_adjustnofile(void) { -#if defined(__linux__) || defined(__sun) - isc_result_t result; - isc_resourcevalue_t newvalue; + int r; + struct rlimit rl; + rlim_t rlim_old; + char strbuf[ISC_STRERRORSIZE]; - /* - * Linux: max number of open files specified by one thread doesn't seem - * to apply to other threads on Linux. - * Sun: restriction needs to be removed sooner when hundreds of CPUs - * are available. - */ - newvalue = ISC_RESOURCE_UNLIMITED; + r = getrlimit(RLIMIT_NOFILE, &rl); + if (r != 0) { + goto fail; + } + + rlim_old = rl.rlim_cur; - result = isc_resource_setlimit(isc_resource_openfiles, newvalue); - if (result != ISC_R_SUCCESS) { - named_main_earlywarning("couldn't adjust limit on open files"); + if (rl.rlim_cur == rl.rlim_max) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "the limit on open files is already at the " + "maximum allowed value: " + "%" PRIu64, + (uint64_t)rl.rlim_max); + return; + } + + rl.rlim_cur = rl.rlim_max; + r = setrlimit(RLIMIT_NOFILE, &rl); + if (r != 0) { + goto fail; } -#endif /* if defined(__linux__) || defined(__sun) */ + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "adjusted limit on open files from " + "%" PRIu64 " to " + "%" PRIu64, + (uint64_t)rlim_old, (uint64_t)rl.rlim_cur); + return; + +fail: + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlywarning("adjusting limit on open files failed: %s", + strbuf); + return; } void diff --git a/bin/named/server.c b/bin/named/server.c index 63535328a0d..09eb53e2ed2 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -4354,8 +4354,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, max_cache_size = SIZE_AS_PERCENT; max_cache_size_percent = cfg_obj_aspercentage(obj); } else { - isc_resourcevalue_t value; - value = cfg_obj_asuint64(obj); + uint64_t value = cfg_obj_asuint64(obj); if (value > SIZE_MAX) { cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, "'max-cache-size " diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index f7e5914fbd2..795db7bf6eb 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -1362,8 +1362,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, journal_size = -1; } } else { - isc_resourcevalue_t value; - value = cfg_obj_asuint64(obj); + uint64_t value = cfg_obj_asuint64(obj); if (value > DNS_JOURNAL_SIZE_MAX) { cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, "'max-journal-size " @@ -1508,8 +1507,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, journal_size = -1; } } else { - isc_resourcevalue_t value; - value = cfg_obj_asuint64(obj); + uint64_t value = cfg_obj_asuint64(obj); if (value > DNS_JOURNAL_SIZE_MAX) { cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, "'max-journal-size " diff --git a/lib/isc/Makefile.am b/lib/isc/Makefile.am index 2d8976a3633..f44a5a00dd5 100644 --- a/lib/isc/Makefile.am +++ b/lib/isc/Makefile.am @@ -77,7 +77,6 @@ libisc_la_HEADERS = \ include/isc/refcount.h \ include/isc/regex.h \ include/isc/region.h \ - include/isc/resource.h \ include/isc/result.h \ include/isc/rwlock.h \ include/isc/safe.h \ @@ -189,7 +188,6 @@ libisc_la_SOURCES = \ ratelimiter.c \ regex.c \ region.c \ - resource.c \ result.c \ safe.c \ serial.c \ diff --git a/lib/isc/include/isc/resource.h b/lib/isc/include/isc/resource.h deleted file mode 100644 index dc4b2b19dcd..00000000000 --- a/lib/isc/include/isc/resource.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#pragma once - -/*! \file isc/resource.h */ - -#include -#include - -#define ISC_RESOURCE_UNLIMITED ((isc_resourcevalue_t)UINT64_MAX) - -ISC_LANG_BEGINDECLS - -isc_result_t -isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value); -/*%< - * Set the maximum limit for a system resource. - * - * Notes: - *\li If 'value' exceeds the maximum possible on the operating system, - * it is silently limited to that maximum -- or to "infinity", if - * the operating system has that concept. #ISC_RESOURCE_UNLIMITED - * can be used to explicitly ask for the maximum. - * - * Requires: - *\li 'resource' is a valid member of the isc_resource_t enumeration. - * - * Returns: - *\li #ISC_R_SUCCESS Success. - *\li #ISC_R_NOTIMPLEMENTED 'resource' is not a type known by the OS. - *\li #ISC_R_NOPERM The calling process did not have adequate permission - * to change the resource limit. - */ - -isc_result_t -isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value); -/*%< - * Get the maximum limit for a system resource. - * - * Notes: - *\li 'value' is set to the maximum limit. - * - *\li #ISC_RESOURCE_UNLIMITED is the maximum value of isc_resourcevalue_t. - * - *\li On many (all?) Unix systems, RLIM_INFINITY is a valid value that is - * significantly less than #ISC_RESOURCE_UNLIMITED, but which in practice - * behaves the same. - * - *\li The current ISC libdns configuration file parser assigns a value - * of UINT32_MAX for a size_spec of "unlimited" and ISC_UNIT32_MAX - 1 - * for "default", the latter of which is supposed to represent "the - * limit that was in force when the server started". Since these are - * valid values in the middle of the range of isc_resourcevalue_t, - * there is the possibility for confusion over what exactly those - * particular values are supposed to represent in a particular context -- - * discrete integral values or generalized concepts. - * - * Requires: - *\li 'resource' is a valid member of the isc_resource_t enumeration. - * - * Returns: - *\li #ISC_R_SUCCESS Success. - *\li #ISC_R_NOTIMPLEMENTED 'resource' is not a type known by the OS. - */ - -isc_result_t -isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value); -/*%< - * Same as isc_resource_getlimit(), but returns the current (soft) limit. - * - * Returns: - *\li #ISC_R_SUCCESS Success. - *\li #ISC_R_NOTIMPLEMENTED 'resource' is not a type known by the OS. - */ - -ISC_LANG_ENDDECLS diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h index ecbbf489763..51a246dfabc 100644 --- a/lib/isc/include/isc/types.h +++ b/lib/isc/include/isc/types.h @@ -71,14 +71,13 @@ typedef struct isc_nmsocket isc_nmsocket_t; /*%< Network manager socket */ typedef struct isc_nmhandle isc_nmhandle_t; /*%< Network manager handle */ typedef struct isc_portset isc_portset_t; /*%< Port Set */ typedef struct isc_quota isc_quota_t; /*%< Quota */ -typedef struct isc_ratelimiter isc_ratelimiter_t; /*%< Rate Limiter */ -typedef struct isc_region isc_region_t; /*%< Region */ -typedef uint64_t isc_resourcevalue_t; /*%< Resource Value */ -typedef struct isc_signal isc_signal_t; /*%< Signal handler */ -typedef struct isc_sockaddr isc_sockaddr_t; /*%< Socket Address */ -typedef ISC_LIST(isc_sockaddr_t) isc_sockaddrlist_t; /*%< Socket Address List - * */ -typedef struct isc_stats isc_stats_t; /*%< Statistics */ +typedef struct isc_ratelimiter isc_ratelimiter_t; /*%< Rate Limiter */ +typedef struct isc_region isc_region_t; /*%< Region */ +typedef struct isc_signal isc_signal_t; /*%< Signal handler */ +typedef struct isc_sockaddr isc_sockaddr_t; /*%< Socket Address */ +typedef ISC_LIST(isc_sockaddr_t) isc_sockaddrlist_t; /*%< Socket Address List + * */ +typedef struct isc_stats isc_stats_t; /*%< Statistics */ typedef int_fast64_t isc_statscounter_t; typedef struct isc_symtab isc_symtab_t; /*%< Symbol Table */ typedef struct isc_task isc_task_t; /*%< Task */ @@ -96,19 +95,6 @@ typedef struct isc_nm_http_endpoints isc_nm_http_endpoints_t; typedef void (*isc_taskaction_t)(isc_task_t *, isc_event_t *); -/*% Resource */ -typedef enum { - isc_resource_coresize = 1, - isc_resource_cputime, - isc_resource_datasize, - isc_resource_filesize, - isc_resource_lockedmemory, - isc_resource_openfiles, - isc_resource_processes, - isc_resource_residentsize, - isc_resource_stacksize -} isc_resource_t; - /*% Statistics formats (text file or XML) */ typedef enum { isc_statsformat_file, diff --git a/lib/isc/resource.c b/lib/isc/resource.c deleted file mode 100644 index f6965755dbe..00000000000 --- a/lib/isc/resource.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#include -#include -#include -#include /* Required on some systems for . */ -#include - -#include -#include -#include - -#ifdef __linux__ -#include /* To get the large NR_OPEN. */ -#endif /* ifdef __linux__ */ - -#include "errno2result.h" - -static isc_result_t -resource2rlim(isc_resource_t resource, int *rlim_resource) { - isc_result_t result = ISC_R_SUCCESS; - - switch (resource) { - case isc_resource_coresize: - *rlim_resource = RLIMIT_CORE; - break; - case isc_resource_cputime: - *rlim_resource = RLIMIT_CPU; - break; - case isc_resource_datasize: - *rlim_resource = RLIMIT_DATA; - break; - case isc_resource_filesize: - *rlim_resource = RLIMIT_FSIZE; - break; - case isc_resource_lockedmemory: -#ifdef RLIMIT_MEMLOCK - *rlim_resource = RLIMIT_MEMLOCK; -#else /* ifdef RLIMIT_MEMLOCK */ - result = ISC_R_NOTIMPLEMENTED; -#endif /* ifdef RLIMIT_MEMLOCK */ - break; - case isc_resource_openfiles: -#ifdef RLIMIT_NOFILE - *rlim_resource = RLIMIT_NOFILE; -#else /* ifdef RLIMIT_NOFILE */ - result = ISC_R_NOTIMPLEMENTED; -#endif /* ifdef RLIMIT_NOFILE */ - break; - case isc_resource_processes: -#ifdef RLIMIT_NPROC - *rlim_resource = RLIMIT_NPROC; -#else /* ifdef RLIMIT_NPROC */ - result = ISC_R_NOTIMPLEMENTED; -#endif /* ifdef RLIMIT_NPROC */ - break; - case isc_resource_residentsize: -#ifdef RLIMIT_RSS - *rlim_resource = RLIMIT_RSS; -#else /* ifdef RLIMIT_RSS */ - result = ISC_R_NOTIMPLEMENTED; -#endif /* ifdef RLIMIT_RSS */ - break; - case isc_resource_stacksize: - *rlim_resource = RLIMIT_STACK; - break; - default: - /* - * This test is not very robust if isc_resource_t - * changes, but generates a clear assertion message. - */ - REQUIRE(resource >= isc_resource_coresize && - resource <= isc_resource_stacksize); - - result = ISC_R_RANGE; - break; - } - - return (result); -} - -isc_result_t -isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) { - struct rlimit rl; - rlim_t rlim_value; - int unixresult; - int unixresource; - isc_result_t result; - - result = resource2rlim(resource, &unixresource); - if (result != ISC_R_SUCCESS) { - return (result); - } - - if (value == ISC_RESOURCE_UNLIMITED) { - rlim_value = RLIM_INFINITY; - } else { - /* - * Carefully ensure the range of rlim_t is not overflowed, by - * calculating how many bytes wider is isc_resourcevalue_t than - * rlim_t, and whether rlim_t has a sign bit. - */ - isc_resourcevalue_t rlim_max = UINT64_MAX; - size_t wider = sizeof(rlim_max) - sizeof(rlim_t); - size_t sign_bit = (size_t)(0.0 > (double)(rlim_t)-1); - - rlim_max >>= CHAR_BIT * wider + sign_bit; - rlim_value = ISC_MIN(value, rlim_max); - } - - rl.rlim_cur = rl.rlim_max = rlim_value; - unixresult = setrlimit(unixresource, &rl); - - if (unixresult == 0) { - return (ISC_R_SUCCESS); - } - -#if defined(OPEN_MAX) && defined(__APPLE__) - /* - * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the - * maximum possible value is OPEN_MAX. BIND8 used to use - * sysconf(_SC_OPEN_MAX) for such a case, but this value is much - * smaller than OPEN_MAX and is not really effective. - */ - if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { - rl.rlim_cur = OPEN_MAX; - unixresult = setrlimit(unixresource, &rl); - if (unixresult == 0) { - return (ISC_R_SUCCESS); - } - } -#elif defined(__linux__) -#ifndef NR_OPEN -#define NR_OPEN (1024 * 1024) -#endif /* ifndef NR_OPEN */ - - /* - * Some Linux kernels don't accept RLIM_INFINIT; the maximum - * possible value is the NR_OPEN defined in linux/fs.h. - */ - if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { - rl.rlim_cur = rl.rlim_max = NR_OPEN; - unixresult = setrlimit(unixresource, &rl); - if (unixresult == 0) { - return (ISC_R_SUCCESS); - } - } -#endif /* if defined(OPEN_MAX) && defined(__APPLE__) */ - if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { - if (getrlimit(unixresource, &rl) == 0) { - rl.rlim_cur = rl.rlim_max; - unixresult = setrlimit(unixresource, &rl); - if (unixresult == 0) { - return (ISC_R_SUCCESS); - } - } - } - return (isc__errno2result(errno)); -} - -isc_result_t -isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) { - int unixresource; - struct rlimit rl; - isc_result_t result; - - result = resource2rlim(resource, &unixresource); - if (result != ISC_R_SUCCESS) { - return (result); - } - - if (getrlimit(unixresource, &rl) != 0) { - return (isc__errno2result(errno)); - } - - *value = rl.rlim_max; - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) { - int unixresource; - struct rlimit rl; - isc_result_t result; - - result = resource2rlim(resource, &unixresource); - if (result != ISC_R_SUCCESS) { - return (result); - } - - if (getrlimit(unixresource, &rl) != 0) { - return (isc__errno2result(errno)); - } - - *value = rl.rlim_cur; - return (ISC_R_SUCCESS); -} diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 9543c1a02e4..0ea0cf151fe 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -2651,7 +2651,7 @@ cfg_type_t cfg_type_addzoneconf = { "addzoneconf", cfg_parse_mapbody, &cfg_rep_map, addzoneconf_clausesets }; static isc_result_t -parse_unitstring(char *str, isc_resourcevalue_t *valuep) { +parse_unitstring(char *str, uint64_t *valuep) { char *endp; unsigned int len; uint64_t value; diff --git a/tests/libtest/ns.c b/tests/libtest/ns.c index 3c813fc6bac..079d80b8d7c 100644 --- a/tests/libtest/ns.c +++ b/tests/libtest/ns.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include