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 #include <signal.h>
32 #include <setjmp.h>
33
34 #include <kstat.h>
35
36 #include <sys/nsctl/rdc.h>
37 #include <sys/nsctl/rdc_io.h>
38 #include <sys/nsctl/rdc_bitmap.h>
39
40 #include "sdbc_stats.h"
41 #include "sndr_stats.h"
42
43 #include "dsstat.h"
44 #include "common.h"
45 #include "report.h"
46
47 static sndrstat_t *sndr_top;
48
49 void sndr_add_stat(sndrstat_t *);
50 sndrstat_t *sndr_del_stat(sndrstat_t *);
51
52 int sndr_value_check(sndrstat_t *);
53 int sndr_validate(kstat_t *);
54 int sndr_strcmp(char *, char *);
55 int sndr_vol_selected(kstat_t *);
56
57 void getType(kstat_t *, char *);
58 void getStat(kstat_t *, char *);
59 void getQueue(kstat_t *, char *);
60 void printQueueStats(int, kstat_t *);
61 float getSyncNeeded(kstat_t *);
62
63 static void update_sighandler(int);
64 static void discover_sighandler(int);
65
66 static sigjmp_buf update_env, discover_env;
67 static sig_atomic_t sig_raised = 0;
68 /*
69 * sndr_discover() - looks for new statistics to be monitored.
70 * Verifies that any statistics found are now already being
71 * monitored.
72 *
73 */
74 int
sndr_discover(kstat_ctl_t * kc)75 sndr_discover(kstat_ctl_t *kc)
76 {
77 static int validated = 0;
78 struct sigaction segv_act;
79 int rc = 0;
80 kstat_t *ksp;
81
82
83 (void) signal(SIGSEGV, discover_sighandler);
84 (void) sigaction(SIGSEGV, NULL, &segv_act);
85
86 /* Loop on all kstats */
87 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
88 int kinst;
89 char kname[KSTAT_STRLEN + 1];
90 sndrstat_t *cur;
91 sndrstat_t *sndrstat = NULL;
92 kstat_t *bmp_ksp;
93 kstat_t *sec_ksp;
94
95 /* Serach for SNDR set */
96 if (strcmp(ksp->ks_module, RDC_KSTAT_MODULE) != 0 ||
97 strcmp(ksp->ks_name, RDC_KSTAT_INFO) != 0) {
98 continue;
99 }
100
101 if (kstat_read(kc, ksp, NULL) == -1)
102 continue;
103
104 /*
105 * Validate kstat structure
106 */
107 if (! validated) {
108 if (sndr_validate(ksp))
109 return (EINVAL);
110
111 validated++;
112 }
113
114 /*
115 * Duplicate check
116 */
117 for (cur = sndr_top; cur != NULL; cur = cur->next) {
118 char *cur_vname, *tst_vname;
119 uint32_t cur_inst, tst_inst;
120
121 cur_vname = kstat_value(cur->pre_set, RDC_IKSTAT_FILE);
122 cur_inst = cur->pre_set->ks_instance;
123
124 tst_vname = kstat_value(ksp, RDC_IKSTAT_FILE);
125 tst_inst = ksp->ks_instance;
126
127 if (strcmp(cur_vname, tst_vname) == 0 &&
128 cur_inst == tst_inst)
129 goto next;
130 }
131
132 /*
133 * Initialize new record
134 */
135 sndrstat = (sndrstat_t *)calloc(1, sizeof (sndrstat_t));
136 kinst = ksp->ks_instance;
137
138 /*
139 * Set kstat
140 */
141 sndrstat->pre_set = kstat_retrieve(kc, ksp);
142
143 if (sndrstat->pre_set == NULL)
144 goto next;
145
146 sndrstat->collected |= GOT_SET_KSTAT;
147
148 /*
149 * Bitmap kstat
150 */
151 (void) sprintf(kname, "%s%d", RDC_KSTAT_BMPNAME, kinst);
152
153 bmp_ksp = kstat_lookup(kc, RDC_KSTAT_BMPNAME, kinst, kname);
154 sndrstat->pre_bmp = kstat_retrieve(kc, bmp_ksp);
155
156 if (sndrstat->pre_bmp == NULL)
157 goto next;
158
159 sndrstat->collected |= GOT_BMP_KSTAT;
160
161 /*
162 * Secondary kstat
163 */
164 (void) sprintf(kname, "%s%d", RDC_KSTAT_RDCNAME, kinst);
165
166 sec_ksp = kstat_lookup(kc, RDC_KSTAT_MODULE, kinst, kname);
167 sndrstat->pre_sec = kstat_retrieve(kc, sec_ksp);
168
169 if (sndrstat->pre_sec == NULL)
170 goto next;
171
172 sndrstat->collected |= GOT_SEC_KSTAT;
173
174 next:
175 /*
176 * Check if we got a complete set of stats
177 */
178 if (sndrstat == NULL)
179 continue;
180
181 if (SNDR_COMPLETE(sndrstat->collected)) {
182 (void) sndr_del_stat(sndrstat);
183 continue;
184 }
185
186 /*
187 * Add to linked list
188 */
189 sndr_add_stat(sndrstat);
190 }
191
192 (void) sigsetjmp(discover_env, 0);
193 if (sig_raised) {
194 sig_raised = 0;
195 rc = -1;
196 }
197 (void) sigaction(SIGSEGV, &segv_act, NULL);
198
199 return (rc);
200 }
201
202 void
discover_sighandler(int sig)203 discover_sighandler(int sig)
204 {
205 switch (sig) {
206 case SIGSEGV:
207 sig_raised = 1;
208 siglongjmp(discover_env, sig);
209 default:
210 exit(sig);
211 }
212 }
213
214 void
update_sighandler(int sig)215 update_sighandler(int sig)
216 {
217 switch (sig) {
218 case SIGSEGV:
219 sig_raised = 1;
220 siglongjmp(update_env, sig);
221 default:
222 exit(sig);
223 }
224 }
225
226 /*
227 * sndr_update() - updates all of the statistics currently being monitored.
228 *
229 */
230 int
sndr_update(kstat_ctl_t * kc)231 sndr_update(kstat_ctl_t *kc)
232 {
233 sndrstat_t *cur;
234 struct sigaction segv_act;
235 int rc = 0;
236
237 (void) signal(SIGSEGV, update_sighandler);
238 (void) sigaction(SIGSEGV, NULL, &segv_act);
239
240 for (cur = sndr_top; cur != NULL; cur = cur->next) {
241 int kinst;
242 char kname[KSTAT_STRLEN + 1];
243 kstat_t *ksp = NULL;
244 char *cur_vname, *tst_vname;
245
246 cur->collected = 0;
247
248 /*
249 * Age off old stats
250 */
251 if (cur->cur_set != NULL) {
252 kstat_free(cur->pre_set);
253 kstat_free(cur->pre_bmp);
254 kstat_free(cur->pre_sec);
255
256 cur->pre_set = cur->cur_set;
257 cur->pre_bmp = cur->cur_bmp;
258 cur->pre_sec = cur->cur_sec;
259 }
260
261 /*
262 * Set kstat
263 */
264 (void) strncpy(kname, cur->pre_set->ks_name, KSTAT_STRLEN);
265 kname[KSTAT_STRLEN] = '\0';
266
267 kinst = cur->pre_set->ks_instance;
268
269 ksp = kstat_lookup(kc, RDC_KSTAT_MODULE, kinst, kname);
270
271 if ((cur->cur_set = kstat_retrieve(kc, ksp)) == NULL)
272 continue;
273
274 cur->collected |= GOT_SET_KSTAT;
275
276 /*
277 * Validate set
278 */
279 cur_vname = kstat_value(cur->pre_set, RDC_IKSTAT_FILE);
280 tst_vname = kstat_value(cur->cur_set, RDC_IKSTAT_FILE);
281
282 if (strcmp(cur_vname, tst_vname) != 0)
283 continue;
284
285 /*
286 * Bitmap kstat
287 */
288 (void) sprintf(kname, "%s%d", RDC_KSTAT_BMPNAME, kinst);
289
290 ksp = kstat_lookup(kc, RDC_KSTAT_BMPNAME, kinst, kname);
291
292 if ((cur->cur_bmp = kstat_retrieve(kc, ksp)) == NULL)
293 continue;
294
295 cur->collected |= GOT_BMP_KSTAT;
296
297 /*
298 * Secondary kstat
299 */
300 (void) sprintf(kname, "%s%d", RDC_KSTAT_RDCNAME, kinst);
301
302 ksp = kstat_lookup(kc, RDC_KSTAT_MODULE, kinst, kname);
303
304 if ((cur->cur_sec = kstat_retrieve(kc, ksp)) == NULL)
305 continue;
306
307 cur->collected |= GOT_SEC_KSTAT;
308
309 }
310
311 (void) sigsetjmp(update_env, 0);
312 if (sig_raised) {
313 sig_raised = 0;
314 rc = -1;
315 }
316 (void) sigaction(SIGSEGV, &segv_act, NULL);
317
318 return (rc);
319 }
320
321 /*
322 * sndr_report() - outputs statistics for the statistics currently being
323 * monitored. Deletes statistics for volumes that have been disabled.
324 *
325 */
326 int
sndr_report()327 sndr_report()
328 {
329 int padsz;
330 char pad[20] = "";
331 sndrstat_t *cur, *pre = NULL;
332
333 if (sndr_top == NULL)
334 return (0);
335
336 /* Create padding string for secondary report lines */
337 padsz = 0;
338 if (dflags & FLAGS) {
339 padsz += STAT_HDR_SIZE;
340 padsz += STAT_HDR_SIZE;
341 }
342
343 if (dflags & ASYNC_QUEUE)
344 padsz += STAT_HDR_SIZE;
345
346 if (dflags & PCTS)
347 padsz += PCT_HDR_SIZE;
348
349 if (padsz) {
350 char fmt[20];
351 (void) sprintf(fmt, "%%%ds", padsz);
352 (void) sprintf(pad, fmt, " ");
353 }
354
355 for (cur = sndr_top; cur != NULL; ) { /*CSTYLED */
356 int first = 1;
357 char data[20] = "";
358
359 /* Check to see if this is this a complete */
360 if (SNDR_COMPLETE(cur->collected)) {
361 char *c;
362 char vn[NSC_MAXPATH + 1];
363 sndrstat_t *next;
364
365 /* notify user of set being disabled */
366 c = kstat_value(cur->pre_set, RDC_IKSTAT_SECFILE);
367 (void) strncpy(vn, c, NSC_MAXPATH);
368 vn[NSC_MAXPATH] = '\0';
369
370 (void) printf(DATA_C16, vn);
371 (void) printf(" %s\n", RDC_DISABLED);
372
373 next = sndr_del_stat(cur);
374
375 /* free memory and remove stat from list */
376 if (! pre)
377 cur = sndr_top = next;
378 else
379 cur = pre->next = next;
380
381 continue;
382 }
383
384 /* Check to see if the user specified this volume */
385 if (! sndr_vol_selected(cur->pre_set))
386 goto next;
387
388 /* Check to see if zflag applies */
389 if (zflag && sndr_value_check(cur) == 0)
390 goto next;
391
392 /* Calculate flags */
393 if (dflags & FLAGS) {
394 char c[STAT_HDR_SIZE];
395 char vtype[STAT_HDR_SIZE];
396 char vstat[STAT_HDR_SIZE];
397
398 getType(cur->cur_set, &c[0]);
399 (void) sprintf(vtype, DATA_C2, c);
400 (void) strcat(data, vtype);
401
402 getStat(cur->cur_set, &c[0]);
403 (void) sprintf(vstat, DATA_C2, c);
404 (void) strcat(data, vstat);
405 }
406
407 /* Async. queue statistics */
408 if (dflags & ASYNC_QUEUE) {
409 char c[STAT_HDR_SIZE];
410 char qtype[STAT_HDR_SIZE];
411
412 getQueue(cur->cur_set, &c[0]);
413 (void) sprintf(qtype, DATA_C2, c);
414 (void) strcat(data, qtype);
415 }
416
417 /* Calculate sync needed percentages */
418 if (dflags & PCTS) {
419 char snpct[10];
420
421 (void) sprintf(snpct, DATA_F62,
422 getSyncNeeded(cur->cur_set));
423 (void) strcat(data, snpct);
424 }
425
426 /* Output */
427 if (rflags & SNDR_NET) {
428 char *c;
429 char type[STAT_HDR_SIZE];
430 char vn[NAMED_LEN + 1];
431
432 getType(cur->cur_set, &type[0]);
433
434 if (type[0] == 'S') {
435 c = kstat_value(cur->pre_set,
436 RDC_IKSTAT_FILE);
437 } else {
438 c = kstat_value(cur->pre_set,
439 RDC_IKSTAT_SECFILE);
440 }
441
442 /* Only print last 15 characters */
443 if (strlen(c) >= NAMED_LEN) {
444 c += strlen(c) - NAMED_LEN;
445 }
446 (void) strncpy(vn, c, NAMED_LEN);
447 vn[NAMED_LEN] = '\0';
448
449 header();
450 (void) printf(DATA_C16, vn);
451 (void) printf("%s", data);
452 (void) printf(ROLE_INF_FMT, RDC_SECONDARY);
453
454 /* Async. queue statistics */
455 if (dflags & ASYNC_QUEUE)
456 printQueueStats(first, cur->cur_set);
457
458 io_report(cur->cur_sec, cur->pre_sec,
459 sdbc_getstat(vn));
460 (void) printf("\n");
461
462 if (first) {
463 (void) strcpy(data, strlen(pad) > 0 ? pad : "");
464 first = 0;
465 }
466 }
467
468 if (rflags & SNDR_BMP) {
469 char *c;
470 char vn[16];
471
472 c = kstat_value(cur->pre_set, RDC_IKSTAT_BITMAP);
473
474 /* Only print last 15 characters */
475 if (strlen(c) >= NAMED_LEN) {
476 c += strlen(c) - NAMED_LEN;
477 }
478 (void) strncpy(vn, c, NAMED_LEN);
479 vn[NAMED_LEN] = '\0';
480
481 header();
482 (void) printf(DATA_C16, vn);
483 (void) printf("%s", data);
484 (void) printf(ROLE_INF_FMT, RDC_BITMAP);
485
486 /* Async. queue statistics */
487 if (dflags & ASYNC_QUEUE)
488 printQueueStats(first, cur->cur_set);
489
490 io_report(cur->cur_bmp, cur->pre_bmp,
491 sdbc_getstat(vn));
492 (void) printf("\n");
493
494 if (first) {
495 (void) strcpy(data, strlen(pad) > 0 ? pad : "");
496 first = 0;
497 }
498 }
499 next:
500 pre = cur;
501 cur = cur->next;
502 }
503
504 return (0);
505 }
506
507 /*
508 * sndr_add_stat() - adds a fully populated sndrstat_t structure
509 * to the linked list of currently monitored kstats. The structure
510 * will be added in alphabetical order, using the volume name as the
511 * key.
512 *
513 * parameters
514 * sndrstat_t *sndrstat - to be added to the list.
515 *
516 */
517 void
sndr_add_stat(sndrstat_t * sndrstat)518 sndr_add_stat(sndrstat_t *sndrstat)
519 {
520
521 sndrstat_t *cur;
522
523 if (sndr_top == NULL) {
524 sndr_top = sndrstat;
525 return;
526 }
527
528 for (cur = sndr_top; cur != NULL; cur = cur->next) {
529 char *cur_vname, *nxt_vname, *tst_vname;
530
531 cur_vname = kstat_value(cur->pre_set, RDC_IKSTAT_FILE);
532 tst_vname = kstat_value(sndrstat->pre_set, RDC_IKSTAT_FILE);
533
534 if (strcmp(cur_vname, tst_vname) <= 0) {
535 /*
536 * If we get to the last item in the list, then just
537 * add this one to the end
538 */
539 if (cur->next == NULL) {
540 cur->next = sndrstat;
541 return;
542 }
543
544 nxt_vname = kstat_value(cur->next->pre_set,
545 RDC_IKSTAT_FILE);
546
547 if (strcmp(nxt_vname, tst_vname) > 0) {
548 sndrstat->next = cur->next;
549 cur->next = sndrstat;
550 return;
551 }
552 } else {
553 if (cur == sndr_top)
554 sndr_top = sndrstat;
555
556 sndrstat->next = cur;
557
558 return;
559 }
560 }
561 }
562
563 /*
564 * sndr_del_stat() - deallocate memory for the structure being
565 * passed in.
566 *
567 * parameters
568 * sndrstat_t *sndrstat - structure to be deallocated
569 *
570 * returns
571 * sndrstat_t * - pointer to the "next" structures in the
572 * linked list. May be NULL if we are removing the last
573 * structure in the linked list.
574 *
575 */
576 sndrstat_t *
sndr_del_stat(sndrstat_t * sndrstat)577 sndr_del_stat(sndrstat_t *sndrstat)
578 {
579
580 sndrstat_t *next = sndrstat->next;
581
582 kstat_free(sndrstat->pre_set);
583 kstat_free(sndrstat->pre_bmp);
584 kstat_free(sndrstat->pre_sec);
585 kstat_free(sndrstat->cur_set);
586 kstat_free(sndrstat->cur_bmp);
587 kstat_free(sndrstat->cur_sec);
588
589 free(sndrstat);
590
591 return (next);
592 }
593
594 /*
595 * sndr_value_check() - check to determine if any activity was registered
596 * on this volume by checking the previous stats vs. the current stats.
597 *
598 * parameters
599 * sndrstat_t *sndrstat - structure to be checked
600 *
601 * returns
602 * 0 - no activity
603 * 1 - activity
604 */
605 int
sndr_value_check(sndrstat_t * sndrstat)606 sndr_value_check(sndrstat_t *sndrstat)
607 {
608 if (SNDR_COMPLETE(sndrstat->collected))
609 return (1);
610
611 if (io_value_check(sndrstat->pre_bmp->ks_data,
612 sndrstat->cur_bmp->ks_data)) {
613 return (1);
614 }
615
616 if (io_value_check(sndrstat->pre_sec->ks_data,
617 sndrstat->cur_sec->ks_data)) {
618 return (1);
619 }
620
621 return (0);
622 }
623
624 /*
625 * sndr_validate() - validates the fields required by dsstat exist in
626 * the kstat_t structure passed in. This check keeps dsstat from
627 * core dumping if the kstat_named_t structures change in any of the
628 * services that dsstat monitors.
629 *
630 * paramaters
631 * kstat_t *ksp - kstat_t structure to check. The ks_data field
632 * should have been populated with a call to kstat_read()
633 *
634 * returns
635 * 0 - all fields are contained in the kstat
636 * 1 - a field required by dsstat is not in the kstat
637 */
638 int
sndr_validate(kstat_t * ksp)639 sndr_validate(kstat_t *ksp)
640 {
641 if (! kstat_value(ksp, RDC_IKSTAT_FILE) ||
642 ! kstat_value(ksp, RDC_IKSTAT_FLAGS) ||
643 ! kstat_value(ksp, RDC_IKSTAT_SYNCFLAGS) ||
644 ! kstat_value(ksp, RDC_IKSTAT_BMPFLAGS) ||
645 ! kstat_value(ksp, RDC_IKSTAT_VOLSIZE) ||
646 ! kstat_value(ksp, RDC_IKSTAT_BITSSET) ||
647 ! kstat_value(ksp, RDC_IKSTAT_QUEUE_TYPE) ||
648 ! kstat_value(ksp, RDC_IKSTAT_ASYNC_ITEMS) ||
649 ! kstat_value(ksp, RDC_IKSTAT_ASYNC_BLOCKS) ||
650 ! kstat_value(ksp, RDC_IKSTAT_ASYNC_ITEM_HWM) ||
651 ! kstat_value(ksp, RDC_IKSTAT_ASYNC_BLOCK_HWM))
652 return (1);
653
654 return (0);
655 }
656
657 void
getType(kstat_t * ksp,char * vtype)658 getType(kstat_t *ksp, char *vtype)
659 {
660 uint32_t *set_flags;
661
662 set_flags = kstat_value(ksp, RDC_IKSTAT_FLAGS);
663
664 if (*set_flags & RDC_PRIMARY)
665 (void) strcpy(vtype, "P");
666 else
667 (void) strcpy(vtype, "S");
668 }
669
670 void
getStat(kstat_t * ksp,char * vstat)671 getStat(kstat_t *ksp, char *vstat)
672 {
673 uint32_t *set_flags;
674 uint32_t *syn_flags;
675 uint32_t *bmp_flags;
676
677 set_flags = kstat_value(ksp, RDC_IKSTAT_FLAGS);
678 syn_flags = kstat_value(ksp, RDC_IKSTAT_SYNCFLAGS);
679 bmp_flags = kstat_value(ksp, RDC_IKSTAT_BMPFLAGS);
680
681 (void) strcpy(vstat, "R");
682
683 if (*set_flags & RDC_SYNCING) {
684 if (*set_flags & RDC_SLAVE)
685 if (*set_flags & RDC_PRIMARY)
686 (void) strcpy(vstat, "RS");
687 else
688 (void) strcpy(vstat, "SY");
689 else
690 if (*set_flags & RDC_PRIMARY)
691 (void) strcpy(vstat, "SY");
692 else
693 (void) strcpy(vstat, "RS");
694 }
695
696 if (*set_flags & RDC_LOGGING) {
697 (void) strcpy(vstat, "L");
698
699 if (*set_flags & RDC_QUEUING)
700 (void) strcpy(vstat, "Q");
701
702 if (*set_flags & RDC_DISKQ_FAILED)
703 (void) strcpy(vstat, "QF");
704
705 if (*syn_flags & RDC_SYNC_NEEDED)
706 (void) strcpy(vstat, "SN");
707
708 if (*syn_flags & RDC_RSYNC_NEEDED)
709 (void) strcpy(vstat, "RN");
710 }
711
712 if (*syn_flags & RDC_FCAL_FAILED)
713 (void) strcpy(vstat, "FF");
714
715 if (*bmp_flags & RDC_BMP_FAILED)
716 (void) strcpy(vstat, "BF");
717
718 if (*syn_flags & RDC_VOL_FAILED)
719 (void) strcpy(vstat, "VF");
720 }
721
722 void
getQueue(kstat_t * ksp,char * vqueue)723 getQueue(kstat_t *ksp, char *vqueue)
724 {
725 char *qtype;
726
727 (void) strcpy(vqueue, "-");
728
729 qtype = kstat_value(ksp, RDC_IKSTAT_QUEUE_TYPE);
730
731 if (strcmp(qtype, "memory") == 0)
732 (void) strcpy(vqueue, "M");
733
734 if (strcmp(qtype, "disk") == 0)
735 (void) strcpy(vqueue, "D");
736 }
737
738 float
getSyncNeeded(kstat_t * ksp)739 getSyncNeeded(kstat_t *ksp)
740 {
741 uint32_t *volsize, *bitsset;
742 uint32_t bits, segs;
743 float pct;
744
745 volsize = kstat_value(ksp, RDC_IKSTAT_VOLSIZE);
746 bitsset = kstat_value(ksp, RDC_IKSTAT_BITSSET);
747
748 segs = FBA_TO_LOG_LEN(*volsize);
749 bits = *bitsset > 0 ? *bitsset : 0;
750
751 pct = segs ? ((float)bits/(float)segs) : 0.0;
752 pct *= 100;
753
754 return (pct);
755 }
756
757 /*
758 * Special handling for compatibility.
759 * "dsstat -s <set>" allows set name to be the last 15 chars,
760 * due to 15 characters limit of old kstat information.
761 *
762 * return 0 if:
763 * 1) full and partial are same
764 * 2) partial is the last 15 chars of full
765 */
766 int
sndr_strcmp(char * full,char * partial)767 sndr_strcmp(char *full, char *partial)
768 {
769 char *f = full;
770 int rc;
771
772 rc = strcmp(full, partial);
773
774 if (rc != 0 &&
775 (strlen(partial) == NAMED_LEN) &&
776 (strlen(full) > NAMED_LEN)) {
777 f += strlen(full) - NAMED_LEN;
778 rc = strncmp(f, partial, NAMED_LEN);
779 }
780
781 return (rc);
782 }
783
784 int
sndr_vol_selected(kstat_t * ksp)785 sndr_vol_selected(kstat_t *ksp)
786 {
787 vslist_t *vslist = vs_top;
788
789 for (vslist = vs_top; vslist != NULL; vslist = vslist->next) {
790 char *vn;
791 char *vh;
792
793 /* If no host specified, check local only */
794 if (vslist->volhost == NULL) {
795 vn = kstat_value(ksp, RDC_IKSTAT_FILE);
796
797 if (sndr_strcmp(vn, vslist->volname))
798 continue;
799 else
800 break;
801 }
802
803 /* Check primary */
804 vn = kstat_value(ksp, RDC_IKSTAT_FILE);
805 vh = kstat_value(ksp, RDC_IKSTAT_PRIMARY_HOST);
806
807 if (sndr_strcmp(vn, vslist->volname) == 0 &&
808 sndr_strcmp(vh, vslist->volhost) == 0)
809 break;
810
811 /* Check secondary */
812 vn = kstat_value(ksp, RDC_IKSTAT_SECFILE);
813 vh = kstat_value(ksp, RDC_IKSTAT_SECONDARY_HOST);
814
815 if (sndr_strcmp(vn, vslist->volname) == 0 &&
816 sndr_strcmp(vh, vslist->volhost) == 0)
817 break;
818 }
819
820 if (vs_top != NULL && vslist == NULL)
821 return (0);
822
823 return (1);
824 }
825
826 void
printQueueStats(int first,kstat_t * cur_set)827 printQueueStats(int first, kstat_t *cur_set)
828 {
829 uint32_t *val;
830
831 if (! first) {
832 /* Filler for async. queue fields */
833 (void) printf(TPS_HDR_FMT, NO_INFO);
834 (void) printf(KPS_HDR_FMT, NO_INFO);
835 (void) printf(TPS_HDR_FMT, NO_INFO);
836 (void) printf(KPS_HDR_FMT, NO_INFO);
837
838 return;
839 }
840
841 val = (uint32_t *)kstat_value(cur_set, RDC_IKSTAT_ASYNC_ITEMS);
842 (void) printf(TPS_INF_FMT, *val);
843
844 val = (uint32_t *)kstat_value(cur_set, RDC_IKSTAT_ASYNC_BLOCKS);
845 (void) printf(KPS_INF_FMT, (float)(*val / 2));
846
847 val = (uint32_t *)kstat_value(cur_set, RDC_IKSTAT_ASYNC_ITEM_HWM);
848 (void) printf(TPS_INF_FMT, *val);
849
850 val = (uint32_t *)kstat_value(cur_set, RDC_IKSTAT_ASYNC_BLOCK_HWM);
851 (void) printf(KPS_INF_FMT, (float)(*val / 2));
852 }
853