summaryrefslogtreecommitdiffstats
path: root/lib/isc/unix/resource.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2008-07-12 05:00:28 +0000
committerpeter <peter@FreeBSD.org>2008-07-12 05:00:28 +0000
commitba8f85b49c38af7bc2a9acdef5dcde2de008d25e (patch)
treeceac31a567976fd5866cb5791b059781f6e045de /lib/isc/unix/resource.c
parent0f328cea2580ffb8f9e363be671a517787111472 (diff)
downloadFreeBSD-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.c204
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);
+}
OpenPOWER on IntegriCloud