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 #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 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 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 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 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 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 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 sprintf(fmt, "%%%ds", padsz); 352 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 strncpy(vn, c, NSC_MAXPATH); 368 vn[NSC_MAXPATH] = '\0'; 369 370 printf(DATA_C16, vn); 371 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 sprintf(vtype, DATA_C2, c); 400 strcat(data, vtype); 401 402 getStat(cur->cur_set, &c[0]); 403 sprintf(vstat, DATA_C2, c); 404 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 sprintf(qtype, DATA_C2, c); 414 strcat(data, qtype); 415 } 416 417 /* Calculate sync needed percentages */ 418 if (dflags & PCTS) { 419 char snpct[10]; 420 421 sprintf(snpct, DATA_F62, getSyncNeeded(cur->cur_set)); 422 strcat(data, snpct); 423 } 424 425 /* Output */ 426 if (rflags & SNDR_NET) { 427 char *c; 428 char type[STAT_HDR_SIZE]; 429 char vn[NAMED_LEN + 1]; 430 431 getType(cur->cur_set, &type[0]); 432 433 if (type[0] == 'S') { 434 c = kstat_value(cur->pre_set, 435 RDC_IKSTAT_FILE); 436 } else { 437 c = kstat_value(cur->pre_set, 438 RDC_IKSTAT_SECFILE); 439 } 440 441 /* Only print last 15 characters */ 442 if (strlen(c) >= NAMED_LEN) { 443 c += strlen(c) - NAMED_LEN; 444 } 445 strncpy(vn, c, NAMED_LEN); 446 vn[NAMED_LEN] = '\0'; 447 448 header(); 449 printf(DATA_C16, vn); 450 printf("%s", data); 451 printf(ROLE_INF_FMT, RDC_SECONDARY); 452 453 /* Async. queue statistics */ 454 if (dflags & ASYNC_QUEUE) 455 printQueueStats(first, cur->cur_set); 456 457 io_report(cur->cur_sec->ks_data, cur->pre_sec->ks_data, 458 sdbc_getstat(vn)); 459 printf("\n"); 460 461 if (first) { 462 strcpy(data, strlen(pad) > 0 ? pad : ""); 463 first = 0; 464 } 465 } 466 467 if (rflags & SNDR_BMP) { 468 char *c; 469 char vn[16]; 470 471 c = kstat_value(cur->pre_set, RDC_IKSTAT_BITMAP); 472 473 /* Only print last 15 characters */ 474 if (strlen(c) >= NAMED_LEN) { 475 c += strlen(c) - NAMED_LEN; 476 } 477 strncpy(vn, c, NAMED_LEN); 478 vn[NAMED_LEN] = '\0'; 479 480 header(); 481 printf(DATA_C16, vn); 482 printf("%s", data); 483 printf(ROLE_INF_FMT, RDC_BITMAP); 484 485 /* Async. queue statistics */ 486 if (dflags & ASYNC_QUEUE) 487 printQueueStats(first, cur->cur_set); 488 489 io_report(cur->cur_bmp->ks_data, cur->pre_bmp->ks_data, 490 sdbc_getstat(vn)); 491 printf("\n"); 492 493 if (first) { 494 strcpy(data, strlen(pad) > 0 ? pad : ""); 495 first = 0; 496 } 497 } 498 next: 499 pre = cur; 500 cur = cur->next; 501 } 502 503 return (0); 504 } 505 506 /* 507 * sndr_add_stat() - adds a fully populated sndrstat_t structure 508 * to the linked list of currently monitored kstats. The structure 509 * will be added in alphabetical order, using the volume name as the 510 * key. 511 * 512 * parameters 513 * sndrstat_t *sndrstat - to be added to the list. 514 * 515 */ 516 void 517 sndr_add_stat(sndrstat_t *sndrstat) 518 { 519 520 sndrstat_t *cur; 521 522 if (sndr_top == NULL) { 523 sndr_top = sndrstat; 524 return; 525 } 526 527 for (cur = sndr_top; cur != NULL; cur = cur->next) { 528 char *cur_vname, *nxt_vname, *tst_vname; 529 530 cur_vname = kstat_value(cur->pre_set, RDC_IKSTAT_FILE); 531 tst_vname = kstat_value(sndrstat->pre_set, RDC_IKSTAT_FILE); 532 533 if (strcmp(cur_vname, tst_vname) <= 0) { 534 /* 535 * If we get to the last item in the list, then just 536 * add this one to the end 537 */ 538 if (cur->next == NULL) { 539 cur->next = sndrstat; 540 return; 541 } 542 543 nxt_vname = kstat_value(cur->next->pre_set, 544 RDC_IKSTAT_FILE); 545 546 if (strcmp(nxt_vname, tst_vname) > 0) { 547 sndrstat->next = cur->next; 548 cur->next = sndrstat; 549 return; 550 } 551 } else { 552 if (cur == sndr_top) 553 sndr_top = sndrstat; 554 555 sndrstat->next = cur; 556 557 return; 558 } 559 } 560 } 561 562 /* 563 * sndr_del_stat() - deallocate memory for the structure being 564 * passed in. 565 * 566 * parameters 567 * sndrstat_t *sndrstat - structure to be deallocated 568 * 569 * returns 570 * sndrstat_t * - pointer to the "next" structures in the 571 * linked list. May be NULL if we are removing the last 572 * structure in the linked list. 573 * 574 */ 575 sndrstat_t * 576 sndr_del_stat(sndrstat_t *sndrstat) 577 { 578 579 sndrstat_t *next = sndrstat->next; 580 581 kstat_free(sndrstat->pre_set); 582 kstat_free(sndrstat->pre_bmp); 583 kstat_free(sndrstat->pre_sec); 584 kstat_free(sndrstat->cur_set); 585 kstat_free(sndrstat->cur_bmp); 586 kstat_free(sndrstat->cur_sec); 587 588 free(sndrstat); 589 590 return (next); 591 } 592 593 /* 594 * sndr_value_check() - check to determine if any activity was registered 595 * on this volume by checking the previous stats vs. the current stats. 596 * 597 * parameters 598 * sndrstat_t *sndrstat - structure to be checked 599 * 600 * returns 601 * 0 - no activity 602 * 1 - activity 603 */ 604 int 605 sndr_value_check(sndrstat_t *sndrstat) 606 { 607 if (SNDR_COMPLETE(sndrstat->collected)) 608 return (1); 609 610 if (io_value_check(sndrstat->pre_bmp->ks_data, 611 sndrstat->cur_bmp->ks_data)) { 612 return (1); 613 } 614 615 if (io_value_check(sndrstat->pre_sec->ks_data, 616 sndrstat->cur_sec->ks_data)) { 617 return (1); 618 } 619 620 return (0); 621 } 622 623 /* 624 * sndr_validate() - validates the fields required by dsstat exist in 625 * the kstat_t structure passed in. This check keeps dsstat from 626 * core dumping if the kstat_named_t structures change in any of the 627 * services that dsstat monitors. 628 * 629 * paramaters 630 * kstat_t *ksp - kstat_t structure to check. The ks_data field 631 * should have been populated with a call to kstat_read() 632 * 633 * returns 634 * 0 - all fields are contained in the kstat 635 * 1 - a field required by dsstat is not in the kstat 636 */ 637 int 638 sndr_validate(kstat_t *ksp) 639 { 640 if (! kstat_value(ksp, RDC_IKSTAT_FILE) || 641 ! kstat_value(ksp, RDC_IKSTAT_FLAGS) || 642 ! kstat_value(ksp, RDC_IKSTAT_SYNCFLAGS) || 643 ! kstat_value(ksp, RDC_IKSTAT_BMPFLAGS) || 644 ! kstat_value(ksp, RDC_IKSTAT_VOLSIZE) || 645 ! kstat_value(ksp, RDC_IKSTAT_BITSSET) || 646 ! kstat_value(ksp, RDC_IKSTAT_QUEUE_TYPE) || 647 ! kstat_value(ksp, RDC_IKSTAT_ASYNC_ITEMS) || 648 ! kstat_value(ksp, RDC_IKSTAT_ASYNC_BLOCKS) || 649 ! kstat_value(ksp, RDC_IKSTAT_ASYNC_ITEM_HWM) || 650 ! kstat_value(ksp, RDC_IKSTAT_ASYNC_BLOCK_HWM)) 651 return (1); 652 653 return (0); 654 } 655 656 void 657 getType(kstat_t *ksp, char *vtype) 658 { 659 uint32_t *set_flags; 660 661 set_flags = kstat_value(ksp, RDC_IKSTAT_FLAGS); 662 663 if (*set_flags & RDC_PRIMARY) 664 (void) strcpy(vtype, "P"); 665 else 666 (void) strcpy(vtype, "S"); 667 } 668 669 void 670 getStat(kstat_t *ksp, char *vstat) 671 { 672 uint32_t *set_flags; 673 uint32_t *syn_flags; 674 uint32_t *bmp_flags; 675 676 set_flags = kstat_value(ksp, RDC_IKSTAT_FLAGS); 677 syn_flags = kstat_value(ksp, RDC_IKSTAT_SYNCFLAGS); 678 bmp_flags = kstat_value(ksp, RDC_IKSTAT_BMPFLAGS); 679 680 (void) strcpy(vstat, "R"); 681 682 if (*set_flags & RDC_SYNCING) { 683 if (*set_flags & RDC_SLAVE) 684 if (*set_flags & RDC_PRIMARY) 685 (void) strcpy(vstat, "RS"); 686 else 687 (void) strcpy(vstat, "SY"); 688 else 689 if (*set_flags & RDC_PRIMARY) 690 (void) strcpy(vstat, "SY"); 691 else 692 (void) strcpy(vstat, "RS"); 693 } 694 695 if (*set_flags & RDC_LOGGING) { 696 (void) strcpy(vstat, "L"); 697 698 if (*set_flags & RDC_QUEUING) 699 (void) strcpy(vstat, "Q"); 700 701 if (*set_flags & RDC_DISKQ_FAILED) 702 (void) strcpy(vstat, "QF"); 703 704 if (*syn_flags & RDC_SYNC_NEEDED) 705 (void) strcpy(vstat, "SN"); 706 707 if (*syn_flags & RDC_RSYNC_NEEDED) 708 (void) strcpy(vstat, "RN"); 709 } 710 711 if (*syn_flags & RDC_FCAL_FAILED) 712 (void) strcpy(vstat, "FF"); 713 714 if (*bmp_flags & RDC_BMP_FAILED) 715 (void) strcpy(vstat, "BF"); 716 717 if (*syn_flags & RDC_VOL_FAILED) 718 (void) strcpy(vstat, "VF"); 719 } 720 721 void 722 getQueue(kstat_t *ksp, char *vqueue) 723 { 724 char *qtype; 725 726 (void) strcpy(vqueue, "-"); 727 728 qtype = kstat_value(ksp, RDC_IKSTAT_QUEUE_TYPE); 729 730 if (strcmp(qtype, "memory") == 0) 731 (void) strcpy(vqueue, "M"); 732 733 if (strcmp(qtype, "disk") == 0) 734 (void) strcpy(vqueue, "D"); 735 } 736 737 float 738 getSyncNeeded(kstat_t *ksp) 739 { 740 uint32_t *volsize, *bitsset; 741 uint32_t bits, segs; 742 float pct; 743 744 volsize = kstat_value(ksp, RDC_IKSTAT_VOLSIZE); 745 bitsset = kstat_value(ksp, RDC_IKSTAT_BITSSET); 746 747 segs = FBA_TO_LOG_LEN(*volsize); 748 bits = *bitsset > 0 ? *bitsset : 0; 749 750 pct = segs ? ((float)bits/(float)segs) : 0.0; 751 pct *= 100; 752 753 return (pct); 754 } 755 756 /* 757 * Special handling for compatibility. 758 * "dsstat -s <set>" allows set name to be the last 15 chars, 759 * due to 15 characters limit of old kstat information. 760 * 761 * return 0 if: 762 * 1) full and partial are same 763 * 2) partial is the last 15 chars of full 764 */ 765 int 766 sndr_strcmp(char *full, char *partial) 767 { 768 char *f = full; 769 int rc; 770 771 rc = strcmp(full, partial); 772 773 if (rc != 0 && 774 (strlen(partial) == NAMED_LEN) && 775 (strlen(full) > NAMED_LEN)) { 776 f += strlen(full) - NAMED_LEN; 777 rc = strncmp(f, partial, NAMED_LEN); 778 } 779 780 return (rc); 781 } 782 783 int 784 sndr_vol_selected(kstat_t *ksp) 785 { 786 vslist_t *vslist = vs_top; 787 788 for (vslist = vs_top; vslist != NULL; vslist = vslist->next) { 789 char *vn; 790 char *vh; 791 792 /* If no host specified, check local only */ 793 if (vslist->volhost == NULL) { 794 vn = kstat_value(ksp, RDC_IKSTAT_FILE); 795 796 if (sndr_strcmp(vn, vslist->volname)) 797 continue; 798 else 799 break; 800 } 801 802 /* Check primary */ 803 vn = kstat_value(ksp, RDC_IKSTAT_FILE); 804 vh = kstat_value(ksp, RDC_IKSTAT_PRIMARY_HOST); 805 806 if (sndr_strcmp(vn, vslist->volname) == 0 && 807 sndr_strcmp(vh, vslist->volhost) == 0) 808 break; 809 810 /* Check secondary */ 811 vn = kstat_value(ksp, RDC_IKSTAT_SECFILE); 812 vh = kstat_value(ksp, RDC_IKSTAT_SECONDARY_HOST); 813 814 if (sndr_strcmp(vn, vslist->volname) == 0 && 815 sndr_strcmp(vh, vslist->volhost) == 0) 816 break; 817 } 818 819 if (vs_top != NULL && vslist == NULL) 820 return (0); 821 822 return (1); 823 } 824 825 void 826 printQueueStats(int first, kstat_t *cur_set) 827 { 828 uint32_t *val; 829 830 if (! first) { 831 /* Filler for async. queue fields */ 832 printf(TPS_HDR_FMT, NO_INFO); 833 printf(KPS_HDR_FMT, NO_INFO); 834 printf(TPS_HDR_FMT, NO_INFO); 835 printf(KPS_HDR_FMT, NO_INFO); 836 837 return; 838 } 839 840 val = (uint32_t *)kstat_value(cur_set, RDC_IKSTAT_ASYNC_ITEMS); 841 printf(TPS_INF_FMT, *val); 842 843 val = (uint32_t *)kstat_value(cur_set, RDC_IKSTAT_ASYNC_BLOCKS); 844 printf(KPS_INF_FMT, (float)(*val / 2)); 845 846 val = (uint32_t *)kstat_value(cur_set, RDC_IKSTAT_ASYNC_ITEM_HWM); 847 printf(TPS_INF_FMT, *val); 848 849 val = (uint32_t *)kstat_value(cur_set, RDC_IKSTAT_ASYNC_BLOCK_HWM); 850 printf(KPS_INF_FMT, (float)(*val / 2)); 851 } 852