xref: /openbsd/usr.bin/systat/pool.c (revision 898184e3)
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