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 <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
48static iistat_t *ii_top = NULL;
49
50void ii_add_stat(iistat_t *);
51iistat_t *ii_del_stat(iistat_t *);
52
53int ii_value_check(iistat_t *iistat);
54int ii_validate(kstat_t *ksp);
55int 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 */
63int
64ii_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
182next:
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 */
210int
211ii_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		(void) 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 */
337int
338ii_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		(void) sprintf(fmt, "%%%ds", padsz);
361		(void) 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			(void) strncpy(vol, c, NAMED_LEN);
378			c = kstat_value(cur->pre_set, DSW_SKSTAT_SETB);
379			(void) strncat(vol, c, NAMED_LEN);
380			c = kstat_value(cur->pre_set, DSW_SKSTAT_SETC);
381			(void) strncat(vol, c, NAMED_LEN);
382			c = kstat_value(cur->pre_set, DSW_SKSTAT_SETD);
383			(void) strncat(vol, c, NAMED_LEN);
384
385			offset = strlen(vol) - NAMED_LEN;
386
387			if (offset < 0)
388				offset = 0;
389
390			(void) printf(DATA_C16, vol + offset);
391			(void) 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				(void) strcpy(c, II_INDEPENDENT);
423			else
424				(void) strcpy(c, II_DEPENDENT);
425
426			(void) sprintf(vtype, DATA_C2, c);
427			(void) strcat(data, vtype);
428
429			if (*flags & DSW_COPYINGP)
430				(void) strcpy(c, II_COPYING);
431			else
432				(void) strcpy(c, NO_INFO);
433
434
435			(void) sprintf(vstat, DATA_C2, c);
436			(void) 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			(void) sprintf(snpct, DATA_F62, pct);
464
465			(void) 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			(void) strncat(vol, c, NAMED_LEN);
476			c = kstat_value(cur->cur_set, DSW_SKSTAT_MSTB);
477			(void) strncat(vol, c, NAMED_LEN);
478			c = kstat_value(cur->cur_set, DSW_SKSTAT_MSTC);
479			(void) strncat(vol, c, NAMED_LEN);
480			c = kstat_value(cur->cur_set, DSW_SKSTAT_MSTD);
481			(void) strncat(vol, c, NAMED_LEN);
482
483			offset = strlen(vol) - NAMED_LEN;
484
485			if (offset < 0)
486				offset = 0;
487
488			header();
489			(void) printf(DATA_C16, vol + offset);
490			(void) printf("%s", data);
491			(void) printf(ROLE_INF_FMT, II_MASTER);
492
493			if (*flags & DSW_MSTOFFLINE) {
494				(void) printf(" <<offline>>");
495				linesout++;
496			} else {
497				io_report(cur->cur_mst, cur->pre_mst,
498				    sdbc_getstat(vol + offset));
499			}
500
501			(void) printf("\n");
502
503			if (first) {
504				(void) 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			(void) strncat(vol, c, NAMED_LEN);
517			c = kstat_value(cur->cur_set, DSW_SKSTAT_SETB);
518			(void) strncat(vol, c, NAMED_LEN);
519			c = kstat_value(cur->cur_set, DSW_SKSTAT_SETC);
520			(void) strncat(vol, c, NAMED_LEN);
521			c = kstat_value(cur->cur_set, DSW_SKSTAT_SETD);
522			(void) strncat(vol, c, NAMED_LEN);
523
524			offset = strlen(vol) - NAMED_LEN;
525
526			if (offset < 0)
527				offset = 0;
528
529			header();
530			(void) printf(DATA_C16, vol + offset);
531			(void) printf("%s", data);
532			(void) printf(ROLE_INF_FMT, II_SHADOW);
533
534			if (*flags & DSW_SHDOFFLINE) {
535				(void) printf(" <<offline>>");
536				linesout++;
537			} else {
538				io_report(cur->cur_shd, cur->pre_shd,
539				    sdbc_getstat(vol + offset));
540			}
541
542			(void) printf("\n");
543
544			if (first) {
545				(void) 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			(void) strncat(vol, c, NAMED_LEN);
558			c = kstat_value(cur->cur_set, DSW_SKSTAT_BMPB);
559			(void) strncat(vol, c, NAMED_LEN);
560			c = kstat_value(cur->cur_set, DSW_SKSTAT_BMPC);
561			(void) strncat(vol, c, NAMED_LEN);
562			c = kstat_value(cur->cur_set, DSW_SKSTAT_BMPD);
563			(void) strncat(vol, c, NAMED_LEN);
564
565			offset = strlen(vol) - NAMED_LEN;
566
567			if (offset < 0)
568				offset = 0;
569
570			header();
571			(void) printf(DATA_C16, vol + offset);
572			(void) printf("%s", data);
573			(void) printf(ROLE_INF_FMT, II_BITMAP);
574
575			if (*flags & DSW_BMPOFFLINE) {
576				(void) printf(" <<offline>>");
577				linesout++;
578			} else {
579				io_report(cur->cur_bmp, cur->pre_bmp,
580				    sdbc_getstat(vol + offset));
581			}
582			(void) printf("\n");
583
584			if (first) {
585				(void) 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				(void) strcpy(msg, " <<attached>>");
599
600			if (! (cur->collected & GOT_OVRSTAT))
601				(void) strcpy(msg, " <<not attached>>");
602
603			c = kstat_value(cur->cur_set, DSW_SKSTAT_OVRA);
604			(void) strncpy(vol, c, NAMED_LEN);
605			c = kstat_value(cur->cur_set, DSW_SKSTAT_OVRB);
606			(void) strncat(vol, c, NAMED_LEN);
607			c = kstat_value(cur->cur_set, DSW_SKSTAT_OVRC);
608			(void) strncat(vol, c, NAMED_LEN);
609			c = kstat_value(cur->cur_set, DSW_SKSTAT_OVRD);
610			(void) strncat(vol, c, NAMED_LEN);
611
612			offset = strlen(vol) - NAMED_LEN;
613
614			if (offset < 0)
615				offset = 0;
616
617			header();
618			(void) printf(DATA_C16, vol + offset);
619			(void) printf("%s", data);
620			(void) printf(ROLE_INF_FMT, II_OVERFLOW);
621
622			if (strlen(msg)) {
623				(void) printf("%s\n", msg);
624				linesout++;
625				goto next;
626			}
627
628			if (*flags & DSW_OVROFFLINE) {
629				(void) printf(" <<offline>>");
630				linesout++;
631			} else {
632				io_report(cur->cur_ovr, cur->pre_ovr,
633				    sdbc_getstat(vol + offset));
634			}
635
636			(void) printf("\n");
637
638			if (first) {
639				(void) strcpy(data, strlen(pad) > 0 ? pad : "");
640				first = 0;
641			}
642		}
643
644
645next:
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 */
660void
661ii_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 */
713iistat_t *
714ii_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
735int
736ii_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
766int
767ii_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
786int
787ii_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