resource.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000, 2001  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id: resource.c,v 1.23 2009/02/13 23:48:14 tbox Exp $ */
00019 
00020 #include <config.h>
00021 
00022 #include <sys/types.h>
00023 #include <sys/time.h>   /* Required on some systems for <sys/resource.h>. */
00024 #include <sys/resource.h>
00025 
00026 #include <isc/platform.h>
00027 #include <isc/resource.h>
00028 #include <isc/result.h>
00029 #include <isc/util.h>
00030 
00031 #ifdef __linux__
00032 #include <linux/fs.h>   /* To get the large NR_OPEN. */
00033 #endif
00034 
00035 #if defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
00036 #include <sys/dyntune.h>
00037 #endif
00038 
00039 #include "errno2result.h"
00040 
00041 static isc_result_t
00042 resource2rlim(isc_resource_t resource, int *rlim_resource) {
00043         isc_result_t result = ISC_R_SUCCESS;
00044 
00045         switch (resource) {
00046         case isc_resource_coresize:
00047                 *rlim_resource = RLIMIT_CORE;
00048                 break;
00049         case isc_resource_cputime:
00050                 *rlim_resource = RLIMIT_CPU;
00051                 break;
00052         case isc_resource_datasize:
00053                 *rlim_resource = RLIMIT_DATA;
00054                 break;
00055         case isc_resource_filesize:
00056                 *rlim_resource = RLIMIT_FSIZE;
00057                 break;
00058         case isc_resource_lockedmemory:
00059 #ifdef RLIMIT_MEMLOCK
00060                 *rlim_resource = RLIMIT_MEMLOCK;
00061 #else
00062                 result = ISC_R_NOTIMPLEMENTED;
00063 #endif
00064                 break;
00065         case isc_resource_openfiles:
00066 #ifdef RLIMIT_NOFILE
00067                 *rlim_resource = RLIMIT_NOFILE;
00068 #else
00069                 result = ISC_R_NOTIMPLEMENTED;
00070 #endif
00071                 break;
00072         case isc_resource_processes:
00073 #ifdef RLIMIT_NPROC
00074                 *rlim_resource = RLIMIT_NPROC;
00075 #else
00076                 result = ISC_R_NOTIMPLEMENTED;
00077 #endif
00078                 break;
00079         case isc_resource_residentsize:
00080 #ifdef RLIMIT_RSS
00081                 *rlim_resource = RLIMIT_RSS;
00082 #else
00083                 result = ISC_R_NOTIMPLEMENTED;
00084 #endif
00085                 break;
00086         case isc_resource_stacksize:
00087                 *rlim_resource = RLIMIT_STACK;
00088                 break;
00089         default:
00090                 /*
00091                  * This test is not very robust if isc_resource_t
00092                  * changes, but generates a clear assertion message.
00093                  */
00094                 REQUIRE(resource >= isc_resource_coresize &&
00095                         resource <= isc_resource_stacksize);
00096 
00097                 result = ISC_R_RANGE;
00098                 break;
00099         }
00100 
00101         return (result);
00102 }
00103 
00104 isc_result_t
00105 isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
00106         struct rlimit rl;
00107         ISC_PLATFORM_RLIMITTYPE rlim_value;
00108         int unixresult;
00109         int unixresource;
00110         isc_result_t result;
00111 
00112         result = resource2rlim(resource, &unixresource);
00113         if (result != ISC_R_SUCCESS)
00114                 return (result);
00115 
00116         if (value == ISC_RESOURCE_UNLIMITED)
00117                 rlim_value = RLIM_INFINITY;
00118 
00119         else {
00120                 /*
00121                  * isc_resourcevalue_t was chosen as an unsigned 64 bit
00122                  * integer so that it could contain the maximum range of
00123                  * reasonable values.  Unfortunately, this exceeds the typical
00124                  * range on Unix systems.  Ensure the range of
00125                  * ISC_PLATFORM_RLIMITTYPE is not overflowed.
00126                  */
00127                 isc_resourcevalue_t rlim_max;
00128                 isc_boolean_t rlim_t_is_signed =
00129                         ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0);
00130 
00131                 if (rlim_t_is_signed)
00132                         rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 <<
00133                                      (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1));
00134                 else
00135                         rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1;
00136 
00137                 if (value > rlim_max)
00138                         value = rlim_max;
00139 
00140                 rlim_value = value;
00141         }
00142 
00143         rl.rlim_cur = rl.rlim_max = rlim_value;
00144         unixresult = setrlimit(unixresource, &rl);
00145 
00146         if (unixresult == 0)
00147                 return (ISC_R_SUCCESS);
00148 
00149 #if defined(OPEN_MAX) && defined(__APPLE__)
00150         /*
00151          * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the
00152          * maximum possible value is OPEN_MAX.  BIND8 used to use
00153          * sysconf(_SC_OPEN_MAX) for such a case, but this value is much
00154          * smaller than OPEN_MAX and is not really effective.
00155          */
00156         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
00157                 rl.rlim_cur = OPEN_MAX;
00158                 unixresult = setrlimit(unixresource, &rl);
00159                 if (unixresult == 0)
00160                         return (ISC_R_SUCCESS);
00161         }
00162 #elif defined(__linux__)
00163 #ifndef NR_OPEN
00164 #define NR_OPEN (1024*1024)
00165 #endif
00166 
00167         /*
00168          * Some Linux kernels don't accept RLIM_INFINIT; the maximum
00169          * possible value is the NR_OPEN defined in linux/fs.h.
00170          */
00171         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
00172                 rl.rlim_cur = rl.rlim_max = NR_OPEN;
00173                 unixresult = setrlimit(unixresource, &rl);
00174                 if (unixresult == 0)
00175                         return (ISC_R_SUCCESS);
00176         }
00177 #elif defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
00178         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
00179                 uint64_t maxfiles;
00180                 if (gettune("maxfiles_lim", &maxfiles) == 0) {
00181                         rl.rlim_cur = rl.rlim_max = maxfiles;
00182                         unixresult = setrlimit(unixresource, &rl);
00183                         if (unixresult == 0)
00184                                 return (ISC_R_SUCCESS);
00185                 }
00186         }
00187 #endif
00188         if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
00189                 if (getrlimit(unixresource, &rl) == 0) {
00190                         rl.rlim_cur = rl.rlim_max;
00191                         unixresult = setrlimit(unixresource, &rl);
00192                         if (unixresult == 0)
00193                                 return (ISC_R_SUCCESS);
00194                 }
00195         }
00196         return (isc__errno2result(errno));
00197 }
00198 
00199 isc_result_t
00200 isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
00201         int unixresult;
00202         int unixresource;
00203         struct rlimit rl;
00204         isc_result_t result;
00205 
00206         result = resource2rlim(resource, &unixresource);
00207         if (result == ISC_R_SUCCESS) {
00208                 unixresult = getrlimit(unixresource, &rl);
00209                 INSIST(unixresult == 0);
00210                 *value = rl.rlim_max;
00211         }
00212 
00213         return (result);
00214 }
00215 
00216 isc_result_t
00217 isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
00218         int unixresult;
00219         int unixresource;
00220         struct rlimit rl;
00221         isc_result_t result;
00222 
00223         result = resource2rlim(resource, &unixresource);
00224         if (result == ISC_R_SUCCESS) {
00225                 unixresult = getrlimit(unixresource, &rl);
00226                 INSIST(unixresult == 0);
00227                 *value = rl.rlim_cur;
00228         }
00229 
00230         return (result);
00231 }

Generated on Tue Apr 28 17:41:05 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha