xref: /titanic_41/usr/src/cmd/avs/dsstat/report.c (revision 570de38f63910201fdd77246630b7aa8f9dc5661)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include <kstat.h>
30 #include <sys/inttypes.h>
31 
32 #include <nsctl.h>
33 
34 #include "dsstat.h"
35 #include "common.h"
36 
37 #include "sdbc_stats.h"
38 #include "report.h"
39 
40 extern short dflags;
41 
42 /*
43  * Return the number of ticks delta between two hrtime_t
44  * values. Attempt to cater for various kinds of overflow
45  * in hrtime_t - no matter how improbable.
46  */
47 uint64_t
hrtime_delta(hrtime_t old,hrtime_t new)48 hrtime_delta(hrtime_t old, hrtime_t new)
49 {
50 
51 	uint64_t del;
52 
53 	if ((new >= old) && (old >= 0L)) {
54 		return (new - old);
55 	} else {
56 		/*
57 		 * We've overflowed the positive portion of an
58 		 * hrtime_t.
59 		 */
60 		if (new < 0L) {
61 			/*
62 			 * The new value is negative. Handle the
63 			 * case where the old value is positive or
64 			 * negative.
65 			 */
66 			uint64_t n1;
67 			uint64_t o1;
68 
69 			n1 = -new;
70 
71 			if (old > 0L) {
72 				return (n1 - old);
73 			} else {
74 				o1 = -old;
75 				del = n1 - o1;
76 				return (del);
77 			}
78 		} else {
79 			/*
80 			 * Either we've just gone from being negative
81 			 * to positive *or* the last entry was positive
82 			 * and the new entry is also positive but *less*
83 			 * than the old entry. This implies we waited
84 			 * quite a few days on a very fast system between
85 			 * iostat displays.
86 			 */
87 			if (old < 0L) {
88 				uint64_t o2;
89 
90 				o2 = -old;
91 				del = UINT64_MAX - o2;
92 			} else {
93 				del = UINT64_MAX - old;
94 			}
95 
96 			del += new;
97 
98 			return (del);
99 		}
100 	}
101 }
102 
103 /*
104  * Take the difference of an unsigned 32
105  * bit int attempting to cater for
106  * overflow.
107  */
108 uint32_t
u32_delta(uint32_t old,uint32_t new)109 u32_delta(uint32_t old, uint32_t new)
110 {
111 
112 	if (new >= old)
113 		return (new - old);
114 	else
115 		return ((UINT32_MAX - old) + new + 1);
116 }
117 
118 /*
119  * Take the difference of an unsigned 64
120  * bit int attempting to cater for
121  * overflow.
122  */
123 uint64_t
u64_delta(uint64_t old,uint64_t new)124 u64_delta(uint64_t old, uint64_t new)
125 {
126 
127 	if (new >= old)
128 		return (new - old);
129 	else
130 		return ((UINT64_MAX - old) + new + 1);
131 }
132 
133 /*
134  * io_report() - diffs and reports data contained in
135  * kstat_io_t structures.
136  *
137  * parameters
138  * 	kstat_io_t *cur - pointer to current data
139  *
140  * 	kstat_io_t *pre - pointer to data as it was
141  * 	at the beginning of an interval.
142  */
143 void
io_report(kstat_t * cur_kstat,kstat_t * pre_kstat,sdbcstat_t * sdbcstat)144 io_report(kstat_t *cur_kstat, kstat_t *pre_kstat, sdbcstat_t *sdbcstat)
145 {
146 	sdbcvals_t vals;
147 
148 	double rd_cnt, wr_cnt;
149 	double rd_kb, wr_kb, hr_etime;
150 
151 	double rtm, tps, avs, etime;
152 
153 	kstat_io_t *cur = cur_kstat->ks_data;
154 	kstat_io_t *pre = pre_kstat->ks_data;
155 
156 	if (sdbcstat &&
157 	    sdbc_getvalues(sdbcstat, &vals, (SDBC_KBYTES | SDBC_INTAVG)))
158 		return;
159 
160 	/* Time */
161 	hr_etime = hrtime_delta(pre_kstat->ks_snaptime, cur_kstat->ks_snaptime);
162 	etime = hr_etime / (double)NANOSEC;
163 
164 	/* Read count */
165 	rd_cnt = (double)u32_delta(pre->reads, cur->reads);
166 	if (rd_cnt) rd_cnt /= etime;
167 
168 	/* Bytes read */
169 	rd_kb = (double)u64_delta(pre->nread, cur->nread) / KILOBYTE;
170 	if (rd_kb) rd_kb /= etime;
171 
172 	/* Write count    */
173 	wr_cnt = (double)u32_delta(pre->writes, cur->writes);
174 	if (wr_cnt) wr_cnt /= etime;
175 
176 	/* Bytes written  */
177 	wr_kb = (double)u64_delta(pre->nwritten, cur->nwritten) / KILOBYTE;
178 	if (wr_kb) wr_kb /= etime;
179 
180 	/* Calculate service times */
181 	avs = (double)hrtime_delta(pre->rlentime, cur->rlentime) / hr_etime;
182 	tps = (double)rd_cnt + wr_cnt;
183 
184 	if (tps > 0)
185 		rtm = (1000 / tps) * avs;
186 	else
187 		rtm = 0.0;
188 
189 	/* Output */
190 	if (dflags & SUMMARY) {
191 		if ((mode & MULTI) && (mode & SDBC)) {
192 			if (sdbcstat) {
193 				(void) printf(KPS_INF_FMT,
194 				    (float)vals.total_cache);
195 				(void) printf(KPS_INF_FMT,
196 				    (float)vals.total_disk);
197 			} else {
198 				(void) printf(DATA_C6, NO_INFO);
199 				(void) printf(KPS_INF_FMT, rd_kb + wr_kb);
200 			}
201 		} else
202 			(void) printf(KPS_INF_FMT, rd_kb + wr_kb);
203 
204 		(void) printf(TPS_INF_FMT, (uint32_t)(rd_cnt + wr_cnt));
205 		(void) printf(SVT_INF_FMT, rtm);
206 
207 		goto done;
208 	}
209 
210 	if (dflags & READ) {
211 		if ((mode & MULTI) && (mode & SDBC)) {
212 			if (sdbcstat) {
213 				(void) printf(KPS_INF_FMT,
214 				    (float)vals.cache_read);
215 				(void) printf(KPS_INF_FMT,
216 				    (float)vals.disk_read);
217 			} else {
218 				(void) printf(DATA_C6, NO_INFO);
219 				(void) printf(KPS_INF_FMT, rd_kb);
220 			}
221 
222 		} else
223 			(void) printf(KPS_INF_FMT, rd_kb);
224 
225 		(void) printf(TPS_INF_FMT, (uint32_t)rd_cnt);
226 	}
227 
228 	if (dflags & WRITE) {
229 		if ((mode & MULTI) && (mode & SDBC)) {
230 			if (sdbcstat) {
231 				(void) printf(KPS_INF_FMT,
232 				    (float)vals.cache_write);
233 				(void) printf(KPS_INF_FMT,
234 				    (float)vals.disk_write);
235 			} else {
236 				(void) printf(DATA_C6, NO_INFO);
237 				(void) printf(KPS_INF_FMT, wr_kb);
238 			}
239 
240 		} else
241 			(void) printf(KPS_INF_FMT, wr_kb);
242 
243 		(void) printf(TPS_INF_FMT, (uint32_t)wr_cnt);
244 	}
245 
246 	if (dflags & TIMING) {
247 		(void) printf(SVT_INF_FMT, rtm);
248 	}
249 
250 done:
251 	linesout++;
252 }
253 
254 int
io_value_check(kstat_io_t * pre,kstat_io_t * cur)255 io_value_check(kstat_io_t *pre, kstat_io_t *cur)
256 {
257 	if (u32_delta(pre->reads, cur->reads))
258 		return (1);
259 	if (u32_delta(pre->writes, cur->writes))
260 		return (1);
261 
262 	return (0);
263 }
264 
265 /*
266  * cd_report() - reports cache desriptor related statistics
267  * based on the dflags global variable
268  *
269  * parameters
270  * 	sdbcstat_t *sdbcstat - pointer to the cache structure
271  * 	to be reported on.
272  */
273 void
cd_report(sdbcstat_t * sdbcstat)274 cd_report(sdbcstat_t *sdbcstat)
275 {
276 	sdbcvals_t vals;
277 
278 	/* Extract statistics, average for time */
279 	if (sdbc_getvalues(sdbcstat, &vals, (SDBC_KBYTES | SDBC_INTAVG)))
280 		return;
281 
282 	/* Output */
283 	if (rflags & MULTI) {
284 		(void) printf(VOL_HDR_FMT, "");
285 
286 		if (dflags & FLAGS) {
287 			(void) printf(STAT_HDR_FMT, "");
288 			(void) printf(STAT_HDR_FMT, "");
289 		}
290 
291 		if (dflags & PCTS)
292 			(void) printf(PCT_HDR_FMT, "");
293 
294 		if (dflags & SUMMARY) {
295 			(void) printf(KPS_INF_FMT, (float)vals.total_cache);
296 			(void) printf(DATA_C4, NO_INFO);
297 			(void) printf(DATA_C4, NO_INFO);
298 			(void) printf("\n");
299 			linesout++;
300 			return;
301 		}
302 
303 		if (dflags & READ) {
304 			(void) printf(KPS_INF_FMT, (float)vals.cache_read);
305 			(void) printf(DATA_C4, NO_INFO);
306 		}
307 
308 		if (dflags & WRITE) {
309 			(void) printf(KPS_INF_FMT, (float)vals.cache_write);
310 			(void) printf(DATA_C4, NO_INFO);
311 		}
312 
313 		if (dflags & TIMING) {
314 			(void) printf(DATA_C4, NO_INFO);
315 		}
316 
317 		linesout++;
318 		(void) printf("\n");
319 		return;
320 	}
321 
322 	if (dflags & SUMMARY) {
323 		(void) printf(DATA_I32, vals.total_cache);
324 		(void) printf(DATA_I32, vals.total_disk);
325 		(void) printf(HIT_INF_FMT, vals.cache_hit);
326 
327 		linesout++;
328 		(void) printf("\n");
329 		return;
330 	}
331 
332 	if (dflags & READ) {
333 		(void) printf(DATA_I32, vals.cache_read);
334 		(void) printf(DATA_I32, vals.disk_read);
335 		(void) printf(HIT_INF_FMT, vals.read_hit);
336 	}
337 
338 	if (dflags & WRITE) {
339 		(void) printf(DATA_I32, vals.cache_write);
340 		(void) printf(DATA_I32, vals.disk_write);
341 		(void) printf(HIT_INF_FMT, vals.write_hit);
342 	}
343 
344 	if (dflags & DESTAGED)
345 		(void) printf(DATA_I32, vals.destaged);
346 
347 	if (dflags & WRCANCEL)
348 		(void) printf(DATA_I32, vals.write_cancellations);
349 
350 	linesout++;
351 	(void) printf("\n");
352 }
353 
354 /*
355  * header() - outputs an appropriate header by referencing the
356  * global variables dflsgs and rflags
357  *
358  */
359 void
header()360 header()
361 {
362 	if (hflags & HEADERS_EXL)
363 		if ((linesout % DISPLAY_LINES) != 0)
364 			return;
365 
366 	if (hflags & HEADERS_BOR)
367 		if (linesout != 0)
368 			return;
369 
370 	if (hflags & HEADERS_ATT)
371 		if (hflags & HEADERS_OUT)
372 			return;
373 		else
374 			hflags |= HEADERS_OUT;
375 
376 	if (linesout)
377 		(void) printf("\n");
378 
379 	(void) printf(VOL_HDR_FMT, SET_HDR_TXT);
380 
381 	if (dflags & FLAGS) {
382 		(void) printf(STAT_HDR_FMT, TYPE_HDR_TXT);
383 		(void) printf(STAT_HDR_FMT, STAT_HDR_TXT);
384 	}
385 
386 	if (dflags & ASYNC_QUEUE)
387 		(void) printf(STAT_HDR_FMT, QUEUE_HDR_TXT);
388 
389 	if (dflags & PCTS)
390 		(void) printf(PCT_HDR_FMT, PCT_HDR_TXT);
391 
392 	(void) printf(ROLE_HDR_FMT, ROLE_HDR_TXT);
393 
394 	if (dflags & ASYNC_QUEUE) {
395 		(void) printf(TPS_HDR_FMT, QUEUE_ITEMS_TXT);
396 		(void) printf(KPS_HDR_FMT, QUEUE_KBYTES_TXT);
397 		(void) printf(TPS_HDR_FMT, QUEUE_ITEMS_HW_TXT);
398 		(void) printf(KPS_HDR_FMT, QUEUE_KBYTES_HW_TXT);
399 	}
400 
401 	if (dflags & SUMMARY) {
402 		if ((mode & MULTI) && (mode & SDBC)) {
403 			(void) printf(KPS_HDR_FMT, CKPS_HDR_TXT);
404 			(void) printf(KPS_HDR_FMT, DKPS_HDR_TXT);
405 		} else
406 			(void) printf(KPS_HDR_FMT, KPS_HDR_TXT);
407 		(void) printf(TPS_HDR_FMT, TPS_HDR_TXT);
408 		(void) printf(SVT_HDR_FMT, SVT_HDR_TXT);
409 
410 		(void) printf("\n");
411 
412 		return;
413 	}
414 
415 	if (dflags & READ) {
416 		if ((mode & MULTI) && (mode & SDBC)) {
417 			(void) printf(KPS_HDR_FMT, CRKPS_HDR_TXT);
418 			(void) printf(KPS_HDR_FMT, DRKPS_HDR_TXT);
419 		} else
420 			(void) printf(KPS_HDR_FMT, RKPS_HDR_TXT);
421 
422 		(void) printf(TPS_HDR_FMT, RTPS_HDR_TXT);
423 	}
424 
425 	if (dflags & WRITE) {
426 		if ((mode & MULTI) && (mode & SDBC)) {
427 			(void) printf(KPS_HDR_FMT, CWKPS_HDR_TXT);
428 			(void) printf(KPS_HDR_FMT, DWKPS_HDR_TXT);
429 		} else
430 			(void) printf(KPS_HDR_FMT, WKPS_HDR_TXT);
431 
432 		(void) printf(TPS_HDR_FMT, WTPS_HDR_TXT);
433 	}
434 
435 	if (dflags & TIMING)
436 		(void) printf(SVT_HDR_FMT, SVT_HDR_TXT);
437 
438 	(void) printf("\n");
439 }
440