8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / avs / dsstat / ii_stats.c
blobe37ea891cb7f6684863fd805de4bed981c76cb3a
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <errno.h>
32 #include <sys/mutex.h>
34 #include <kstat.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"
42 #include "ii_stats.h"
44 #include "dsstat.h"
45 #include "common.h"
46 #include "report.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
60 * monitored.
63 int
64 ii_discover(kstat_ctl_t *kc)
66 static int validated = 0;
68 kstat_t *ksp;
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;
80 /* Search for II set */
81 if (strcmp(ksp->ks_class, II_KSTAT_CLASS) != 0)
82 continue;
84 if (kstat_read(kc, ksp, NULL) == -1)
85 continue;
88 * Validate kstat structure
90 if (! validated) {
91 if (ii_validate(ksp))
92 return (EINVAL);
94 validated++;
98 * Duplicate check
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)
112 goto next;
116 * Initialize new record
118 iistat = (iistat_t *)calloc(1, sizeof (iistat_t));
121 * Set kstat
123 iistat->pre_set = kstat_retrieve(kc, ksp);
125 if (iistat->pre_set == NULL)
126 goto next;
128 iistat->collected |= GOT_SETSTAT;
131 * Master kstat
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)
139 goto next;
141 iistat->collected |= GOT_MSTSTAT;
144 * Shadow kstat
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)
152 goto next;
154 iistat->collected |= GOT_SHDSTAT;
157 * Bitmap kstat
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)
165 goto next;
167 iistat->collected |= GOT_BMPSTAT;
170 * Overflow kstat
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)
178 goto next;
180 iistat->collected |= GOT_OVRSTAT;
182 next:
184 * Check if we got a complete set of stats
186 if (iistat == NULL)
187 continue;
189 if (IIMG_COMPLETE(iistat->collected)) {
190 (void) ii_del_stat(iistat);
191 continue;
195 * Add to linked list
197 ii_add_stat(iistat);
200 if (ii_top == NULL)
201 return (EAGAIN);
203 return (0);
207 * ii_update() - updates all of the statistics currently being monitored.
211 ii_update(kstat_ctl_t *kc)
213 iistat_t *cur;
215 for (cur = ii_top; cur != NULL; cur = cur->next) {
216 char volname[KSTAT_STRLEN + 1];
217 char *kname;
219 kstat_t *ksp = NULL;
221 cur->collected = 0;
224 * Age off old stats
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;
244 * Set kstat
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)
252 continue;
254 cur->collected |= GOT_SETSTAT;
257 * Validate set
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;
264 * Master kstat
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)
271 continue;
273 cur->collected |= GOT_MSTSTAT;
276 * Shadow kstat
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)
283 continue;
285 cur->collected |= GOT_SHDSTAT;
288 * Bitmap kstat
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)
295 continue;
297 cur->collected |= GOT_BMPSTAT;
300 * Overflow kstat
302 kname = kstat_value(cur->cur_set, DSW_SKSTAT_OVRIO);
304 ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname);
306 if (ksp == NULL) {
307 if (cur->pre_ovr != NULL) {
308 kstat_free(cur->pre_ovr);
309 cur->pre_ovr = NULL;
311 if (cur->cur_ovr != NULL) {
312 kstat_free(cur->cur_ovr);
313 cur->cur_ovr = NULL;
315 continue;
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;
326 cur->collected |= GOT_OVRSTAT;
329 return (0);
333 * ii_report() - outputs statistics for the statistics currently being
334 * monitored. Deletes statistics for volumes that have been disabled.
338 ii_report()
340 uint32_t *flags;
341 int padsz = 0;
342 char pad[20] = {0};
343 iistat_t *cur, *pre = NULL;
345 if (ii_top == NULL) {
346 return (0);
349 /* Create padding string for secondary report lines */
350 if (dflags & FLAGS) {
351 padsz += STAT_HDR_SIZE;
352 padsz += STAT_HDR_SIZE;
355 if (dflags & PCTS)
356 padsz += PCT_HDR_SIZE;
358 if (padsz) {
359 char fmt[20];
360 (void) sprintf(fmt, "%%%ds", padsz);
361 (void) sprintf(pad, fmt, "");
364 for (cur = ii_top; cur; /* CSTYLED */) {
365 int first = 1;
366 char data[20] = {0};
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;
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;
387 if (offset < 0)
388 offset = 0;
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);
396 if (! pre)
397 cur = ii_top = next;
398 else
399 cur = pre->next = next;
401 continue;
404 /* Check to see if the user specified this volume */
405 if (! ii_vol_selected(cur->pre_set))
406 goto next;
408 /* Check to see if zflag applies */
409 if (zflag && ii_value_check(cur) == 0)
410 goto next;
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);
423 else
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);
431 else
432 (void) strcpy(c, NO_INFO);
435 (void) sprintf(vstat, DATA_C2, c);
436 (void) strcat(data, vstat);
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;
448 cpybits =
449 kstat_value(cur->cur_set, DSW_SKSTAT_COPYBITS);
451 shdbits =
452 kstat_value(cur->cur_set, DSW_SKSTAT_SHDBITS);
454 volsize =
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) {
470 char *c;
471 char vol[(NAMED_LEN * 4) + 1] = {0};
472 int offset;
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;
485 if (offset < 0)
486 offset = 0;
488 header();
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>>");
495 linesout++;
496 } else {
497 io_report(cur->cur_mst, cur->pre_mst,
498 sdbc_getstat(vol + offset));
501 (void) printf("\n");
503 if (first) {
504 (void) strcpy(data, strlen(pad) > 0 ? pad : "");
505 first = 0;
509 /* Shadow statistics */
510 if (rflags & IIMG_SHD) {
511 char *c;
512 char vol[(NAMED_LEN * 4) + 1] = {0};
513 int offset;
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;
526 if (offset < 0)
527 offset = 0;
529 header();
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>>");
536 linesout++;
537 } else {
538 io_report(cur->cur_shd, cur->pre_shd,
539 sdbc_getstat(vol + offset));
542 (void) printf("\n");
544 if (first) {
545 (void) strcpy(data, strlen(pad) > 0 ? pad : "");
546 first = 0;
550 /* Bitmap statistics */
551 if (rflags & IIMG_BMP) {
552 char *c;
553 char vol[(NAMED_LEN * 4) + 1] = {0};
554 int offset;
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;
567 if (offset < 0)
568 offset = 0;
570 header();
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>>");
577 linesout++;
578 } else {
579 io_report(cur->cur_bmp, cur->pre_bmp,
580 sdbc_getstat(vol + offset));
582 (void) printf("\n");
584 if (first) {
585 (void) strcpy(data, strlen(pad) > 0 ? pad : "");
586 first = 0;
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;
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;
614 if (offset < 0)
615 offset = 0;
617 header();
618 (void) printf(DATA_C16, vol + offset);
619 (void) printf("%s", data);
620 (void) printf(ROLE_INF_FMT, II_OVERFLOW);
622 if (strlen(msg)) {
623 (void) printf("%s\n", msg);
624 linesout++;
625 goto next;
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));
636 (void) printf("\n");
638 if (first) {
639 (void) strcpy(data, strlen(pad) > 0 ? pad : "");
640 first = 0;
645 next:
646 pre = cur;
647 cur = cur->next;
650 return (0);
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.
660 void
661 ii_add_stat(iistat_t *iistat)
664 iistat_t *cur;
666 if (ii_top == NULL) {
667 ii_top = iistat;
668 return;
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) {
679 cur->next = iistat;
680 return;
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;
689 } else {
690 if (cur == ii_top)
691 ii_top = iistat;
693 iistat->next = cur;
695 return;
701 * ii_del_stat() - deallocate memory for the structure being
702 * passed in.
704 * parameters
705 * iistat_t *iistat - structure to be deallocated
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.
713 iistat_t *
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);
730 free(iistat);
732 return (next);
736 ii_value_check(iistat_t *iistat)
738 if (IIMG_COMPLETE(iistat->collected))
739 return (1);
741 if (io_value_check(iistat->pre_mst->ks_data,
742 iistat->cur_mst->ks_data)) {
743 return (1);
746 if (io_value_check(iistat->pre_shd->ks_data,
747 iistat->cur_shd->ks_data)) {
748 return (1);
751 if (io_value_check(iistat->pre_bmp->ks_data,
752 iistat->cur_bmp->ks_data)) {
753 return (1);
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);
763 return (0);
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))
781 return (1);
783 return (0);
787 ii_vol_selected(kstat_t *ksp)
789 vslist_t *vslist = vs_top;
791 for (vslist = vs_top; vslist != NULL; vslist = vslist->next) {
792 char *vn;
793 int off = 0;
795 vn = ksp->ks_name;
797 if ((off = strlen(vn) - NAMED_LEN) <= 0) {
798 off = 0;
801 if (strcmp(vslist->volname, &vn[off]) == 0) {
802 break;
806 if (vs_top != NULL && vslist == NULL) {
807 return (0);
808 } else {
809 return (1);