PageRenderTime 54ms CodeModel.GetById 32ms app.highlight 16ms RepoModel.GetById 2ms app.codeStats 0ms

/contrib/bind9/lib/isc/unix/resource.c

https://bitbucket.org/freebsd/freebsd-head/
C | 231 lines | 165 code | 28 blank | 38 comment | 47 complexity | 6053f982a4cc670c2fd50be8fab67c57 MD5 | raw file
  1/*
  2 * Copyright (C) 2004, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
  3 * Copyright (C) 2000, 2001  Internet Software Consortium.
  4 *
  5 * Permission to use, copy, modify, and/or distribute this software for any
  6 * purpose with or without fee is hereby granted, provided that the above
  7 * copyright notice and this permission notice appear in all copies.
  8 *
  9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 15 * PERFORMANCE OF THIS SOFTWARE.
 16 */
 17
 18/* $Id: resource.c,v 1.23 2009/02/13 23:48:14 tbox Exp $ */
 19
 20#include <config.h>
 21
 22#include <sys/types.h>
 23#include <sys/time.h>	/* Required on some systems for <sys/resource.h>. */
 24#include <sys/resource.h>
 25
 26#include <isc/platform.h>
 27#include <isc/resource.h>
 28#include <isc/result.h>
 29#include <isc/util.h>
 30
 31#ifdef __linux__
 32#include <linux/fs.h>	/* To get the large NR_OPEN. */
 33#endif
 34
 35#if defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
 36#include <sys/dyntune.h>
 37#endif
 38
 39#include "errno2result.h"
 40
 41static isc_result_t
 42resource2rlim(isc_resource_t resource, int *rlim_resource) {
 43	isc_result_t result = ISC_R_SUCCESS;
 44
 45	switch (resource) {
 46	case isc_resource_coresize:
 47		*rlim_resource = RLIMIT_CORE;
 48		break;
 49	case isc_resource_cputime:
 50		*rlim_resource = RLIMIT_CPU;
 51		break;
 52	case isc_resource_datasize:
 53		*rlim_resource = RLIMIT_DATA;
 54		break;
 55	case isc_resource_filesize:
 56		*rlim_resource = RLIMIT_FSIZE;
 57		break;
 58	case isc_resource_lockedmemory:
 59#ifdef RLIMIT_MEMLOCK
 60		*rlim_resource = RLIMIT_MEMLOCK;
 61#else
 62		result = ISC_R_NOTIMPLEMENTED;
 63#endif
 64		break;
 65	case isc_resource_openfiles:
 66#ifdef RLIMIT_NOFILE
 67		*rlim_resource = RLIMIT_NOFILE;
 68#else
 69		result = ISC_R_NOTIMPLEMENTED;
 70#endif
 71		break;
 72	case isc_resource_processes:
 73#ifdef RLIMIT_NPROC
 74		*rlim_resource = RLIMIT_NPROC;
 75#else
 76		result = ISC_R_NOTIMPLEMENTED;
 77#endif
 78		break;
 79	case isc_resource_residentsize:
 80#ifdef RLIMIT_RSS
 81		*rlim_resource = RLIMIT_RSS;
 82#else
 83		result = ISC_R_NOTIMPLEMENTED;
 84#endif
 85		break;
 86	case isc_resource_stacksize:
 87		*rlim_resource = RLIMIT_STACK;
 88		break;
 89	default:
 90		/*
 91		 * This test is not very robust if isc_resource_t
 92		 * changes, but generates a clear assertion message.
 93		 */
 94		REQUIRE(resource >= isc_resource_coresize &&
 95			resource <= isc_resource_stacksize);
 96
 97		result = ISC_R_RANGE;
 98		break;
 99	}
100
101	return (result);
102}
103
104isc_result_t
105isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
106	struct rlimit rl;
107	ISC_PLATFORM_RLIMITTYPE rlim_value;
108	int unixresult;
109	int unixresource;
110	isc_result_t result;
111
112	result = resource2rlim(resource, &unixresource);
113	if (result != ISC_R_SUCCESS)
114		return (result);
115
116	if (value == ISC_RESOURCE_UNLIMITED)
117		rlim_value = RLIM_INFINITY;
118
119	else {
120		/*
121		 * isc_resourcevalue_t was chosen as an unsigned 64 bit
122		 * integer so that it could contain the maximum range of
123		 * reasonable values.  Unfortunately, this exceeds the typical
124		 * range on Unix systems.  Ensure the range of
125		 * ISC_PLATFORM_RLIMITTYPE is not overflowed.
126		 */
127		isc_resourcevalue_t rlim_max;
128		isc_boolean_t rlim_t_is_signed =
129			ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0);
130
131		if (rlim_t_is_signed)
132			rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 <<
133				     (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1));
134		else
135			rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1;
136
137		if (value > rlim_max)
138			value = rlim_max;
139
140		rlim_value = value;
141	}
142
143	rl.rlim_cur = rl.rlim_max = rlim_value;
144	unixresult = setrlimit(unixresource, &rl);
145
146	if (unixresult == 0)
147		return (ISC_R_SUCCESS);
148
149#if defined(OPEN_MAX) && defined(__APPLE__)
150	/*
151	 * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the
152	 * maximum possible value is OPEN_MAX.  BIND8 used to use
153	 * sysconf(_SC_OPEN_MAX) for such a case, but this value is much
154	 * smaller than OPEN_MAX and is not really effective.
155	 */
156	if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
157		rl.rlim_cur = OPEN_MAX;
158		unixresult = setrlimit(unixresource, &rl);
159		if (unixresult == 0)
160			return (ISC_R_SUCCESS);
161	}
162#elif defined(__linux__)
163#ifndef NR_OPEN
164#define NR_OPEN (1024*1024)
165#endif
166
167	/*
168	 * Some Linux kernels don't accept RLIM_INFINIT; the maximum
169	 * possible value is the NR_OPEN defined in linux/fs.h.
170	 */
171	if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
172		rl.rlim_cur = rl.rlim_max = NR_OPEN;
173		unixresult = setrlimit(unixresource, &rl);
174		if (unixresult == 0)
175			return (ISC_R_SUCCESS);
176	}
177#elif defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
178	if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
179		uint64_t maxfiles;
180		if (gettune("maxfiles_lim", &maxfiles) == 0) {
181			rl.rlim_cur = rl.rlim_max = maxfiles;
182			unixresult = setrlimit(unixresource, &rl);
183			if (unixresult == 0)
184				return (ISC_R_SUCCESS);
185		}
186	}
187#endif
188	if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
189		if (getrlimit(unixresource, &rl) == 0) {
190			rl.rlim_cur = rl.rlim_max;
191			unixresult = setrlimit(unixresource, &rl);
192			if (unixresult == 0)
193				return (ISC_R_SUCCESS);
194		}
195	}
196	return (isc__errno2result(errno));
197}
198
199isc_result_t
200isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
201	int unixresult;
202	int unixresource;
203	struct rlimit rl;
204	isc_result_t result;
205
206	result = resource2rlim(resource, &unixresource);
207	if (result == ISC_R_SUCCESS) {
208		unixresult = getrlimit(unixresource, &rl);
209		INSIST(unixresult == 0);
210		*value = rl.rlim_max;
211	}
212
213	return (result);
214}
215
216isc_result_t
217isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
218	int unixresult;
219	int unixresource;
220	struct rlimit rl;
221	isc_result_t result;
222
223	result = resource2rlim(resource, &unixresource);
224	if (result == ISC_R_SUCCESS) {
225		unixresult = getrlimit(unixresource, &rl);
226		INSIST(unixresult == 0);
227		*value = rl.rlim_cur;
228	}
229
230	return (result);
231}