1 /* $OpenBSD: pool.c,v 1.6 2011/03/02 06:48:17 jasper Exp $ */ 2 /* 3 * Copyright (c) 2008 Can Erkin Acar <canacar@openbsd.org> 4 * 5 * Permission to use, copy, modify, and 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 THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/types.h> 19 #include <sys/param.h> 20 #include <sys/sysctl.h> 21 #include <sys/pool.h> 22 #include <errno.h> 23 #include <stdlib.h> 24 #include <string.h> 25 26 #include "systat.h" 27 28 void print_pool(void); 29 int read_pool(void); 30 void sort_pool(void); 31 int select_pool(void); 32 void showpool(int k); 33 34 /* qsort callbacks */ 35 int sort_name_callback(const void *s1, const void *s2); 36 int sort_req_callback(const void *s1, const void *s2); 37 int sort_psize_callback(const void *s1, const void *s2); 38 int sort_npage_callback(const void *s1, const void *s2); 39 40 struct pool_info { 41 char name[32]; 42 struct pool pool; 43 }; 44 45 46 int num_pools = 0; 47 struct pool_info *pools = NULL; 48 49 50 field_def fields_pool[] = { 51 {"NAME", 11, 32, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, 52 {"SIZE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 53 {"REQUESTS", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 54 {"FAIL", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 55 {"INUSE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 56 {"PGREQ", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 57 {"PGREL", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 58 {"NPAGE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 59 {"HIWAT", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 60 {"MINPG", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 61 {"MAXPG", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 62 {"IDLE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0} 63 }; 64 65 66 #define FLD_POOL_NAME FIELD_ADDR(fields_pool,0) 67 #define FLD_POOL_SIZE FIELD_ADDR(fields_pool,1) 68 #define FLD_POOL_REQS FIELD_ADDR(fields_pool,2) 69 #define FLD_POOL_FAIL FIELD_ADDR(fields_pool,3) 70 #define FLD_POOL_INUSE FIELD_ADDR(fields_pool,4) 71 #define FLD_POOL_PGREQ FIELD_ADDR(fields_pool,5) 72 #define FLD_POOL_PGREL FIELD_ADDR(fields_pool,6) 73 #define FLD_POOL_NPAGE FIELD_ADDR(fields_pool,7) 74 #define FLD_POOL_HIWAT FIELD_ADDR(fields_pool,8) 75 #define FLD_POOL_MINPG FIELD_ADDR(fields_pool,9) 76 #define FLD_POOL_MAXPG FIELD_ADDR(fields_pool,10) 77 #define FLD_POOL_IDLE FIELD_ADDR(fields_pool,11) 78 79 /* Define views */ 80 field_def *view_pool_0[] = { 81 FLD_POOL_NAME, FLD_POOL_SIZE, FLD_POOL_REQS, FLD_POOL_FAIL, 82 FLD_POOL_INUSE, FLD_POOL_PGREQ, FLD_POOL_PGREL, FLD_POOL_NPAGE, 83 FLD_POOL_HIWAT, FLD_POOL_MINPG, FLD_POOL_MAXPG, FLD_POOL_IDLE, NULL 84 }; 85 86 order_type pool_order_list[] = { 87 {"name", "name", 'N', sort_name_callback}, 88 {"requests", "requests", 'Q', sort_req_callback}, 89 {"size", "size", 'Z', sort_psize_callback}, 90 {"npages", "npages", 'P', sort_npage_callback}, 91 {NULL, NULL, 0, NULL} 92 }; 93 94 /* Define view managers */ 95 struct view_manager pool_mgr = { 96 "Pool", select_pool, read_pool, sort_pool, print_header, 97 print_pool, keyboard_callback, pool_order_list, pool_order_list 98 }; 99 100 field_view views_pool[] = { 101 {view_pool_0, "pool", '5', &pool_mgr}, 102 {NULL, NULL, 0, NULL} 103 }; 104 105 106 int 107 sort_name_callback(const void *s1, const void *s2) 108 { 109 struct pool_info *p1, *p2; 110 p1 = (struct pool_info *)s1; 111 p2 = (struct pool_info *)s2; 112 113 return strcmp(p1->name, p2->name) * sortdir; 114 } 115 116 int 117 sort_req_callback(const void *s1, const void *s2) 118 { 119 struct pool_info *p1, *p2; 120 p1 = (struct pool_info *)s1; 121 p2 = (struct pool_info *)s2; 122 123 if (p1->pool.pr_nget < p2->pool.pr_nget) 124 return sortdir; 125 if (p1->pool.pr_nget > p2->pool.pr_nget) 126 return -sortdir; 127 128 return sort_name_callback(s1, s2); 129 } 130 131 int 132 sort_npage_callback(const void *s1, const void *s2) 133 { 134 struct pool_info *p1, *p2; 135 p1 = (struct pool_info *)s1; 136 p2 = (struct pool_info *)s2; 137 138 if (p1->pool.pr_npages < p2->pool.pr_npages) 139 return sortdir; 140 if (p1->pool.pr_npages > p2->pool.pr_npages) 141 return -sortdir; 142 143 return sort_name_callback(s1, s2); 144 } 145 146 int 147 sort_psize_callback(const void *s1, const void *s2) 148 { 149 struct pool_info *p1, *p2; 150 size_t ps1, ps2; 151 152 p1 = (struct pool_info *)s1; 153 p2 = (struct pool_info *)s2; 154 155 ps1 = (size_t)(p1->pool.pr_nget - p1->pool.pr_nput) * 156 (size_t)p1->pool.pr_size; 157 ps2 = (size_t)(p2->pool.pr_nget - p2->pool.pr_nput) * 158 (size_t)p2->pool.pr_size; 159 160 if (ps1 < ps2) 161 return sortdir; 162 if (ps1 > ps2) 163 return -sortdir; 164 165 return sort_npage_callback(s1, s2); 166 } 167 168 void 169 sort_pool(void) 170 { 171 order_type *ordering; 172 173 if (curr_mgr == NULL) 174 return; 175 176 ordering = curr_mgr->order_curr; 177 178 if (ordering == NULL) 179 return; 180 if (ordering->func == NULL) 181 return; 182 if (pools == NULL) 183 return; 184 if (num_pools <= 0) 185 return; 186 187 mergesort(pools, num_pools, sizeof(struct pool_info), ordering->func); 188 } 189 190 int 191 select_pool(void) 192 { 193 num_disp = num_pools; 194 return (0); 195 } 196 197 int 198 read_pool(void) 199 { 200 int mib[4], np, i; 201 size_t size; 202 203 mib[0] = CTL_KERN; 204 mib[1] = KERN_POOL; 205 mib[2] = KERN_POOL_NPOOLS; 206 size = sizeof(np); 207 208 if (sysctl(mib, 3, &np, &size, NULL, 0) < 0) { 209 error("sysctl(npools): %s", strerror(errno)); 210 return (-1); 211 } 212 213 if (np <= 0) { 214 num_pools = 0; 215 return (0); 216 } 217 218 if (np > num_pools || pools == NULL) { 219 struct pool_info *p = realloc(pools, sizeof(*pools) * np); 220 if (p == NULL) { 221 error("realloc: %s", strerror(errno)); 222 return (-1); 223 } 224 pools = p; 225 num_pools = np; 226 } 227 228 num_disp = num_pools; 229 230 for (i = 0; i < num_pools; i++) { 231 mib[0] = CTL_KERN; 232 mib[1] = KERN_POOL; 233 mib[2] = KERN_POOL_POOL; 234 mib[3] = i + 1; 235 size = sizeof(struct pool); 236 if (sysctl(mib, 4, &pools[i].pool, &size, NULL, 0) < 0) { 237 memset(&pools[i], 0, sizeof(pools[i])); 238 num_disp--; 239 continue; 240 } 241 mib[2] = KERN_POOL_NAME; 242 size = sizeof(pools[i].name); 243 if (sysctl(mib, 4, &pools[i].name, &size, NULL, 0) < 0) { 244 snprintf(pools[i].name, size, "#%d#", mib[3]); 245 } 246 } 247 248 if (i != num_pools) { 249 memset(pools, 0, sizeof(*pools) * num_pools); 250 return (-1); 251 } 252 253 return 0; 254 } 255 256 257 void 258 print_pool(void) 259 { 260 int i, n, count = 0; 261 262 if (pools == NULL) 263 return; 264 265 for (n = i = 0; i < num_pools; i++) { 266 if (pools[i].name[0] == 0) 267 continue; 268 if (n++ < dispstart) 269 continue; 270 showpool(i); 271 count++; 272 if (maxprint > 0 && count >= maxprint) 273 break; 274 } 275 } 276 277 int 278 initpool(void) 279 { 280 field_view *v; 281 282 for (v = views_pool; v->name != NULL; v++) 283 add_view(v); 284 285 read_pool(); 286 287 return(0); 288 } 289 290 void 291 showpool(int k) 292 { 293 struct pool_info *p = pools + k; 294 295 if (k < 0 || k >= num_pools) 296 return; 297 298 print_fld_str(FLD_POOL_NAME, p->name); 299 print_fld_uint(FLD_POOL_SIZE, p->pool.pr_size); 300 301 print_fld_size(FLD_POOL_REQS, p->pool.pr_nget); 302 print_fld_size(FLD_POOL_FAIL, p->pool.pr_nfail); 303 print_fld_ssize(FLD_POOL_INUSE, p->pool.pr_nget - p->pool.pr_nput); 304 print_fld_size(FLD_POOL_PGREQ, p->pool.pr_npagealloc); 305 print_fld_size(FLD_POOL_PGREL, p->pool.pr_npagefree); 306 307 print_fld_size(FLD_POOL_NPAGE, p->pool.pr_npages); 308 print_fld_size(FLD_POOL_HIWAT, p->pool.pr_hiwat); 309 print_fld_size(FLD_POOL_MINPG, p->pool.pr_minpages); 310 311 if (p->pool.pr_maxpages == UINT_MAX) 312 print_fld_str(FLD_POOL_MAXPG, "inf"); 313 else 314 print_fld_size(FLD_POOL_MAXPG, p->pool.pr_maxpages); 315 316 print_fld_size(FLD_POOL_IDLE, p->pool.pr_nidle); 317 318 end_line(); 319 } 320