1258945Sroberto/* 2258945Sroberto * Copyright (C) 2004, 2007-2009 Internet Systems Consortium, Inc. ("ISC") 3258945Sroberto * Copyright (C) 2000, 2001 Internet Software Consortium. 4258945Sroberto * 5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any 6258945Sroberto * purpose with or without fee is hereby granted, provided that the above 7258945Sroberto * copyright notice and this permission notice appear in all copies. 8258945Sroberto * 9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11258945Sroberto * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15258945Sroberto * PERFORMANCE OF THIS SOFTWARE. 16258945Sroberto */ 17258945Sroberto 18280849Scy/* $Id: resource.c,v 1.23 2009/02/13 23:48:14 tbox Exp $ */ 19258945Sroberto 20258945Sroberto#include <config.h> 21258945Sroberto 22258945Sroberto#include <sys/types.h> 23258945Sroberto#include <sys/time.h> /* Required on some systems for <sys/resource.h>. */ 24258945Sroberto#include <sys/resource.h> 25258945Sroberto 26258945Sroberto#include <isc/platform.h> 27258945Sroberto#include <isc/resource.h> 28258945Sroberto#include <isc/result.h> 29258945Sroberto#include <isc/util.h> 30258945Sroberto 31258945Sroberto#ifdef __linux__ 32258945Sroberto#include <linux/fs.h> /* To get the large NR_OPEN. */ 33258945Sroberto#endif 34258945Sroberto 35258945Sroberto#if defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H) 36258945Sroberto#include <sys/dyntune.h> 37258945Sroberto#endif 38258945Sroberto 39258945Sroberto#include "errno2result.h" 40258945Sroberto 41258945Srobertostatic isc_result_t 42258945Srobertoresource2rlim(isc_resource_t resource, int *rlim_resource) { 43258945Sroberto isc_result_t result = ISC_R_SUCCESS; 44258945Sroberto 45258945Sroberto switch (resource) { 46258945Sroberto case isc_resource_coresize: 47258945Sroberto *rlim_resource = RLIMIT_CORE; 48258945Sroberto break; 49258945Sroberto case isc_resource_cputime: 50258945Sroberto *rlim_resource = RLIMIT_CPU; 51258945Sroberto break; 52258945Sroberto case isc_resource_datasize: 53258945Sroberto *rlim_resource = RLIMIT_DATA; 54258945Sroberto break; 55258945Sroberto case isc_resource_filesize: 56258945Sroberto *rlim_resource = RLIMIT_FSIZE; 57258945Sroberto break; 58258945Sroberto case isc_resource_lockedmemory: 59258945Sroberto#ifdef RLIMIT_MEMLOCK 60258945Sroberto *rlim_resource = RLIMIT_MEMLOCK; 61258945Sroberto#else 62258945Sroberto result = ISC_R_NOTIMPLEMENTED; 63258945Sroberto#endif 64258945Sroberto break; 65258945Sroberto case isc_resource_openfiles: 66258945Sroberto#ifdef RLIMIT_NOFILE 67258945Sroberto *rlim_resource = RLIMIT_NOFILE; 68258945Sroberto#else 69258945Sroberto result = ISC_R_NOTIMPLEMENTED; 70258945Sroberto#endif 71258945Sroberto break; 72258945Sroberto case isc_resource_processes: 73258945Sroberto#ifdef RLIMIT_NPROC 74258945Sroberto *rlim_resource = RLIMIT_NPROC; 75258945Sroberto#else 76258945Sroberto result = ISC_R_NOTIMPLEMENTED; 77258945Sroberto#endif 78258945Sroberto break; 79258945Sroberto case isc_resource_residentsize: 80258945Sroberto#ifdef RLIMIT_RSS 81258945Sroberto *rlim_resource = RLIMIT_RSS; 82258945Sroberto#else 83258945Sroberto result = ISC_R_NOTIMPLEMENTED; 84258945Sroberto#endif 85258945Sroberto break; 86258945Sroberto case isc_resource_stacksize: 87258945Sroberto *rlim_resource = RLIMIT_STACK; 88258945Sroberto break; 89258945Sroberto default: 90258945Sroberto /* 91258945Sroberto * This test is not very robust if isc_resource_t 92258945Sroberto * changes, but generates a clear assertion message. 93258945Sroberto */ 94258945Sroberto REQUIRE(resource >= isc_resource_coresize && 95258945Sroberto resource <= isc_resource_stacksize); 96258945Sroberto 97258945Sroberto result = ISC_R_RANGE; 98258945Sroberto break; 99258945Sroberto } 100258945Sroberto 101258945Sroberto return (result); 102258945Sroberto} 103258945Sroberto 104258945Srobertoisc_result_t 105258945Srobertoisc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) { 106258945Sroberto struct rlimit rl; 107258945Sroberto ISC_PLATFORM_RLIMITTYPE rlim_value; 108258945Sroberto int unixresult; 109258945Sroberto int unixresource; 110258945Sroberto isc_result_t result; 111258945Sroberto 112258945Sroberto result = resource2rlim(resource, &unixresource); 113258945Sroberto if (result != ISC_R_SUCCESS) 114258945Sroberto return (result); 115258945Sroberto 116258945Sroberto if (value == ISC_RESOURCE_UNLIMITED) 117258945Sroberto rlim_value = RLIM_INFINITY; 118258945Sroberto 119258945Sroberto else { 120258945Sroberto /* 121258945Sroberto * isc_resourcevalue_t was chosen as an unsigned 64 bit 122258945Sroberto * integer so that it could contain the maximum range of 123258945Sroberto * reasonable values. Unfortunately, this exceeds the typical 124258945Sroberto * range on Unix systems. Ensure the range of 125258945Sroberto * ISC_PLATFORM_RLIMITTYPE is not overflowed. 126258945Sroberto */ 127258945Sroberto isc_resourcevalue_t rlim_max; 128258945Sroberto isc_boolean_t rlim_t_is_signed = 129258945Sroberto ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0); 130258945Sroberto 131258945Sroberto if (rlim_t_is_signed) 132258945Sroberto rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 << 133258945Sroberto (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1)); 134258945Sroberto else 135258945Sroberto rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1; 136258945Sroberto 137258945Sroberto if (value > rlim_max) 138258945Sroberto value = rlim_max; 139258945Sroberto 140258945Sroberto rlim_value = value; 141258945Sroberto } 142258945Sroberto 143258945Sroberto rl.rlim_cur = rl.rlim_max = rlim_value; 144258945Sroberto unixresult = setrlimit(unixresource, &rl); 145258945Sroberto 146258945Sroberto if (unixresult == 0) 147258945Sroberto return (ISC_R_SUCCESS); 148258945Sroberto 149258945Sroberto#if defined(OPEN_MAX) && defined(__APPLE__) 150258945Sroberto /* 151258945Sroberto * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the 152258945Sroberto * maximum possible value is OPEN_MAX. BIND8 used to use 153258945Sroberto * sysconf(_SC_OPEN_MAX) for such a case, but this value is much 154258945Sroberto * smaller than OPEN_MAX and is not really effective. 155258945Sroberto */ 156258945Sroberto if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { 157258945Sroberto rl.rlim_cur = OPEN_MAX; 158258945Sroberto unixresult = setrlimit(unixresource, &rl); 159258945Sroberto if (unixresult == 0) 160258945Sroberto return (ISC_R_SUCCESS); 161258945Sroberto } 162258945Sroberto#elif defined(__linux__) 163258945Sroberto#ifndef NR_OPEN 164258945Sroberto#define NR_OPEN (1024*1024) 165258945Sroberto#endif 166258945Sroberto 167258945Sroberto /* 168258945Sroberto * Some Linux kernels don't accept RLIM_INFINIT; the maximum 169258945Sroberto * possible value is the NR_OPEN defined in linux/fs.h. 170258945Sroberto */ 171258945Sroberto if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { 172258945Sroberto rl.rlim_cur = rl.rlim_max = NR_OPEN; 173258945Sroberto unixresult = setrlimit(unixresource, &rl); 174258945Sroberto if (unixresult == 0) 175258945Sroberto return (ISC_R_SUCCESS); 176258945Sroberto } 177258945Sroberto#elif defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H) 178258945Sroberto if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { 179258945Sroberto uint64_t maxfiles; 180258945Sroberto if (gettune("maxfiles_lim", &maxfiles) == 0) { 181258945Sroberto rl.rlim_cur = rl.rlim_max = maxfiles; 182258945Sroberto unixresult = setrlimit(unixresource, &rl); 183258945Sroberto if (unixresult == 0) 184258945Sroberto return (ISC_R_SUCCESS); 185258945Sroberto } 186258945Sroberto } 187258945Sroberto#endif 188258945Sroberto if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { 189258945Sroberto if (getrlimit(unixresource, &rl) == 0) { 190258945Sroberto rl.rlim_cur = rl.rlim_max; 191258945Sroberto unixresult = setrlimit(unixresource, &rl); 192258945Sroberto if (unixresult == 0) 193258945Sroberto return (ISC_R_SUCCESS); 194258945Sroberto } 195258945Sroberto } 196258945Sroberto return (isc__errno2result(errno)); 197258945Sroberto} 198258945Sroberto 199258945Srobertoisc_result_t 200258945Srobertoisc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) { 201258945Sroberto int unixresult; 202258945Sroberto int unixresource; 203258945Sroberto struct rlimit rl; 204258945Sroberto isc_result_t result; 205258945Sroberto 206258945Sroberto result = resource2rlim(resource, &unixresource); 207258945Sroberto if (result == ISC_R_SUCCESS) { 208258945Sroberto unixresult = getrlimit(unixresource, &rl); 209258945Sroberto INSIST(unixresult == 0); 210258945Sroberto *value = rl.rlim_max; 211258945Sroberto } 212258945Sroberto 213258945Sroberto return (result); 214258945Sroberto} 215258945Sroberto 216258945Srobertoisc_result_t 217258945Srobertoisc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) { 218258945Sroberto int unixresult; 219258945Sroberto int unixresource; 220258945Sroberto struct rlimit rl; 221258945Sroberto isc_result_t result; 222258945Sroberto 223258945Sroberto result = resource2rlim(resource, &unixresource); 224258945Sroberto if (result == ISC_R_SUCCESS) { 225258945Sroberto unixresult = getrlimit(unixresource, &rl); 226258945Sroberto INSIST(unixresult == 0); 227258945Sroberto *value = rl.rlim_cur; 228258945Sroberto } 229258945Sroberto 230258945Sroberto return (result); 231258945Sroberto} 232