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 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 (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 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 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 * 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 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 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 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 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 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 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 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 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 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 }