xref: /onnv-gate/usr/src/cmd/avs/dsstat/sdbc_stats.c (revision 11576:b23c42c0c9d6)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
22*11576SSurya.Prakki@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237836SJohn.Forte@Sun.COM  * Use is subject to license terms.
247836SJohn.Forte@Sun.COM  */
257836SJohn.Forte@Sun.COM 
267836SJohn.Forte@Sun.COM #include <stdio.h>
277836SJohn.Forte@Sun.COM #include <stdlib.h>
287836SJohn.Forte@Sun.COM #include <string.h>
297836SJohn.Forte@Sun.COM #include <unistd.h>
307836SJohn.Forte@Sun.COM #include <errno.h>
317836SJohn.Forte@Sun.COM #include <inttypes.h>
327836SJohn.Forte@Sun.COM 
337836SJohn.Forte@Sun.COM #include <kstat.h>
347836SJohn.Forte@Sun.COM 
357836SJohn.Forte@Sun.COM #include <sys/nsctl/nsctl.h>
367836SJohn.Forte@Sun.COM #include <sys/nsctl/sd_bcache.h>
377836SJohn.Forte@Sun.COM 
387836SJohn.Forte@Sun.COM #include "sdbc_stats.h"
397836SJohn.Forte@Sun.COM 
407836SJohn.Forte@Sun.COM #include "dsstat.h"
417836SJohn.Forte@Sun.COM #include "common.h"
427836SJohn.Forte@Sun.COM #include "report.h"
437836SJohn.Forte@Sun.COM 
447836SJohn.Forte@Sun.COM static sdbcstat_t *sdbc_top;
457836SJohn.Forte@Sun.COM kstat_t *sdbc_global = NULL;
467836SJohn.Forte@Sun.COM 
477836SJohn.Forte@Sun.COM void sdbc_header();
487836SJohn.Forte@Sun.COM int sdbc_value_check(sdbcstat_t *);
497836SJohn.Forte@Sun.COM int sdbc_validate(kstat_t *);
507836SJohn.Forte@Sun.COM uint32_t sdbc_getdelta(sdbcstat_t *, char *);
517836SJohn.Forte@Sun.COM 
527836SJohn.Forte@Sun.COM void sdbc_addstat(sdbcstat_t *);
537836SJohn.Forte@Sun.COM sdbcstat_t *sdbc_delstat(sdbcstat_t *);
547836SJohn.Forte@Sun.COM void center(int, char *);
557836SJohn.Forte@Sun.COM 
567836SJohn.Forte@Sun.COM /*
577836SJohn.Forte@Sun.COM  * sdbc_discover() - looks for new statistics to be monitored.
587836SJohn.Forte@Sun.COM  * Verifies that any statistics found are now already being
597836SJohn.Forte@Sun.COM  * monitored.
607836SJohn.Forte@Sun.COM  *
617836SJohn.Forte@Sun.COM  */
627836SJohn.Forte@Sun.COM int
sdbc_discover(kstat_ctl_t * kc)637836SJohn.Forte@Sun.COM sdbc_discover(kstat_ctl_t *kc)
647836SJohn.Forte@Sun.COM {
657836SJohn.Forte@Sun.COM 	static int validated = 0;
667836SJohn.Forte@Sun.COM 
677836SJohn.Forte@Sun.COM 	kstat_t *ksp;
687836SJohn.Forte@Sun.COM 
697836SJohn.Forte@Sun.COM 	for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
707836SJohn.Forte@Sun.COM 		int kinst;
717836SJohn.Forte@Sun.COM 		char kname[KSTAT_STRLEN + 1];
727836SJohn.Forte@Sun.COM 		sdbcstat_t *cur;
737836SJohn.Forte@Sun.COM 		sdbcstat_t *sdbcstat = NULL;
747836SJohn.Forte@Sun.COM 		kstat_t *io_ksp;
757836SJohn.Forte@Sun.COM 
767836SJohn.Forte@Sun.COM 		if (strcmp(ksp->ks_module, SDBC_KSTAT_MODULE) != 0 ||
777836SJohn.Forte@Sun.COM 		    strncmp(ksp->ks_name, SDBC_KSTAT_CDSTATS, 2) != 0)
787836SJohn.Forte@Sun.COM 			continue;
797836SJohn.Forte@Sun.COM 
807836SJohn.Forte@Sun.COM 		if (kstat_read(kc, ksp, NULL) == -1)
817836SJohn.Forte@Sun.COM 			continue;
827836SJohn.Forte@Sun.COM 
837836SJohn.Forte@Sun.COM 		/*
847836SJohn.Forte@Sun.COM 		 * Validate kstat structure
857836SJohn.Forte@Sun.COM 		 */
867836SJohn.Forte@Sun.COM 		if (! validated) {
877836SJohn.Forte@Sun.COM 			if (sdbc_validate(ksp))
887836SJohn.Forte@Sun.COM 				return (EINVAL);
897836SJohn.Forte@Sun.COM 
907836SJohn.Forte@Sun.COM 			validated++;
917836SJohn.Forte@Sun.COM 		}
927836SJohn.Forte@Sun.COM 
937836SJohn.Forte@Sun.COM 		/*
947836SJohn.Forte@Sun.COM 		 * Duplicate check
957836SJohn.Forte@Sun.COM 		 */
967836SJohn.Forte@Sun.COM 		for (cur = sdbc_top; cur; cur = cur->next) {
977836SJohn.Forte@Sun.COM 			char *cur_vname, *tst_vname;
987836SJohn.Forte@Sun.COM 
997836SJohn.Forte@Sun.COM 			cur_vname = kstat_value(cur->pre_set,
1007836SJohn.Forte@Sun.COM 			    SDBC_CDKSTAT_VOL_NAME);
1017836SJohn.Forte@Sun.COM 
1027836SJohn.Forte@Sun.COM 			tst_vname = kstat_value(ksp,
1037836SJohn.Forte@Sun.COM 			    SDBC_CDKSTAT_VOL_NAME);
1047836SJohn.Forte@Sun.COM 
1057836SJohn.Forte@Sun.COM 			if (strncmp(cur_vname, tst_vname, NAMED_LEN) == 0)
1067836SJohn.Forte@Sun.COM 				goto next;
1077836SJohn.Forte@Sun.COM 		}
1087836SJohn.Forte@Sun.COM 
1097836SJohn.Forte@Sun.COM 		/*
1107836SJohn.Forte@Sun.COM 		 * Initialize new record
1117836SJohn.Forte@Sun.COM 		 */
1127836SJohn.Forte@Sun.COM 		sdbcstat = (sdbcstat_t *)calloc(1, sizeof (sdbcstat_t));
1137836SJohn.Forte@Sun.COM 
1147836SJohn.Forte@Sun.COM 		kinst = ksp->ks_instance;
1157836SJohn.Forte@Sun.COM 
1167836SJohn.Forte@Sun.COM 		/*
1177836SJohn.Forte@Sun.COM 		 * Set kstat
1187836SJohn.Forte@Sun.COM 		 */
1197836SJohn.Forte@Sun.COM 		sdbcstat->pre_set = kstat_retrieve(kc, ksp);
1207836SJohn.Forte@Sun.COM 
1217836SJohn.Forte@Sun.COM 		if (sdbcstat->pre_set == NULL)
1227836SJohn.Forte@Sun.COM 			goto next;
1237836SJohn.Forte@Sun.COM 
1247836SJohn.Forte@Sun.COM 		sdbcstat->collected |= GOT_SET_KSTAT;
1257836SJohn.Forte@Sun.COM 
1267836SJohn.Forte@Sun.COM 		/*
1277836SJohn.Forte@Sun.COM 		 * I/O kstat
1287836SJohn.Forte@Sun.COM 		 */
129*11576SSurya.Prakki@Sun.COM 		(void) sprintf(kname, "%s%d",  SDBC_IOKSTAT_CDSTATS, kinst);
1307836SJohn.Forte@Sun.COM 
1317836SJohn.Forte@Sun.COM 		io_ksp = kstat_lookup(kc, SDBC_KSTAT_MODULE, kinst, kname);
1327836SJohn.Forte@Sun.COM 		sdbcstat->pre_io = kstat_retrieve(kc, io_ksp);
1337836SJohn.Forte@Sun.COM 
1347836SJohn.Forte@Sun.COM 		if (sdbcstat->pre_io == NULL)
1357836SJohn.Forte@Sun.COM 			goto next;
1367836SJohn.Forte@Sun.COM 
1377836SJohn.Forte@Sun.COM 		sdbcstat->collected |= GOT_IO_KSTAT;
1387836SJohn.Forte@Sun.COM 
1397836SJohn.Forte@Sun.COM next:
1407836SJohn.Forte@Sun.COM 		/*
1417836SJohn.Forte@Sun.COM 		 * Check if we got a complete set of stats
1427836SJohn.Forte@Sun.COM 		 */
1437836SJohn.Forte@Sun.COM 		if (sdbcstat == NULL)
1447836SJohn.Forte@Sun.COM 			continue;
1457836SJohn.Forte@Sun.COM 
1467836SJohn.Forte@Sun.COM 		if (SDBC_COMPLETE(sdbcstat->collected)) {
1477836SJohn.Forte@Sun.COM 			(void) sdbc_delstat(sdbcstat);
1487836SJohn.Forte@Sun.COM 			continue;
1497836SJohn.Forte@Sun.COM 		}
1507836SJohn.Forte@Sun.COM 
1517836SJohn.Forte@Sun.COM 		sdbc_addstat(sdbcstat);
1527836SJohn.Forte@Sun.COM 	}
1537836SJohn.Forte@Sun.COM 
1547836SJohn.Forte@Sun.COM 	if (sdbc_top == NULL)
1557836SJohn.Forte@Sun.COM 		return (EAGAIN);
1567836SJohn.Forte@Sun.COM 
1577836SJohn.Forte@Sun.COM 	return (0);
1587836SJohn.Forte@Sun.COM }
1597836SJohn.Forte@Sun.COM 
1607836SJohn.Forte@Sun.COM /*
1617836SJohn.Forte@Sun.COM  * sdbc_update() - updates all of the statistics currently being monitored.
1627836SJohn.Forte@Sun.COM  *
1637836SJohn.Forte@Sun.COM  */
1647836SJohn.Forte@Sun.COM int
sdbc_update(kstat_ctl_t * kc)1657836SJohn.Forte@Sun.COM sdbc_update(kstat_ctl_t *kc)
1667836SJohn.Forte@Sun.COM {
1677836SJohn.Forte@Sun.COM 	kstat_t *ksp;
1687836SJohn.Forte@Sun.COM 	sdbcstat_t *cur;
1697836SJohn.Forte@Sun.COM 
1707836SJohn.Forte@Sun.COM 	/* Update global kstat information */
1717836SJohn.Forte@Sun.COM 	ksp = kstat_lookup(kc, SDBC_KSTAT_MODULE, -1, SDBC_KSTAT_GSTATS);
1727836SJohn.Forte@Sun.COM 
1737836SJohn.Forte@Sun.COM 	if (ksp == NULL)
1747836SJohn.Forte@Sun.COM 		return (EAGAIN);
1757836SJohn.Forte@Sun.COM 
1767836SJohn.Forte@Sun.COM 	if (sdbc_global)
1777836SJohn.Forte@Sun.COM 		kstat_free(sdbc_global);
1787836SJohn.Forte@Sun.COM 
1797836SJohn.Forte@Sun.COM 	sdbc_global = kstat_retrieve(kc, ksp);
1807836SJohn.Forte@Sun.COM 
1817836SJohn.Forte@Sun.COM 	for (cur = sdbc_top; cur != NULL; cur = cur->next) {
1827836SJohn.Forte@Sun.COM 		int kinst;
1837836SJohn.Forte@Sun.COM 		char *kname, *cname, *pname;
1847836SJohn.Forte@Sun.COM 
1857836SJohn.Forte@Sun.COM 		kstat_t *set_ksp, *io_ksp;
1867836SJohn.Forte@Sun.COM 
1877836SJohn.Forte@Sun.COM 		cur->collected = 0;
1887836SJohn.Forte@Sun.COM 
1897836SJohn.Forte@Sun.COM 		/*
1907836SJohn.Forte@Sun.COM 		 * Age off old stats
1917836SJohn.Forte@Sun.COM 		 */
1927836SJohn.Forte@Sun.COM 		if (cur->cur_set != NULL) {
1937836SJohn.Forte@Sun.COM 			kstat_free(cur->pre_set);
1947836SJohn.Forte@Sun.COM 			kstat_free(cur->pre_io);
1957836SJohn.Forte@Sun.COM 
1967836SJohn.Forte@Sun.COM 			cur->pre_set = cur->cur_set;
1977836SJohn.Forte@Sun.COM 			cur->pre_io = cur->cur_io;
1987836SJohn.Forte@Sun.COM 		}
1997836SJohn.Forte@Sun.COM 
2007836SJohn.Forte@Sun.COM 		/*
2017836SJohn.Forte@Sun.COM 		 * Update set kstat
2027836SJohn.Forte@Sun.COM 		 */
2037836SJohn.Forte@Sun.COM 		kinst = cur->pre_set->ks_instance;
2047836SJohn.Forte@Sun.COM 		kname = cur->pre_set->ks_name;
2057836SJohn.Forte@Sun.COM 
2067836SJohn.Forte@Sun.COM 		set_ksp = kstat_lookup(kc, SDBC_KSTAT_MODULE, kinst, kname);
2077836SJohn.Forte@Sun.COM 
2087836SJohn.Forte@Sun.COM 		if ((cur->cur_set = kstat_retrieve(kc, set_ksp)) == NULL)
2097836SJohn.Forte@Sun.COM 			continue;
2107836SJohn.Forte@Sun.COM 
2117836SJohn.Forte@Sun.COM 		cur->collected |= GOT_SET_KSTAT;
2127836SJohn.Forte@Sun.COM 
2137836SJohn.Forte@Sun.COM 		/*
2147836SJohn.Forte@Sun.COM 		 * Validate set
2157836SJohn.Forte@Sun.COM 		 */
2167836SJohn.Forte@Sun.COM 		pname = kstat_value(cur->pre_set, SDBC_CDKSTAT_VOL_NAME);
2177836SJohn.Forte@Sun.COM 		cname = kstat_value(cur->cur_set, SDBC_CDKSTAT_VOL_NAME);
2187836SJohn.Forte@Sun.COM 
2197836SJohn.Forte@Sun.COM 		if (strncmp(pname, cname, NAMED_LEN) != 0)
2207836SJohn.Forte@Sun.COM 			continue;
2217836SJohn.Forte@Sun.COM 
2227836SJohn.Forte@Sun.COM 		/*
2237836SJohn.Forte@Sun.COM 		 * Update I/O kstat
2247836SJohn.Forte@Sun.COM 		 */
2257836SJohn.Forte@Sun.COM 		kinst = cur->pre_io->ks_instance;
2267836SJohn.Forte@Sun.COM 		kname = cur->pre_io->ks_name;
2277836SJohn.Forte@Sun.COM 
2287836SJohn.Forte@Sun.COM 		io_ksp = kstat_lookup(kc, SDBC_KSTAT_MODULE, kinst, kname);
2297836SJohn.Forte@Sun.COM 
2307836SJohn.Forte@Sun.COM 		if ((cur->cur_io = kstat_retrieve(kc, io_ksp)) == NULL)
2317836SJohn.Forte@Sun.COM 			continue;
2327836SJohn.Forte@Sun.COM 
2337836SJohn.Forte@Sun.COM 		cur->collected |= GOT_IO_KSTAT;
2347836SJohn.Forte@Sun.COM 	}
2357836SJohn.Forte@Sun.COM 
2367836SJohn.Forte@Sun.COM 	return (0);
2377836SJohn.Forte@Sun.COM }
2387836SJohn.Forte@Sun.COM 
2397836SJohn.Forte@Sun.COM /*
2407836SJohn.Forte@Sun.COM  * sdbc_report() - outputs statistics for the statistics currently being
2417836SJohn.Forte@Sun.COM  * monitored.  Deletes statistics for volumes that have been disabled.
2427836SJohn.Forte@Sun.COM  *
2437836SJohn.Forte@Sun.COM  */
2447836SJohn.Forte@Sun.COM int
sdbc_report()2457836SJohn.Forte@Sun.COM sdbc_report()
2467836SJohn.Forte@Sun.COM {
2477836SJohn.Forte@Sun.COM 	vslist_t *vslist = vs_top;
2487836SJohn.Forte@Sun.COM 	sdbcstat_t *cur, *pre = NULL;
2497836SJohn.Forte@Sun.COM 
2507836SJohn.Forte@Sun.COM 	if (sdbc_top == NULL)
2517836SJohn.Forte@Sun.COM 		return (0);
2527836SJohn.Forte@Sun.COM 
2537836SJohn.Forte@Sun.COM 	for (cur = sdbc_top; cur != NULL; ) { /* CSTYLED */
2547836SJohn.Forte@Sun.COM 		static uint32_t linesout = 0;
2557836SJohn.Forte@Sun.COM 		uint32_t *offline;
2567836SJohn.Forte@Sun.COM 
2577836SJohn.Forte@Sun.COM 		char volname[NAMED_LEN + 1];
2587836SJohn.Forte@Sun.COM 		char rmode[STAT_HDR_SIZE];
2597836SJohn.Forte@Sun.COM 		char wmode[STAT_HDR_SIZE];
2607836SJohn.Forte@Sun.COM 
2617836SJohn.Forte@Sun.COM 		/* Parse volume name */
262*11576SSurya.Prakki@Sun.COM 		(void) strncpy(volname, kstat_value(cur->pre_set,
2637836SJohn.Forte@Sun.COM 		    SDBC_CDKSTAT_VOL_NAME), NAMED_LEN);
2647836SJohn.Forte@Sun.COM 		volname[NAMED_LEN] = '\0';
2657836SJohn.Forte@Sun.COM 
2667836SJohn.Forte@Sun.COM 		/* Check to see if the user specified this volume */
2677836SJohn.Forte@Sun.COM 		for (vslist = vs_top; vslist != NULL; vslist = vslist->next)
2687836SJohn.Forte@Sun.COM 			if (strcmp(volname, vslist->volname) == 0)
2697836SJohn.Forte@Sun.COM 				break;
2707836SJohn.Forte@Sun.COM 
2717836SJohn.Forte@Sun.COM 		if (vs_top != NULL && vslist == NULL)
2727836SJohn.Forte@Sun.COM 			goto next;
2737836SJohn.Forte@Sun.COM 
2747836SJohn.Forte@Sun.COM 		/* Check if volume is offline and zflag applies */
2757836SJohn.Forte@Sun.COM 		if (zflag && sdbc_value_check(cur) == 0)
2767836SJohn.Forte@Sun.COM 			goto next;
2777836SJohn.Forte@Sun.COM 
2787836SJohn.Forte@Sun.COM 		/* Output volume name */
2797836SJohn.Forte@Sun.COM 		sdbc_header();
2807836SJohn.Forte@Sun.COM 
2817836SJohn.Forte@Sun.COM 		(void) printf(DATA_C16, volname);
2827836SJohn.Forte@Sun.COM 
2837836SJohn.Forte@Sun.COM 		if (SDBC_COMPLETE(cur->collected)) {
2847836SJohn.Forte@Sun.COM 			sdbcstat_t *next = sdbc_delstat(cur);
2857836SJohn.Forte@Sun.COM 
2867836SJohn.Forte@Sun.COM 			if (! pre)
2877836SJohn.Forte@Sun.COM 				cur = sdbc_top = next;
2887836SJohn.Forte@Sun.COM 			else
2897836SJohn.Forte@Sun.COM 				cur = pre->next = next;
2907836SJohn.Forte@Sun.COM 
2917836SJohn.Forte@Sun.COM 			(void) printf(" <<volume disabled>>\n");
2927836SJohn.Forte@Sun.COM 			continue;
2937836SJohn.Forte@Sun.COM 		}
2947836SJohn.Forte@Sun.COM 
2957836SJohn.Forte@Sun.COM 		offline = kstat_value(cur->cur_set, SDBC_CDKSTAT_FAILED);
2967836SJohn.Forte@Sun.COM 		if (*offline) {
2977836SJohn.Forte@Sun.COM 			(void) printf(" <<volume offline>>\n");
2987836SJohn.Forte@Sun.COM 			linesout++;
2997836SJohn.Forte@Sun.COM 			goto next;
3007836SJohn.Forte@Sun.COM 		}
3017836SJohn.Forte@Sun.COM 
3027836SJohn.Forte@Sun.COM 		/* Type/status flags */
3037836SJohn.Forte@Sun.COM 		if (dflags & FLAGS) {
3047836SJohn.Forte@Sun.COM 
3057836SJohn.Forte@Sun.COM 			uint32_t *dhint, *nhint;
3067836SJohn.Forte@Sun.COM 			uint32_t hints;
3077836SJohn.Forte@Sun.COM 
3087836SJohn.Forte@Sun.COM 			dhint = kstat_value(cur->cur_set, SDBC_CDKSTAT_CDHINTS);
3097836SJohn.Forte@Sun.COM 			nhint = kstat_value(sdbc_global, SDBC_GKSTAT_NODEHINTS);
3107836SJohn.Forte@Sun.COM 
3117836SJohn.Forte@Sun.COM 			if (! nhint)
3127836SJohn.Forte@Sun.COM 				return (EINVAL);
3137836SJohn.Forte@Sun.COM 
3147836SJohn.Forte@Sun.COM 			hints = *nhint;
3157836SJohn.Forte@Sun.COM 			hints &= (NSC_FORCED_WRTHRU | NSC_NO_FORCED_WRTHRU |
3167836SJohn.Forte@Sun.COM 			    NSC_NOCACHE);
3177836SJohn.Forte@Sun.COM 			hints |= *dhint;
3187836SJohn.Forte@Sun.COM 
3197836SJohn.Forte@Sun.COM 			if (hints & NSC_NOCACHE)
3207836SJohn.Forte@Sun.COM 				(void) strcpy(rmode, "D");
3217836SJohn.Forte@Sun.COM 			else
3227836SJohn.Forte@Sun.COM 				(void) strcpy(rmode, "C");
3237836SJohn.Forte@Sun.COM 
3247836SJohn.Forte@Sun.COM 			if ((hints & NSC_FORCED_WRTHRU) || (hints & NSC_WRTHRU))
3257836SJohn.Forte@Sun.COM 				(void) strcpy(wmode, "D");
3267836SJohn.Forte@Sun.COM 			else
3277836SJohn.Forte@Sun.COM 				(void) strcpy(wmode, "C");
3287836SJohn.Forte@Sun.COM 
3297836SJohn.Forte@Sun.COM 			(void) printf(DATA_C2, rmode);
3307836SJohn.Forte@Sun.COM 			(void) printf(DATA_C2, wmode);
3317836SJohn.Forte@Sun.COM 		}
3327836SJohn.Forte@Sun.COM 
3337836SJohn.Forte@Sun.COM 		/* Output set information */
3347836SJohn.Forte@Sun.COM 		cd_report(cur);
3357836SJohn.Forte@Sun.COM 
3367836SJohn.Forte@Sun.COM next:
3377836SJohn.Forte@Sun.COM 		pre = cur;
3387836SJohn.Forte@Sun.COM 		cur = cur->next;
3397836SJohn.Forte@Sun.COM 	}
3407836SJohn.Forte@Sun.COM 
3417836SJohn.Forte@Sun.COM 	return (0);
3427836SJohn.Forte@Sun.COM }
3437836SJohn.Forte@Sun.COM 
3447836SJohn.Forte@Sun.COM /*
3457836SJohn.Forte@Sun.COM  * sdbc_header() - outputs an appropriate header by referencing the
3467836SJohn.Forte@Sun.COM  * global variables dflsgs
3477836SJohn.Forte@Sun.COM  *
3487836SJohn.Forte@Sun.COM  */
3497836SJohn.Forte@Sun.COM void
sdbc_header()3507836SJohn.Forte@Sun.COM sdbc_header()
3517836SJohn.Forte@Sun.COM {
3527836SJohn.Forte@Sun.COM 	int rcount = 0;
3537836SJohn.Forte@Sun.COM 
3547836SJohn.Forte@Sun.COM 	if (hflags == HEADERS_EXL)
3557836SJohn.Forte@Sun.COM 		if ((linesout % DISPLAY_LINES) != 0)
3567836SJohn.Forte@Sun.COM 			return;
3577836SJohn.Forte@Sun.COM 
3587836SJohn.Forte@Sun.COM 	if (hflags == HEADERS_BOR)
3597836SJohn.Forte@Sun.COM 		if (linesout != 0)
3607836SJohn.Forte@Sun.COM 			return;
3617836SJohn.Forte@Sun.COM 
3627836SJohn.Forte@Sun.COM 	if (hflags & HEADERS_ATT)
3637836SJohn.Forte@Sun.COM 		if (hflags & HEADERS_OUT)
3647836SJohn.Forte@Sun.COM 			return;
3657836SJohn.Forte@Sun.COM 		else
3667836SJohn.Forte@Sun.COM 			hflags |= HEADERS_OUT;
3677836SJohn.Forte@Sun.COM 
3687836SJohn.Forte@Sun.COM 	if (linesout)
369*11576SSurya.Prakki@Sun.COM 		(void) printf("\n");
3707836SJohn.Forte@Sun.COM 
3717836SJohn.Forte@Sun.COM 	/* first line header */
3727836SJohn.Forte@Sun.COM 	if (! (dflags & SUMMARY) && dflags != FLAGS) {
3737836SJohn.Forte@Sun.COM 
3747836SJohn.Forte@Sun.COM 		(void) printf(VOL_HDR_FMT, " ");
3757836SJohn.Forte@Sun.COM 
3767836SJohn.Forte@Sun.COM 		if (dflags & FLAGS) {
3777836SJohn.Forte@Sun.COM 			(void) printf(STAT_HDR_FMT, " ");
3787836SJohn.Forte@Sun.COM 			(void) printf(STAT_HDR_FMT, " ");
3797836SJohn.Forte@Sun.COM 		}
3807836SJohn.Forte@Sun.COM 
3817836SJohn.Forte@Sun.COM 		if (dflags & READ) {
3827836SJohn.Forte@Sun.COM 			int size;
3837836SJohn.Forte@Sun.COM 
3847836SJohn.Forte@Sun.COM 			size = KPS_HDR_SIZE * 2 + HIT_HDR_SIZE;
3857836SJohn.Forte@Sun.COM 			center(size, "- read -");
3867836SJohn.Forte@Sun.COM 			rcount++;
3877836SJohn.Forte@Sun.COM 		}
3887836SJohn.Forte@Sun.COM 
3897836SJohn.Forte@Sun.COM 		if (dflags & WRITE) {
3907836SJohn.Forte@Sun.COM 			int size;
3917836SJohn.Forte@Sun.COM 
3927836SJohn.Forte@Sun.COM 			size = KPS_HDR_SIZE * 2 + HIT_HDR_SIZE;
3937836SJohn.Forte@Sun.COM 			center(size, "- write -");
3947836SJohn.Forte@Sun.COM 			rcount++;
3957836SJohn.Forte@Sun.COM 		}
3967836SJohn.Forte@Sun.COM 
3977836SJohn.Forte@Sun.COM 		if (dflags != FLAGS)
3987836SJohn.Forte@Sun.COM 			(void) printf("\n");
3997836SJohn.Forte@Sun.COM 	}
4007836SJohn.Forte@Sun.COM 
4017836SJohn.Forte@Sun.COM 	/* second line header */
4027836SJohn.Forte@Sun.COM 	(void) printf(VOL_HDR_FMT, "volume");
4037836SJohn.Forte@Sun.COM 
4047836SJohn.Forte@Sun.COM 	if (dflags & FLAGS) {
4057836SJohn.Forte@Sun.COM 		(void) printf(STAT_HDR_FMT, "rd");
4067836SJohn.Forte@Sun.COM 		(void) printf(STAT_HDR_FMT, "wr");
4077836SJohn.Forte@Sun.COM 	}
4087836SJohn.Forte@Sun.COM 
4097836SJohn.Forte@Sun.COM 	if (dflags & SUMMARY) {
4107836SJohn.Forte@Sun.COM 		(void) printf(KPS_HDR_FMT, "ckps");
4117836SJohn.Forte@Sun.COM 		(void) printf(KPS_HDR_FMT, "dkps");
4127836SJohn.Forte@Sun.COM 		(void) printf(HIT_HDR_FMT, HIT_HDR_TXT);
4137836SJohn.Forte@Sun.COM 
4147836SJohn.Forte@Sun.COM 		goto out;
4157836SJohn.Forte@Sun.COM 	}
4167836SJohn.Forte@Sun.COM 
4177836SJohn.Forte@Sun.COM 	if (dflags & READ) {
4187836SJohn.Forte@Sun.COM 		(void) printf(KPS_HDR_FMT, "ckps");
4197836SJohn.Forte@Sun.COM 		(void) printf(KPS_HDR_FMT, "dkps");
4207836SJohn.Forte@Sun.COM 		(void) printf(HIT_HDR_FMT, RHIT_HDR_TXT);
4217836SJohn.Forte@Sun.COM 	}
4227836SJohn.Forte@Sun.COM 
4237836SJohn.Forte@Sun.COM 	if (dflags & WRITE) {
4247836SJohn.Forte@Sun.COM 		(void) printf(KPS_HDR_FMT, "ckps");
4257836SJohn.Forte@Sun.COM 		(void) printf(KPS_HDR_FMT, "dkps");
4267836SJohn.Forte@Sun.COM 		(void) printf(HIT_HDR_FMT, WHIT_HDR_TXT);
4277836SJohn.Forte@Sun.COM 	}
4287836SJohn.Forte@Sun.COM 
4297836SJohn.Forte@Sun.COM 	if (dflags & DESTAGED)
4307836SJohn.Forte@Sun.COM 		(void) printf(KPS_HDR_FMT, "dstg");
4317836SJohn.Forte@Sun.COM 
4327836SJohn.Forte@Sun.COM 	if (dflags & WRCANCEL)
4337836SJohn.Forte@Sun.COM 		(void) printf(KPS_HDR_FMT, "cwrl");
4347836SJohn.Forte@Sun.COM 
4357836SJohn.Forte@Sun.COM out:
4367836SJohn.Forte@Sun.COM 	(void) printf("\n");
4377836SJohn.Forte@Sun.COM }
4387836SJohn.Forte@Sun.COM 
4397836SJohn.Forte@Sun.COM /*
4407836SJohn.Forte@Sun.COM  * sdbc_getstat() - find cache stat by name matching
4417836SJohn.Forte@Sun.COM  *
4427836SJohn.Forte@Sun.COM  * paraemters
4437836SJohn.Forte@Sun.COM  * 	char *vn - the volume name to match against
4447836SJohn.Forte@Sun.COM  * returns
4457836SJohn.Forte@Sun.COM  * 	sdbcstat_t * - the matching strcture, NULL if not found
4467836SJohn.Forte@Sun.COM  */
4477836SJohn.Forte@Sun.COM sdbcstat_t *
sdbc_getstat(char * vn)4487836SJohn.Forte@Sun.COM sdbc_getstat(char *vn)
4497836SJohn.Forte@Sun.COM {
4507836SJohn.Forte@Sun.COM 	sdbcstat_t *cur, *pre = NULL;
4517836SJohn.Forte@Sun.COM 
4527836SJohn.Forte@Sun.COM 	for (cur = sdbc_top; cur; ) { /* CSTYLED */
4537836SJohn.Forte@Sun.COM 		char *volname =
4547836SJohn.Forte@Sun.COM 		    kstat_value(cur->pre_set, SDBC_CDKSTAT_VOL_NAME);
4557836SJohn.Forte@Sun.COM 
4567836SJohn.Forte@Sun.COM 		if (SDBC_COMPLETE(cur->collected)) {
4577836SJohn.Forte@Sun.COM 			sdbcstat_t *next = sdbc_delstat(cur);
4587836SJohn.Forte@Sun.COM 
4597836SJohn.Forte@Sun.COM 			if (! pre)
4607836SJohn.Forte@Sun.COM 				cur = sdbc_top = next;
4617836SJohn.Forte@Sun.COM 			else
4627836SJohn.Forte@Sun.COM 				cur = pre->next = next;
4637836SJohn.Forte@Sun.COM 
4647836SJohn.Forte@Sun.COM 			continue;
4657836SJohn.Forte@Sun.COM 		}
4667836SJohn.Forte@Sun.COM 
4677836SJohn.Forte@Sun.COM 		if (strncmp(volname, vn, NAMED_LEN) == 0)
4687836SJohn.Forte@Sun.COM 			return (cur);
4697836SJohn.Forte@Sun.COM 
4707836SJohn.Forte@Sun.COM 		pre = cur;
4717836SJohn.Forte@Sun.COM 		cur = cur->next;
4727836SJohn.Forte@Sun.COM 	}
4737836SJohn.Forte@Sun.COM 
4747836SJohn.Forte@Sun.COM 	return (NULL);
4757836SJohn.Forte@Sun.COM }
4767836SJohn.Forte@Sun.COM 
4777836SJohn.Forte@Sun.COM /*
4787836SJohn.Forte@Sun.COM  * sdbc_addstat() - adds a fully populated sdbcstat_t structure
4797836SJohn.Forte@Sun.COM  * to the linked list of currently monitored kstats.  The structure
4807836SJohn.Forte@Sun.COM  * will be added in alphabetical order, using the volume name as the
4817836SJohn.Forte@Sun.COM  * key.
4827836SJohn.Forte@Sun.COM  *
4837836SJohn.Forte@Sun.COM  * parameters
4847836SJohn.Forte@Sun.COM  * 	sdbcstat_t *sdbcstat - to be added to the list.
4857836SJohn.Forte@Sun.COM  *
4867836SJohn.Forte@Sun.COM  */
4877836SJohn.Forte@Sun.COM void
sdbc_addstat(sdbcstat_t * sdbcstat)4887836SJohn.Forte@Sun.COM sdbc_addstat(sdbcstat_t *sdbcstat)
4897836SJohn.Forte@Sun.COM {
4907836SJohn.Forte@Sun.COM 	sdbcstat_t *cur;
4917836SJohn.Forte@Sun.COM 
4927836SJohn.Forte@Sun.COM 	if (sdbc_top == NULL) {
4937836SJohn.Forte@Sun.COM 		sdbc_top = sdbcstat;
4947836SJohn.Forte@Sun.COM 		return;
4957836SJohn.Forte@Sun.COM 	}
4967836SJohn.Forte@Sun.COM 
4977836SJohn.Forte@Sun.COM 	for (cur = sdbc_top; cur != NULL; cur = cur->next) {
4987836SJohn.Forte@Sun.COM 		char *cur_vname, *nxt_vname, *tst_vname;
4997836SJohn.Forte@Sun.COM 
5007836SJohn.Forte@Sun.COM 		cur_vname = kstat_value(cur->pre_set,
5017836SJohn.Forte@Sun.COM 		    SDBC_CDKSTAT_VOL_NAME);
5027836SJohn.Forte@Sun.COM 		tst_vname = kstat_value(sdbcstat->pre_set,
5037836SJohn.Forte@Sun.COM 		    SDBC_CDKSTAT_VOL_NAME);
5047836SJohn.Forte@Sun.COM 
5057836SJohn.Forte@Sun.COM 		if (strncmp(cur_vname, tst_vname, NAMED_LEN) > 0) {
5067836SJohn.Forte@Sun.COM 			if (cur == sdbc_top)
5077836SJohn.Forte@Sun.COM 				sdbc_top = sdbcstat;
5087836SJohn.Forte@Sun.COM 
5097836SJohn.Forte@Sun.COM 			sdbcstat->next = cur;
5107836SJohn.Forte@Sun.COM 
5117836SJohn.Forte@Sun.COM 			return;
5127836SJohn.Forte@Sun.COM 		}
5137836SJohn.Forte@Sun.COM 
5147836SJohn.Forte@Sun.COM 		/*
5157836SJohn.Forte@Sun.COM 		 * If we get to the last item in the list, then just
5167836SJohn.Forte@Sun.COM 		 * add this one to the end
5177836SJohn.Forte@Sun.COM 		 */
5187836SJohn.Forte@Sun.COM 		if (cur->next == NULL) {
5197836SJohn.Forte@Sun.COM 			cur->next = sdbcstat;
5207836SJohn.Forte@Sun.COM 			return;
5217836SJohn.Forte@Sun.COM 		}
5227836SJohn.Forte@Sun.COM 
5237836SJohn.Forte@Sun.COM 		nxt_vname = kstat_value(cur->next->pre_set,
5247836SJohn.Forte@Sun.COM 		    SDBC_CDKSTAT_VOL_NAME);
5257836SJohn.Forte@Sun.COM 
5267836SJohn.Forte@Sun.COM 		if (strncmp(nxt_vname, tst_vname, NAMED_LEN) > 0) {
5277836SJohn.Forte@Sun.COM 			sdbcstat->next = cur->next;
5287836SJohn.Forte@Sun.COM 			cur->next = sdbcstat;
5297836SJohn.Forte@Sun.COM 			return;
5307836SJohn.Forte@Sun.COM 		}
5317836SJohn.Forte@Sun.COM 	}
5327836SJohn.Forte@Sun.COM }
5337836SJohn.Forte@Sun.COM 
5347836SJohn.Forte@Sun.COM /*
5357836SJohn.Forte@Sun.COM  * sdbc_delstat() - deallocate memory for the structure being
5367836SJohn.Forte@Sun.COM  * passed in.
5377836SJohn.Forte@Sun.COM  *
5387836SJohn.Forte@Sun.COM  * parameters
5397836SJohn.Forte@Sun.COM  * 	sdbcstat_t *sdbcstat - structure to be deallocated
5407836SJohn.Forte@Sun.COM  *
5417836SJohn.Forte@Sun.COM  * returns
5427836SJohn.Forte@Sun.COM  * 	sdbcstat_t * - pointer to the "next" structures in the
5437836SJohn.Forte@Sun.COM  * 	linked list. May be NULL if we are removing the last
5447836SJohn.Forte@Sun.COM  * 	structure in the linked list.
5457836SJohn.Forte@Sun.COM  */
5467836SJohn.Forte@Sun.COM sdbcstat_t *
sdbc_delstat(sdbcstat_t * sdbcstat)5477836SJohn.Forte@Sun.COM sdbc_delstat(sdbcstat_t *sdbcstat)
5487836SJohn.Forte@Sun.COM {
5497836SJohn.Forte@Sun.COM 
5507836SJohn.Forte@Sun.COM 	sdbcstat_t *next = sdbcstat->next;
5517836SJohn.Forte@Sun.COM 
5527836SJohn.Forte@Sun.COM 	kstat_free(sdbcstat->pre_set);
5537836SJohn.Forte@Sun.COM 	kstat_free(sdbcstat->pre_io);
5547836SJohn.Forte@Sun.COM 	kstat_free(sdbcstat->cur_set);
5557836SJohn.Forte@Sun.COM 	kstat_free(sdbcstat->cur_io);
5567836SJohn.Forte@Sun.COM 
5577836SJohn.Forte@Sun.COM 	free(sdbcstat);
5587836SJohn.Forte@Sun.COM 	sdbcstat = NULL;
5597836SJohn.Forte@Sun.COM 
5607836SJohn.Forte@Sun.COM 	return (next);
5617836SJohn.Forte@Sun.COM }
5627836SJohn.Forte@Sun.COM 
5637836SJohn.Forte@Sun.COM /*
5647836SJohn.Forte@Sun.COM  * sdbc_value_check() - Checks for activity, supports -z switch
5657836SJohn.Forte@Sun.COM  *
5667836SJohn.Forte@Sun.COM  * parameters
5677836SJohn.Forte@Sun.COM  * 	sdbcstat_t *sdbcstat - structure to be checked
5687836SJohn.Forte@Sun.COM  *
5697836SJohn.Forte@Sun.COM  * returns
5707836SJohn.Forte@Sun.COM  * 	1 - activity
5717836SJohn.Forte@Sun.COM  * 	0 - no activity
5727836SJohn.Forte@Sun.COM  */
5737836SJohn.Forte@Sun.COM int
sdbc_value_check(sdbcstat_t * sdbcstat)5747836SJohn.Forte@Sun.COM sdbc_value_check(sdbcstat_t *sdbcstat)
5757836SJohn.Forte@Sun.COM {
5767836SJohn.Forte@Sun.COM 	if (SDBC_COMPLETE(sdbcstat->collected))
5777836SJohn.Forte@Sun.COM 		return (1);
5787836SJohn.Forte@Sun.COM 
5797836SJohn.Forte@Sun.COM 	if (sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_CACHE_READ) != 0)
5807836SJohn.Forte@Sun.COM 		return (1);
5817836SJohn.Forte@Sun.COM 
5827836SJohn.Forte@Sun.COM 	if (sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_DISK_READ) != 0)
5837836SJohn.Forte@Sun.COM 		return (1);
5847836SJohn.Forte@Sun.COM 
5857836SJohn.Forte@Sun.COM 	if (sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_CACHE_WRITE) != 0)
5867836SJohn.Forte@Sun.COM 		return (1);
5877836SJohn.Forte@Sun.COM 
5887836SJohn.Forte@Sun.COM 	if (sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_DISK_WRITE) != 0)
5897836SJohn.Forte@Sun.COM 		return (1);
5907836SJohn.Forte@Sun.COM 
5917836SJohn.Forte@Sun.COM 	if (sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_WRCANCELNS) != 0)
5927836SJohn.Forte@Sun.COM 		return (1);
5937836SJohn.Forte@Sun.COM 
5947836SJohn.Forte@Sun.COM 	if (io_value_check(sdbcstat->pre_io->ks_data,
5957836SJohn.Forte@Sun.COM 	    sdbcstat->cur_io->ks_data) != 0)
5967836SJohn.Forte@Sun.COM 		return (1);
5977836SJohn.Forte@Sun.COM 
5987836SJohn.Forte@Sun.COM 	return (0);
5997836SJohn.Forte@Sun.COM }
6007836SJohn.Forte@Sun.COM 
6017836SJohn.Forte@Sun.COM /*
6027836SJohn.Forte@Sun.COM  * sdbc_validate() - validates the structure of the kstats by attempting to
6037836SJohn.Forte@Sun.COM  *                   lookup fields used by this module
6047836SJohn.Forte@Sun.COM  *
6057836SJohn.Forte@Sun.COM  * parameters
6067836SJohn.Forte@Sun.COM  *	kstat_t *ksp - kstat to be examined
6077836SJohn.Forte@Sun.COM  *
6087836SJohn.Forte@Sun.COM  * returns
6097836SJohn.Forte@Sun.COM  * 	1 - one or more fields missing
6107836SJohn.Forte@Sun.COM  * 	0 - all fields present
6117836SJohn.Forte@Sun.COM  */
6127836SJohn.Forte@Sun.COM int
sdbc_validate(kstat_t * ksp)6137836SJohn.Forte@Sun.COM sdbc_validate(kstat_t *ksp)
6147836SJohn.Forte@Sun.COM {
6157836SJohn.Forte@Sun.COM 	if (! kstat_value(ksp, SDBC_CDKSTAT_VOL_NAME) ||
6167836SJohn.Forte@Sun.COM 	    ! kstat_value(ksp, SDBC_CDKSTAT_FAILED) ||
6177836SJohn.Forte@Sun.COM 	    ! kstat_value(ksp, SDBC_CDKSTAT_CDHINTS) ||
6187836SJohn.Forte@Sun.COM 	    ! kstat_value(ksp, SDBC_CDKSTAT_CACHE_READ) ||
6197836SJohn.Forte@Sun.COM 	    ! kstat_value(ksp, SDBC_CDKSTAT_DISK_READ) ||
6207836SJohn.Forte@Sun.COM 	    ! kstat_value(ksp, SDBC_CDKSTAT_CACHE_WRITE) ||
6217836SJohn.Forte@Sun.COM 	    ! kstat_value(ksp, SDBC_CDKSTAT_DISK_WRITE) ||
6227836SJohn.Forte@Sun.COM 	    ! kstat_value(ksp, SDBC_CDKSTAT_DESTAGED) ||
6237836SJohn.Forte@Sun.COM 	    ! kstat_value(ksp, SDBC_CDKSTAT_WRCANCELNS))
6247836SJohn.Forte@Sun.COM 		return (1);
6257836SJohn.Forte@Sun.COM 
6267836SJohn.Forte@Sun.COM 	return (0);
6277836SJohn.Forte@Sun.COM }
6287836SJohn.Forte@Sun.COM 
6297836SJohn.Forte@Sun.COM /*
6307836SJohn.Forte@Sun.COM  * sdbc_getvalues() - populates a values structure with data obtained from the
6317836SJohn.Forte@Sun.COM  *                    kstat
6327836SJohn.Forte@Sun.COM  *
6337836SJohn.Forte@Sun.COM  * parameters
6347836SJohn.Forte@Sun.COM  * 	sdbcstat_t *sdbcstat - pointer to the structure containing the kstats
6357836SJohn.Forte@Sun.COM  * 	sdbcvals_t *vals - pointer to the structure that will receive the values
6367836SJohn.Forte@Sun.COM  * 	int flags - flags that describe adjustments made to the values
6377836SJohn.Forte@Sun.COM  *
6387836SJohn.Forte@Sun.COM  * returns
6397836SJohn.Forte@Sun.COM  * 	1 - failure
6407836SJohn.Forte@Sun.COM  * 	0 - success
6417836SJohn.Forte@Sun.COM  */
6427836SJohn.Forte@Sun.COM int
sdbc_getvalues(sdbcstat_t * sdbcstat,sdbcvals_t * vals,int flags)6437836SJohn.Forte@Sun.COM sdbc_getvalues(sdbcstat_t *sdbcstat, sdbcvals_t *vals, int flags)
6447836SJohn.Forte@Sun.COM {
6457836SJohn.Forte@Sun.COM 	int divisor = 0;
6467836SJohn.Forte@Sun.COM 	int factors;
6477836SJohn.Forte@Sun.COM 	uint64_t hr_etime;
6487836SJohn.Forte@Sun.COM 	double etime;
6497836SJohn.Forte@Sun.COM 
6507836SJohn.Forte@Sun.COM 	kstat_io_t *cur;
6517836SJohn.Forte@Sun.COM 	kstat_io_t *pre;
6527836SJohn.Forte@Sun.COM 
6537836SJohn.Forte@Sun.COM 	if (sdbcstat == NULL)
6547836SJohn.Forte@Sun.COM 		return (1);
6557836SJohn.Forte@Sun.COM 
6567836SJohn.Forte@Sun.COM 	cur = sdbcstat->cur_io->ks_data;
6577836SJohn.Forte@Sun.COM 	pre = sdbcstat->pre_io->ks_data;
6587836SJohn.Forte@Sun.COM 
6597836SJohn.Forte@Sun.COM 	hr_etime = hrtime_delta(pre->rlastupdate, cur->rlastupdate);
6607836SJohn.Forte@Sun.COM 	etime = hr_etime / (double)NANOSEC;
6617836SJohn.Forte@Sun.COM 
6627836SJohn.Forte@Sun.COM 	/* read data */
6637836SJohn.Forte@Sun.COM 	vals->cache_read =
6647836SJohn.Forte@Sun.COM 	    FBA_SIZE(sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_CACHE_READ));
6657836SJohn.Forte@Sun.COM 	vals->disk_read =
6667836SJohn.Forte@Sun.COM 	    FBA_SIZE(sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_DISK_READ));
6677836SJohn.Forte@Sun.COM 
6687836SJohn.Forte@Sun.COM 
6697836SJohn.Forte@Sun.COM 	vals->total_reads = vals->cache_read + vals->disk_read;
6707836SJohn.Forte@Sun.COM 
6717836SJohn.Forte@Sun.COM 	if (vals->cache_read == 0)
6727836SJohn.Forte@Sun.COM 		vals->read_hit = 0.0;
6737836SJohn.Forte@Sun.COM 	else
6747836SJohn.Forte@Sun.COM 		vals->read_hit =
6757836SJohn.Forte@Sun.COM 		    ((float)vals->cache_read / vals->total_reads) * 100.0;
6767836SJohn.Forte@Sun.COM 
6777836SJohn.Forte@Sun.COM 	/* write data */
6787836SJohn.Forte@Sun.COM 	vals->cache_write =
6797836SJohn.Forte@Sun.COM 	    FBA_SIZE(sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_CACHE_WRITE));
6807836SJohn.Forte@Sun.COM 	vals->disk_write =
6817836SJohn.Forte@Sun.COM 	    FBA_SIZE(sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_DISK_WRITE));
6827836SJohn.Forte@Sun.COM 
6837836SJohn.Forte@Sun.COM 	vals->total_writes = vals->cache_write + vals->disk_write;
6847836SJohn.Forte@Sun.COM 
6857836SJohn.Forte@Sun.COM 	vals->destaged =
686*11576SSurya.Prakki@Sun.COM 	    FBA_SIZE(sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_DESTAGED));
6877836SJohn.Forte@Sun.COM 
6887836SJohn.Forte@Sun.COM 	if (vals->cache_write == 0)
6897836SJohn.Forte@Sun.COM 		vals->write_hit = 0.0;
6907836SJohn.Forte@Sun.COM 	else
6917836SJohn.Forte@Sun.COM 		vals->write_hit = ((float)vals->cache_write /
6927836SJohn.Forte@Sun.COM 		    (vals->total_writes - vals->destaged)) * 100.0;
6937836SJohn.Forte@Sun.COM 
6947836SJohn.Forte@Sun.COM 	/* miscellaneous */
6957836SJohn.Forte@Sun.COM 	vals->write_cancellations =
6967836SJohn.Forte@Sun.COM 	    FBA_SIZE(sdbc_getdelta(sdbcstat, SDBC_CDKSTAT_WRCANCELNS));
6977836SJohn.Forte@Sun.COM 
6987836SJohn.Forte@Sun.COM 	vals->total_cache = vals->cache_read + vals->cache_write;
6997836SJohn.Forte@Sun.COM 	vals->total_disk = vals->disk_read + vals->disk_write;
7007836SJohn.Forte@Sun.COM 
7017836SJohn.Forte@Sun.COM 	/* total cache hit calculation */
7027836SJohn.Forte@Sun.COM 	vals->cache_hit = 0;
7037836SJohn.Forte@Sun.COM 	factors = 0;
7047836SJohn.Forte@Sun.COM 
7057836SJohn.Forte@Sun.COM 	if (vals->cache_read != 0) {
7067836SJohn.Forte@Sun.COM 		vals->cache_hit += vals->read_hit;
7077836SJohn.Forte@Sun.COM 		factors++;
7087836SJohn.Forte@Sun.COM 	}
7097836SJohn.Forte@Sun.COM 
7107836SJohn.Forte@Sun.COM 	if (vals->cache_write != 0) {
7117836SJohn.Forte@Sun.COM 		vals->cache_hit += vals->write_hit;
7127836SJohn.Forte@Sun.COM 		factors++;
7137836SJohn.Forte@Sun.COM 	}
7147836SJohn.Forte@Sun.COM 
7157836SJohn.Forte@Sun.COM 	if (vals->cache_hit)
7167836SJohn.Forte@Sun.COM 		vals->cache_hit /= (float)factors;
7177836SJohn.Forte@Sun.COM 
7187836SJohn.Forte@Sun.COM 	/* adjustments */
7197836SJohn.Forte@Sun.COM 	divisor = 1;
7207836SJohn.Forte@Sun.COM 
7217836SJohn.Forte@Sun.COM 	if (flags & SDBC_KBYTES)
7227836SJohn.Forte@Sun.COM 		divisor *= KILOBYTE;
7237836SJohn.Forte@Sun.COM 	if ((flags & SDBC_INTAVG) && (etime > 0))
7247836SJohn.Forte@Sun.COM 		divisor *= etime;
7257836SJohn.Forte@Sun.COM 
7267836SJohn.Forte@Sun.COM 	if (divisor != 1) {
7277836SJohn.Forte@Sun.COM 		vals->cache_read /= divisor;
7287836SJohn.Forte@Sun.COM 		vals->disk_read /= divisor;
7297836SJohn.Forte@Sun.COM 		vals->total_reads /= divisor;
7307836SJohn.Forte@Sun.COM 
7317836SJohn.Forte@Sun.COM 		vals->cache_write /= divisor;
7327836SJohn.Forte@Sun.COM 		vals->disk_write /= divisor;
7337836SJohn.Forte@Sun.COM 		vals->total_writes /= divisor;
7347836SJohn.Forte@Sun.COM 
7357836SJohn.Forte@Sun.COM 		vals->total_cache /= divisor;
7367836SJohn.Forte@Sun.COM 		vals->total_disk /= divisor;
7377836SJohn.Forte@Sun.COM 
7387836SJohn.Forte@Sun.COM 		vals->destaged /= divisor;
7397836SJohn.Forte@Sun.COM 		vals->write_cancellations /= divisor;
7407836SJohn.Forte@Sun.COM 	}
7417836SJohn.Forte@Sun.COM 
7427836SJohn.Forte@Sun.COM 	return (0);
7437836SJohn.Forte@Sun.COM }
7447836SJohn.Forte@Sun.COM 
7457836SJohn.Forte@Sun.COM /*
7467836SJohn.Forte@Sun.COM  * sdbc_getdelta() - calculates the difference between two kstat fields
7477836SJohn.Forte@Sun.COM  *
7487836SJohn.Forte@Sun.COM  * parameters
7497836SJohn.Forte@Sun.COM  * 	sdbcstat_t *sdbcstat - the SDBC stat strcture containing the two fields
7507836SJohn.Forte@Sun.COM  * 	char *name - the name of the fields
7517836SJohn.Forte@Sun.COM  * returns
7527836SJohn.Forte@Sun.COM  * 	uint32_t value of the differences adjusted for overflow of the data type
7537836SJohn.Forte@Sun.COM  */
7547836SJohn.Forte@Sun.COM uint32_t
sdbc_getdelta(sdbcstat_t * sdbcstat,char * name)7557836SJohn.Forte@Sun.COM sdbc_getdelta(sdbcstat_t *sdbcstat, char *name)
7567836SJohn.Forte@Sun.COM {
7577836SJohn.Forte@Sun.COM 	uint32_t *cur_val;
7587836SJohn.Forte@Sun.COM 	uint32_t *pre_val;
7597836SJohn.Forte@Sun.COM 
7607836SJohn.Forte@Sun.COM 	pre_val = kstat_value(sdbcstat->pre_set, name);
7617836SJohn.Forte@Sun.COM 	cur_val = kstat_value(sdbcstat->cur_set, name);
7627836SJohn.Forte@Sun.COM 
7637836SJohn.Forte@Sun.COM 	return (u32_delta(*pre_val, *cur_val));
7647836SJohn.Forte@Sun.COM }
7657836SJohn.Forte@Sun.COM 
7667836SJohn.Forte@Sun.COM void
center(int size,char * hdr)7677836SJohn.Forte@Sun.COM center(int size, char *hdr)
7687836SJohn.Forte@Sun.COM {
7697836SJohn.Forte@Sun.COM 	int lpad = 0;
7707836SJohn.Forte@Sun.COM 	int rpad = 0;
7717836SJohn.Forte@Sun.COM 	char fmt[10];
7727836SJohn.Forte@Sun.COM 
7737836SJohn.Forte@Sun.COM 	if (size == 0)
7747836SJohn.Forte@Sun.COM 		return;
7757836SJohn.Forte@Sun.COM 
7767836SJohn.Forte@Sun.COM 	if (strlen(hdr) < size) {
7777836SJohn.Forte@Sun.COM 		lpad = (size - strlen(hdr)) / 2;
7787836SJohn.Forte@Sun.COM 
7797836SJohn.Forte@Sun.COM 		if (lpad * 2 < size)
7807836SJohn.Forte@Sun.COM 			lpad++;
7817836SJohn.Forte@Sun.COM 
7827836SJohn.Forte@Sun.COM 		rpad = size - (lpad + strlen(hdr));
7837836SJohn.Forte@Sun.COM 	}
7847836SJohn.Forte@Sun.COM 
7857836SJohn.Forte@Sun.COM output:
7867836SJohn.Forte@Sun.COM 	(void) sprintf(fmt, "%%%ds%%s%%%ds", lpad, rpad);
7877836SJohn.Forte@Sun.COM 	(void) printf(fmt, " ", hdr, " ");
7887836SJohn.Forte@Sun.COM }
789