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.
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.
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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
32 #include <sys/mutex.h>
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>
41 #include "sdbc_stats.h"
48 static iistat_t
*ii_top
= NULL
;
50 void ii_add_stat(iistat_t
*);
51 iistat_t
*ii_del_stat(iistat_t
*);
53 int ii_value_check(iistat_t
*iistat
);
54 int ii_validate(kstat_t
*ksp
);
55 int ii_vol_selected(kstat_t
*);
58 * ii_discover() - looks for new statistics to be monitored.
59 * Verifies that any statistics found are now already being
64 ii_discover(kstat_ctl_t
*kc
)
66 static int validated
= 0;
70 /* Loop on all kstats */
71 for (ksp
= kc
->kc_chain
; ksp
; ksp
= ksp
->ks_next
) {
74 iistat_t
*iistat
= NULL
;
80 /* Search for II set */
81 if (strcmp(ksp
->ks_class
, II_KSTAT_CLASS
) != 0)
84 if (kstat_read(kc
, ksp
, NULL
) == -1)
88 * Validate kstat structure
100 for (cur
= ii_top
; cur
!= NULL
; cur
= cur
->next
) {
101 char *cur_vname
, *tst_vname
;
102 uint32_t cur_inst
, tst_inst
;
104 cur_vname
= cur
->pre_set
->ks_name
;
105 cur_inst
= cur
->pre_set
->ks_instance
;
107 tst_vname
= ksp
->ks_name
;
108 tst_inst
= ksp
->ks_instance
;
110 if (strcmp(cur_vname
, tst_vname
) == 0 &&
111 cur_inst
== tst_inst
)
116 * Initialize new record
118 iistat
= (iistat_t
*)calloc(1, sizeof (iistat_t
));
123 iistat
->pre_set
= kstat_retrieve(kc
, ksp
);
125 if (iistat
->pre_set
== NULL
)
128 iistat
->collected
|= GOT_SETSTAT
;
133 kname
= kstat_value(iistat
->pre_set
, DSW_SKSTAT_MSTIO
);
135 mst_ksp
= kstat_lookup(kc
, II_KSTAT_MODULE
, -1, kname
);
136 iistat
->pre_mst
= kstat_retrieve(kc
, mst_ksp
);
138 if (iistat
->pre_mst
== NULL
)
141 iistat
->collected
|= GOT_MSTSTAT
;
146 kname
= kstat_value(iistat
->pre_set
, DSW_SKSTAT_SHDIO
);
148 shd_ksp
= kstat_lookup(kc
, II_KSTAT_MODULE
, -1, kname
);
149 iistat
->pre_shd
= kstat_retrieve(kc
, shd_ksp
);
151 if (iistat
->pre_shd
== NULL
)
154 iistat
->collected
|= GOT_SHDSTAT
;
159 kname
= kstat_value(iistat
->pre_set
, DSW_SKSTAT_BMPIO
);
161 bmp_ksp
= kstat_lookup(kc
, II_KSTAT_MODULE
, -1, kname
);
162 iistat
->pre_bmp
= kstat_retrieve(kc
, bmp_ksp
);
164 if (iistat
->pre_bmp
== NULL
)
167 iistat
->collected
|= GOT_BMPSTAT
;
172 kname
= kstat_value(iistat
->pre_set
, DSW_SKSTAT_OVRIO
);
174 ovr_ksp
= kstat_lookup(kc
, II_KSTAT_MODULE
, -1, kname
);
175 iistat
->pre_ovr
= kstat_retrieve(kc
, ovr_ksp
);
177 if (iistat
->pre_ovr
== NULL
)
180 iistat
->collected
|= GOT_OVRSTAT
;
184 * Check if we got a complete set of stats
189 if (IIMG_COMPLETE(iistat
->collected
)) {
190 (void) ii_del_stat(iistat
);
207 * ii_update() - updates all of the statistics currently being monitored.
211 ii_update(kstat_ctl_t
*kc
)
215 for (cur
= ii_top
; cur
!= NULL
; cur
= cur
->next
) {
216 char volname
[KSTAT_STRLEN
+ 1];
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
);
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
;
237 if (cur
->cur_ovr
!= NULL
) {
238 kstat_free(cur
->pre_ovr
);
239 cur
->pre_ovr
= cur
->cur_ovr
;
246 (void) strncpy(volname
, cur
->pre_set
->ks_name
, KSTAT_STRLEN
);
247 volname
[KSTAT_STRLEN
] = '\0';
249 ksp
= kstat_lookup(kc
, II_KSTAT_MODULE
, -1, volname
);
251 if ((cur
->cur_set
= kstat_retrieve(kc
, ksp
)) == NULL
)
254 cur
->collected
|= GOT_SETSTAT
;
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
)
266 kname
= kstat_value(cur
->cur_set
, DSW_SKSTAT_MSTIO
);
268 ksp
= kstat_lookup(kc
, II_KSTAT_MODULE
, -1, kname
);
270 if ((cur
->cur_mst
= kstat_retrieve(kc
, ksp
)) == NULL
)
273 cur
->collected
|= GOT_MSTSTAT
;
278 kname
= kstat_value(cur
->cur_set
, DSW_SKSTAT_SHDIO
);
280 ksp
= kstat_lookup(kc
, II_KSTAT_MODULE
, -1, kname
);
282 if ((cur
->cur_shd
= kstat_retrieve(kc
, ksp
)) == NULL
)
285 cur
->collected
|= GOT_SHDSTAT
;
290 kname
= kstat_value(cur
->pre_set
, DSW_SKSTAT_BMPIO
);
292 ksp
= kstat_lookup(kc
, II_KSTAT_MODULE
, -1, kname
);
294 if ((cur
->cur_bmp
= kstat_retrieve(kc
, ksp
)) == NULL
)
297 cur
->collected
|= GOT_BMPSTAT
;
302 kname
= kstat_value(cur
->cur_set
, DSW_SKSTAT_OVRIO
);
304 ksp
= kstat_lookup(kc
, II_KSTAT_MODULE
, -1, kname
);
307 if (cur
->pre_ovr
!= NULL
) {
308 kstat_free(cur
->pre_ovr
);
311 if (cur
->cur_ovr
!= NULL
) {
312 kstat_free(cur
->cur_ovr
);
318 if (cur
->pre_ovr
== NULL
) {
319 if ((cur
->pre_ovr
= kstat_retrieve(kc
, ksp
)) == NULL
)
322 if ((cur
->cur_ovr
= kstat_retrieve(kc
, ksp
)) == NULL
)
326 cur
->collected
|= GOT_OVRSTAT
;
333 * ii_report() - outputs statistics for the statistics currently being
334 * monitored. Deletes statistics for volumes that have been disabled.
343 iistat_t
*cur
, *pre
= NULL
;
345 if (ii_top
== NULL
) {
349 /* Create padding string for secondary report lines */
350 if (dflags
& FLAGS
) {
351 padsz
+= STAT_HDR_SIZE
;
352 padsz
+= STAT_HDR_SIZE
;
356 padsz
+= PCT_HDR_SIZE
;
360 (void) sprintf(fmt
, "%%%ds", padsz
);
361 (void) sprintf(pad
, fmt
, "");
364 for (cur
= ii_top
; cur
; /* CSTYLED */) {
368 /* Check to see if this is this a complete */
369 if (IIMG_COMPLETE(cur
->collected
)) {
371 char vol
[(NAMED_LEN
* 4) + 1] = {0};
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
);
385 offset
= strlen(vol
) - NAMED_LEN
;
390 (void) printf(DATA_C16
, vol
+ offset
);
391 (void) printf(" %s\n", II_DISABLED
);
393 /* free memory and remove stat from list */
394 next
= ii_del_stat(cur
);
399 cur
= pre
->next
= next
;
404 /* Check to see if the user specified this volume */
405 if (! ii_vol_selected(cur
->pre_set
))
408 /* Check to see if zflag applies */
409 if (zflag
&& ii_value_check(cur
) == 0)
412 /* Calculate flags */
413 flags
= kstat_value(cur
->cur_set
, DSW_SKSTAT_FLAGS
);
415 if (dflags
& FLAGS
) {
417 char c
[STAT_HDR_SIZE
];
418 char vtype
[STAT_HDR_SIZE
];
419 char vstat
[STAT_HDR_SIZE
];
421 if (*flags
& DSW_GOLDEN
)
422 (void) strcpy(c
, II_INDEPENDENT
);
424 (void) strcpy(c
, II_DEPENDENT
);
426 (void) sprintf(vtype
, DATA_C2
, c
);
427 (void) strcat(data
, vtype
);
429 if (*flags
& DSW_COPYINGP
)
430 (void) strcpy(c
, II_COPYING
);
432 (void) strcpy(c
, NO_INFO
);
435 (void) sprintf(vstat
, DATA_C2
, c
);
436 (void) strcat(data
, vstat
);
439 /* Calculate sync needed precentage */
449 kstat_value(cur
->cur_set
, DSW_SKSTAT_COPYBITS
);
452 kstat_value(cur
->cur_set
, DSW_SKSTAT_SHDBITS
);
455 kstat_value(cur
->cur_set
, DSW_SKSTAT_SIZE
);
457 *volsize
/= DSW_SIZE
;
459 chkbits
= *cpybits
>= *shdbits
? cpybits
: shdbits
;
461 pct
= ((float)*chkbits
/ *volsize
) * 100.0;
463 (void) sprintf(snpct
, DATA_F62
, pct
);
465 (void) strcat(data
, snpct
);
468 /* Master statistics */
469 if (rflags
& IIMG_MST
) {
471 char vol
[(NAMED_LEN
* 4) + 1] = {0};
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
);
483 offset
= strlen(vol
) - NAMED_LEN
;
489 (void) printf(DATA_C16
, vol
+ offset
);
490 (void) printf("%s", data
);
491 (void) printf(ROLE_INF_FMT
, II_MASTER
);
493 if (*flags
& DSW_MSTOFFLINE
) {
494 (void) printf(" <<offline>>");
497 io_report(cur
->cur_mst
, cur
->pre_mst
,
498 sdbc_getstat(vol
+ offset
));
504 (void) strcpy(data
, strlen(pad
) > 0 ? pad
: "");
509 /* Shadow statistics */
510 if (rflags
& IIMG_SHD
) {
512 char vol
[(NAMED_LEN
* 4) + 1] = {0};
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
);
524 offset
= strlen(vol
) - NAMED_LEN
;
530 (void) printf(DATA_C16
, vol
+ offset
);
531 (void) printf("%s", data
);
532 (void) printf(ROLE_INF_FMT
, II_SHADOW
);
534 if (*flags
& DSW_SHDOFFLINE
) {
535 (void) printf(" <<offline>>");
538 io_report(cur
->cur_shd
, cur
->pre_shd
,
539 sdbc_getstat(vol
+ offset
));
545 (void) strcpy(data
, strlen(pad
) > 0 ? pad
: "");
550 /* Bitmap statistics */
551 if (rflags
& IIMG_BMP
) {
553 char vol
[(NAMED_LEN
* 4) + 1] = {0};
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
);
565 offset
= strlen(vol
) - NAMED_LEN
;
571 (void) printf(DATA_C16
, vol
+ offset
);
572 (void) printf("%s", data
);
573 (void) printf(ROLE_INF_FMT
, II_BITMAP
);
575 if (*flags
& DSW_BMPOFFLINE
) {
576 (void) printf(" <<offline>>");
579 io_report(cur
->cur_bmp
, cur
->pre_bmp
,
580 sdbc_getstat(vol
+ offset
));
585 (void) strcpy(data
, strlen(pad
) > 0 ? pad
: "");
590 /* Overflow statistics */
591 if (rflags
& IIMG_OVR
) {
594 char vol
[(NAMED_LEN
* 4) + 1] = {0};
597 if (cur
->cur_ovr
== NULL
&& cur
->pre_ovr
!= NULL
)
598 (void) strcpy(msg
, " <<attached>>");
600 if (! (cur
->collected
& GOT_OVRSTAT
))
601 (void) strcpy(msg
, " <<not attached>>");
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
);
612 offset
= strlen(vol
) - NAMED_LEN
;
618 (void) printf(DATA_C16
, vol
+ offset
);
619 (void) printf("%s", data
);
620 (void) printf(ROLE_INF_FMT
, II_OVERFLOW
);
623 (void) printf("%s\n", msg
);
628 if (*flags
& DSW_OVROFFLINE
) {
629 (void) printf(" <<offline>>");
632 io_report(cur
->cur_ovr
, cur
->pre_ovr
,
633 sdbc_getstat(vol
+ offset
));
639 (void) strcpy(data
, strlen(pad
) > 0 ? pad
: "");
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.
661 ii_add_stat(iistat_t
*iistat
)
666 if (ii_top
== NULL
) {
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) {
675 * If we get to the last item in the list, then just
676 * add this one to the end
678 if (cur
->next
== NULL
) {
683 if (strcmp(cur
->next
->pre_set
->ks_name
,
684 iistat
->pre_set
->ks_name
) > 0) {
685 iistat
->next
= cur
->next
;
701 * ii_del_stat() - deallocate memory for the structure being
705 * iistat_t *iistat - structure to be deallocated
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.
714 ii_del_stat(iistat_t
*iistat
)
717 iistat_t
*next
= iistat
->next
;
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
);
736 ii_value_check(iistat_t
*iistat
)
738 if (IIMG_COMPLETE(iistat
->collected
))
741 if (io_value_check(iistat
->pre_mst
->ks_data
,
742 iistat
->cur_mst
->ks_data
)) {
746 if (io_value_check(iistat
->pre_shd
->ks_data
,
747 iistat
->cur_shd
->ks_data
)) {
751 if (io_value_check(iistat
->pre_bmp
->ks_data
,
752 iistat
->cur_bmp
->ks_data
)) {
756 if (iistat
->pre_ovr
&& iistat
->cur_ovr
) {
757 if (io_value_check(iistat
->pre_ovr
->ks_data
,
758 iistat
->cur_ovr
->ks_data
)) {
767 ii_validate(kstat_t
*ksp
)
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
))
787 ii_vol_selected(kstat_t
*ksp
)
789 vslist_t
*vslist
= vs_top
;
791 for (vslist
= vs_top
; vslist
!= NULL
; vslist
= vslist
->next
) {
797 if ((off
= strlen(vn
) - NAMED_LEN
) <= 0) {
801 if (strcmp(vslist
->volname
, &vn
[off
]) == 0) {
806 if (vs_top
!= NULL
&& vslist
== NULL
) {