1 /* $OpenBSD: pool.c,v 1.5 2008/12/31 05:37:24 canacar 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 FIELD_ADDR(x) (&fields_pool[x]) 67 68 #define FLD_POOL_NAME FIELD_ADDR(0) 69 #define FLD_POOL_SIZE FIELD_ADDR(1) 70 #define FLD_POOL_REQS FIELD_ADDR(2) 71 #define FLD_POOL_FAIL FIELD_ADDR(3) 72 #define FLD_POOL_INUSE FIELD_ADDR(4) 73 #define FLD_POOL_PGREQ FIELD_ADDR(5) 74 #define FLD_POOL_PGREL FIELD_ADDR(6) 75 #define FLD_POOL_NPAGE FIELD_ADDR(7) 76 #define FLD_POOL_HIWAT FIELD_ADDR(8) 77 #define FLD_POOL_MINPG FIELD_ADDR(9) 78 #define FLD_POOL_MAXPG FIELD_ADDR(10) 79 #define FLD_POOL_IDLE FIELD_ADDR(11) 80 81 /* Define views */ 82 field_def *view_pool_0[] = { 83 FLD_POOL_NAME, FLD_POOL_SIZE, FLD_POOL_REQS, FLD_POOL_FAIL, 84 FLD_POOL_INUSE, FLD_POOL_PGREQ, FLD_POOL_PGREL, FLD_POOL_NPAGE, 85 FLD_POOL_HIWAT, FLD_POOL_MINPG, FLD_POOL_MAXPG, FLD_POOL_IDLE, NULL 86 }; 87 88 order_type pool_order_list[] = { 89 {"name", "name", 'N', sort_name_callback}, 90 {"requests", "requests", 'Q', sort_req_callback}, 91 {"size", "size", 'Z', sort_psize_callback}, 92 {"npages", "npages", 'P', sort_npage_callback}, 93 {NULL, NULL, 0, NULL} 94 }; 95 96 /* Define view managers */ 97 struct view_manager pool_mgr = { 98 "Pool", select_pool, read_pool, sort_pool, print_header, 99 print_pool, keyboard_callback, pool_order_list, pool_order_list 100 }; 101 102 field_view views_pool[] = { 103 {view_pool_0, "pool", '5', &pool_mgr}, 104 {NULL, NULL, 0, NULL} 105 }; 106 107 108 int 109 sort_name_callback(const void *s1, const void *s2) 110 { 111 struct pool_info *p1, *p2; 112 p1 = (struct pool_info *)s1; 113 p2 = (struct pool_info *)s2; 114 115 return strcmp(p1->name, p2->name) * sortdir; 116 } 117 118 int 119 sort_req_callback(const void *s1, const void *s2) 120 { 121 struct pool_info *p1, *p2; 122 p1 = (struct pool_info *)s1; 123 p2 = (struct pool_info *)s2; 124 125 if (p1->pool.pr_nget < p2->pool.pr_nget) 126 return sortdir; 127 if (p1->pool.pr_nget > p2->pool.pr_nget) 128 return -sortdir; 129 130 return sort_name_callback(s1, s2); 131 } 132 133 int 134 sort_npage_callback(const void *s1, const void *s2) 135 { 136 struct pool_info *p1, *p2; 137 p1 = (struct pool_info *)s1; 138 p2 = (struct pool_info *)s2; 139 140 if (p1->pool.pr_npages < p2->pool.pr_npages) 141 return sortdir; 142 if (p1->pool.pr_npages > p2->pool.pr_npages) 143 return -sortdir; 144 145 return sort_name_callback(s1, s2); 146 } 147 148 int 149 sort_psize_callback(const void *s1, const void *s2) 150 { 151 struct pool_info *p1, *p2; 152 size_t ps1, ps2; 153 154 p1 = (struct pool_info *)s1; 155 p2 = (struct pool_info *)s2; 156 157 ps1 = (size_t)(p1->pool.pr_nget - p1->pool.pr_nput) * 158 (size_t)p1->pool.pr_size; 159 ps2 = (size_t)(p2->pool.pr_nget - p2->pool.pr_nput) * 160 (size_t)p2->pool.pr_size; 161 162 if (ps1 < ps2) 163 return sortdir; 164 if (ps1 > ps2) 165 return -sortdir; 166 167 return sort_npage_callback(s1, s2); 168 } 169 170 void 171 sort_pool(void) 172 { 173 order_type *ordering; 174 175 if (curr_mgr == NULL) 176 return; 177 178 ordering = curr_mgr->order_curr; 179 180 if (ordering == NULL) 181 return; 182 if (ordering->func == NULL) 183 return; 184 if (pools == NULL) 185 return; 186 if (num_pools <= 0) 187 return; 188 189 mergesort(pools, num_pools, sizeof(struct pool_info), ordering->func); 190 } 191 192 int 193 select_pool(void) 194 { 195 num_disp = num_pools; 196 return (0); 197 } 198 199 int 200 read_pool(void) 201 { 202 int mib[4], np, i; 203 size_t size; 204 205 mib[0] = CTL_KERN; 206 mib[1] = KERN_POOL; 207 mib[2] = KERN_POOL_NPOOLS; 208 size = sizeof(np); 209 210 if (sysctl(mib, 3, &np, &size, NULL, 0) < 0) { 211 error("sysctl(npools): %s", strerror(errno)); 212 return (-1); 213 } 214 215 if (np <= 0) { 216 num_pools = 0; 217 return (0); 218 } 219 220 if (np > num_pools || pools == NULL) { 221 struct pool_info *p = realloc(pools, sizeof(*pools) * np); 222 if (p == NULL) { 223 error("realloc: %s", strerror(errno)); 224 return (-1); 225 } 226 pools = p; 227 num_pools = np; 228 } 229 230 num_disp = num_pools; 231 232 for (i = 0; i < num_pools; i++) { 233 mib[0] = CTL_KERN; 234 mib[1] = KERN_POOL; 235 mib[2] = KERN_POOL_POOL; 236 mib[3] = i + 1; 237 size = sizeof(struct pool); 238 if (sysctl(mib, 4, &pools[i].pool, &size, NULL, 0) < 0) { 239 memset(&pools[i], 0, sizeof(pools[i])); 240 num_disp--; 241 continue; 242 } 243 mib[2] = KERN_POOL_NAME; 244 size = sizeof(pools[i].name); 245 if (sysctl(mib, 4, &pools[i].name, &size, NULL, 0) < 0) { 246 snprintf(pools[i].name, size, "#%d#", mib[3]); 247 } 248 } 249 250 if (i != num_pools) { 251 memset(pools, 0, sizeof(*pools) * num_pools); 252 return (-1); 253 } 254 255 return 0; 256 } 257 258 259 void 260 print_pool(void) 261 { 262 int i, n, count = 0; 263 264 if (pools == NULL) 265 return; 266 267 for (n = i = 0; i < num_pools; i++) { 268 if (pools[i].name[0] == 0) 269 continue; 270 if (n++ < dispstart) 271 continue; 272 showpool(i); 273 count++; 274 if (maxprint > 0 && count >= maxprint) 275 break; 276 } 277 } 278 279 int 280 initpool(void) 281 { 282 field_view *v; 283 284 for (v = views_pool; v->name != NULL; v++) 285 add_view(v); 286 287 read_pool(); 288 289 return(0); 290 } 291 292 void 293 showpool(int k) 294 { 295 struct pool_info *p = pools + k; 296 297 if (k < 0 || k >= num_pools) 298 return; 299 300 print_fld_str(FLD_POOL_NAME, p->name); 301 print_fld_uint(FLD_POOL_SIZE, p->pool.pr_size); 302 303 print_fld_size(FLD_POOL_REQS, p->pool.pr_nget); 304 print_fld_size(FLD_POOL_FAIL, p->pool.pr_nfail); 305 print_fld_ssize(FLD_POOL_INUSE, p->pool.pr_nget - p->pool.pr_nput); 306 print_fld_size(FLD_POOL_PGREQ, p->pool.pr_npagealloc); 307 print_fld_size(FLD_POOL_PGREL, p->pool.pr_npagefree); 308 309 print_fld_size(FLD_POOL_NPAGE, p->pool.pr_npages); 310 print_fld_size(FLD_POOL_HIWAT, p->pool.pr_hiwat); 311 print_fld_size(FLD_POOL_MINPG, p->pool.pr_minpages); 312 313 if (p->pool.pr_maxpages == UINT_MAX) 314 print_fld_str(FLD_POOL_MAXPG, "inf"); 315 else 316 print_fld_size(FLD_POOL_MAXPG, p->pool.pr_maxpages); 317 318 print_fld_size(FLD_POOL_IDLE, p->pool.pr_nidle); 319 320 end_line(); 321 } 322