diff options
author | peter <peter@FreeBSD.org> | 2008-07-12 05:00:28 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2008-07-12 05:00:28 +0000 |
commit | ba8f85b49c38af7bc2a9acdef5dcde2de008d25e (patch) | |
tree | ceac31a567976fd5866cb5791b059781f6e045de /lib/isc/unix/resource.c | |
parent | 0f328cea2580ffb8f9e363be671a517787111472 (diff) | |
download | FreeBSD-src-ba8f85b49c38af7bc2a9acdef5dcde2de008d25e.zip FreeBSD-src-ba8f85b49c38af7bc2a9acdef5dcde2de008d25e.tar.gz |
Flatten bind9 vendor work area
Diffstat (limited to 'lib/isc/unix/resource.c')
-rw-r--r-- | lib/isc/unix/resource.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/lib/isc/unix/resource.c b/lib/isc/unix/resource.c new file mode 100644 index 0000000..703ec27 --- /dev/null +++ b/lib/isc/unix/resource.c @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2000, 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: resource.c,v 1.12 2004/03/05 05:11:46 marka Exp $ */ + +#include <config.h> + +#include <sys/types.h> +#include <sys/time.h> /* Required on some systems for <sys/resource.h>. */ +#include <sys/resource.h> + +#include <isc/platform.h> +#include <isc/resource.h> +#include <isc/result.h> +#include <isc/util.h> + +#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 + result = ISC_R_NOTIMPLEMENTED; +#endif + break; + case isc_resource_openfiles: +#ifdef RLIMIT_NOFILE + *rlim_resource = RLIMIT_NOFILE; +#else + result = ISC_R_NOTIMPLEMENTED; +#endif + break; + case isc_resource_processes: +#ifdef RLIMIT_NPROC + *rlim_resource = RLIMIT_NPROC; +#else + result = ISC_R_NOTIMPLEMENTED; +#endif + break; + case isc_resource_residentsize: +#ifdef RLIMIT_RSS + *rlim_resource = RLIMIT_RSS; +#else + result = ISC_R_NOTIMPLEMENTED; +#endif + 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; + ISC_PLATFORM_RLIMITTYPE 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 { + /* + * isc_resourcevalue_t was chosen as an unsigned 64 bit + * integer so that it could contain the maximum range of + * reasonable values. Unfortunately, this exceeds the typical + * range on Unix systems. Ensure the range of + * ISC_PLATFORM_RLIMITTYPE is not overflowed. + */ + isc_resourcevalue_t rlim_max; + isc_boolean_t rlim_t_is_signed = + ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0); + + if (rlim_t_is_signed) + rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 << + (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1)); + else + rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1; + + if (value > rlim_max) + value = rlim_max; + + rlim_value = value; + } + + /* + * The BIND 8 documentation reports: + * + * Note: on some operating systems the server cannot set an + * unlimited value and cannot determine the maximum number of + * open files the kernel can support. On such systems, choosing + * unlimited will cause the server to use the larger of the + * rlim_max for RLIMIT_NOFILE and the value returned by + * sysconf(_SC_OPEN_MAX). If the actual kernel limit is larger + * than this value, use limit files to specify the limit + * explicitly. + * + * The CHANGES for 8.1.2-T3A also mention: + * + * 352. [bug] Because of problems with setting an infinite + * rlim_max for RLIMIT_NOFILE on some systems, previous versions + * of the server implemented "limit files unlimited" by setting + * the limit to the value returned by sysconf(_SC_OPEN_MAX). The + * server will now use RLIM_INFINITY on systems which allow it. + * + * At some point the BIND 8 server stopped using SC_OPEN_MAX for this + * purpose at all, but it isn't clear to me when or why, as my access + * to the CVS archive is limited at the time of this writing. What + * BIND 8 *does* do is to set RLIMIT_NOFILE to either RLIMIT_INFINITY + * on a half dozen operating systems or to FD_SETSIZE on the rest, + * the latter of which is probably fewer than the real limit. (Note + * that libisc's socket module will have problems with any fd over + * FD_SETSIZE. This should be fixed in the socket module, not a + * limitation here. BIND 8's eventlib also has a problem, making + * its RLIMIT_INFINITY setting useless, because it closes and ignores + * any fd over FD_SETSIZE.) + * + * More troubling is the reference to some operating systems not being + * able to set an unlimited value for the number of open files. I'd + * hate to put in code that is really only there to support archaic + * systems that the rest of libisc won't work on anyway. So what this + * extremely verbose comment is here to say is the following: + * + * I'm aware there might be an issue with not limiting the value + * for RLIMIT_NOFILE on some systems, but since I don't know yet + * what those systems are and what the best workaround is (use + * sysconf()? rlim_max from getrlimit()? FD_SETSIZE?) so nothing + * is currently being done to clamp the value for open files. + */ + + rl.rlim_cur = rl.rlim_max = rlim_value; + unixresult = setrlimit(unixresource, &rl); + + if (unixresult == 0) + return (ISC_R_SUCCESS); + else + return (isc__errno2result(errno)); +} + +isc_result_t +isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) { + int unixresult; + int unixresource; + struct rlimit rl; + isc_result_t result; + + result = resource2rlim(resource, &unixresource); + if (result == ISC_R_SUCCESS) { + unixresult = getrlimit(unixresource, &rl); + INSIST(unixresult == 0); + *value = rl.rlim_max; + } + + return (result); +} |