]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bind9/lib/isc/unix/resource.c
- Update ncurses to 5.7-20081102 (5.7 release) and build glue
[FreeBSD/FreeBSD.git] / contrib / bind9 / lib / isc / unix / resource.c
1 /*
2  * Copyright (C) 2004, 2008  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.12.944.4 2008/07/28 22:44:46 marka 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 #ifdef __hpux
36 #include <sys/dyntune.h>
37 #endif
38
39 #include "errno2result.h"
40
41 static isc_result_t
42 resource2rlim(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
104 isc_result_t
105 isc_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         /*
144          * The BIND 8 documentation reports:
145          *
146          *      Note: on some operating systems the server cannot set an
147          *      unlimited value and cannot determine the maximum number of
148          *      open files the kernel can support. On such systems, choosing
149          *      unlimited will cause the server to use the larger of the
150          *      rlim_max for RLIMIT_NOFILE and the value returned by
151          *      sysconf(_SC_OPEN_MAX). If the actual kernel limit is larger
152          *      than this value, use limit files to specify the limit
153          *      explicitly.
154          *
155          * The CHANGES for 8.1.2-T3A also mention:
156          *
157          *      352. [bug] Because of problems with setting an infinite
158          *      rlim_max for RLIMIT_NOFILE on some systems, previous versions
159          *      of the server implemented "limit files unlimited" by setting
160          *      the limit to the value returned by sysconf(_SC_OPEN_MAX).  The
161          *      server will now use RLIM_INFINITY on systems which allow it.
162          *
163          * At some point the BIND 8 server stopped using SC_OPEN_MAX for this
164          * purpose at all, but it isn't clear to me when or why, as my access
165          * to the CVS archive is limited at the time of this writing.  What
166          * BIND 8 *does* do is to set RLIMIT_NOFILE to either RLIMIT_INFINITY
167          * on a half dozen operating systems or to FD_SETSIZE on the rest,
168          * the latter of which is probably fewer than the real limit.  (Note
169          * that libisc's socket module will have problems with any fd over
170          * FD_SETSIZE.  This should be fixed in the socket module, not a
171          * limitation here.  BIND 8's eventlib also has a problem, making
172          * its RLIMIT_INFINITY setting useless, because it closes and ignores
173          * any fd over FD_SETSIZE.)
174          *
175          * More troubling is the reference to some operating systems not being
176          * able to set an unlimited value for the number of open files.  I'd
177          * hate to put in code that is really only there to support archaic
178          * systems that the rest of libisc won't work on anyway.  So what this
179          * extremely verbose comment is here to say is the following:
180          *
181          *   I'm aware there might be an issue with not limiting the value
182          *   for RLIMIT_NOFILE on some systems, but since I don't know yet
183          *   what those systems are and what the best workaround is (use
184          *   sysconf()?  rlim_max from getrlimit()?  FD_SETSIZE?) so nothing
185          *   is currently being done to clamp the value for open files.
186          */
187
188         rl.rlim_cur = rl.rlim_max = rlim_value;
189         unixresult = setrlimit(unixresource, &rl);
190
191         if (unixresult == 0)
192                 return (ISC_R_SUCCESS);
193
194 #if defined(OPEN_MAX) && defined(__APPLE__)
195         /*
196          * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the
197          * maximum possible value is OPEN_MAX.  BIND8 used to use
198          * sysconf(_SC_OPEN_MAX) for such a case, but this value is much
199          * smaller than OPEN_MAX and is not really effective.
200          */
201         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
202                 rl.rlim_cur = OPEN_MAX;
203                 unixresult = setrlimit(unixresource, &rl);
204                 if (unixresult == 0)
205                         return (ISC_R_SUCCESS);
206         }
207 #elif defined(NR_OPEN) && defined(__linux__)
208         /*
209          * Some Linux kernels don't accept RLIM_INFINIT; the maximum
210          * possible value is the NR_OPEN defined in linux/fs.h.
211          */
212         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
213                 rl.rlim_cur = rl.rlim_max = NR_OPEN;
214                 unixresult = setrlimit(unixresource, &rl);
215                 if (unixresult == 0)
216                         return (ISC_R_SUCCESS);
217         }
218 #elif defined(__hpux)
219         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
220                 uint64_t maxfiles;
221                 if (gettune("maxfiles_lim", &maxfiles) == 0) {
222                         rl.rlim_cur = rl.rlim_max = maxfiles;
223                         unixresult = setrlimit(unixresource, &rl);
224                         if (unixresult == 0)
225                                 return (ISC_R_SUCCESS);
226                 }
227         }
228 #endif
229         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
230                 if (getrlimit(unixresource, &rl) == 0) {
231                         rl.rlim_cur = rl.rlim_max;
232                         unixresult = setrlimit(unixresource, &rl);
233                         if (unixresult == 0)
234                                 return (ISC_R_SUCCESS);
235                 }
236         }
237         return (isc__errno2result(errno));
238 }
239
240 isc_result_t
241 isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
242         int unixresult;
243         int unixresource;
244         struct rlimit rl;
245         isc_result_t result;
246
247         result = resource2rlim(resource, &unixresource);
248         if (result == ISC_R_SUCCESS) {
249                 unixresult = getrlimit(unixresource, &rl);
250                 INSIST(unixresult == 0);
251                 *value = rl.rlim_max;
252         }
253
254         return (result);
255 }
256
257 isc_result_t
258 isc_resource_curlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
259         int unixresult;
260         int unixresource;
261         struct rlimit rl;
262         isc_result_t result;
263
264         result = resource2rlim(resource, &unixresource);
265         if (result == ISC_R_SUCCESS) {
266                 unixresult = getrlimit(unixresource, &rl);
267                 INSIST(unixresult == 0);
268                 *value = rl.rlim_cur;
269         }
270
271         return (result);
272 }