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