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 }