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} 232