Home | History | Annotate | Download | only in dsstat
      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 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include <unistd.h>
     30 #include <errno.h>
     31 
     32 #include <sys/mutex.h>
     33 
     34 #include <kstat.h>
     35 
     36 #include <sys/unistat/spcs_s.h>
     37 #include <sys/nsctl/dsw.h>
     38 #include "../../../uts/common/avs/ns/dsw/dsw_dev.h"
     39 #include <sys/nsctl/dsw_dev.h>
     40 
     41 #include "sdbc_stats.h"
     42 #include "ii_stats.h"
     43 
     44 #include "dsstat.h"
     45 #include "common.h"
     46 #include "report.h"
     47 
     48 static iistat_t *ii_top = NULL;
     49 
     50 void ii_add_stat(iistat_t *);
     51 iistat_t *ii_del_stat(iistat_t *);
     52 
     53 int ii_value_check(iistat_t *iistat);
     54 int ii_validate(kstat_t *ksp);
     55 int ii_vol_selected(kstat_t *);
     56 
     57 /*
     58  * ii_discover() - looks for new statistics to be monitored.
     59  * Verifies that any statistics found are now already being
     60  * monitored.
     61  *
     62  */
     63 int
     64 ii_discover(kstat_ctl_t *kc)
     65 {
     66 	static int validated = 0;
     67 
     68 	kstat_t *ksp;
     69 
     70 	/* Loop on all kstats */
     71 	for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
     72 		char *kname;
     73 		iistat_t *cur;
     74 		iistat_t *iistat = NULL;
     75 		kstat_t *mst_ksp;
     76 		kstat_t *shd_ksp;
     77 		kstat_t *bmp_ksp;
     78 		kstat_t *ovr_ksp;
     79 
     80 		/* Search for II set */
     81 		if (strcmp(ksp->ks_class, II_KSTAT_CLASS) != 0)
     82 			continue;
     83 
     84 		if (kstat_read(kc, ksp, NULL) == -1)
     85 			continue;
     86 
     87 		/*
     88 		 * Validate kstat structure
     89 		 */
     90 		if (! validated) {
     91 			if (ii_validate(ksp))
     92 				return (EINVAL);
     93 
     94 			validated++;
     95 		}
     96 
     97 		/*
     98 		 * Duplicate check
     99 		 */
    100 		for (cur = ii_top; cur != NULL; cur = cur->next) {
    101 			char *cur_vname, *tst_vname;
    102 			uint32_t cur_inst, tst_inst;
    103 
    104 			cur_vname = cur->pre_set->ks_name;
    105 			cur_inst = cur->pre_set->ks_instance;
    106 
    107 			tst_vname = ksp->ks_name;
    108 			tst_inst = ksp->ks_instance;
    109 
    110 			if (strcmp(cur_vname, tst_vname) == 0 &&
    111 			    cur_inst == tst_inst)
    112 				goto next;
    113 		}
    114 
    115 		/*
    116 		 * Initialize new record
    117 		 */
    118 		iistat = (iistat_t *)calloc(1, sizeof (iistat_t));
    119 
    120 		/*
    121 		 * Set kstat
    122 		 */
    123 		iistat->pre_set = kstat_retrieve(kc, ksp);
    124 
    125 		if (iistat->pre_set == NULL)
    126 			goto next;
    127 
    128 		iistat->collected |= GOT_SETSTAT;
    129 
    130 		/*
    131 		 * Master kstat
    132 		 */
    133 		kname = kstat_value(iistat->pre_set, DSW_SKSTAT_MSTIO);
    134 
    135 		mst_ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname);
    136 		iistat->pre_mst = kstat_retrieve(kc, mst_ksp);
    137 
    138 		if (iistat->pre_mst == NULL)
    139 			goto next;
    140 
    141 		iistat->collected |= GOT_MSTSTAT;
    142 
    143 		/*
    144 		 * Shadow kstat
    145 		 */
    146 		kname = kstat_value(iistat->pre_set, DSW_SKSTAT_SHDIO);
    147 
    148 		shd_ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname);
    149 		iistat->pre_shd = kstat_retrieve(kc, shd_ksp);
    150 
    151 		if (iistat->pre_shd == NULL)
    152 			goto next;
    153 
    154 		iistat->collected |= GOT_SHDSTAT;
    155 
    156 		/*
    157 		 * Bitmap kstat
    158 		 */
    159 		kname = kstat_value(iistat->pre_set, DSW_SKSTAT_BMPIO);
    160 
    161 		bmp_ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname);
    162 		iistat->pre_bmp = kstat_retrieve(kc, bmp_ksp);
    163 
    164 		if (iistat->pre_bmp == NULL)
    165 			goto next;
    166 
    167 		iistat->collected |= GOT_BMPSTAT;
    168 
    169 		/*
    170 		 * Overflow kstat
    171 		 */
    172 		kname = kstat_value(iistat->pre_set, DSW_SKSTAT_OVRIO);
    173 
    174 		ovr_ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname);
    175 		iistat->pre_ovr = kstat_retrieve(kc, ovr_ksp);
    176 
    177 		if (iistat->pre_ovr == NULL)
    178 			goto next;
    179 
    180 		iistat->collected |= GOT_OVRSTAT;
    181 
    182 next:
    183 		/*
    184 		 * Check if we got a complete set of stats
    185 		 */
    186 		if (iistat == NULL)
    187 			continue;
    188 
    189 		if (IIMG_COMPLETE(iistat->collected)) {
    190 			(void) ii_del_stat(iistat);
    191 			continue;
    192 		}
    193 
    194 		/*
    195 		 * Add to linked list
    196 		 */
    197 		ii_add_stat(iistat);
    198 	}
    199 
    200 	if (ii_top == NULL)
    201 		return (EAGAIN);
    202 
    203 	return (0);
    204 }
    205 
    206 /*
    207  * ii_update() - updates all of the statistics currently being monitored.
    208  *
    209  */
    210 int
    211 ii_update(kstat_ctl_t *kc)
    212 {
    213 	iistat_t *cur;
    214 
    215 	for (cur = ii_top; cur != NULL; cur = cur->next) {
    216 		char volname[KSTAT_STRLEN + 1];
    217 		char *kname;
    218 
    219 		kstat_t *ksp = NULL;
    220 
    221 		cur->collected = 0;
    222 
    223 		/*
    224 		 * Age off old stats
    225 		 */
    226 		if (cur->cur_set != NULL) {
    227 			kstat_free(cur->pre_set);
    228 			kstat_free(cur->pre_mst);
    229 			kstat_free(cur->pre_shd);
    230 			kstat_free(cur->pre_bmp);
    231 
    232 			cur->pre_set = cur->cur_set;
    233 			cur->pre_mst = cur->cur_mst;
    234 			cur->pre_shd = cur->cur_shd;
    235 			cur->pre_bmp = cur->cur_bmp;
    236 
    237 			if (cur->cur_ovr != NULL) {
    238 				kstat_free(cur->pre_ovr);
    239 				cur->pre_ovr = cur->cur_ovr;
    240 			}
    241 		}
    242 
    243 		/*
    244 		 * Set kstat
    245 		 */
    246 		strncpy(volname, cur->pre_set->ks_name, KSTAT_STRLEN);
    247 		volname[KSTAT_STRLEN] = '\0';
    248 
    249 		ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, volname);
    250 
    251 		if ((cur->cur_set = kstat_retrieve(kc, ksp)) == NULL)
    252 			continue;
    253 
    254 		cur->collected |= GOT_SETSTAT;
    255 
    256 		/*
    257 		 * Validate set
    258 		 */
    259 		if (strcmp(cur->pre_set->ks_name, cur->cur_set->ks_name) != 0 ||
    260 		    cur->pre_set->ks_instance != cur->cur_set->ks_instance)
    261 			continue;
    262 
    263 		/*
    264 		 * Master kstat
    265 		 */
    266 		kname = kstat_value(cur->cur_set, DSW_SKSTAT_MSTIO);
    267 
    268 		ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname);
    269 
    270 		if ((cur->cur_mst = kstat_retrieve(kc, ksp)) == NULL)
    271 			continue;
    272 
    273 		cur->collected |= GOT_MSTSTAT;
    274 
    275 		/*
    276 		 * Shadow kstat
    277 		 */
    278 		kname = kstat_value(cur->cur_set, DSW_SKSTAT_SHDIO);
    279 
    280 		ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname);
    281 
    282 		if ((cur->cur_shd = kstat_retrieve(kc, ksp)) == NULL)
    283 			continue;
    284 
    285 		cur->collected |= GOT_SHDSTAT;
    286 
    287 		/*
    288 		 * Bitmap kstat
    289 		 */
    290 		kname = kstat_value(cur->pre_set, DSW_SKSTAT_BMPIO);
    291 
    292 		ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname);
    293 
    294 		if ((cur->cur_bmp = kstat_retrieve(kc, ksp)) == NULL)
    295 			continue;
    296 
    297 		cur->collected |= GOT_BMPSTAT;
    298 
    299 		/*
    300 		 * Overflow kstat
    301 		 */
    302 		kname = kstat_value(cur->cur_set, DSW_SKSTAT_OVRIO);
    303 
    304 		ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname);
    305 
    306 		if (ksp == NULL) {
    307 			if (cur->pre_ovr != NULL) {
    308 				kstat_free(cur->pre_ovr);
    309 				cur->pre_ovr = NULL;
    310 			}
    311 			if (cur->cur_ovr != NULL) {
    312 				kstat_free(cur->cur_ovr);
    313 				cur->cur_ovr = NULL;
    314 			}
    315 			continue;
    316 		}
    317 
    318 		if (cur->pre_ovr == NULL) {
    319 			if ((cur->pre_ovr = kstat_retrieve(kc, ksp)) == NULL)
    320 				continue;
    321 		} else {
    322 			if ((cur->cur_ovr = kstat_retrieve(kc, ksp)) == NULL)
    323 				continue;
    324 		}
    325 
    326 		cur->collected |= GOT_OVRSTAT;
    327 	}
    328 
    329 	return (0);
    330 }
    331 
    332 /*
    333  * ii_report() - outputs statistics for the statistics currently being
    334  * monitored.  Deletes statistics for volumes that have been disabled.
    335  *
    336  */
    337 int
    338 ii_report()
    339 {
    340 	uint32_t *flags;
    341 	int padsz = 0;
    342 	char pad[20] = {0};
    343 	iistat_t *cur, *pre = NULL;
    344 
    345 	if (ii_top == NULL) {
    346 		return (0);
    347 	}
    348 
    349 	/* Create padding string for secondary report lines */
    350 	if (dflags & FLAGS) {
    351 		padsz += STAT_HDR_SIZE;
    352 		padsz += STAT_HDR_SIZE;
    353 	}
    354 
    355 	if (dflags & PCTS)
    356 		padsz += PCT_HDR_SIZE;
    357 
    358 	if (padsz) {
    359 		char fmt[20];
    360 		sprintf(fmt, "%%%ds", padsz);
    361 		sprintf(pad, fmt, "");
    362 	}
    363 
    364 	for (cur = ii_top; cur; /* CSTYLED */) {
    365 		int first = 1;
    366 		char data[20] = {0};
    367 
    368 		/* Check to see if this is this a complete */
    369 		if (IIMG_COMPLETE(cur->collected)) {
    370 			char *c;
    371 			char vol[(NAMED_LEN * 4) + 1] = {0};
    372 			int offset;
    373 			iistat_t *next;
    374 
    375 			/* notify user of set being disabled */
    376 			c = kstat_value(cur->pre_set, DSW_SKSTAT_SETA);
    377 			strncpy(vol, c, NAMED_LEN);
    378 			c = kstat_value(cur->pre_set, DSW_SKSTAT_SETB);
    379 			strncat(vol, c, NAMED_LEN);
    380 			c = kstat_value(cur->pre_set, DSW_SKSTAT_SETC);
    381 			strncat(vol, c, NAMED_LEN);
    382 			c = kstat_value(cur->pre_set, DSW_SKSTAT_SETD);
    383 			strncat(vol, c, NAMED_LEN);
    384 
    385 			offset = strlen(vol) - NAMED_LEN;
    386 
    387 			if (offset < 0)
    388 				offset = 0;
    389 
    390 			printf(DATA_C16, vol + offset);
    391 			printf(" %s\n", II_DISABLED);
    392 
    393 			/* free memory and remove stat from list */
    394 			next = ii_del_stat(cur);
    395 
    396 			if (! pre)
    397 				cur = ii_top = next;
    398 			else
    399 				cur = pre->next = next;
    400 
    401 			continue;
    402 		}
    403 
    404 		/* Check to see if the user specified this volume */
    405 		if (! ii_vol_selected(cur->pre_set))
    406 			goto next;
    407 
    408 		/* Check to see if zflag applies */
    409 		if (zflag && ii_value_check(cur) == 0)
    410 			goto next;
    411 
    412 		/* Calculate flags */
    413 		flags = kstat_value(cur->cur_set, DSW_SKSTAT_FLAGS);
    414 
    415 		if (dflags & FLAGS) {
    416 
    417 			char c[STAT_HDR_SIZE];
    418 			char vtype[STAT_HDR_SIZE];
    419 			char vstat[STAT_HDR_SIZE];
    420 
    421 			if (*flags & DSW_GOLDEN)
    422 				strcpy(c, II_INDEPENDENT);
    423 			else
    424 				strcpy(c, II_DEPENDENT);
    425 
    426 			sprintf(vtype, DATA_C2, c);
    427 			strcat(data, vtype);
    428 
    429 			if (*flags & DSW_COPYINGP)
    430 				strcpy(c, II_COPYING);
    431 			else
    432 				strcpy(c, NO_INFO);
    433 
    434 
    435 			sprintf(vstat, DATA_C2, c);
    436 			strcat(data, vstat);
    437 		}
    438 
    439 		/* Calculate sync needed precentage */
    440 		if (dflags & PCTS) {
    441 			char snpct[10];
    442 			uint32_t *chkbits;
    443 			uint32_t *cpybits;
    444 			uint32_t *shdbits;
    445 			uint32_t *volsize;
    446 			float pct;
    447 
    448 			cpybits =
    449 			    kstat_value(cur->cur_set, DSW_SKSTAT_COPYBITS);
    450 
    451 			shdbits =
    452 			    kstat_value(cur->cur_set, DSW_SKSTAT_SHDBITS);
    453 
    454 			volsize =
    455 			    kstat_value(cur->cur_set, DSW_SKSTAT_SIZE);
    456 
    457 			*volsize /= DSW_SIZE;
    458 
    459 			chkbits = *cpybits >= *shdbits ? cpybits : shdbits;
    460 
    461 			pct = ((float)*chkbits / *volsize) * 100.0;
    462 
    463 			sprintf(snpct, DATA_F62, pct);
    464 
    465 			strcat(data, snpct);
    466 		}
    467 
    468 		/* Master statistics */
    469 		if (rflags & IIMG_MST) {
    470 			char *c;
    471 			char vol[(NAMED_LEN * 4) + 1] = {0};
    472 			int offset;
    473 
    474 			c = kstat_value(cur->cur_set, DSW_SKSTAT_MSTA);
    475 			strncat(vol, c, NAMED_LEN);
    476 			c = kstat_value(cur->cur_set, DSW_SKSTAT_MSTB);
    477 			strncat(vol, c, NAMED_LEN);
    478 			c = kstat_value(cur->cur_set, DSW_SKSTAT_MSTC);
    479 			strncat(vol, c, NAMED_LEN);
    480 			c = kstat_value(cur->cur_set, DSW_SKSTAT_MSTD);
    481 			strncat(vol, c, NAMED_LEN);
    482 
    483 			offset = strlen(vol) - NAMED_LEN;
    484 
    485 			if (offset < 0)
    486 				offset = 0;
    487 
    488 			header();
    489 			printf(DATA_C16, vol + offset);
    490 			printf("%s", data);
    491 			printf(ROLE_INF_FMT, II_MASTER);
    492 
    493 			if (*flags & DSW_MSTOFFLINE) {
    494 				printf(" <<offline>>");
    495 				linesout++;
    496 			} else {
    497 				io_report(cur->cur_mst, cur->pre_mst,
    498 				    sdbc_getstat(vol + offset));
    499 			}
    500 
    501 			printf("\n");
    502 
    503 			if (first) {
    504 				strcpy(data, strlen(pad) > 0 ? pad : "");
    505 				first = 0;
    506 			}
    507 		}
    508 
    509 		/* Shadow statistics */
    510 		if (rflags & IIMG_SHD) {
    511 			char *c;
    512 			char vol[(NAMED_LEN * 4) + 1] = {0};
    513 			int offset;
    514 
    515 			c = kstat_value(cur->cur_set, DSW_SKSTAT_SETA);
    516 			strncat(vol, c, NAMED_LEN);
    517 			c = kstat_value(cur->cur_set, DSW_SKSTAT_SETB);
    518 			strncat(vol, c, NAMED_LEN);
    519 			c = kstat_value(cur->cur_set, DSW_SKSTAT_SETC);
    520 			strncat(vol, c, NAMED_LEN);
    521 			c = kstat_value(cur->cur_set, DSW_SKSTAT_SETD);
    522 			strncat(vol, c, NAMED_LEN);
    523 
    524 			offset = strlen(vol) - NAMED_LEN;
    525 
    526 			if (offset < 0)
    527 				offset = 0;
    528 
    529 			header();
    530 			printf(DATA_C16, vol + offset);
    531 			printf("%s", data);
    532 			printf(ROLE_INF_FMT, II_SHADOW);
    533 
    534 			if (*flags & DSW_SHDOFFLINE) {
    535 				printf(" <<offline>>");
    536 				linesout++;
    537 			} else {
    538 				io_report(cur->cur_shd, cur->pre_shd,
    539 				    sdbc_getstat(vol + offset));
    540 			}
    541 
    542 			printf("\n");
    543 
    544 			if (first) {
    545 				strcpy(data, strlen(pad) > 0 ? pad : "");
    546 				first = 0;
    547 			}
    548 		}
    549 
    550 		/* Bitmap statistics */
    551 		if (rflags & IIMG_BMP) {
    552 			char *c;
    553 			char vol[(NAMED_LEN * 4) + 1] = {0};
    554 			int offset;
    555 
    556 			c = kstat_value(cur->cur_set, DSW_SKSTAT_BMPA);
    557 			strncat(vol, c, NAMED_LEN);
    558 			c = kstat_value(cur->cur_set, DSW_SKSTAT_BMPB);
    559 			strncat(vol, c, NAMED_LEN);
    560 			c = kstat_value(cur->cur_set, DSW_SKSTAT_BMPC);
    561 			strncat(vol, c, NAMED_LEN);
    562 			c = kstat_value(cur->cur_set, DSW_SKSTAT_BMPD);
    563 			strncat(vol, c, NAMED_LEN);
    564 
    565 			offset = strlen(vol) - NAMED_LEN;
    566 
    567 			if (offset < 0)
    568 				offset = 0;
    569 
    570 			header();
    571 			printf(DATA_C16, vol + offset);
    572 			printf("%s", data);
    573 			printf(ROLE_INF_FMT, II_BITMAP);
    574 
    575 			if (*flags & DSW_BMPOFFLINE) {
    576 				printf(" <<offline>>");
    577 				linesout++;
    578 			} else {
    579 				io_report(cur->cur_bmp, cur->pre_bmp,
    580 				    sdbc_getstat(vol + offset));
    581 			}
    582 			printf("\n");
    583 
    584 			if (first) {
    585 				strcpy(data, strlen(pad) > 0 ? pad : "");
    586 				first = 0;
    587 			}
    588 		}
    589 
    590 		/* Overflow statistics */
    591 		if (rflags & IIMG_OVR) {
    592 			char *c;
    593 			char msg[20] = {0};
    594 			char vol[(NAMED_LEN * 4) + 1] = {0};
    595 			int offset;
    596 
    597 			if (cur->cur_ovr == NULL && cur->pre_ovr != NULL)
    598 				strcpy(msg, " <<attached>>");
    599 
    600 			if (! (cur->collected & GOT_OVRSTAT))
    601 				strcpy(msg, " <<not attached>>");
    602 
    603 			c = kstat_value(cur->cur_set, DSW_SKSTAT_OVRA);
    604 			strncpy(vol, c, NAMED_LEN);
    605 			c = kstat_value(cur->cur_set, DSW_SKSTAT_OVRB);
    606 			strncat(vol, c, NAMED_LEN);
    607 			c = kstat_value(cur->cur_set, DSW_SKSTAT_OVRC);
    608 			strncat(vol, c, NAMED_LEN);
    609 			c = kstat_value(cur->cur_set, DSW_SKSTAT_OVRD);
    610 			strncat(vol, c, NAMED_LEN);
    611 
    612 			offset = strlen(vol) - NAMED_LEN;
    613 
    614 			if (offset < 0)
    615 				offset = 0;
    616 
    617 			header();
    618 			printf(DATA_C16, vol + offset);
    619 			printf("%s", data);
    620 			printf(ROLE_INF_FMT, II_OVERFLOW);
    621 
    622 			if (strlen(msg)) {
    623 				printf("%s\n", msg);
    624 				linesout++;
    625 				goto next;
    626 			}
    627 
    628 			if (*flags & DSW_OVROFFLINE) {
    629 				printf(" <<offline>>");
    630 				linesout++;
    631 			} else {
    632 				io_report(cur->cur_ovr, cur->pre_ovr,
    633 				    sdbc_getstat(vol + offset));
    634 			}
    635 
    636 			printf("\n");
    637 
    638 			if (first) {
    639 				strcpy(data, strlen(pad) > 0 ? pad : "");
    640 				first = 0;
    641 			}
    642 		}
    643 
    644 
    645 next:
    646 		pre = cur;
    647 		cur = cur->next;
    648 	}
    649 
    650 	return (0);
    651 }
    652 
    653 /*
    654  * ii_add_stat() - adds a fully populated iistat_t structure
    655  * to the linked list of currently monitored kstats.  The structure
    656  * will be added in alphabetical order, using the volume name of
    657  * the shadow volume as the key.
    658  *
    659  */
    660 void
    661 ii_add_stat(iistat_t *iistat)
    662 {
    663 
    664 	iistat_t *cur;
    665 
    666 	if (ii_top == NULL) {
    667 		ii_top = iistat;
    668 		return;
    669 	}
    670 
    671 	for (cur = ii_top; cur != NULL; cur = cur->next) {
    672 		if (strcmp(cur->pre_set->ks_name,
    673 		    iistat->pre_set->ks_name) <= 0) {
    674 			/*
    675 			 * If we get to the last item in the list, then just
    676 			 * add this one to the end
    677 			 */
    678 			if (cur->next == NULL) {
    679 				cur->next = iistat;
    680 				return;
    681 			}
    682 
    683 			if (strcmp(cur->next->pre_set->ks_name,
    684 			    iistat->pre_set->ks_name) > 0) {
    685 				iistat->next = cur->next;
    686 				cur->next = iistat;
    687 				return;
    688 			}
    689 		} else {
    690 			if (cur == ii_top)
    691 				ii_top = iistat;
    692 
    693 			iistat->next = cur;
    694 
    695 			return;
    696 		}
    697 	}
    698 }
    699 
    700 /*
    701  * ii_del_stat() - deallocate memory for the structure being
    702  * passed in.
    703  *
    704  * parameters
    705  * 	iistat_t *iistat - structure to be deallocated
    706  *
    707  * returns
    708  * 	iistat_t * - pointer to the "next" structures in the
    709  * 	linked list. May be NULL if we are removing the last
    710  * 	structure in the linked list.
    711  *
    712  */
    713 iistat_t *
    714 ii_del_stat(iistat_t *iistat)
    715 {
    716 
    717 	iistat_t *next = iistat->next;
    718 
    719 	kstat_free(iistat->pre_set);
    720 	kstat_free(iistat->pre_mst);
    721 	kstat_free(iistat->pre_shd);
    722 	kstat_free(iistat->pre_bmp);
    723 	kstat_free(iistat->pre_ovr);
    724 	kstat_free(iistat->cur_set);
    725 	kstat_free(iistat->cur_mst);
    726 	kstat_free(iistat->cur_shd);
    727 	kstat_free(iistat->cur_bmp);
    728 	kstat_free(iistat->cur_ovr);
    729 
    730 	free(iistat);
    731 
    732 	return (next);
    733 }
    734 
    735 int
    736 ii_value_check(iistat_t *iistat)
    737 {
    738 	if (IIMG_COMPLETE(iistat->collected))
    739 		return (1);
    740 
    741 	if (io_value_check(iistat->pre_mst->ks_data,
    742 	    iistat->cur_mst->ks_data)) {
    743 		return (1);
    744 	}
    745 
    746 	if (io_value_check(iistat->pre_shd->ks_data,
    747 	    iistat->cur_shd->ks_data)) {
    748 		return (1);
    749 	}
    750 
    751 	if (io_value_check(iistat->pre_bmp->ks_data,
    752 	    iistat->cur_bmp->ks_data)) {
    753 		return (1);
    754 	}
    755 
    756 	if (iistat->pre_ovr && iistat->cur_ovr) {
    757 		if (io_value_check(iistat->pre_ovr->ks_data,
    758 		    iistat->cur_ovr->ks_data)) {
    759 			return (1);
    760 		}
    761 	}
    762 
    763 	return (0);
    764 }
    765 
    766 int
    767 ii_validate(kstat_t *ksp)
    768 {
    769 	if (! kstat_value(ksp, DSW_SKSTAT_MSTIO) ||
    770 	    ! kstat_value(ksp, DSW_SKSTAT_SHDIO) ||
    771 	    ! kstat_value(ksp, DSW_SKSTAT_BMPIO) ||
    772 	    ! kstat_value(ksp, DSW_SKSTAT_OVRIO) ||
    773 	    ! kstat_value(ksp, DSW_SKSTAT_FLAGS) ||
    774 	    ! kstat_value(ksp, DSW_SKSTAT_MSTA) ||
    775 	    ! kstat_value(ksp, DSW_SKSTAT_SETA) ||
    776 	    ! kstat_value(ksp, DSW_SKSTAT_BMPA) ||
    777 	    ! kstat_value(ksp, DSW_SKSTAT_OVRA) ||
    778 	    ! kstat_value(ksp, DSW_SKSTAT_SHDBITS) ||
    779 	    ! kstat_value(ksp, DSW_SKSTAT_COPYBITS) ||
    780 	    ! kstat_value(ksp, DSW_SKSTAT_SIZE))
    781 		return (1);
    782 
    783 	return (0);
    784 }
    785 
    786 int
    787 ii_vol_selected(kstat_t *ksp)
    788 {
    789 	vslist_t *vslist = vs_top;
    790 
    791 	for (vslist = vs_top; vslist != NULL; vslist = vslist->next) {
    792 		char *vn;
    793 		int off = 0;
    794 
    795 		vn = ksp->ks_name;
    796 
    797 		if ((off = strlen(vn) - NAMED_LEN) <= 0) {
    798 			off = 0;
    799 		}
    800 
    801 		if (strcmp(vslist->volname, &vn[off]) == 0) {
    802 			break;
    803 		}
    804 	}
    805 
    806 	if (vs_top != NULL && vslist == NULL) {
    807 		return (0);
    808 	} else {
    809 		return (1);
    810 	}
    811 }
    812