1 |
|
|
/* $OpenBSD: pool.c,v 1.15 2017/07/31 04:23:30 dlg 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/signal.h> |
20 |
|
|
#include <sys/sysctl.h> |
21 |
|
|
#include <sys/pool.h> |
22 |
|
|
#include <errno.h> |
23 |
|
|
#include <stdlib.h> |
24 |
|
|
#include <string.h> |
25 |
|
|
#include <limits.h> |
26 |
|
|
|
27 |
|
|
#include "systat.h" |
28 |
|
|
|
29 |
|
|
#ifndef nitems |
30 |
|
|
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) |
31 |
|
|
#endif |
32 |
|
|
|
33 |
|
|
static int sysctl_rdint(const int *, unsigned int); |
34 |
|
|
static int hw_ncpusfound(void); |
35 |
|
|
|
36 |
|
|
static int pool_get_npools(void); |
37 |
|
|
static int pool_get_name(int, char *, size_t); |
38 |
|
|
static int pool_get_cache(int, struct kinfo_pool_cache *); |
39 |
|
|
static int pool_get_cache_cpus(int, struct kinfo_pool_cache_cpu *, |
40 |
|
|
unsigned int); |
41 |
|
|
|
42 |
|
|
void print_pool(void); |
43 |
|
|
int read_pool(void); |
44 |
|
|
void sort_pool(void); |
45 |
|
|
int select_pool(void); |
46 |
|
|
void showpool(int k); |
47 |
|
|
int pool_keyboard_callback(int); |
48 |
|
|
|
49 |
|
|
/* qsort callbacks */ |
50 |
|
|
int sort_name_callback(const void *s1, const void *s2); |
51 |
|
|
int sort_req_callback(const void *s1, const void *s2); |
52 |
|
|
int sort_psize_callback(const void *s1, const void *s2); |
53 |
|
|
int sort_npage_callback(const void *s1, const void *s2); |
54 |
|
|
|
55 |
|
|
struct pool_info { |
56 |
|
|
char name[32]; |
57 |
|
|
struct kinfo_pool pool; |
58 |
|
|
}; |
59 |
|
|
|
60 |
|
|
/* |
61 |
|
|
* the kernel gives an array of ncpusfound * kinfo_pool_cache structs, but |
62 |
|
|
* it's idea of how big that struct is may differ from here. we fetch both |
63 |
|
|
* ncpusfound and the size it thinks kinfo_pool_cache is from sysctl, and |
64 |
|
|
* then allocate the memory for this here. |
65 |
|
|
*/ |
66 |
|
|
struct pool_cache_info { |
67 |
|
|
char name[32]; |
68 |
|
|
struct kinfo_pool_cache cache; |
69 |
|
|
struct kinfo_pool_cache_cpu *cache_cpus; |
70 |
|
|
}; |
71 |
|
|
|
72 |
|
|
int print_all = 0; |
73 |
|
|
int num_pools = 0; |
74 |
|
|
struct pool_info *pools = NULL; |
75 |
|
|
int num_pool_caches = 0; |
76 |
|
|
struct pool_cache_info *pool_caches = NULL; |
77 |
|
|
|
78 |
|
|
int ncpusfound = 0; |
79 |
|
|
|
80 |
|
|
field_def fields_pool[] = { |
81 |
|
|
{"NAME", 12, 32, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
82 |
|
|
{"SIZE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
83 |
|
|
{"REQUESTS", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
84 |
|
|
{"FAIL", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
85 |
|
|
{"INUSE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
86 |
|
|
{"PGREQ", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
87 |
|
|
{"PGREL", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
88 |
|
|
{"NPAGE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
89 |
|
|
{"HIWAT", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
90 |
|
|
{"MINPG", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
91 |
|
|
{"MAXPG", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
92 |
|
|
{"IDLE", 8, 24, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0} |
93 |
|
|
}; |
94 |
|
|
|
95 |
|
|
#define FLD_POOL_NAME FIELD_ADDR(fields_pool,0) |
96 |
|
|
#define FLD_POOL_SIZE FIELD_ADDR(fields_pool,1) |
97 |
|
|
#define FLD_POOL_REQS FIELD_ADDR(fields_pool,2) |
98 |
|
|
#define FLD_POOL_FAIL FIELD_ADDR(fields_pool,3) |
99 |
|
|
#define FLD_POOL_INUSE FIELD_ADDR(fields_pool,4) |
100 |
|
|
#define FLD_POOL_PGREQ FIELD_ADDR(fields_pool,5) |
101 |
|
|
#define FLD_POOL_PGREL FIELD_ADDR(fields_pool,6) |
102 |
|
|
#define FLD_POOL_NPAGE FIELD_ADDR(fields_pool,7) |
103 |
|
|
#define FLD_POOL_HIWAT FIELD_ADDR(fields_pool,8) |
104 |
|
|
#define FLD_POOL_MINPG FIELD_ADDR(fields_pool,9) |
105 |
|
|
#define FLD_POOL_MAXPG FIELD_ADDR(fields_pool,10) |
106 |
|
|
#define FLD_POOL_IDLE FIELD_ADDR(fields_pool,11) |
107 |
|
|
|
108 |
|
|
/* Define views */ |
109 |
|
|
field_def *view_pool_0[] = { |
110 |
|
|
FLD_POOL_NAME, FLD_POOL_SIZE, FLD_POOL_REQS, FLD_POOL_FAIL, |
111 |
|
|
FLD_POOL_INUSE, FLD_POOL_PGREQ, FLD_POOL_PGREL, FLD_POOL_NPAGE, |
112 |
|
|
FLD_POOL_HIWAT, FLD_POOL_MINPG, FLD_POOL_MAXPG, FLD_POOL_IDLE, NULL |
113 |
|
|
}; |
114 |
|
|
|
115 |
|
|
order_type pool_order_list[] = { |
116 |
|
|
{"name", "name", 'N', sort_name_callback}, |
117 |
|
|
{"requests", "requests", 'Q', sort_req_callback}, |
118 |
|
|
{"size", "size", 'Z', sort_psize_callback}, |
119 |
|
|
{"npages", "npages", 'P', sort_npage_callback}, |
120 |
|
|
{NULL, NULL, 0, NULL} |
121 |
|
|
}; |
122 |
|
|
|
123 |
|
|
/* Define view managers */ |
124 |
|
|
struct view_manager pool_mgr = { |
125 |
|
|
"Pool", select_pool, read_pool, sort_pool, print_header, |
126 |
|
|
print_pool, pool_keyboard_callback, pool_order_list, pool_order_list |
127 |
|
|
}; |
128 |
|
|
|
129 |
|
|
field_view pool_view = { |
130 |
|
|
view_pool_0, |
131 |
|
|
"pool", |
132 |
|
|
'5', |
133 |
|
|
&pool_mgr |
134 |
|
|
}; |
135 |
|
|
|
136 |
|
|
void pool_cache_print(void); |
137 |
|
|
int pool_cache_read(void); |
138 |
|
|
void pool_cache_sort(void); |
139 |
|
|
void pool_cache_show(const struct pool_cache_info *); |
140 |
|
|
int pool_cache_kbd_cb(int); |
141 |
|
|
|
142 |
|
|
field_def pool_cache_fields[] = { |
143 |
|
|
{"NAME", 12, 32, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
144 |
|
|
{"LEN", 4, 4, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
145 |
|
|
{"IDLE", 4, 4, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
146 |
|
|
{"NGC", 4, 4, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
147 |
|
|
{"CPU", 4, 4, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
148 |
|
|
{"REQ", 8, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
149 |
|
|
{"REL", 8, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
150 |
|
|
{"LREQ", 8, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
151 |
|
|
{"LREL", 8, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
152 |
|
|
}; |
153 |
|
|
|
154 |
|
|
#define FLD_POOL_CACHE_NAME FIELD_ADDR(pool_cache_fields, 0) |
155 |
|
|
#define FLD_POOL_CACHE_LEN FIELD_ADDR(pool_cache_fields, 1) |
156 |
|
|
#define FLD_POOL_CACHE_IDLE FIELD_ADDR(pool_cache_fields, 2) |
157 |
|
|
#define FLD_POOL_CACHE_NGC FIELD_ADDR(pool_cache_fields, 3) |
158 |
|
|
#define FLD_POOL_CACHE_CPU FIELD_ADDR(pool_cache_fields, 4) |
159 |
|
|
#define FLD_POOL_CACHE_GET FIELD_ADDR(pool_cache_fields, 5) |
160 |
|
|
#define FLD_POOL_CACHE_PUT FIELD_ADDR(pool_cache_fields, 6) |
161 |
|
|
#define FLD_POOL_CACHE_LGET FIELD_ADDR(pool_cache_fields, 7) |
162 |
|
|
#define FLD_POOL_CACHE_LPUT FIELD_ADDR(pool_cache_fields, 8) |
163 |
|
|
|
164 |
|
|
field_def *view_pool_cache_0[] = { |
165 |
|
|
FLD_POOL_CACHE_NAME, |
166 |
|
|
FLD_POOL_CACHE_LEN, |
167 |
|
|
FLD_POOL_CACHE_IDLE, |
168 |
|
|
FLD_POOL_CACHE_NGC, |
169 |
|
|
FLD_POOL_CACHE_CPU, |
170 |
|
|
FLD_POOL_CACHE_GET, |
171 |
|
|
FLD_POOL_CACHE_PUT, |
172 |
|
|
FLD_POOL_CACHE_LGET, |
173 |
|
|
FLD_POOL_CACHE_LPUT, |
174 |
|
|
NULL, |
175 |
|
|
}; |
176 |
|
|
|
177 |
|
|
order_type pool_cache_order_list[] = { |
178 |
|
|
{"name", "name", 'N', sort_name_callback}, |
179 |
|
|
{"requests", "requests", 'G', sort_req_callback}, |
180 |
|
|
{"releases", "releases", 'P', sort_req_callback}, |
181 |
|
|
{NULL, NULL, 0, NULL} |
182 |
|
|
}; |
183 |
|
|
|
184 |
|
|
/* Define view managers */ |
185 |
|
|
struct view_manager pool_cache_mgr = { |
186 |
|
|
"PoolCache", |
187 |
|
|
select_pool, |
188 |
|
|
pool_cache_read, |
189 |
|
|
pool_cache_sort, |
190 |
|
|
print_header, |
191 |
|
|
pool_cache_print, |
192 |
|
|
pool_keyboard_callback, |
193 |
|
|
pool_cache_order_list, |
194 |
|
|
pool_cache_order_list |
195 |
|
|
}; |
196 |
|
|
|
197 |
|
|
field_view pool_cache_view = { |
198 |
|
|
view_pool_cache_0, |
199 |
|
|
"pcaches", |
200 |
|
|
'5', |
201 |
|
|
&pool_cache_mgr |
202 |
|
|
}; |
203 |
|
|
|
204 |
|
|
int |
205 |
|
|
sort_name_callback(const void *s1, const void *s2) |
206 |
|
|
{ |
207 |
|
|
struct pool_info *p1, *p2; |
208 |
|
|
p1 = (struct pool_info *)s1; |
209 |
|
|
p2 = (struct pool_info *)s2; |
210 |
|
|
|
211 |
|
|
return strcmp(p1->name, p2->name) * sortdir; |
212 |
|
|
} |
213 |
|
|
|
214 |
|
|
int |
215 |
|
|
sort_req_callback(const void *s1, const void *s2) |
216 |
|
|
{ |
217 |
|
|
struct pool_info *p1, *p2; |
218 |
|
|
p1 = (struct pool_info *)s1; |
219 |
|
|
p2 = (struct pool_info *)s2; |
220 |
|
|
|
221 |
|
|
if (p1->pool.pr_nget < p2->pool.pr_nget) |
222 |
|
|
return sortdir; |
223 |
|
|
if (p1->pool.pr_nget > p2->pool.pr_nget) |
224 |
|
|
return -sortdir; |
225 |
|
|
|
226 |
|
|
return sort_name_callback(s1, s2); |
227 |
|
|
} |
228 |
|
|
|
229 |
|
|
int |
230 |
|
|
sort_npage_callback(const void *s1, const void *s2) |
231 |
|
|
{ |
232 |
|
|
struct pool_info *p1, *p2; |
233 |
|
|
p1 = (struct pool_info *)s1; |
234 |
|
|
p2 = (struct pool_info *)s2; |
235 |
|
|
|
236 |
|
|
if (p1->pool.pr_npages < p2->pool.pr_npages) |
237 |
|
|
return sortdir; |
238 |
|
|
if (p1->pool.pr_npages > p2->pool.pr_npages) |
239 |
|
|
return -sortdir; |
240 |
|
|
|
241 |
|
|
return sort_name_callback(s1, s2); |
242 |
|
|
} |
243 |
|
|
|
244 |
|
|
int |
245 |
|
|
sort_psize_callback(const void *s1, const void *s2) |
246 |
|
|
{ |
247 |
|
|
struct pool_info *p1, *p2; |
248 |
|
|
size_t ps1, ps2; |
249 |
|
|
|
250 |
|
|
p1 = (struct pool_info *)s1; |
251 |
|
|
p2 = (struct pool_info *)s2; |
252 |
|
|
|
253 |
|
|
ps1 = (size_t)(p1->pool.pr_nget - p1->pool.pr_nput) * |
254 |
|
|
(size_t)p1->pool.pr_size; |
255 |
|
|
ps2 = (size_t)(p2->pool.pr_nget - p2->pool.pr_nput) * |
256 |
|
|
(size_t)p2->pool.pr_size; |
257 |
|
|
|
258 |
|
|
if (ps1 < ps2) |
259 |
|
|
return sortdir; |
260 |
|
|
if (ps1 > ps2) |
261 |
|
|
return -sortdir; |
262 |
|
|
|
263 |
|
|
return sort_npage_callback(s1, s2); |
264 |
|
|
} |
265 |
|
|
|
266 |
|
|
void |
267 |
|
|
sort_pool(void) |
268 |
|
|
{ |
269 |
|
|
order_type *ordering; |
270 |
|
|
|
271 |
|
|
if (curr_mgr == NULL) |
272 |
|
|
return; |
273 |
|
|
|
274 |
|
|
ordering = curr_mgr->order_curr; |
275 |
|
|
|
276 |
|
|
if (ordering == NULL) |
277 |
|
|
return; |
278 |
|
|
if (ordering->func == NULL) |
279 |
|
|
return; |
280 |
|
|
if (pools == NULL) |
281 |
|
|
return; |
282 |
|
|
if (num_pools <= 0) |
283 |
|
|
return; |
284 |
|
|
|
285 |
|
|
mergesort(pools, num_pools, sizeof(struct pool_info), ordering->func); |
286 |
|
|
} |
287 |
|
|
|
288 |
|
|
int |
289 |
|
|
select_pool(void) |
290 |
|
|
{ |
291 |
|
|
num_disp = num_pools; |
292 |
|
|
return (0); |
293 |
|
|
} |
294 |
|
|
|
295 |
|
|
int |
296 |
|
|
read_pool(void) |
297 |
|
|
{ |
298 |
|
|
int mib[] = { CTL_KERN, KERN_POOL, KERN_POOL_POOL, 0 }; |
299 |
|
|
struct pool_info *p; |
300 |
|
|
int np, i; |
301 |
|
|
size_t size; |
302 |
|
|
|
303 |
|
|
np = pool_get_npools(); |
304 |
|
|
if (np == -1) { |
305 |
|
|
error("sysctl(npools): %s", strerror(errno)); |
306 |
|
|
return (-1); |
307 |
|
|
} |
308 |
|
|
|
309 |
|
|
if (np == 0) { |
310 |
|
|
free(pools); |
311 |
|
|
pools = NULL; |
312 |
|
|
num_pools = 0; |
313 |
|
|
return (0); |
314 |
|
|
} |
315 |
|
|
|
316 |
|
|
if (np > num_pools || pools == NULL) { |
317 |
|
|
p = reallocarray(pools, np, sizeof(*pools)); |
318 |
|
|
if (p == NULL) { |
319 |
|
|
error("realloc: %s", strerror(errno)); |
320 |
|
|
return (-1); |
321 |
|
|
} |
322 |
|
|
/* commit */ |
323 |
|
|
pools = p; |
324 |
|
|
num_pools = np; |
325 |
|
|
} |
326 |
|
|
|
327 |
|
|
num_disp = num_pools; |
328 |
|
|
|
329 |
|
|
for (i = 0; i < num_pools; i++) { |
330 |
|
|
p = &pools[i]; |
331 |
|
|
np = i + 1; |
332 |
|
|
|
333 |
|
|
mib[3] = np; |
334 |
|
|
size = sizeof(pools[i].pool); |
335 |
|
|
if (sysctl(mib, nitems(mib), &p->pool, &size, NULL, 0) < 0) { |
336 |
|
|
p->name[0] = '\0'; |
337 |
|
|
num_disp--; |
338 |
|
|
continue; |
339 |
|
|
} |
340 |
|
|
|
341 |
|
|
if (pool_get_name(np, p->name, sizeof(p->name)) < 0) |
342 |
|
|
snprintf(p->name, sizeof(p->name), "#%d#", i + 1); |
343 |
|
|
} |
344 |
|
|
|
345 |
|
|
return 0; |
346 |
|
|
} |
347 |
|
|
|
348 |
|
|
|
349 |
|
|
void |
350 |
|
|
print_pool(void) |
351 |
|
|
{ |
352 |
|
|
struct pool_info *p; |
353 |
|
|
int i, n, count = 0; |
354 |
|
|
|
355 |
|
|
if (pools == NULL) |
356 |
|
|
return; |
357 |
|
|
|
358 |
|
|
for (n = i = 0; i < num_pools; i++) { |
359 |
|
|
p = &pools[i]; |
360 |
|
|
if (p->name[0] == 0) |
361 |
|
|
continue; |
362 |
|
|
|
363 |
|
|
if (!print_all && |
364 |
|
|
(p->pool.pr_nget == 0 && p->pool.pr_npagealloc == 0)) |
365 |
|
|
continue; |
366 |
|
|
|
367 |
|
|
if (n++ < dispstart) |
368 |
|
|
continue; |
369 |
|
|
showpool(i); |
370 |
|
|
count++; |
371 |
|
|
if (maxprint > 0 && count >= maxprint) |
372 |
|
|
break; |
373 |
|
|
} |
374 |
|
|
} |
375 |
|
|
|
376 |
|
|
int |
377 |
|
|
initpool(void) |
378 |
|
|
{ |
379 |
|
|
field_view *v; |
380 |
|
|
|
381 |
|
|
add_view(&pool_view); |
382 |
|
|
read_pool(); |
383 |
|
|
|
384 |
|
|
ncpusfound = hw_ncpusfound(); |
385 |
|
|
if (ncpusfound == -1) { |
386 |
|
|
error("sysctl(ncpusfound): %s", strerror(errno)); |
387 |
|
|
exit(1); |
388 |
|
|
} |
389 |
|
|
|
390 |
|
|
add_view(&pool_cache_view); |
391 |
|
|
pool_cache_read(); |
392 |
|
|
|
393 |
|
|
return(0); |
394 |
|
|
} |
395 |
|
|
|
396 |
|
|
void |
397 |
|
|
showpool(int k) |
398 |
|
|
{ |
399 |
|
|
struct pool_info *p = pools + k; |
400 |
|
|
|
401 |
|
|
if (k < 0 || k >= num_pools) |
402 |
|
|
return; |
403 |
|
|
|
404 |
|
|
print_fld_str(FLD_POOL_NAME, p->name); |
405 |
|
|
print_fld_uint(FLD_POOL_SIZE, p->pool.pr_size); |
406 |
|
|
|
407 |
|
|
print_fld_size(FLD_POOL_REQS, p->pool.pr_nget); |
408 |
|
|
print_fld_size(FLD_POOL_FAIL, p->pool.pr_nfail); |
409 |
|
|
print_fld_ssize(FLD_POOL_INUSE, p->pool.pr_nget - p->pool.pr_nput); |
410 |
|
|
print_fld_size(FLD_POOL_PGREQ, p->pool.pr_npagealloc); |
411 |
|
|
print_fld_size(FLD_POOL_PGREL, p->pool.pr_npagefree); |
412 |
|
|
|
413 |
|
|
print_fld_size(FLD_POOL_NPAGE, p->pool.pr_npages); |
414 |
|
|
print_fld_size(FLD_POOL_HIWAT, p->pool.pr_hiwat); |
415 |
|
|
print_fld_size(FLD_POOL_MINPG, p->pool.pr_minpages); |
416 |
|
|
|
417 |
|
|
if (p->pool.pr_maxpages == UINT_MAX) |
418 |
|
|
print_fld_str(FLD_POOL_MAXPG, "inf"); |
419 |
|
|
else |
420 |
|
|
print_fld_size(FLD_POOL_MAXPG, p->pool.pr_maxpages); |
421 |
|
|
|
422 |
|
|
print_fld_size(FLD_POOL_IDLE, p->pool.pr_nidle); |
423 |
|
|
|
424 |
|
|
end_line(); |
425 |
|
|
} |
426 |
|
|
|
427 |
|
|
int |
428 |
|
|
pool_keyboard_callback(int ch) |
429 |
|
|
{ |
430 |
|
|
switch (ch) { |
431 |
|
|
case 'A': |
432 |
|
|
print_all ^= 1; |
433 |
|
|
gotsig_alarm = 1; |
434 |
|
|
default: |
435 |
|
|
return keyboard_callback(ch); |
436 |
|
|
}; |
437 |
|
|
|
438 |
|
|
return (1); |
439 |
|
|
} |
440 |
|
|
|
441 |
|
|
int |
442 |
|
|
pool_cache_read(void) |
443 |
|
|
{ |
444 |
|
|
struct pool_cache_info *pc; |
445 |
|
|
int np, i; |
446 |
|
|
|
447 |
|
|
np = pool_get_npools(); |
448 |
|
|
if (np == -1) { |
449 |
|
|
error("sysctl(npools): %s", strerror(errno)); |
450 |
|
|
return (-1); |
451 |
|
|
} |
452 |
|
|
|
453 |
|
|
if (np > num_pool_caches) { |
454 |
|
|
pc = reallocarray(pool_caches, np, sizeof(*pc)); |
455 |
|
|
if (pc == NULL) { |
456 |
|
|
error("realloc: %s", strerror(errno)); |
457 |
|
|
return (-1); |
458 |
|
|
} |
459 |
|
|
/* commit to using the new memory */ |
460 |
|
|
pool_caches = pc; |
461 |
|
|
|
462 |
|
|
for (i = num_pool_caches; i < np; i++) { |
463 |
|
|
pc = &pool_caches[i]; |
464 |
|
|
pc->name[0] = '\0'; |
465 |
|
|
|
466 |
|
|
pc->cache_cpus = reallocarray(NULL, ncpusfound, |
467 |
|
|
sizeof(*pc->cache_cpus)); |
468 |
|
|
if (pc->cache_cpus == NULL) { |
469 |
|
|
error("malloc cache cpus: %s", strerror(errno)); |
470 |
|
|
goto unalloc; |
471 |
|
|
} |
472 |
|
|
} |
473 |
|
|
|
474 |
|
|
/* commit to using the new cache_infos */ |
475 |
|
|
num_pool_caches = np; |
476 |
|
|
} |
477 |
|
|
|
478 |
|
|
for (i = 0; i < num_pool_caches; i++) { |
479 |
|
|
pc = &pool_caches[i]; |
480 |
|
|
np = i + 1; |
481 |
|
|
|
482 |
|
|
if (pool_get_cache(np, &pc->cache) < 0 || |
483 |
|
|
pool_get_cache_cpus(np, pc->cache_cpus, ncpusfound) < 0) { |
484 |
|
|
pc->name[0] = '\0'; |
485 |
|
|
continue; |
486 |
|
|
} |
487 |
|
|
|
488 |
|
|
if (pool_get_name(np, pc->name, sizeof(pc->name)) < 0) |
489 |
|
|
snprintf(pc->name, sizeof(pc->name), "#%d#", i + 1); |
490 |
|
|
} |
491 |
|
|
|
492 |
|
|
return 0; |
493 |
|
|
|
494 |
|
|
unalloc: |
495 |
|
|
while (i > num_pool_caches) { |
496 |
|
|
pc = &pool_caches[--i]; |
497 |
|
|
free(pc->cache_cpus); |
498 |
|
|
} |
499 |
|
|
return (-1); |
500 |
|
|
} |
501 |
|
|
|
502 |
|
|
void |
503 |
|
|
pool_cache_sort(void) |
504 |
|
|
{ |
505 |
|
|
/* XXX */ |
506 |
|
|
order_type *ordering; |
507 |
|
|
|
508 |
|
|
if (curr_mgr == NULL) |
509 |
|
|
return; |
510 |
|
|
|
511 |
|
|
ordering = curr_mgr->order_curr; |
512 |
|
|
|
513 |
|
|
if (ordering == NULL) |
514 |
|
|
return; |
515 |
|
|
if (ordering->func == NULL) |
516 |
|
|
return; |
517 |
|
|
if (pools == NULL) |
518 |
|
|
return; |
519 |
|
|
if (num_pools <= 0) |
520 |
|
|
return; |
521 |
|
|
|
522 |
|
|
mergesort(pools, num_pools, sizeof(struct pool_info), ordering->func); |
523 |
|
|
} |
524 |
|
|
|
525 |
|
|
void |
526 |
|
|
pool_cache_print(void) |
527 |
|
|
{ |
528 |
|
|
struct pool_cache_info *pc; |
529 |
|
|
int i, n, count = 0; |
530 |
|
|
|
531 |
|
|
if (pool_caches == NULL) |
532 |
|
|
return; |
533 |
|
|
|
534 |
|
|
for (n = i = 0; i < num_pool_caches; i++) { |
535 |
|
|
pc = &pool_caches[i]; |
536 |
|
|
if (pc->name[0] == '\0') |
537 |
|
|
continue; |
538 |
|
|
|
539 |
|
|
if (n++ < dispstart) |
540 |
|
|
continue; |
541 |
|
|
|
542 |
|
|
pool_cache_show(pc); |
543 |
|
|
count++; |
544 |
|
|
if (maxprint > 0 && count >= maxprint) |
545 |
|
|
break; |
546 |
|
|
} |
547 |
|
|
} |
548 |
|
|
|
549 |
|
|
void |
550 |
|
|
pool_cache_show(const struct pool_cache_info *pc) |
551 |
|
|
{ |
552 |
|
|
const struct kinfo_pool_cache *kpc; |
553 |
|
|
const struct kinfo_pool_cache_cpu *kpcc; |
554 |
|
|
int cpu; |
555 |
|
|
|
556 |
|
|
kpc = &pc->cache; |
557 |
|
|
|
558 |
|
|
print_fld_str(FLD_POOL_CACHE_NAME, pc->name); |
559 |
|
|
print_fld_uint(FLD_POOL_CACHE_LEN, kpc->pr_len); |
560 |
|
|
print_fld_uint(FLD_POOL_CACHE_IDLE, kpc->pr_nitems); |
561 |
|
|
print_fld_size(FLD_POOL_CACHE_NGC, kpc->pr_ngc); |
562 |
|
|
|
563 |
|
|
for (cpu = 0; cpu < ncpusfound; cpu++) { |
564 |
|
|
kpcc = &pc->cache_cpus[cpu]; |
565 |
|
|
|
566 |
|
|
print_fld_uint(FLD_POOL_CACHE_CPU, kpcc->pr_cpu); |
567 |
|
|
|
568 |
|
|
print_fld_size(FLD_POOL_CACHE_GET, kpcc->pr_nget); |
569 |
|
|
print_fld_size(FLD_POOL_CACHE_PUT, kpcc->pr_nput); |
570 |
|
|
print_fld_size(FLD_POOL_CACHE_LGET, kpcc->pr_nlget); |
571 |
|
|
print_fld_size(FLD_POOL_CACHE_LPUT, kpcc->pr_nlput); |
572 |
|
|
end_line(); |
573 |
|
|
} |
574 |
|
|
|
575 |
|
|
} |
576 |
|
|
|
577 |
|
|
static int |
578 |
|
|
pool_get_npools(void) |
579 |
|
|
{ |
580 |
|
|
int mib[] = { CTL_KERN, KERN_POOL, KERN_POOL_NPOOLS }; |
581 |
|
|
|
582 |
|
|
return (sysctl_rdint(mib, nitems(mib))); |
583 |
|
|
} |
584 |
|
|
|
585 |
|
|
static int |
586 |
|
|
pool_get_cache(int pool, struct kinfo_pool_cache *kpc) |
587 |
|
|
{ |
588 |
|
|
int mib[] = { CTL_KERN, KERN_POOL, KERN_POOL_CACHE, pool }; |
589 |
|
|
size_t len = sizeof(*kpc); |
590 |
|
|
|
591 |
|
|
return (sysctl(mib, nitems(mib), kpc, &len, NULL, 0)); |
592 |
|
|
} |
593 |
|
|
|
594 |
|
|
static int |
595 |
|
|
pool_get_cache_cpus(int pool, struct kinfo_pool_cache_cpu *kpcc, |
596 |
|
|
unsigned int ncpus) |
597 |
|
|
{ |
598 |
|
|
int mib[] = { CTL_KERN, KERN_POOL, KERN_POOL_CACHE_CPUS, pool }; |
599 |
|
|
size_t len = sizeof(*kpcc) * ncpus; |
600 |
|
|
|
601 |
|
|
return (sysctl(mib, nitems(mib), kpcc, &len, NULL, 0)); |
602 |
|
|
} |
603 |
|
|
|
604 |
|
|
static int |
605 |
|
|
pool_get_name(int pool, char *name, size_t len) |
606 |
|
|
{ |
607 |
|
|
int mib[] = { CTL_KERN, KERN_POOL, KERN_POOL_NAME, pool }; |
608 |
|
|
|
609 |
|
|
return (sysctl(mib, nitems(mib), name, &len, NULL, 0)); |
610 |
|
|
} |
611 |
|
|
|
612 |
|
|
static int |
613 |
|
|
hw_ncpusfound(void) |
614 |
|
|
{ |
615 |
|
|
int mib[] = { CTL_HW, HW_NCPUFOUND }; |
616 |
|
|
|
617 |
|
|
return (sysctl_rdint(mib, nitems(mib))); |
618 |
|
|
} |
619 |
|
|
|
620 |
|
|
static int |
621 |
|
|
sysctl_rdint(const int *mib, unsigned int nmib) |
622 |
|
|
{ |
623 |
|
|
int i; |
624 |
|
|
size_t size = sizeof(i); |
625 |
|
|
|
626 |
|
|
if (sysctl(mib, nmib, &i, &size, NULL, 0) == -1) |
627 |
|
|
return (-1); |
628 |
|
|
|
629 |
|
|
return (i); |
630 |
|
|
} |