xref: /titanic_51/usr/src/cmd/avs/dsstat/ii_stats.c (revision dcda19f50b2b80bfc622fff718ac04fb0e1cb670)
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 2008 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->ks_data,
498 				    cur->pre_mst->ks_data,
499 				    sdbc_getstat(vol + offset));
500 			}
501 
502 			printf("\n");
503 
504 			if (first) {
505 				strcpy(data, strlen(pad) > 0 ? pad : "");
506 				first = 0;
507 			}
508 		}
509 
510 		/* Shadow statistics */
511 		if (rflags & IIMG_SHD) {
512 			char *c;
513 			char vol[(NAMED_LEN * 4) + 1] = {0};
514 			int offset;
515 
516 			c = kstat_value(cur->cur_set, DSW_SKSTAT_SETA);
517 			strncat(vol, c, NAMED_LEN);
518 			c = kstat_value(cur->cur_set, DSW_SKSTAT_SETB);
519 			strncat(vol, c, NAMED_LEN);
520 			c = kstat_value(cur->cur_set, DSW_SKSTAT_SETC);
521 			strncat(vol, c, NAMED_LEN);
522 			c = kstat_value(cur->cur_set, DSW_SKSTAT_SETD);
523 			strncat(vol, c, NAMED_LEN);
524 
525 			offset = strlen(vol) - NAMED_LEN;
526 
527 			if (offset < 0)
528 				offset = 0;
529 
530 			header();
531 			printf(DATA_C16, vol + offset);
532 			printf("%s", data);
533 			printf(ROLE_INF_FMT, II_SHADOW);
534 
535 			if (*flags & DSW_SHDOFFLINE) {
536 				printf(" <<offline>>");
537 				linesout++;
538 			} else {
539 				io_report(cur->cur_shd->ks_data,
540 				    cur->pre_shd->ks_data,
541 				    sdbc_getstat(vol + offset));
542 			}
543 
544 			printf("\n");
545 
546 			if (first) {
547 				strcpy(data, strlen(pad) > 0 ? pad : "");
548 				first = 0;
549 			}
550 		}
551 
552 		/* Bitmap statistics */
553 		if (rflags & IIMG_BMP) {
554 			char *c;
555 			char vol[(NAMED_LEN * 4) + 1] = {0};
556 			int offset;
557 
558 			c = kstat_value(cur->cur_set, DSW_SKSTAT_BMPA);
559 			strncat(vol, c, NAMED_LEN);
560 			c = kstat_value(cur->cur_set, DSW_SKSTAT_BMPB);
561 			strncat(vol, c, NAMED_LEN);
562 			c = kstat_value(cur->cur_set, DSW_SKSTAT_BMPC);
563 			strncat(vol, c, NAMED_LEN);
564 			c = kstat_value(cur->cur_set, DSW_SKSTAT_BMPD);
565 			strncat(vol, c, NAMED_LEN);
566 
567 			offset = strlen(vol) - NAMED_LEN;
568 
569 			if (offset < 0)
570 				offset = 0;
571 
572 			header();
573 			printf(DATA_C16, vol + offset);
574 			printf("%s", data);
575 			printf(ROLE_INF_FMT, II_BITMAP);
576 
577 			if (*flags & DSW_BMPOFFLINE) {
578 				printf(" <<offline>>");
579 				linesout++;
580 			} else {
581 				io_report(cur->cur_bmp->ks_data,
582 				    cur->pre_bmp->ks_data,
583 				    sdbc_getstat(vol + offset));
584 			}
585 			printf("\n");
586 
587 			if (first) {
588 				strcpy(data, strlen(pad) > 0 ? pad : "");
589 				first = 0;
590 			}
591 		}
592 
593 		/* Overflow statistics */
594 		if (rflags & IIMG_OVR) {
595 			char *c;
596 			char msg[20] = {0};
597 			char vol[(NAMED_LEN * 4) + 1] = {0};
598 			int offset;
599 
600 			if (cur->cur_ovr == NULL && cur->pre_ovr != NULL)
601 				strcpy(msg, " <<attached>>");
602 
603 			if (! (cur->collected & GOT_OVRSTAT))
604 				strcpy(msg, " <<not attached>>");
605 
606 			c = kstat_value(cur->cur_set, DSW_SKSTAT_OVRA);
607 			strncpy(vol, c, NAMED_LEN);
608 			c = kstat_value(cur->cur_set, DSW_SKSTAT_OVRB);
609 			strncat(vol, c, NAMED_LEN);
610 			c = kstat_value(cur->cur_set, DSW_SKSTAT_OVRC);
611 			strncat(vol, c, NAMED_LEN);
612 			c = kstat_value(cur->cur_set, DSW_SKSTAT_OVRD);
613 			strncat(vol, c, NAMED_LEN);
614 
615 			offset = strlen(vol) - NAMED_LEN;
616 
617 			if (offset < 0)
618 				offset = 0;
619 
620 			header();
621 			printf(DATA_C16, vol + offset);
622 			printf("%s", data);
623 			printf(ROLE_INF_FMT, II_OVERFLOW);
624 
625 			if (strlen(msg)) {
626 				printf("%s\n", msg);
627 				linesout++;
628 				goto next;
629 			}
630 
631 			if (*flags & DSW_OVROFFLINE) {
632 				printf(" <<offline>>");
633 				linesout++;
634 			} else {
635 				io_report(cur->cur_ovr->ks_data,
636 				    cur->pre_ovr->ks_data,
637 				    sdbc_getstat(vol + offset));
638 			}
639 
640 			printf("\n");
641 
642 			if (first) {
643 				strcpy(data, strlen(pad) > 0 ? pad : "");
644 				first = 0;
645 			}
646 		}
647 
648 
649 next:
650 		pre = cur;
651 		cur = cur->next;
652 	}
653 
654 	return (0);
655 }
656 
657 /*
658  * ii_add_stat() - adds a fully populated iistat_t structure
659  * to the linked list of currently monitored kstats.  The structure
660  * will be added in alphabetical order, using the volume name of
661  * the shadow volume as the key.
662  *
663  */
664 void
665 ii_add_stat(iistat_t *iistat)
666 {
667 
668 	iistat_t *cur;
669 
670 	if (ii_top == NULL) {
671 		ii_top = iistat;
672 		return;
673 	}
674 
675 	for (cur = ii_top; cur != NULL; cur = cur->next) {
676 		if (strcmp(cur->pre_set->ks_name,
677 		    iistat->pre_set->ks_name) <= 0) {
678 			/*
679 			 * If we get to the last item in the list, then just
680 			 * add this one to the end
681 			 */
682 			if (cur->next == NULL) {
683 				cur->next = iistat;
684 				return;
685 			}
686 
687 			if (strcmp(cur->next->pre_set->ks_name,
688 			    iistat->pre_set->ks_name) > 0) {
689 				iistat->next = cur->next;
690 				cur->next = iistat;
691 				return;
692 			}
693 		} else {
694 			if (cur == ii_top)
695 				ii_top = iistat;
696 
697 			iistat->next = cur;
698 
699 			return;
700 		}
701 	}
702 }
703 
704 /*
705  * ii_del_stat() - deallocate memory for the structure being
706  * passed in.
707  *
708  * parameters
709  * 	iistat_t *iistat - structure to be deallocated
710  *
711  * returns
712  * 	iistat_t * - pointer to the "next" structures in the
713  * 	linked list. May be NULL if we are removing the last
714  * 	structure in the linked list.
715  *
716  */
717 iistat_t *
718 ii_del_stat(iistat_t *iistat)
719 {
720 
721 	iistat_t *next = iistat->next;
722 
723 	kstat_free(iistat->pre_set);
724 	kstat_free(iistat->pre_mst);
725 	kstat_free(iistat->pre_shd);
726 	kstat_free(iistat->pre_bmp);
727 	kstat_free(iistat->pre_ovr);
728 	kstat_free(iistat->cur_set);
729 	kstat_free(iistat->cur_mst);
730 	kstat_free(iistat->cur_shd);
731 	kstat_free(iistat->cur_bmp);
732 	kstat_free(iistat->cur_ovr);
733 
734 	free(iistat);
735 
736 	return (next);
737 }
738 
739 int
740 ii_value_check(iistat_t *iistat)
741 {
742 	if (IIMG_COMPLETE(iistat->collected))
743 		return (1);
744 
745 	if (io_value_check(iistat->pre_mst->ks_data,
746 	    iistat->cur_mst->ks_data)) {
747 		return (1);
748 	}
749 
750 	if (io_value_check(iistat->pre_shd->ks_data,
751 	    iistat->cur_shd->ks_data)) {
752 		return (1);
753 	}
754 
755 	if (io_value_check(iistat->pre_bmp->ks_data,
756 	    iistat->cur_bmp->ks_data)) {
757 		return (1);
758 	}
759 
760 	if (iistat->pre_ovr && iistat->cur_ovr) {
761 		if (io_value_check(iistat->pre_ovr->ks_data,
762 		    iistat->cur_ovr->ks_data)) {
763 			return (1);
764 		}
765 	}
766 
767 	return (0);
768 }
769 
770 int
771 ii_validate(kstat_t *ksp)
772 {
773 	if (! kstat_value(ksp, DSW_SKSTAT_MSTIO) ||
774 	    ! kstat_value(ksp, DSW_SKSTAT_SHDIO) ||
775 	    ! kstat_value(ksp, DSW_SKSTAT_BMPIO) ||
776 	    ! kstat_value(ksp, DSW_SKSTAT_OVRIO) ||
777 	    ! kstat_value(ksp, DSW_SKSTAT_FLAGS) ||
778 	    ! kstat_value(ksp, DSW_SKSTAT_MSTA) ||
779 	    ! kstat_value(ksp, DSW_SKSTAT_SETA) ||
780 	    ! kstat_value(ksp, DSW_SKSTAT_BMPA) ||
781 	    ! kstat_value(ksp, DSW_SKSTAT_OVRA) ||
782 	    ! kstat_value(ksp, DSW_SKSTAT_SHDBITS) ||
783 	    ! kstat_value(ksp, DSW_SKSTAT_COPYBITS) ||
784 	    ! kstat_value(ksp, DSW_SKSTAT_SIZE))
785 		return (1);
786 
787 	return (0);
788 }
789 
790 int
791 ii_vol_selected(kstat_t *ksp)
792 {
793 	vslist_t *vslist = vs_top;
794 
795 	for (vslist = vs_top; vslist != NULL; vslist = vslist->next) {
796 		char *vn;
797 		int off = 0;
798 
799 		vn = ksp->ks_name;
800 
801 		if ((off = strlen(vn) - NAMED_LEN) <= 0) {
802 			off = 0;
803 		}
804 
805 		if (strcmp(vslist->volname, &vn[off]) == 0) {
806 			break;
807 		}
808 	}
809 
810 	if (vs_top != NULL && vslist == NULL) {
811 		return (0);
812 	} else {
813 		return (1);
814 	}
815 }
816