/contrib/bind9/lib/isc/unix/resource.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 231 lines · 165 code · 28 blank · 38 comment · 47 complexity · 6053f982a4cc670c2fd50be8fab67c57 MD5 · raw file

  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. /* $Id: resource.c,v 1.23 2009/02/13 23:48:14 tbox Exp $ */
  18. #include <config.h>
  19. #include <sys/types.h>
  20. #include <sys/time.h> /* Required on some systems for <sys/resource.h>. */
  21. #include <sys/resource.h>
  22. #include <isc/platform.h>
  23. #include <isc/resource.h>
  24. #include <isc/result.h>
  25. #include <isc/util.h>
  26. #ifdef __linux__
  27. #include <linux/fs.h> /* To get the large NR_OPEN. */
  28. #endif
  29. #if defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
  30. #include <sys/dyntune.h>
  31. #endif
  32. #include "errno2result.h"
  33. static isc_result_t
  34. resource2rlim(isc_resource_t resource, int *rlim_resource) {
  35. isc_result_t result = ISC_R_SUCCESS;
  36. switch (resource) {
  37. case isc_resource_coresize:
  38. *rlim_resource = RLIMIT_CORE;
  39. break;
  40. case isc_resource_cputime:
  41. *rlim_resource = RLIMIT_CPU;
  42. break;
  43. case isc_resource_datasize:
  44. *rlim_resource = RLIMIT_DATA;
  45. break;
  46. case isc_resource_filesize:
  47. *rlim_resource = RLIMIT_FSIZE;
  48. break;
  49. case isc_resource_lockedmemory:
  50. #ifdef RLIMIT_MEMLOCK
  51. *rlim_resource = RLIMIT_MEMLOCK;
  52. #else
  53. result = ISC_R_NOTIMPLEMENTED;
  54. #endif
  55. break;
  56. case isc_resource_openfiles:
  57. #ifdef RLIMIT_NOFILE
  58. *rlim_resource = RLIMIT_NOFILE;
  59. #else
  60. result = ISC_R_NOTIMPLEMENTED;
  61. #endif
  62. break;
  63. case isc_resource_processes:
  64. #ifdef RLIMIT_NPROC
  65. *rlim_resource = RLIMIT_NPROC;
  66. #else
  67. result = ISC_R_NOTIMPLEMENTED;
  68. #endif
  69. break;
  70. case isc_resource_residentsize:
  71. #ifdef RLIMIT_RSS
  72. *rlim_resource = RLIMIT_RSS;
  73. #else
  74. result = ISC_R_NOTIMPLEMENTED;
  75. #endif
  76. break;
  77. case isc_resource_stacksize:
  78. *rlim_resource = RLIMIT_STACK;
  79. break;
  80. default:
  81. /*
  82. * This test is not very robust if isc_resource_t
  83. * changes, but generates a clear assertion message.
  84. */
  85. REQUIRE(resource >= isc_resource_coresize &&
  86. resource <= isc_resource_stacksize);
  87. result = ISC_R_RANGE;
  88. break;
  89. }
  90. return (result);
  91. }
  92. isc_result_t
  93. isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
  94. struct rlimit rl;
  95. ISC_PLATFORM_RLIMITTYPE rlim_value;
  96. int unixresult;
  97. int unixresource;
  98. isc_result_t result;
  99. result = resource2rlim(resource, &unixresource);
  100. if (result != ISC_R_SUCCESS)
  101. return (result);
  102. if (value == ISC_RESOURCE_UNLIMITED)
  103. rlim_value = RLIM_INFINITY;
  104. else {
  105. /*
  106. * isc_resourcevalue_t was chosen as an unsigned 64 bit
  107. * integer so that it could contain the maximum range of
  108. * reasonable values. Unfortunately, this exceeds the typical
  109. * range on Unix systems. Ensure the range of
  110. * ISC_PLATFORM_RLIMITTYPE is not overflowed.
  111. */
  112. isc_resourcevalue_t rlim_max;
  113. isc_boolean_t rlim_t_is_signed =
  114. ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0);
  115. if (rlim_t_is_signed)
  116. rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 <<
  117. (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1));
  118. else
  119. rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1;
  120. if (value > rlim_max)
  121. value = rlim_max;
  122. rlim_value = value;
  123. }
  124. rl.rlim_cur = rl.rlim_max = rlim_value;
  125. unixresult = setrlimit(unixresource, &rl);
  126. if (unixresult == 0)
  127. return (ISC_R_SUCCESS);
  128. #if defined(OPEN_MAX) && defined(__APPLE__)
  129. /*
  130. * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the
  131. * maximum possible value is OPEN_MAX. BIND8 used to use
  132. * sysconf(_SC_OPEN_MAX) for such a case, but this value is much
  133. * smaller than OPEN_MAX and is not really effective.
  134. */
  135. if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
  136. rl.rlim_cur = OPEN_MAX;
  137. unixresult = setrlimit(unixresource, &rl);
  138. if (unixresult == 0)
  139. return (ISC_R_SUCCESS);
  140. }
  141. #elif defined(__linux__)
  142. #ifndef NR_OPEN
  143. #define NR_OPEN (1024*1024)
  144. #endif
  145. /*
  146. * Some Linux kernels don't accept RLIM_INFINIT; the maximum
  147. * possible value is the NR_OPEN defined in linux/fs.h.
  148. */
  149. if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
  150. rl.rlim_cur = rl.rlim_max = NR_OPEN;
  151. unixresult = setrlimit(unixresource, &rl);
  152. if (unixresult == 0)
  153. return (ISC_R_SUCCESS);
  154. }
  155. #elif defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
  156. if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
  157. uint64_t maxfiles;
  158. if (gettune("maxfiles_lim", &maxfiles) == 0) {
  159. rl.rlim_cur = rl.rlim_max = maxfiles;
  160. unixresult = setrlimit(unixresource, &rl);
  161. if (unixresult == 0)
  162. return (ISC_R_SUCCESS);
  163. }
  164. }
  165. #endif
  166. if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
  167. if (getrlimit(unixresource, &rl) == 0) {
  168. rl.rlim_cur = rl.rlim_max;
  169. unixresult = setrlimit(unixresource, &rl);
  170. if (unixresult == 0)
  171. return (ISC_R_SUCCESS);
  172. }
  173. }
  174. return (isc__errno2result(errno));
  175. }
  176. isc_result_t
  177. isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
  178. int unixresult;
  179. int unixresource;
  180. struct rlimit rl;
  181. isc_result_t result;
  182. result = resource2rlim(resource, &unixresource);
  183. if (result == ISC_R_SUCCESS) {
  184. unixresult = getrlimit(unixresource, &rl);
  185. INSIST(unixresult == 0);
  186. *value = rl.rlim_max;
  187. }
  188. return (result);
  189. }
  190. isc_result_t
  191. isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
  192. int unixresult;
  193. int unixresource;
  194. struct rlimit rl;
  195. isc_result_t result;
  196. result = resource2rlim(resource, &unixresource);
  197. if (result == ISC_R_SUCCESS) {
  198. unixresult = getrlimit(unixresource, &rl);
  199. INSIST(unixresult == 0);
  200. *value = rl.rlim_cur;
  201. }
  202. return (result);
  203. }