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 32 #include <sys/mutex.h> 33 34 #include <kstat.h> 35 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> 40 41 #include "sdbc_stats.h" 42 #include "ii_stats.h" 43 44 #include "dsstat.h" 45 #include "common.h" 46 #include "report.h" 47 48 static iistat_t *ii_top = NULL; 49 50 void ii_add_stat(iistat_t *); 51 iistat_t *ii_del_stat(iistat_t *); 52 53 int ii_value_check(iistat_t *iistat); 54 int ii_validate(kstat_t *ksp); 55 int ii_vol_selected(kstat_t *); 56 57 /* 58 * ii_discover() - looks for new statistics to be monitored. 59 * Verifies that any statistics found are now already being 60 * monitored. 61 * 62 */ 63 int 64 ii_discover(kstat_ctl_t *kc) 65 { 66 static int validated = 0; 67 68 kstat_t *ksp; 69 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; 79 80 /* Search for II set */ 81 if (strcmp(ksp->ks_class, II_KSTAT_CLASS) != 0) 82 continue; 83 84 if (kstat_read(kc, ksp, NULL) == -1) 85 continue; 86 87 /* 88 * Validate kstat structure 89 */ 90 if (! validated) { 91 if (ii_validate(ksp)) 92 return (EINVAL); 93 94 validated++; 95 } 96 97 /* 98 * Duplicate check 99 */ 100 for (cur = ii_top; cur != NULL; cur = cur->next) { 101 char *cur_vname, *tst_vname; 102 uint32_t cur_inst, tst_inst; 103 104 cur_vname = cur->pre_set->ks_name; 105 cur_inst = cur->pre_set->ks_instance; 106 107 tst_vname = ksp->ks_name; 108 tst_inst = ksp->ks_instance; 109 110 if (strcmp(cur_vname, tst_vname) == 0 && 111 cur_inst == tst_inst) 112 goto next; 113 } 114 115 /* 116 * Initialize new record 117 */ 118 iistat = (iistat_t *)calloc(1, sizeof (iistat_t)); 119 120 /* 121 * Set kstat 122 */ 123 iistat->pre_set = kstat_retrieve(kc, ksp); 124 125 if (iistat->pre_set == NULL) 126 goto next; 127 128 iistat->collected |= GOT_SETSTAT; 129 130 /* 131 * Master kstat 132 */ 133 kname = kstat_value(iistat->pre_set, DSW_SKSTAT_MSTIO); 134 135 mst_ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname); 136 iistat->pre_mst = kstat_retrieve(kc, mst_ksp); 137 138 if (iistat->pre_mst == NULL) 139 goto next; 140 141 iistat->collected |= GOT_MSTSTAT; 142 143 /* 144 * Shadow kstat 145 */ 146 kname = kstat_value(iistat->pre_set, DSW_SKSTAT_SHDIO); 147 148 shd_ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname); 149 iistat->pre_shd = kstat_retrieve(kc, shd_ksp); 150 151 if (iistat->pre_shd == NULL) 152 goto next; 153 154 iistat->collected |= GOT_SHDSTAT; 155 156 /* 157 * Bitmap kstat 158 */ 159 kname = kstat_value(iistat->pre_set, DSW_SKSTAT_BMPIO); 160 161 bmp_ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname); 162 iistat->pre_bmp = kstat_retrieve(kc, bmp_ksp); 163 164 if (iistat->pre_bmp == NULL) 165 goto next; 166 167 iistat->collected |= GOT_BMPSTAT; 168 169 /* 170 * Overflow kstat 171 */ 172 kname = kstat_value(iistat->pre_set, DSW_SKSTAT_OVRIO); 173 174 ovr_ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname); 175 iistat->pre_ovr = kstat_retrieve(kc, ovr_ksp); 176 177 if (iistat->pre_ovr == NULL) 178 goto next; 179 180 iistat->collected |= GOT_OVRSTAT; 181 182 next: 183 /* 184 * Check if we got a complete set of stats 185 */ 186 if (iistat == NULL) 187 continue; 188 189 if (IIMG_COMPLETE(iistat->collected)) { 190 (void) ii_del_stat(iistat); 191 continue; 192 } 193 194 /* 195 * Add to linked list 196 */ 197 ii_add_stat(iistat); 198 } 199 200 if (ii_top == NULL) 201 return (EAGAIN); 202 203 return (0); 204 } 205 206 /* 207 * ii_update() - updates all of the statistics currently being monitored. 208 * 209 */ 210 int 211 ii_update(kstat_ctl_t *kc) 212 { 213 iistat_t *cur; 214 215 for (cur = ii_top; cur != NULL; cur = cur->next) { 216 char volname[KSTAT_STRLEN + 1]; 217 char *kname; 218 219 kstat_t *ksp = NULL; 220 221 cur->collected = 0; 222 223 /* 224 * Age off old stats 225 */ 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); 231 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; 236 237 if (cur->cur_ovr != NULL) { 238 kstat_free(cur->pre_ovr); 239 cur->pre_ovr = cur->cur_ovr; 240 } 241 } 242 243 /* 244 * Set kstat 245 */ 246 (void) strncpy(volname, cur->pre_set->ks_name, KSTAT_STRLEN); 247 volname[KSTAT_STRLEN] = '\0'; 248 249 ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, volname); 250 251 if ((cur->cur_set = kstat_retrieve(kc, ksp)) == NULL) 252 continue; 253 254 cur->collected |= GOT_SETSTAT; 255 256 /* 257 * Validate set 258 */ 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; 262 263 /* 264 * Master kstat 265 */ 266 kname = kstat_value(cur->cur_set, DSW_SKSTAT_MSTIO); 267 268 ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname); 269 270 if ((cur->cur_mst = kstat_retrieve(kc, ksp)) == NULL) 271 continue; 272 273 cur->collected |= GOT_MSTSTAT; 274 275 /* 276 * Shadow kstat 277 */ 278 kname = kstat_value(cur->cur_set, DSW_SKSTAT_SHDIO); 279 280 ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname); 281 282 if ((cur->cur_shd = kstat_retrieve(kc, ksp)) == NULL) 283 continue; 284 285 cur->collected |= GOT_SHDSTAT; 286 287 /* 288 * Bitmap kstat 289 */ 290 kname = kstat_value(cur->pre_set, DSW_SKSTAT_BMPIO); 291 292 ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname); 293 294 if ((cur->cur_bmp = kstat_retrieve(kc, ksp)) == NULL) 295 continue; 296 297 cur->collected |= GOT_BMPSTAT; 298 299 /* 300 * Overflow kstat 301 */ 302 kname = kstat_value(cur->cur_set, DSW_SKSTAT_OVRIO); 303 304 ksp = kstat_lookup(kc, II_KSTAT_MODULE, -1, kname); 305 306 if (ksp == NULL) { 307 if (cur->pre_ovr != NULL) { 308 kstat_free(cur->pre_ovr); 309 cur->pre_ovr = NULL; 310 } 311 if (cur->cur_ovr != NULL) { 312 kstat_free(cur->cur_ovr); 313 cur->cur_ovr = NULL; 314 } 315 continue; 316 } 317 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; 324 } 325 326 cur->collected |= GOT_OVRSTAT; 327 } 328 329 return (0); 330 } 331 332 /* 333 * ii_report() - outputs statistics for the statistics currently being 334 * monitored. Deletes statistics for volumes that have been disabled. 335 * 336 */ 337 int 338 ii_report() 339 { 340 uint32_t *flags; 341 int padsz = 0; 342 char pad[20] = {0}; 343 iistat_t *cur, *pre = NULL; 344 345 if (ii_top == NULL) { 346 return (0); 347 } 348 349 /* Create padding string for secondary report lines */ 350 if (dflags & FLAGS) { 351 padsz += STAT_HDR_SIZE; 352 padsz += STAT_HDR_SIZE; 353 } 354 355 if (dflags & PCTS) 356 padsz += PCT_HDR_SIZE; 357 358 if (padsz) { 359 char fmt[20]; 360 (void) sprintf(fmt, "%%%ds", padsz); 361 (void) sprintf(pad, fmt, ""); 362 } 363 364 for (cur = ii_top; cur; /* CSTYLED */) { 365 int first = 1; 366 char data[20] = {0}; 367 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; 374 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); 384 385 offset = strlen(vol) - NAMED_LEN; 386 387 if (offset < 0) 388 offset = 0; 389 390 (void) printf(DATA_C16, vol + offset); 391 (void) printf(" %s\n", II_DISABLED); 392 393 /* free memory and remove stat from list */ 394 next = ii_del_stat(cur); 395 396 if (! pre) 397 cur = ii_top = next; 398 else 399 cur = pre->next = next; 400 401 continue; 402 } 403 404 /* Check to see if the user specified this volume */ 405 if (! ii_vol_selected(cur->pre_set)) 406 goto next; 407 408 /* Check to see if zflag applies */ 409 if (zflag && ii_value_check(cur) == 0) 410 goto next; 411 412 /* Calculate flags */ 413 flags = kstat_value(cur->cur_set, DSW_SKSTAT_FLAGS); 414 415 if (dflags & FLAGS) { 416 417 char c[STAT_HDR_SIZE]; 418 char vtype[STAT_HDR_SIZE]; 419 char vstat[STAT_HDR_SIZE]; 420 421 if (*flags & DSW_GOLDEN) 422 (void) strcpy(c, II_INDEPENDENT); 423 else 424 (void) strcpy(c, II_DEPENDENT); 425 426 (void) sprintf(vtype, DATA_C2, c); 427 (void) strcat(data, vtype); 428 429 if (*flags & DSW_COPYINGP) 430 (void) strcpy(c, II_COPYING); 431 else 432 (void) strcpy(c, NO_INFO); 433 434 435 (void) sprintf(vstat, DATA_C2, c); 436 (void) strcat(data, vstat); 437 } 438 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; 447 448 cpybits = 449 kstat_value(cur->cur_set, DSW_SKSTAT_COPYBITS); 450 451 shdbits = 452 kstat_value(cur->cur_set, DSW_SKSTAT_SHDBITS); 453 454 volsize = 455 kstat_value(cur->cur_set, DSW_SKSTAT_SIZE); 456 457 *volsize /= DSW_SIZE; 458 459 chkbits = *cpybits >= *shdbits ? cpybits : shdbits; 460 461 pct = ((float)*chkbits / *volsize) * 100.0; 462 463 (void) sprintf(snpct, DATA_F62, pct); 464 465 (void) strcat(data, snpct); 466 } 467 468 /* Master statistics */ 469 if (rflags & IIMG_MST) { 470 char *c; 471 char vol[(NAMED_LEN * 4) + 1] = {0}; 472 int offset; 473 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); 482 483 offset = strlen(vol) - NAMED_LEN; 484 485 if (offset < 0) 486 offset = 0; 487 488 header(); 489 (void) printf(DATA_C16, vol + offset); 490 (void) printf("%s", data); 491 (void) printf(ROLE_INF_FMT, II_MASTER); 492 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)); 499 } 500 501 (void) printf("\n"); 502 503 if (first) { 504 (void) strcpy(data, strlen(pad) > 0 ? pad : ""); 505 first = 0; 506 } 507 } 508 509 /* Shadow statistics */ 510 if (rflags & IIMG_SHD) { 511 char *c; 512 char vol[(NAMED_LEN * 4) + 1] = {0}; 513 int offset; 514 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); 523 524 offset = strlen(vol) - NAMED_LEN; 525 526 if (offset < 0) 527 offset = 0; 528 529 header(); 530 (void) printf(DATA_C16, vol + offset); 531 (void) printf("%s", data); 532 (void) printf(ROLE_INF_FMT, II_SHADOW); 533 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)); 540 } 541 542 (void) printf("\n"); 543 544 if (first) { 545 (void) strcpy(data, strlen(pad) > 0 ? pad : ""); 546 first = 0; 547 } 548 } 549 550 /* Bitmap statistics */ 551 if (rflags & IIMG_BMP) { 552 char *c; 553 char vol[(NAMED_LEN * 4) + 1] = {0}; 554 int offset; 555 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); 564 565 offset = strlen(vol) - NAMED_LEN; 566 567 if (offset < 0) 568 offset = 0; 569 570 header(); 571 (void) printf(DATA_C16, vol + offset); 572 (void) printf("%s", data); 573 (void) printf(ROLE_INF_FMT, II_BITMAP); 574 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)); 581 } 582 (void) printf("\n"); 583 584 if (first) { 585 (void) strcpy(data, strlen(pad) > 0 ? pad : ""); 586 first = 0; 587 } 588 } 589 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; 596 597 if (cur->cur_ovr == NULL && cur->pre_ovr != NULL) 598 (void) strcpy(msg, " <<attached>>"); 599 600 if (! (cur->collected & GOT_OVRSTAT)) 601 (void) strcpy(msg, " <<not attached>>"); 602 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); 611 612 offset = strlen(vol) - NAMED_LEN; 613 614 if (offset < 0) 615 offset = 0; 616 617 header(); 618 (void) printf(DATA_C16, vol + offset); 619 (void) printf("%s", data); 620 (void) printf(ROLE_INF_FMT, II_OVERFLOW); 621 622 if (strlen(msg)) { 623 (void) printf("%s\n", msg); 624 linesout++; 625 goto next; 626 } 627 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)); 634 } 635 636 (void) printf("\n"); 637 638 if (first) { 639 (void) strcpy(data, strlen(pad) > 0 ? pad : ""); 640 first = 0; 641 } 642 } 643 644 645 next: 646 pre = cur; 647 cur = cur->next; 648 } 649 650 return (0); 651 } 652 653 /* 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. 658 * 659 */ 660 void 661 ii_add_stat(iistat_t *iistat) 662 { 663 664 iistat_t *cur; 665 666 if (ii_top == NULL) { 667 ii_top = iistat; 668 return; 669 } 670 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) { 674 /* 675 * If we get to the last item in the list, then just 676 * add this one to the end 677 */ 678 if (cur->next == NULL) { 679 cur->next = iistat; 680 return; 681 } 682 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; 688 } 689 } else { 690 if (cur == ii_top) 691 ii_top = iistat; 692 693 iistat->next = cur; 694 695 return; 696 } 697 } 698 } 699 700 /* 701 * ii_del_stat() - deallocate memory for the structure being 702 * passed in. 703 * 704 * parameters 705 * iistat_t *iistat - structure to be deallocated 706 * 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. 711 * 712 */ 713 iistat_t * 714 ii_del_stat(iistat_t *iistat) 715 { 716 717 iistat_t *next = iistat->next; 718 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); 729 730 free(iistat); 731 732 return (next); 733 } 734 735 int 736 ii_value_check(iistat_t *iistat) 737 { 738 if (IIMG_COMPLETE(iistat->collected)) 739 return (1); 740 741 if (io_value_check(iistat->pre_mst->ks_data, 742 iistat->cur_mst->ks_data)) { 743 return (1); 744 } 745 746 if (io_value_check(iistat->pre_shd->ks_data, 747 iistat->cur_shd->ks_data)) { 748 return (1); 749 } 750 751 if (io_value_check(iistat->pre_bmp->ks_data, 752 iistat->cur_bmp->ks_data)) { 753 return (1); 754 } 755 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); 760 } 761 } 762 763 return (0); 764 } 765 766 int 767 ii_validate(kstat_t *ksp) 768 { 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); 782 783 return (0); 784 } 785 786 int 787 ii_vol_selected(kstat_t *ksp) 788 { 789 vslist_t *vslist = vs_top; 790 791 for (vslist = vs_top; vslist != NULL; vslist = vslist->next) { 792 char *vn; 793 int off = 0; 794 795 vn = ksp->ks_name; 796 797 if ((off = strlen(vn) - NAMED_LEN) <= 0) { 798 off = 0; 799 } 800 801 if (strcmp(vslist->volname, &vn[off]) == 0) { 802 break; 803 } 804 } 805 806 if (vs_top != NULL && vslist == NULL) { 807 return (0); 808 } else { 809 return (1); 810 } 811 } 812