]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/bind9/lib/isc/unix/resource.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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.18.6 2008/08/05 07:17:05 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 #if defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
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         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(NR_OPEN) && defined(__linux__)
163         /*
164          * Some Linux kernels don't accept RLIM_INFINIT; the maximum
165          * possible value is the NR_OPEN defined in linux/fs.h.
166          */
167         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
168                 rl.rlim_cur = rl.rlim_max = NR_OPEN;
169                 unixresult = setrlimit(unixresource, &rl);
170                 if (unixresult == 0)
171                         return (ISC_R_SUCCESS);
172         }
173 #elif defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
174         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
175                 uint64_t maxfiles;
176                 if (gettune("maxfiles_lim", &maxfiles) == 0) {
177                         rl.rlim_cur = rl.rlim_max = maxfiles;
178                         unixresult = setrlimit(unixresource, &rl);
179                         if (unixresult == 0)
180                                 return (ISC_R_SUCCESS);
181                 }
182         }
183 #endif
184         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
185                 if (getrlimit(unixresource, &rl) == 0) {
186                         rl.rlim_cur = rl.rlim_max;
187                         unixresult = setrlimit(unixresource, &rl);
188                         if (unixresult == 0)
189                                 return (ISC_R_SUCCESS);
190                 }
191         }
192         return (isc__errno2result(errno));
193 }
194
195 isc_result_t
196 isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
197         int unixresult;
198         int unixresource;
199         struct rlimit rl;
200         isc_result_t result;
201
202         result = resource2rlim(resource, &unixresource);
203         if (result == ISC_R_SUCCESS) {
204                 unixresult = getrlimit(unixresource, &rl);
205                 INSIST(unixresult == 0);
206                 *value = rl.rlim_max;
207         }
208
209         return (result);
210 }
211
212 isc_result_t
213 isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
214         int unixresult;
215         int unixresource;
216         struct rlimit rl;
217         isc_result_t result;
218
219         result = resource2rlim(resource, &unixresource);
220         if (result == ISC_R_SUCCESS) {
221                 unixresult = getrlimit(unixresource, &rl);
222                 INSIST(unixresult == 0);
223                 *value = rl.rlim_cur;
224         }
225
226         return (result);
227 }