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 2005 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <meta.h> 29 #include <metad.h> 30 31 #include <ctype.h> 32 #include <string.h> 33 34 /* 35 * Just in case we're not in a build environment, make sure that 36 * TEXT_DOMAIN gets set to something. 37 */ 38 #if !defined(TEXT_DOMAIN) 39 #define TEXT_DOMAIN "SYS_TEST" 40 #endif 41 42 /* 43 * Macros to produce a quoted string containing the value of a 44 * preprocessor macro. For example, if SIZE is defined to be 256, 45 * VAL2STR(SIZE) is "256". This is used to construct format 46 * strings for scanf-family functions below. 47 */ 48 #define QUOTE(x) #x 49 #define VAL2STR(x) QUOTE(x) 50 51 extern char *getfullblkname(); 52 extern char *getfullrawname(); 53 54 /* 55 * caches 56 */ 57 static mdsetnamelist_t *setlistp = NULL; 58 static mddrivenamelist_t *drivelistp = NULL; 59 static mdnamelist_t *fastnmlp = NULL; 60 static mdhspnamelist_t *hsplistp = NULL; 61 62 /* 63 * leak proof name conversion 64 */ 65 static char * 66 rawname( 67 char *uname 68 ) 69 { 70 char *p; 71 struct stat sbuf1, sbuf2; 72 73 if ((p = getfullrawname(uname)) == NULL) { 74 return (NULL); 75 } else if (*p == '\0') { 76 Free(p); 77 return (NULL); 78 } else { 79 if (stat(uname, &sbuf1) != 0) { 80 (void) printf(dgettext(TEXT_DOMAIN, 81 "device to mount in /etc/vfstab is " 82 "invalid for device %s\n"), uname); 83 exit(1); 84 } 85 if (stat(p, &sbuf2) != 0) { 86 (void) printf(dgettext(TEXT_DOMAIN, 87 "device to fsck in /etc/vfstab is " 88 "invalid for raw device %s\n"), p); 89 exit(1); 90 } 91 if (sbuf1.st_rdev != sbuf2.st_rdev) { 92 (void) printf(dgettext(TEXT_DOMAIN, 93 "/etc/vfstab entries inconsistent on " 94 "line containing device %s\n"), uname); 95 exit(1); 96 } 97 if (!S_ISCHR(sbuf2.st_mode)) { 98 (void) printf(dgettext(TEXT_DOMAIN, 99 "/etc/vfstab device to fsck is not a " 100 "raw device for device %s\n"), p); 101 exit(1); 102 } 103 return (p); 104 } 105 } 106 107 char * 108 blkname( 109 char *uname 110 ) 111 { 112 char *p; 113 114 if ((p = getfullblkname(uname)) == NULL) { 115 return (NULL); 116 } else if (*p == '\0') { 117 Free(p); 118 return (NULL); 119 } else { 120 return (p); 121 } 122 } 123 124 /* 125 * parse up metadevice name 126 */ 127 static int 128 parse_metadevice( 129 char *uname, 130 char **snamep, 131 unit_t *unitp 132 ) 133 { 134 char *sname = Malloc(strlen(uname) + 1); 135 char *tname = Malloc(strlen(uname) + 1); 136 137 unit_t unit; 138 int len; 139 char *up; 140 char *tp; 141 int lcws; /* last character was slash */ 142 143 /* handle dont cares */ 144 if (unitp == NULL) 145 unitp = &unit; 146 147 /* Now copy uname to tname by throwing away any duplicate '/' */ 148 for (lcws = 0, tp = tname, up = uname; *up; up++) { 149 if (lcws) { 150 if (*up == '/') { 151 continue; 152 } else { 153 lcws = 0; 154 } 155 } 156 if (*up == '/') { 157 lcws = 1; 158 } 159 *tp++ = *up; /* ++ is done by for loop */ 160 } 161 *tp = '\0'; 162 163 /* without set */ 164 if ((sscanf(tname, "d%lu%n", unitp, &len) == 1) && 165 (strlen(tname) == len) && ((long)*unitp >= 0)) { 166 if (snamep != NULL) 167 *snamep = NULL; 168 Free(sname); 169 Free(tname); 170 return (0); 171 } 172 173 /* fully-qualified without set */ 174 if (((sscanf(tname, "/dev/md/dsk/d%lu%n", unitp, &len) == 1) && 175 (strlen(tname) == len) && ((long)*unitp >= 0)) || 176 ((sscanf(tname, "/dev/md/rdsk/d%lu%n", unitp, &len) == 1) && 177 (strlen(tname) == len) && ((long)*unitp >= 0))) { 178 if (snamep != NULL) 179 *snamep = Strdup(MD_LOCAL_NAME); 180 Free(sname); 181 Free(tname); 182 return (0); 183 } 184 185 /* with set */ 186 if (((sscanf(tname, "%[^/]/d%lu%n", sname, unitp, &len) == 2) && 187 (strlen(tname) == len) && ((long)*unitp >= 0)) || 188 ((sscanf(tname, "/dev/md/%[^/]/dsk/d%lu%n", sname, 189 unitp, &len) == 2) && 190 (strlen(tname) == len) && ((long)*unitp >= 0)) || 191 ((sscanf(tname, "/dev/md/%[^/]/rdsk/d%lu%n", sname, 192 unitp, &len) == 2) && 193 (strlen(tname) == len) && ((long)*unitp >= 0))) { 194 if (snamep != NULL) { 195 *snamep = sname; 196 } else { 197 Free(sname); 198 } 199 Free(tname); 200 return (0); 201 } 202 203 /* no match */ 204 if (snamep != NULL) 205 *snamep = NULL; 206 Free(sname); 207 Free(tname); 208 return (-1); 209 } 210 211 /* 212 * FUNCTION: parse_device() 213 * INPUT: sp - pointer to setname struct 214 * uname - Name of either a hotspare pool or metadevice 215 * This can either be a fully qualified path or 216 * in the form [set name/]device 217 * OUTPUT: setnamep - name of the set that uname is in 218 * uname - name of the hotspare pools or metadevice 219 * only contains the name of the device with all 220 * other path information stripped off. 221 * PURPOSE: Parse uname and sp into the set name and device name strings. 222 * If the set name is specified as part of uname then use that 223 * otherwise attempt to get the set name from sp. 224 */ 225 static void 226 parse_device( 227 mdsetname_t *sp, 228 char *uname, 229 char **setnamep /* dynamically alloced - caller must free */ 230 ) 231 { 232 char setname[FILENAME_MAX+1]; 233 char *tname = Malloc(strlen(uname) + 1); 234 235 int len; 236 char *up; 237 char *tp; 238 int lcws; /* last character was slash */ 239 240 /* Now copy uname to tname by throwing away any duplicate '/' */ 241 for (lcws = 0, tp = tname, up = uname; *up; up++) { 242 if (lcws) { 243 if (*up == '/') { 244 continue; 245 } else { 246 lcws = 0; 247 } 248 } 249 if (*up == '/') { 250 lcws = 1; 251 } 252 *tp++ = *up; /* ++ is done by for loop */ 253 } 254 *tp = '\0'; 255 256 /* fully-qualified - local set */ 257 if (((sscanf(tname, "/dev/md/dsk/%" VAL2STR(FILENAME_MAX) "s%n", 258 uname, &len) == 1) && (strlen(tname) == len)) || 259 ((sscanf(tname, "/dev/md/rdsk/%" VAL2STR(FILENAME_MAX) "s%n", 260 uname, &len) == 1) && (strlen(tname) == len))) { 261 if (setnamep != NULL) 262 *setnamep = NULL; 263 Free(tname); 264 return; 265 } 266 267 /* with setname specified - either fully qualified and relative spec */ 268 if (((sscanf(tname, "%" VAL2STR(FILENAME_MAX) "s/%" 269 VAL2STR(FILENAME_MAX) "s%n", setname, uname, &len) == 2) && 270 (strlen(tname) == len)) || 271 ((sscanf(tname, "/dev/md/%[^/]/dsk/%" VAL2STR(FILENAME_MAX) "s%n", 272 setname, uname, &len) == 2) && (strlen(tname) == len)) || 273 ((sscanf(tname, "/dev/md/%[^/]/rdsk/%" VAL2STR(FILENAME_MAX) "s%n", 274 setname, uname, &len) == 2) && (strlen(tname) == len))) { 275 276 if (setnamep != NULL) { 277 *setnamep = Strdup(setname); 278 } 279 Free(tname); 280 return; 281 } 282 283 /* without setname specified */ 284 (void) strcpy(uname, tname); 285 if (setnamep != NULL) { 286 if (sp != NULL && !metaislocalset(sp)) 287 *setnamep = Strdup(sp->setname); 288 else 289 *setnamep = NULL; 290 } 291 Free(tname); 292 } 293 294 /* 295 * parse up hotspare pool name 296 */ 297 static int 298 parse_hsp( 299 char *uname, 300 char **snamep, 301 hsp_t *hspp 302 ) 303 { 304 char *sname = Malloc(strlen(uname) + 1); 305 hsp_t hsp; 306 int len; 307 308 /* handle dont cares */ 309 if (hspp == NULL) 310 hspp = &hsp; 311 312 /* without set */ 313 if ((sscanf(uname, "hsp%03u%n", hspp, &len) == 1) && 314 (strlen(uname) == len) && ((long)*hspp >= 0)) { 315 if (snamep != NULL) 316 *snamep = NULL; 317 Free(sname); 318 return (0); 319 } 320 321 /* with set */ 322 if ((sscanf(uname, "%[^/]/hsp%03u%n", sname, 323 hspp, &len) == 2) && 324 (strlen(uname) == len) && ((long)*hspp >= 0)) { 325 if (snamep != NULL) { 326 *snamep = sname; 327 } else { 328 Free(sname); 329 } 330 return (0); 331 } 332 333 /* no match */ 334 Free(sname); 335 return (-1); 336 } 337 338 /* 339 * canonicalize metadevice name 340 */ 341 static char * 342 canon_metadevice( 343 char *sname, 344 unit_t unit 345 ) 346 { 347 char *cname; 348 size_t len; 349 350 if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) { 351 len = strlen("d") + 20 + 1; 352 cname = Malloc(len); 353 (void) snprintf(cname, len, "d%lu", unit); 354 } else { 355 len = strlen(sname) + strlen("/d") + 20 + 1; 356 cname = Malloc(len); 357 (void) snprintf(cname, len, "%s/d%lu", sname, unit); 358 } 359 360 return (cname); 361 } 362 363 /* 364 * canonicalize hotspare pool name 365 */ 366 static char * 367 canon_hsp( 368 char *sname, 369 hsp_t hsp 370 ) 371 { 372 char *cname; 373 size_t len; 374 375 if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) { 376 cname = Malloc(strlen("hsp000") + 1); 377 (void) sprintf(cname, "hsp%03u", hsp); 378 } else { 379 len = strlen(sname) + strlen("/hsp000") + 1; 380 cname = Malloc(len); 381 (void) snprintf(cname, len, "%s/hsp%03lu", sname, hsp); 382 } 383 384 return (cname); 385 } 386 387 /* 388 * canonicalize name, return type 389 * 390 * NOTE: this is really only for use by meta_tab* 391 */ 392 char * 393 meta_canonicalize( 394 mdsetname_t *sp, 395 char *uname 396 ) 397 { 398 char *sname = NULL; 399 char *cname; 400 401 /* return the set name and dev name */ 402 parse_device(sp, uname, &sname); 403 404 if (sname == NULL) 405 cname = Strdup(uname); 406 else { 407 size_t cname_len; 408 409 cname_len = strlen(uname) + strlen(sname) + 2; 410 cname = Malloc(cname_len); 411 (void) snprintf( 412 cname, cname_len, "%s/%s", sname, uname); 413 Free(sname); 414 } 415 return (cname); 416 } 417 418 /* 419 * check that name is a metadevice 420 */ 421 int 422 is_metaname( 423 char *uname 424 ) 425 { 426 if (parse_metadevice(uname, NULL, NULL) == 0) 427 return (1); 428 else 429 return (0); 430 } 431 432 /* 433 * check that name is a hotspare pool 434 */ 435 int 436 is_hspname( 437 char *uname 438 ) 439 { 440 if (parse_hsp(uname, NULL, NULL) == 0) 441 return (1); 442 else 443 return (0); 444 } 445 446 /* 447 * mdsetname_t stuff 448 */ 449 450 /* 451 * initialize setname 452 */ 453 static void 454 metainitsetname( 455 mdsetname_t *sp 456 ) 457 { 458 (void) memset(sp, '\0', sizeof (*sp)); 459 } 460 461 static void 462 metafreesetdesc(md_set_desc *sd) 463 { 464 md_mnnode_desc *nd; 465 466 if (MD_MNSET_DESC(sd)) { 467 nd = sd->sd_nodelist; 468 while (nd) { 469 sd->sd_nodelist = nd->nd_next; 470 Free(nd); 471 nd = sd->sd_nodelist; 472 } 473 } 474 metafreedrivedesc(&sd->sd_drvs); 475 Free(sd); 476 } 477 478 /* 479 * free allocated setname 480 */ 481 static void 482 metafreesetname( 483 mdsetname_t *sp 484 ) 485 { 486 if (sp->setname != NULL) 487 Free(sp->setname); 488 if (sp->setdesc != NULL) 489 metafreesetdesc(sp->setdesc); 490 metainitsetname(sp); 491 } 492 493 /* 494 * flush the setname cache 495 */ 496 static void 497 metaflushsetnames() 498 { 499 mdsetnamelist_t *p, *n; 500 501 for (p = setlistp, n = NULL; (p != NULL); p = n) { 502 n = p->next; 503 metafreesetname(p->sp); 504 Free(p->sp); 505 Free(p); 506 } 507 setlistp = NULL; 508 } 509 510 /* 511 * get set number 512 */ 513 static int 514 getsetno( 515 char *sname, 516 set_t *setnop, 517 md_error_t *ep 518 ) 519 { 520 md_set_record *sr; 521 size_t len; 522 523 /* local set */ 524 if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) { 525 *setnop = 0; 526 return (0); 527 } 528 529 /* shared set */ 530 if ((sr = getsetbyname(sname, ep)) == NULL) { 531 if (mdisrpcerror(ep, RPC_PROGNOTREGISTERED)) { 532 char *p; 533 534 len = strlen(sname) + 30; 535 p = Malloc(len); 536 537 (void) snprintf(p, len, "setname \"%s\"", sname); 538 (void) mderror(ep, MDE_NO_SET, p); 539 Free(p); 540 } 541 return (-1); 542 } 543 *setnop = sr->sr_setno; 544 free_sr(sr); 545 return (0); 546 } 547 548 /* 549 * find setname from name 550 */ 551 mdsetname_t * 552 metasetname( 553 char *sname, 554 md_error_t *ep 555 ) 556 { 557 mdsetnamelist_t **tail; 558 set_t setno; 559 mdsetname_t *sp; 560 561 /* look for cached value first */ 562 assert(sname != NULL); 563 for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) { 564 sp = (*tail)->sp; 565 if (strcmp(sp->setname, sname) == 0) { 566 return (sp); 567 } 568 } 569 570 /* setup set */ 571 if (getsetno(sname, &setno, ep) != 0) 572 return (NULL); 573 574 /* allocate new list element and setname */ 575 *tail = Zalloc(sizeof (**tail)); 576 sp = (*tail)->sp = Zalloc(sizeof (*sp)); 577 578 sp->setname = Strdup(sname); 579 sp->setno = setno; 580 sp->lockfd = MD_NO_LOCK; 581 582 return (sp); 583 } 584 585 /* 586 * find setname from setno 587 */ 588 mdsetname_t * 589 metasetnosetname( 590 set_t setno, 591 md_error_t *ep 592 ) 593 { 594 mdsetnamelist_t *slp; 595 mdsetname_t *sp; 596 md_set_record *sr; 597 598 /* look for cached value first */ 599 for (slp = setlistp; (slp != NULL); slp = slp->next) { 600 sp = slp->sp; 601 if (sp->setno == setno) 602 return (sp); 603 } 604 605 /* local set */ 606 if (setno == MD_LOCAL_SET) 607 return (metasetname(MD_LOCAL_NAME, ep)); 608 609 /* shared set */ 610 if ((sr = getsetbynum(setno, ep)) == NULL) 611 return (NULL); 612 sp = metasetname(sr->sr_setname, ep); 613 free_sr(sr); 614 return (sp); 615 } 616 617 mdsetname_t * 618 metafakesetname( 619 set_t setno, 620 char *sname 621 ) 622 { 623 mdsetnamelist_t **tail; 624 mdsetname_t *sp; 625 626 /* look for cached value first */ 627 for (tail = &setlistp; (*tail != NULL); tail = &(*tail)->next) { 628 sp = (*tail)->sp; 629 if (sp->setno == setno) { 630 if ((sp->setname == NULL) && (sname != NULL)) 631 sp->setname = Strdup(sname); 632 return (sp); 633 } 634 } 635 636 /* allocate new list element and setname */ 637 *tail = Zalloc(sizeof (**tail)); 638 sp = (*tail)->sp = Zalloc(sizeof (*sp)); 639 640 if (sname != NULL) 641 sp->setname = Strdup(sname); 642 sp->setno = setno; 643 sp->lockfd = MD_NO_LOCK; 644 645 return (sp); 646 } 647 648 649 /* 650 * setup set record (sr) and cache it in the mdsetname_t struct 651 */ 652 md_set_desc * 653 sr2setdesc( 654 md_set_record *sr 655 ) 656 { 657 md_set_desc *sd; 658 int i; 659 md_mnset_record *mnsr; 660 md_mnnode_desc *nd, *nd_prev = 0; 661 md_mnnode_record *nr; 662 md_error_t status = mdnullerror; 663 md_error_t *ep = &status; 664 int nodecnt, nrcnt; 665 mndiskset_membershiplist_t *nl, *nl2; 666 667 sd = Zalloc(sizeof (*sd)); 668 sd->sd_ctime = sr->sr_ctime; 669 sd->sd_genid = sr->sr_genid; 670 sd->sd_setno = sr->sr_setno; 671 sd->sd_flags = sr->sr_flags; 672 673 if (MD_MNSET_DESC(sd)) { 674 mnsr = (md_mnset_record *)sr; 675 (void) strlcpy(sd->sd_mn_master_nodenm, 676 mnsr->sr_master_nodenm, sizeof (sd->sd_mn_master_nodenm)); 677 sd->sd_mn_master_nodeid = mnsr->sr_master_nodeid; 678 if (strcmp(mnsr->sr_master_nodenm, mynode()) == 0) { 679 sd->sd_mn_am_i_master = 1; 680 } 681 682 /* 683 * Get membershiplist from API routine. If there's 684 * an error, just use a NULL nodelist. 685 */ 686 if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) { 687 nodecnt = 0; /* no nodes are alive */ 688 nl = NULL; 689 } 690 nr = mnsr->sr_nodechain; 691 nrcnt = 0; 692 /* 693 * Node descriptor node list must be built in 694 * ascending order of nodeid. The nodechain 695 * in the mnset record is in ascending order, 696 * so just make them the same. 697 */ 698 while (nr) { 699 nd = Zalloc(sizeof (*nd)); 700 if (nd_prev) { 701 nd_prev->nd_next = nd; 702 } else { 703 sd->sd_nodelist = nd; 704 } 705 nd->nd_ctime = nr->nr_ctime; 706 nd->nd_genid = nr->nr_genid; 707 nd->nd_flags = nr->nr_flags; 708 709 (void) strlcpy(nd->nd_nodename, nr->nr_nodename, 710 sizeof (nd->nd_nodename)); 711 nd->nd_nodeid = nr->nr_nodeid; 712 if (strcmp(nd->nd_nodename, mynode()) == 0) { 713 sd->sd_mn_mynode = nd; 714 } 715 if (nd->nd_nodeid == sd->sd_mn_master_nodeid) { 716 sd->sd_mn_masternode = nd; 717 } 718 719 /* 720 * If node is marked ALIVE, then set priv_ic 721 * from membership list. During the early part 722 * of a reconfig cycle, the membership list may 723 * have been changed, (a node entering or leaving 724 * the cluster), but rpc.metad hasn't flushed 725 * its data yet. So, if node is marked alive, but 726 * is no longer in the membership list (node has 727 * left the cluster) then just leave priv_ic to NULL. 728 */ 729 if (nd->nd_flags & MD_MN_NODE_ALIVE) { 730 nl2 = nl; 731 while (nl2) { 732 if (nl2->msl_node_id == nd->nd_nodeid) { 733 (void) strlcpy(nd->nd_priv_ic, 734 nl2->msl_node_addr, 735 sizeof (nd->nd_priv_ic)); 736 break; 737 } 738 nl2 = nl2->next; 739 } 740 } 741 742 nr = nr->nr_next; 743 nrcnt++; 744 nd_prev = nd; 745 } 746 sd->sd_mn_numnodes = nrcnt; 747 if (nodecnt) 748 meta_free_nodelist(nl); 749 750 /* Just copying to keep consistent view between sr & sd */ 751 (void) strlcpy(sd->sd_nodes[0], mnsr->sr_nodes_bw_compat[0], 752 sizeof (sd->sd_nodes[0])); 753 } else { 754 for (i = 0; i < MD_MAXSIDES; i++) 755 (void) strlcpy(sd->sd_nodes[i], sr->sr_nodes[i], 756 sizeof (sd->sd_nodes[i])); 757 } 758 759 sd->sd_med = sr->sr_med; /* structure assignment */ 760 761 return (sd); 762 } 763 764 md_set_desc * 765 metaget_setdesc( 766 mdsetname_t *sp, 767 md_error_t *ep 768 ) 769 { 770 md_set_record *sr; 771 772 if (sp->setdesc != NULL) 773 return (sp->setdesc); 774 775 if (sp->setname != NULL) { 776 if ((sr = getsetbyname(sp->setname, ep)) != NULL) { 777 sp->setdesc = sr2setdesc(sr); 778 free_sr(sr); 779 return (sp->setdesc); 780 } 781 } 782 783 if (sp->setno > 0) { 784 if ((sr = getsetbynum(sp->setno, ep)) != NULL) { 785 sp->setdesc = sr2setdesc(sr); 786 free_sr(sr); 787 return (sp->setdesc); 788 } 789 } 790 791 return (NULL); 792 } 793 794 void 795 metaflushsetname(mdsetname_t *sp) 796 { 797 if (sp == NULL) 798 return; 799 800 if (sp->setdesc == NULL) 801 return; 802 803 metafreesetdesc(sp->setdesc); 804 sp->setdesc = NULL; 805 } 806 807 /* 808 * check for local set 809 */ 810 int 811 metaislocalset( 812 mdsetname_t *sp 813 ) 814 { 815 assert(sp->setname != NULL); 816 if (strcmp(sp->setname, MD_LOCAL_NAME) == 0) { 817 assert(sp->setno == MD_LOCAL_SET); 818 return (1); 819 } else { 820 assert(sp->setno != MD_LOCAL_SET); 821 return (0); 822 } 823 } 824 825 /* 826 * check for same set 827 */ 828 int 829 metaissameset( 830 mdsetname_t *sp1, 831 mdsetname_t *sp2 832 ) 833 { 834 if (strcmp(sp1->setname, sp2->setname) == 0) { 835 assert(sp1->setno == sp2->setno); 836 return (1); 837 } else { 838 assert(sp1->setno != sp2->setno); 839 return (0); 840 } 841 } 842 843 /* 844 * check to see if set changed 845 */ 846 static int 847 chkset( 848 mdsetname_t **spp, 849 char *sname, 850 md_error_t *ep 851 ) 852 { 853 /* if we already have a set, make sure it's the same */ 854 if (*spp != NULL) { 855 if ((*spp)->setname != sname && 856 strcmp((*spp)->setname, sname) != 0) { 857 return (mderror(ep, MDE_SET_DIFF, sname)); 858 } 859 return (0); 860 } 861 862 /* otherwise store new set name and number */ 863 if ((*spp = metasetname(sname, ep)) == NULL) { 864 return (-1); 865 } 866 867 /* return success */ 868 return (0); 869 } 870 871 /* 872 * check to see if set changed from default 873 */ 874 static int 875 chksetname( 876 mdsetname_t **spp, 877 char *sname, 878 md_error_t *ep 879 ) 880 { 881 /* default to *spp's setname, or if that is NULL to MD_LOCAL_NAME */ 882 if (sname == NULL) { 883 if (*spp) { 884 sname = (*spp)->setname; 885 } else { 886 sname = MD_LOCAL_NAME; 887 } 888 } 889 890 /* see if changed */ 891 return (chkset(spp, sname, ep)); 892 } 893 894 /* 895 * check setname from setno 896 */ 897 static int 898 chksetno( 899 mdsetname_t **spp, 900 set_t setno, 901 md_error_t *ep 902 ) 903 { 904 md_set_record *sr; 905 int rval; 906 907 /* local set */ 908 if (setno == 0) 909 return (chkset(spp, MD_LOCAL_NAME, ep)); 910 911 /* shared set */ 912 if ((sr = getsetbynum(setno, ep)) == NULL) 913 return (-1); 914 rval = chkset(spp, sr->sr_setname, ep); 915 free_sr(sr); 916 return (rval); 917 } 918 919 /* 920 * mddrivename_t stuff 921 */ 922 923 /* 924 * initialize name 925 */ 926 static void 927 metainitname( 928 mdname_t *np 929 ) 930 { 931 (void) memset(np, 0, sizeof (*np)); 932 np->dev = NODEV64; 933 np->key = MD_KEYBAD; 934 np->end_blk = -1; 935 np->start_blk = -1; 936 } 937 938 /* 939 * free allocated name 940 */ 941 static void 942 metafreename( 943 mdname_t *np 944 ) 945 { 946 if (np->cname != NULL) 947 Free(np->cname); 948 if (np->bname != NULL) 949 Free(np->bname); 950 if (np->rname != NULL) 951 Free(np->rname); 952 if (np->devicesname != NULL) 953 Free(np->devicesname); 954 metainitname(np); 955 } 956 957 /* 958 * initialize drive name 959 */ 960 static void 961 metainitdrivename( 962 mddrivename_t *dnp 963 ) 964 { 965 (void) memset(dnp, 0, sizeof (*dnp)); 966 dnp->side_names_key = MD_KEYBAD; 967 } 968 969 /* 970 * flush side names 971 */ 972 void 973 metaflushsidenames( 974 mddrivename_t *dnp 975 ) 976 { 977 mdsidenames_t *p, *n; 978 979 for (p = dnp->side_names, n = NULL; (p != NULL); p = n) { 980 n = p->next; 981 if (p->dname != NULL) 982 Free(p->dname); 983 if (p->cname != NULL) 984 Free(p->cname); 985 Free(p); 986 } 987 dnp->side_names = NULL; 988 } 989 990 /* 991 * free drive name 992 */ 993 void 994 metafreedrivename( 995 mddrivename_t *dnp 996 ) 997 { 998 uint_t slice; 999 1000 if (dnp->cname != NULL) 1001 Free(dnp->cname); 1002 if (dnp->rname != NULL) 1003 Free(dnp->rname); 1004 metafreevtoc(&dnp->vtoc); 1005 for (slice = 0; (slice < dnp->parts.parts_len); ++slice) 1006 metafreename(&dnp->parts.parts_val[slice]); 1007 if (dnp->parts.parts_val != NULL) 1008 Free(dnp->parts.parts_val); 1009 metaflushsidenames(dnp); 1010 if (dnp->miscname != NULL) 1011 Free(dnp->miscname); 1012 meta_free_unit(dnp); 1013 metainitdrivename(dnp); 1014 } 1015 1016 /* 1017 * flush the drive name cache 1018 */ 1019 static void 1020 metaflushdrivenames() 1021 { 1022 mddrivenamelist_t *p, *n; 1023 1024 for (p = drivelistp, n = NULL; (p != NULL); p = n) { 1025 n = p->next; 1026 metafreedrivename(p->drivenamep); 1027 Free(p->drivenamep); 1028 Free(p); 1029 } 1030 drivelistp = NULL; 1031 } 1032 1033 /* 1034 * peel off s%u from name 1035 */ 1036 char * 1037 metadiskname( 1038 char *name 1039 ) 1040 { 1041 char *p, *e; 1042 char onmb[BUFSIZ+1], cnmb[BUFSIZ]; 1043 uint_t d = 0; 1044 int l = 0; 1045 int cl = strlen(name); 1046 1047 if (is_metaname(name)) 1048 return (Strdup(name)); 1049 1050 /* 1051 * Handle old style names, which are of the form /dev/rXXNN[a-h]. 1052 */ 1053 if (sscanf(name, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n", 1054 onmb, &d, &l) == 2 && l == cl) { 1055 (void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u", onmb, d); 1056 return (Strdup(cnmb)); 1057 } 1058 1059 /* 1060 * Handle old style names, which are of the form /dev/XXNN[a-h]. 1061 */ 1062 if (sscanf(name, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%*[a-h]%n", 1063 onmb, &d, &l) == 2 && l == cl) { 1064 (void) snprintf(cnmb, sizeof (cnmb), "/dev/%s%u", onmb, d); 1065 return (Strdup(cnmb)); 1066 } 1067 1068 /* gobble number and 's' */ 1069 p = e = name + strlen(name) - 1; 1070 for (; (p > name); --p) { 1071 if (!isdigit(*p)) 1072 break; 1073 } 1074 if ((p == e) || (p <= name)) 1075 return (Strdup(name)); 1076 1077 if (*p != 's' && strchr("dt", *p) == NULL) 1078 return (Strdup(name)); 1079 else if (strchr("dt", *p) != NULL) 1080 return (Strdup(name)); 1081 p--; 1082 1083 if ((p <= name) || (!isdigit(*p))) 1084 return (Strdup(name)); 1085 1086 *(++p) = '\0'; 1087 e = Strdup(name); 1088 *p = 's'; 1089 1090 return (e); 1091 } 1092 1093 /* 1094 * free list of drivenames 1095 */ 1096 void 1097 metafreedrivenamelist( 1098 mddrivenamelist_t *dnlp 1099 ) 1100 { 1101 mddrivenamelist_t *next = NULL; 1102 1103 for (/* void */; (dnlp != NULL); dnlp = next) { 1104 next = dnlp->next; 1105 Free(dnlp); 1106 } 1107 } 1108 1109 /* 1110 * build list of drivenames 1111 */ 1112 int 1113 metadrivenamelist( 1114 mdsetname_t **spp, 1115 mddrivenamelist_t **dnlpp, 1116 int argc, 1117 char *argv[], 1118 md_error_t *ep 1119 ) 1120 { 1121 mddrivenamelist_t **tailpp = dnlpp; 1122 int count = 0; 1123 1124 for (*dnlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 1125 mddrivenamelist_t *dnlp = Zalloc(sizeof (*dnlp)); 1126 1127 if ((dnlp->drivenamep = metadrivename(spp, argv[0], 1128 ep)) == NULL) { 1129 metafreedrivenamelist(*dnlpp); 1130 *dnlpp = NULL; 1131 return (-1); 1132 } 1133 *tailpp = dnlp; 1134 tailpp = &dnlp->next; 1135 } 1136 return (count); 1137 } 1138 1139 /* 1140 * append to end of drivename list 1141 */ 1142 mddrivename_t * 1143 metadrivenamelist_append( 1144 mddrivenamelist_t **dnlpp, 1145 mddrivename_t *dnp 1146 ) 1147 { 1148 mddrivenamelist_t *dnlp; 1149 1150 /* run to end of list */ 1151 for (; (*dnlpp != NULL); dnlpp = &(*dnlpp)->next) 1152 ; 1153 1154 /* allocate new list element */ 1155 dnlp = *dnlpp = Zalloc(sizeof (*dnlp)); 1156 1157 /* append drivename */ 1158 dnlp->drivenamep = dnp; 1159 return (dnp); 1160 } 1161 1162 /* 1163 * FUNCTION: meta_drivenamelist_append_wrapper() 1164 * INPUT: tailpp - pointer to the list tail pointer 1165 * dnp - name node to be appended to list 1166 * OUTPUT: none 1167 * RETURNS: mddrivenamelist_t * - new tail of the list. 1168 * PURPOSE: wrapper to meta_namelist_append for performance. 1169 * metanamelist_append finds the tail each time which slows 1170 * down long lists. By keeping track of the tail ourselves 1171 * we can change metadrivenamelist_append into a 1172 * constant time operation. 1173 */ 1174 mddrivenamelist_t ** 1175 meta_drivenamelist_append_wrapper( 1176 mddrivenamelist_t **tailpp, 1177 mddrivename_t *dnp 1178 ) 1179 { 1180 (void) metadrivenamelist_append(tailpp, dnp); 1181 1182 /* If it's the first item in the list, return it instead of the next */ 1183 if ((*tailpp)->next == NULL) 1184 return (tailpp); 1185 1186 return (&(*tailpp)->next); 1187 } 1188 1189 1190 /* 1191 * mdname_t stuff 1192 */ 1193 1194 /* 1195 * check set and get comparison name 1196 */ 1197 char * 1198 meta_name_getname( 1199 mdsetname_t **spp, 1200 char *uname, 1201 md_error_t *ep 1202 ) 1203 { 1204 char *sname = NULL; 1205 int ismeta = 0; 1206 unit_t unit; 1207 1208 /* check set name */ 1209 if (parse_metadevice(uname, &sname, &unit) == 0) 1210 ismeta = 1; 1211 if (chksetname(spp, sname, ep) != 0) { 1212 if (sname != NULL) 1213 Free(sname); 1214 return (NULL); 1215 } 1216 if (sname != NULL) 1217 Free(sname); 1218 1219 /* return comparison name */ 1220 if (ismeta) 1221 return (canon_metadevice((*spp)->setname, unit)); 1222 else 1223 return (Strdup(uname)); 1224 } 1225 1226 /* 1227 * FUNCTION: getrname() 1228 * INPUT: spp - the setname struct 1229 * uname - the possibly unqualified device name 1230 * OUTPUT: ep - return error pointer 1231 * RETURNS: char* - character string containing the fully 1232 * qualified raw device name 1233 * PURPOSE: Create the fully qualified raw name for the possibly 1234 * unqualified device name. If uname is an absolute 1235 * path the raw name is derived from the input string. 1236 * Otherwise, an attempt is made to get the rawname by 1237 * catting "/dev/md/rdsk" and "/dev/rdsk". 1238 */ 1239 static char * 1240 getrname(mdsetname_t **spp, char *uname, md_error_t *ep) 1241 { 1242 char *rname, 1243 *fname; 1244 int constructed = 0; 1245 1246 assert(uname != NULL); 1247 /* if it is an absolute name then just call rawname on the input */ 1248 if (uname[0] == '/') { 1249 if ((rname = rawname(uname)) != NULL) 1250 return (rname); 1251 1252 /* out of luck */ 1253 (void) mdsyserror(ep, ENOENT, uname); 1254 return (NULL); 1255 } 1256 1257 /* 1258 * Check for metadevice before physical device. 1259 * With the introduction of softpartitions it is more 1260 * likely to be a metadevice. 1261 */ 1262 1263 /* metadevice short form */ 1264 if (metaislocalset(*spp)) { 1265 fname = Malloc(strlen(uname) + strlen("/dev/md/rdsk/") + 1); 1266 (void) strcpy(fname, "/dev/md/rdsk/"); 1267 (void) strcat(fname, uname); 1268 if (*uname == 'd') 1269 constructed = 1; 1270 } else { 1271 char *p; 1272 size_t len; 1273 1274 if ((p = strchr(uname, '/')) != NULL) { 1275 ++p; 1276 } else { 1277 p = uname; 1278 } 1279 len = strlen((*spp)->setname) + strlen(p) + 1280 strlen("/dev/md//rdsk/") + 1; 1281 fname = Malloc(len); 1282 (void) snprintf(fname, len, "/dev/md/%s/rdsk/%s", 1283 (*spp)->setname, p); 1284 if (*p == 'd') 1285 constructed = 1; 1286 } 1287 rname = rawname(fname); 1288 1289 /* 1290 * Handle the case where we have a new metadevice that does not yet 1291 * exist in the name-space. In this case we return the constructed 1292 * metadevice name as that will exist after the metainit call has 1293 * created it. 1294 */ 1295 if ((rname == NULL) && constructed) { 1296 rname = Strdup(fname); 1297 } 1298 Free(fname); 1299 if (rname != NULL) 1300 return (rname); 1301 1302 fname = Malloc(strlen(uname) + strlen("/dev/rdsk/") + 1); 1303 (void) strcpy(fname, "/dev/rdsk/"); 1304 (void) strcat(fname, uname); 1305 rname = rawname(fname); 1306 Free(fname); 1307 if (rname != NULL) 1308 return (rname); 1309 1310 /* 1311 * If all else fails try the straight uname. 1312 * NOTE: This check was at the beginning of getrname instead 1313 * of here. It was moved to avoid a conflict with SC3.0. If 1314 * a diskset was mounted with the same name it would hang 1315 * the cluster in a loop. Example: 1316 * 1317 * fubar/d10 -m fubar/d0 fubar/d1 1318 * mount /dev/md/fubar/dsk/d10 /fubar 1319 * 1320 * When the system was booted DiskSuite would try to take ownership 1321 * of diskset fubar. This would cause rawname("fubar/d10") to be 1322 * called. rawname() stats the string which caused the cluster 1323 * reservation code to try and take ownership which it was already 1324 * doing and a deadlock would occur. By moving this final attempt 1325 * at resolving the rawname to the end we avoid this deadlock. 1326 */ 1327 if (rname = rawname(uname)) 1328 return (rname); 1329 1330 /* out of luck */ 1331 (void) mdsyserror(ep, ENOENT, uname); 1332 return (NULL); 1333 } 1334 1335 /* 1336 * get raw slice and drive names 1337 */ 1338 static char * 1339 getrawnames( 1340 mdsetname_t **spp, 1341 char *uname, 1342 char **dnamep, 1343 md_error_t *ep 1344 ) 1345 { 1346 char *rname; 1347 size_t len; 1348 1349 /* initialize */ 1350 *dnamep = NULL; 1351 1352 /* get slice name */ 1353 if ((rname = getrname(spp, uname, ep)) != NULL) { 1354 *dnamep = metadiskname(rname); 1355 return (rname); 1356 } 1357 1358 /* 1359 * If name cannot be found, if may be because is is not accessible. 1360 * If it is an absolute name, try all possible disk name formats and 1361 * if it is device name, assume it is /dev/rdsk/... 1362 */ 1363 if (mdissyserror(ep, ENOENT)) { 1364 if (uname[0] == '/') { 1365 /* Absolute name */ 1366 char *p; 1367 uint_t d = 0; 1368 int l = 0; 1369 char onmb[BUFSIZ+1], snm[BUFSIZ+1]; 1370 1371 /* 1372 * Handle old style raw names 1373 */ 1374 if (sscanf(uname, 1375 "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u" 1376 "%" VAL2STR(BUFSIZ) "[a-h]%n", 1377 onmb, &d, snm, &l) == 3 && l == strlen(uname)) { 1378 mdclrerror(ep); 1379 rname = Strdup(uname); 1380 *dnamep = metadiskname(rname); 1381 return (rname); 1382 } 1383 1384 /* 1385 * Handle old style block names 1386 */ 1387 if (sscanf(uname, 1388 "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u" 1389 "%" VAL2STR(BUFSIZ) "[a-h]%n", 1390 onmb, &d, snm, &l) == 3 && l == strlen(uname)) { 1391 len = strlen(uname) + 1 + 1; 1392 rname = Malloc(len); 1393 (void) snprintf(rname, len, "/dev/r%s%u%s", 1394 onmb, d, snm); 1395 *dnamep = metadiskname(rname); 1396 return (rname); 1397 } 1398 1399 /* /.../dsk/... */ 1400 if ((p = strstr(uname, "/dsk/")) != NULL) { 1401 mdclrerror(ep); 1402 ++p; 1403 rname = Malloc(strlen(uname) + 1 + 1); 1404 (void) strncpy(rname, uname, (p - uname)); 1405 rname[(p - uname)] = 'r'; 1406 (void) strcpy(&rname[(p - uname) + 1], p); 1407 *dnamep = metadiskname(rname); 1408 return (rname); 1409 } 1410 1411 /* /.../rdsk/... */ 1412 else if (strstr(uname, "/rdsk/") != NULL) { 1413 mdclrerror(ep); 1414 rname = Strdup(uname); 1415 *dnamep = metadiskname(rname); 1416 return (rname); 1417 } 1418 } else { 1419 /* 1420 * If it's not an absolute name but is a valid ctd name, 1421 * guess at /dev/rdsk/... 1422 */ 1423 uint_t s; 1424 if (parse_ctd(uname, &s) == 0) { 1425 len = strlen(uname) + strlen("/dev/rdsk/") + 1; 1426 rname = Malloc(len); 1427 (void) snprintf(rname, len, "/dev/rdsk/%s", 1428 uname); 1429 *dnamep = metadiskname(rname); 1430 return (rname); 1431 } 1432 } 1433 } 1434 1435 /* out of luck */ 1436 return (NULL); 1437 } 1438 1439 /* 1440 * get number of slices for name 1441 */ 1442 static int 1443 getnslice( 1444 char *rname, 1445 char *dname, 1446 uint_t *slicep 1447 ) 1448 { 1449 char *srname; 1450 uint_t nslice; 1451 size_t dl = strlen(dname); 1452 size_t rl = strlen(rname); 1453 size_t l = 0; 1454 size_t len; 1455 1456 /* 1457 * get our slice number - works only with names that end in s%u - 1458 * all others return -1. 1459 */ 1460 if (dl >= rl || 1461 sscanf(&rname[dl], "s%u%n", slicep, &l) != 1 || l != rl || 1462 (int)*slicep < 0) { 1463 return (-1); 1464 } 1465 1466 /* 1467 * go find how many slices there really are 1468 */ 1469 len = strlen(dname) + 20 + 1; 1470 srname = Malloc(len); 1471 for (nslice = 0; /* void */; ++nslice) { 1472 struct stat statbuf; 1473 1474 /* build slice name */ 1475 (void) snprintf(srname, len, "%ss%u", dname, nslice); 1476 1477 /* see if it's there */ 1478 if ((meta_stat(srname, &statbuf) != 0) || 1479 (! S_ISCHR(statbuf.st_mode))) { 1480 break; 1481 } 1482 } 1483 Free(srname); 1484 1485 /* Need to make sure that we at least have V_NUMPAR */ 1486 nslice = max(nslice, V_NUMPAR); 1487 1488 /* make sure we have at least our slice */ 1489 if (nslice < *slicep) 1490 return (-1); 1491 1492 /* return number of slices */ 1493 return (nslice); 1494 } 1495 1496 /* 1497 * Attempt to parse the input string as a c[t]ds specifier 1498 * The target can either be a SCSI target id or if the device 1499 * is in a fabric configuration in a fibre channel setup then 1500 * the target is a standard WWN (world wide name). 1501 * 1502 * if successful return 0 1503 * if c[t]dp name return 1 1504 * otherwise return -1 1505 */ 1506 int 1507 parse_ctd( 1508 char *uname, 1509 uint_t *slice) 1510 { 1511 uint_t channel; 1512 uint_t target; 1513 uint_t device; 1514 int has_target = 1; 1515 uint_t cl; 1516 uint_t target_str_len; 1517 char *partial_ctd_str; 1518 char *target_str; 1519 char *device_start_pos; 1520 int l = -1; 1521 1522 /* pull off the channel spec and the 't' for the target */ 1523 if (sscanf(uname, "c%ut%n", &channel, &l) != 1 || l == -1) { 1524 /* check for cds style name */ 1525 if (sscanf(uname, "c%ud%n", &channel, &l) != 1 || l == -1) { 1526 return (-1); 1527 } else { 1528 l--; /* we want to be on the 'd' */ 1529 has_target = 0; 1530 } 1531 } 1532 partial_ctd_str = uname + l; 1533 1534 /* find the beginning of the device specifier */ 1535 device_start_pos = strrchr(partial_ctd_str, 'd'); 1536 if (device_start_pos == NULL) { 1537 return (-1); 1538 } 1539 1540 /* check to see if it is a ctd with a WWN or SCSI target */ 1541 if (has_target) { 1542 /* pull off the target and see if it is a WWN */ 1543 target_str_len = device_start_pos - partial_ctd_str + 2; 1544 target_str = (char *)Malloc(target_str_len+1); 1545 (void) strcpy(target_str, "0X"); 1546 (void) strncpy(target_str+2, partial_ctd_str, 1547 target_str_len - 2); 1548 target_str[target_str_len] = '\0'; 1549 if (sscanf(target_str, "%x%n", &target, &l) != 1 || 1550 l != target_str_len) { 1551 Free(target_str); 1552 return (-1); 1553 } 1554 Free(target_str); 1555 } 1556 1557 /* check the device and slice */ 1558 cl = strlen(device_start_pos); 1559 if (sscanf(device_start_pos, "d%us%u%n", &device, slice, &l) != 2 || 1560 l != cl) { 1561 /* check the device and partition */ 1562 if (sscanf(device_start_pos, "d%up%u%n", &device, slice, &l) 1563 == 2 && l == cl) { 1564 return (1); 1565 } 1566 return (-1); 1567 } 1568 1569 return (0); 1570 } 1571 1572 1573 /* 1574 * get number of slices for name 1575 */ 1576 static int 1577 uname2sliceno( 1578 char *uname, 1579 uint_t *slicep, 1580 md_error_t *ep 1581 ) 1582 { 1583 uint_t c = 0, t = 0, d = 0; 1584 int l = 0, cl = 0; 1585 int fd; 1586 struct dk_cinfo cinfo; 1587 char *p; 1588 char *rname = NULL; 1589 1590 if (is_metaname(uname)) 1591 return (*slicep = 0); 1592 1593 if ((p = strrchr(uname, '/')) != NULL) 1594 p++; 1595 else 1596 p = uname; 1597 1598 cl = strlen(p); 1599 1600 if (parse_ctd(p, slicep) == 0) 1601 return (*slicep); 1602 else if (sscanf(p, "mc%ut%ud%us%u%n", &c, &t, &d, slicep, &l) == 4 && 1603 l == cl) 1604 return (*slicep); 1605 else if (sscanf(p, "d%us%u%n", &d, slicep, &l) == 2 && l == cl) 1606 return (*slicep); 1607 1608 /* 1609 * If we can't get the slice from the name, then we have to do it the 1610 * hard and expensive way. 1611 */ 1612 if ((rname = rawname(uname)) == NULL) 1613 return (-1); 1614 1615 /* get controller info */ 1616 if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) { 1617 Free(rname); 1618 return (-1); 1619 } 1620 1621 if (ioctl(fd, DKIOCINFO, &cinfo) != 0) { 1622 int save = errno; 1623 1624 if (save == ENOTTY) 1625 (void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname); 1626 else 1627 (void) mdsyserror(ep, save, rname); 1628 1629 Free(rname); 1630 (void) close(fd); 1631 return (-1); 1632 } 1633 (void) close(fd); /* sd/ssd bug */ 1634 1635 if (cinfo.dki_partition < V_NUMPAR) { 1636 Free(rname); 1637 return (*slicep = cinfo.dki_partition); 1638 } 1639 1640 return (mddeverror(ep, MDE_NOT_DISK, NODEV64, rname)); 1641 } 1642 1643 /* 1644 * get partition info 1645 */ 1646 static int 1647 getparts( 1648 mddrivename_t *dnp, 1649 char *rname, 1650 char *dname, 1651 uint_t *npartsp, 1652 uint_t *partnop, 1653 md_error_t *ep 1654 ) 1655 { 1656 int nparts; 1657 uint_t partno; 1658 mdname_t name; 1659 mdvtoc_t *vtocp; 1660 1661 /* metadevice */ 1662 if (is_metaname(rname)) { 1663 dnp->type = MDT_META; 1664 nparts = 1; 1665 partno = 0; 1666 goto gotit; 1667 } 1668 1669 /* see how many partitions in drive, this is really tricky */ 1670 metainitname(&name); 1671 name.rname = rname; 1672 name.drivenamep = dnp; 1673 if ((vtocp = metagetvtoc(&name, TRUE, &partno, ep)) != NULL) { 1674 dnp->type = MDT_COMP; 1675 nparts = vtocp->nparts; 1676 /* partno already setup */ 1677 /* dname already setup */ 1678 goto gotit; 1679 } 1680 1681 if ((ep->info.errclass == MDEC_DEV) && 1682 (ep->info.md_error_info_t_u.dev_error.errnum == MDE_TOO_MANY_PARTS)) 1683 return (-1); 1684 1685 /* fallback and try and guess (used to check for just EACCES here) */ 1686 if ((dname != NULL) && 1687 ((nparts = getnslice(rname, dname, &partno)) > 0)) { 1688 dnp->type = MDT_ACCES; 1689 if (mdanysyserror(ep)) { 1690 dnp->errnum = 1691 ep->info.md_error_info_t_u.sys_error.errnum; 1692 } else { 1693 dnp->errnum = ENOENT; 1694 } 1695 mdclrerror(ep); 1696 /* nparts already setup */ 1697 /* partno already setup */ 1698 /* dname already setup */ 1699 nparts = roundup(nparts, V_NUMPAR); 1700 goto gotit; 1701 } 1702 1703 /* nothing worked */ 1704 dnp->type = MDT_UNKNOWN; 1705 if (mdissyserror(ep, EACCES)) 1706 dnp->type = MDT_ACCES; 1707 1708 if (mdanysyserror(ep)) { 1709 dnp->errnum = ep->info.md_error_info_t_u.sys_error.errnum; 1710 } else { 1711 dnp->errnum = ENOENT; 1712 } 1713 1714 mdclrerror(ep); 1715 nparts = V_NUMPAR; 1716 if (uname2sliceno(rname, &partno, ep) < 0) { 1717 mdclrerror(ep); 1718 partno = 0; 1719 } 1720 1721 /* return success */ 1722 gotit: 1723 assert(nparts > 0); 1724 1725 if (partno >= nparts) 1726 return (mdsyserror(ep, ENOENT, rname)); 1727 1728 *npartsp = nparts; 1729 *partnop = partno; 1730 return (0); 1731 } 1732 1733 /* 1734 * get block name 1735 */ 1736 static int 1737 getbname( 1738 mdname_t *np, 1739 md_error_t *ep 1740 ) 1741 { 1742 char *rname = np->rname; 1743 char *bname; 1744 1745 /* fully qualified */ 1746 assert(rname != NULL); 1747 if ((bname = blkname(rname)) != NULL) { 1748 if (np->bname) 1749 Free(np->bname); 1750 np->bname = bname; 1751 return (0); 1752 } 1753 1754 /* out of luck */ 1755 return (mdsyserror(ep, ENOENT, rname)); 1756 } 1757 1758 static void 1759 getcname( 1760 mdsetname_t *sp, 1761 mdname_t *np 1762 ) 1763 { 1764 char *sname = sp->setname; 1765 char *bname = np->bname; 1766 char *p; 1767 size_t len; 1768 1769 assert(sname != NULL); 1770 assert(bname != NULL); 1771 assert(np->drivenamep->type != MDT_FAST_COMP && 1772 np->drivenamep->type != MDT_FAST_META); 1773 1774 /* regular device */ 1775 if ((strncmp(bname, "/dev/dsk/", strlen("/dev/dsk/")) == 0) && 1776 (strchr((p = bname + strlen("/dev/dsk/")), '/') == NULL)) { 1777 if (np->cname) 1778 Free(np->cname); 1779 np->cname = Strdup(p); 1780 return; 1781 } 1782 1783 if ((strncmp(bname, "/dev/ap/dsk/", strlen("/dev/ap/dsk/")) == 0) && 1784 (strchr((p = bname + strlen("/dev/ap/dsk/")), '/') == NULL)) { 1785 if (np->cname) 1786 Free(np->cname); 1787 np->cname = Strdup(p); 1788 return; 1789 } 1790 1791 if ((strncmp(bname, "/dev/did/dsk/", strlen("/dev/did/dsk/")) == 0) && 1792 (strchr((p = bname + strlen("/dev/did/dsk/")), '/') == NULL)) { 1793 if (np->cname) 1794 Free(np->cname); 1795 np->cname = Strdup(p); 1796 return; 1797 } 1798 1799 /* anything else but metadevice */ 1800 if (np->drivenamep->type != MDT_META) { 1801 if (np->cname) 1802 Free(np->cname); 1803 np->cname = Strdup(bname); 1804 return; 1805 } 1806 1807 /* metadevice */ 1808 p = strrchr(bname, '/'); 1809 assert(p != NULL); 1810 ++p; 1811 if (metaislocalset(sp)) { 1812 if (np->cname) 1813 Free(np->cname); 1814 np->cname = Strdup(p); 1815 } else { 1816 assert(sname[0] != '\0'); 1817 if (np->cname) 1818 Free(np->cname); 1819 len = strlen(sname) + 1 + strlen(p) + 1; 1820 np->cname = Malloc(len); 1821 (void) snprintf(np->cname, len, "%s/%s", sname, p); 1822 } 1823 } 1824 1825 /* 1826 * get dev 1827 */ 1828 int 1829 meta_getdev( 1830 mdsetname_t *sp, 1831 mdname_t *np, 1832 md_error_t *ep 1833 ) 1834 { 1835 struct stat statbuf; 1836 1837 /* get dev */ 1838 if (meta_stat(np->rname, &statbuf) != 0) 1839 return (mdsyserror(ep, errno, np->rname)); 1840 else if (! S_ISCHR(statbuf.st_mode)) 1841 return (mddeverror(ep, MDE_NOT_DISK, NODEV64, np->rname)); 1842 np->dev = meta_expldev(statbuf.st_rdev); 1843 1844 assert(np->drivenamep->type != MDT_FAST_META && 1845 np->drivenamep->type != MDT_FAST_COMP); 1846 1847 /* check set */ 1848 assert((np->drivenamep->type == MDT_META) ? 1849 (sp->setno == MD_MIN2SET(meta_getminor(np->dev))) : 1); 1850 1851 /* return sucess */ 1852 return (0); 1853 } 1854 1855 /* 1856 * set up names for a slice 1857 */ 1858 static int 1859 getnames( 1860 mdsetname_t *sp, 1861 mdname_t *np, 1862 char *rname, 1863 md_error_t *ep 1864 ) 1865 { 1866 /* get names */ 1867 if (np->rname) 1868 Free(np->rname); 1869 np->rname = Strdup(rname); 1870 if (getbname(np, ep) != 0) 1871 return (-1); 1872 getcname(sp, np); 1873 if (meta_getdev(sp, np, ep) != 0) 1874 return (-1); 1875 1876 /* return success */ 1877 return (0); 1878 } 1879 1880 /* 1881 * fake up names for a slice 1882 */ 1883 static void 1884 getfakenames( 1885 mdsetname_t *sp, 1886 mdname_t *np, 1887 char *rname 1888 ) 1889 { 1890 char *p; 1891 char onmb[BUFSIZ+1], snm[BUFSIZ+1]; 1892 uint_t d = 0; 1893 int l = 0; 1894 1895 /* fake names */ 1896 if (np->rname != NULL) 1897 Free(np->rname); 1898 np->rname = Strdup(rname); 1899 1900 if (np->bname != NULL) 1901 Free(np->bname); 1902 np->bname = Strdup(rname); 1903 1904 /* 1905 * Fixup old style names 1906 */ 1907 if (sscanf(rname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u" 1908 "%" VAL2STR(BUFSIZ) "[a-h]%n", 1909 onmb, &d, snm, &l) == 3 && l == strlen(rname)) 1910 (void) snprintf(np->bname, l, "/dev/%s%u%s", onmb, d, snm); 1911 1912 /* 1913 * Fixup new style names 1914 */ 1915 if ((p = strstr(np->bname, "/rdsk/")) != NULL) { 1916 for (++p; (*(p + 1) != '\0'); ++p) 1917 *p = *(p + 1); 1918 *p = '\0'; 1919 } 1920 1921 if (np->cname != NULL) 1922 Free(np->cname); 1923 getcname(sp, np); 1924 } 1925 1926 static mdname_t * 1927 setup_slice( 1928 mdsetname_t *sp, 1929 mddrivename_t *dnp, 1930 char *uname, 1931 char *rname, 1932 char *dname, 1933 uint_t partno, 1934 md_error_t *ep 1935 ) 1936 { 1937 char *srname = NULL; 1938 mdname_t *np; 1939 1940 /* must have a set */ 1941 assert(sp != NULL); 1942 assert(partno < dnp->parts.parts_len); 1943 assert(dname != NULL); 1944 1945 np = &dnp->parts.parts_val[partno]; 1946 1947 if (rname) 1948 srname = rname; 1949 else if (is_metaname(dname)) 1950 srname = dname; 1951 else { 1952 char onmb[BUFSIZ+1]; 1953 uint_t d = 0; 1954 int l = 0, cl = strlen(dname); 1955 size_t len; 1956 1957 len = cl + 20 + 1; 1958 srname = Malloc(len); 1959 1960 /* 1961 * Handle /dev/rXXNN. 1962 */ 1963 if (sscanf(dname, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u%n", 1964 onmb, &d, &l) == 2 && l == cl) { 1965 (void) snprintf(srname, len, "/dev/r%s%u%c", onmb, d, 1966 'a' + partno); 1967 } else if (sscanf(dname, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u%n", 1968 onmb, &d, &l) == 2 && l == cl) { 1969 (void) snprintf(srname, len, "/dev/%s%u%c", onmb, d, 1970 'a' + partno); 1971 } else { 1972 /* build the slice that is wanted */ 1973 (void) snprintf(srname, len, "%ss%u", dname, partno); 1974 } 1975 } 1976 1977 if (getnames(sp, np, srname, ep) != 0) { 1978 if (dnp->type == MDT_UNKNOWN) { 1979 mdclrerror(ep); 1980 getfakenames(sp, np, srname); 1981 } else if (dnp->type == MDT_COMP && mdissyserror(ep, ENOENT)) { 1982 dnp->type = MDT_UNKNOWN; 1983 if (mdanysyserror(ep)) { 1984 dnp->errnum = 1985 ep->info.md_error_info_t_u.sys_error.errnum; 1986 } else { 1987 dnp->errnum = ENOENT; 1988 } 1989 mdclrerror(ep); 1990 getfakenames(sp, np, srname); 1991 } else { 1992 mdclrerror(ep); 1993 if (getnames(sp, np, dname, ep) != 0) { 1994 np = NULL; 1995 goto fixup; 1996 } 1997 } 1998 } 1999 2000 out: 2001 if ((srname != rname) && (srname != dname)) 2002 Free(srname); 2003 2004 /* return name */ 2005 return (np); 2006 2007 fixup: 2008 if (mdanysyserror(ep)) { 2009 char *p; 2010 int errnum = ep->info.md_error_info_t_u.sys_error.errnum; 2011 2012 mdclrerror(ep); 2013 if (uname && *uname) { 2014 if ((p = strrchr(uname, '/')) != NULL) 2015 (void) mdsyserror(ep, errnum, ++p); 2016 else 2017 (void) mdsyserror(ep, errnum, uname); 2018 } else { 2019 if ((p = strrchr(srname, '/')) != NULL) 2020 (void) mdsyserror(ep, errnum, ++p); 2021 else 2022 (void) mdsyserror(ep, errnum, srname); 2023 } 2024 } 2025 goto out; 2026 } 2027 2028 /* 2029 * flush the fast name cache 2030 */ 2031 static void 2032 metafreefastnm(mdname_t **np) 2033 { 2034 mddrivename_t *dnp; 2035 2036 assert(np != NULL && *np != NULL); 2037 2038 if ((dnp = (*np)->drivenamep) != NULL) { 2039 if (dnp->cname != NULL) 2040 Free(dnp->cname); 2041 if (dnp->rname != NULL) 2042 Free(dnp->rname); 2043 if (dnp->miscname != NULL) 2044 Free(dnp->miscname); 2045 meta_free_unit(dnp); 2046 Free(dnp); 2047 } 2048 if ((*np)->cname != NULL) 2049 Free((*np)->cname); 2050 if ((*np)->bname != NULL) 2051 Free((*np)->bname); 2052 if ((*np)->rname != NULL) 2053 Free((*np)->rname); 2054 if ((*np)->devicesname != NULL) 2055 Free((*np)->devicesname); 2056 Free(*np); 2057 *np = NULL; 2058 } 2059 2060 /* 2061 * flush the fast name cache 2062 */ 2063 static void 2064 metaflushfastnames() 2065 { 2066 mdnamelist_t *p, *n; 2067 2068 for (p = fastnmlp, n = NULL; (p != NULL); p = n) { 2069 n = p->next; 2070 metafreefastnm(&p->namep); 2071 Free(p); 2072 } 2073 fastnmlp = NULL; 2074 } 2075 2076 static char * 2077 getrname_fast(char *unm, md_error_t *ep) 2078 { 2079 uint_t d = 0; 2080 int l = 0; 2081 int cl = strlen(unm); 2082 char onmb[BUFSIZ+1], snm[BUFSIZ+1], cnmb[BUFSIZ]; 2083 char *rnm; 2084 char *p; 2085 size_t len; 2086 2087 if (is_metaname(unm)) { 2088 /* without set */ 2089 if (sscanf(unm, "d%u%n", &d, &l) == 1 && cl == l) { 2090 rnm = Zalloc(14 + cl + 1); 2091 (void) sprintf(rnm, "/dev/md/rdsk/d%u", d); 2092 return (rnm); 2093 } 2094 2095 /* fully-qualified without set */ 2096 if ((sscanf(unm, "/dev/md/dsk/d%u%n", &d, &l) == 1 || 2097 sscanf(unm, "/dev/md/rdsk/d%u%n", &d, &l) == 1) && 2098 cl == l) { 2099 rnm = Zalloc(14 + cl + 1); 2100 (void) sprintf(rnm, "/dev/md/rdsk/d%u", d); 2101 return (rnm); 2102 } 2103 2104 /* with set */ 2105 if ((sscanf(unm, 2106 "%" VAL2STR(BUFSIZ) "[^/]/d%u%n", snm, &d, &l) == 2 || 2107 sscanf(unm, "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/dsk/d%u%n", 2108 snm, &d, &l) == 2 || 2109 sscanf(unm, "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/rdsk/d%u%n", 2110 snm, &d, &l) == 2) && cl == l) { 2111 len = 14 + cl + strlen(snm) + 1; 2112 rnm = Zalloc(len); 2113 (void) snprintf(rnm, len, "/dev/md/%s/rdsk/d%u", 2114 snm, d); 2115 return (rnm); 2116 } 2117 } 2118 2119 /* NOT Fully qualified path, done */ 2120 if (unm[0] != '/') { 2121 (void) mdsyserror(ep, EINVAL, unm); 2122 return (NULL); 2123 } 2124 2125 /* 2126 * Get slice information from old style names of the form 2127 * /dev/rXXNN[a-h] or /dev/XXNN[a-h], must be done before regular 2128 * devices, but after metadevices. 2129 */ 2130 if ((sscanf(unm, "/dev/r%" VAL2STR(BUFSIZ) "[^0-9/]%u" 2131 "%" VAL2STR(BUFSIZ) "[a-h]%n", 2132 onmb, &d, snm, &l) == 3 || 2133 sscanf(unm, "/dev/%" VAL2STR(BUFSIZ) "[^0-9/]%u" 2134 "%" VAL2STR(BUFSIZ) "[a-h]%n", 2135 onmb, &d, snm, &l) == 3) && l == cl) { 2136 if ((p = strchr("abcdefgh", snm[0])) != NULL) { 2137 (void) snprintf(cnmb, sizeof (cnmb), "/dev/r%s%u%s", 2138 onmb, d, snm); 2139 return (Strdup(cnmb)); 2140 } 2141 } 2142 2143 if ((p = strstr(unm, "/dsk/")) != NULL) { /* /.../dsk/... */ 2144 ++p; 2145 rnm = Zalloc(strlen(unm) + 1 + 1); 2146 (void) strncpy(rnm, unm, (p - unm)); 2147 rnm[(p - unm)] = 'r'; 2148 (void) strcpy(&rnm[(p - unm) + 1], p); 2149 return (rnm); 2150 } else if (strstr(unm, "/rdsk/") != NULL) { /* /.../rdsk/... */ 2151 return (Strdup(unm)); 2152 } 2153 2154 /* 2155 * Shouldn't get here but if we do then we have an unrecognized 2156 * fully qualified path - error 2157 */ 2158 (void) mdsyserror(ep, EINVAL, unm); 2159 return (NULL); 2160 } 2161 2162 static mdname_t * 2163 metainitfastname( 2164 mdsetname_t *sp, 2165 char *uname, 2166 md_error_t *ep 2167 ) 2168 { 2169 uint_t c = 0, t = 0, d = 0, s = 0; 2170 int l = 0; 2171 mddrivename_t *dnp; 2172 mdname_t *np; 2173 mdnamelist_t **fnlpp; 2174 2175 for (fnlpp = &fastnmlp; (*fnlpp != NULL); fnlpp = &(*fnlpp)->next) { 2176 np = (*fnlpp)->namep; 2177 2178 if (strcmp(np->bname, uname) == 0) 2179 return (np); 2180 } 2181 2182 *fnlpp = Zalloc(sizeof (**fnlpp)); 2183 np = (*fnlpp)->namep = Zalloc(sizeof (mdname_t)); 2184 metainitname(np); 2185 dnp = np->drivenamep = Zalloc(sizeof (mddrivename_t)); 2186 metainitdrivename(dnp); 2187 2188 2189 /* Metadevices */ 2190 if (is_metaname(uname)) { 2191 char *p; 2192 size_t len; 2193 2194 if ((p = strrchr(uname, '/')) != NULL) 2195 ++p; 2196 else 2197 p = uname; 2198 2199 if (metaislocalset(sp)) { 2200 if (np->cname) 2201 Free(np->cname); 2202 np->cname = Strdup(p); 2203 } else { 2204 if (np->cname) 2205 Free(np->cname); 2206 len = strlen(sp->setname) + 1 + strlen(p) + 1; 2207 np->cname = Zalloc(len); 2208 (void) snprintf(np->cname, len, "%s/%s", 2209 sp->setname, p); 2210 } 2211 dnp->type = MDT_FAST_META; 2212 goto done; 2213 } 2214 2215 /* Others */ 2216 dnp->type = MDT_FAST_COMP; 2217 2218 if (((sscanf(uname, "/dev/rdsk/c%ut%ud%us%u%n", &c, &t, &d, 2219 &s, &l) == 4 || 2220 sscanf(uname, "/dev/dsk/c%ut%ud%us%u%n", &c, &t, &d, 2221 &s, &l) == 4 || 2222 sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%us%u%n", &c, &t, &d, 2223 &s, &l) == 4 || 2224 sscanf(uname, "/dev/ap/dsk/mc%ut%ud%us%u%n", &c, &t, &d, 2225 &s, &l) == 4 || 2226 sscanf(uname, "/dev/did/rdsk/d%us%u%n", &t, &s, &l) == 2 || 2227 sscanf(uname, "/dev/did/dsk/d%us%u%n", &t, &s, &l) == 2|| 2228 sscanf(uname, "/dev/rdsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 || 2229 sscanf(uname, "/dev/dsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 || 2230 sscanf(uname, "/dev/rdsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 || 2231 sscanf(uname, "/dev/dsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 || 2232 sscanf(uname, "/dev/ap/rdsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 || 2233 sscanf(uname, "/dev/ap/dsk/mc%ut%ud%u%n", &c, &t, &d, &l) == 3 || 2234 sscanf(uname, "/dev/did/rdsk/d%u%n", &t, &l) == 1 || 2235 sscanf(uname, "/dev/did/dsk/d%u%n", &t, &l) == 1 || 2236 sscanf(uname, "/dev/rdsk/c%ud%u%n", &c, &d, &l) == 2 || 2237 sscanf(uname, "/dev/dsk/c%ud%u%n", &c, &d, &l) == 2) && 2238 l == strlen(uname))) { 2239 if ((np->cname = strrchr(uname, '/')) == NULL) 2240 np->cname = Strdup(uname); 2241 else 2242 np->cname = Strdup(++np->cname); 2243 } else { 2244 np->cname = Strdup(uname); 2245 } 2246 2247 done: 2248 /* Driver always gives us block names */ 2249 np->bname = Strdup(uname); 2250 2251 /* canonical disk name */ 2252 if ((dnp->cname = metadiskname(np->cname)) == NULL) 2253 dnp->cname = Strdup(np->cname); 2254 2255 if ((np->rname = getrname_fast(uname, ep)) != NULL) { 2256 if ((dnp->rname = metadiskname(np->rname)) == NULL) 2257 dnp->rname = Strdup(np->rname); 2258 } else { 2259 metafreefastnm(&(*fnlpp)->namep); 2260 Free(*fnlpp); 2261 *fnlpp = NULL; 2262 return (NULL); 2263 } 2264 2265 /* cleanup, return success */ 2266 return (np); 2267 } 2268 2269 /* 2270 * set up names for a device 2271 */ 2272 static mdname_t * 2273 metaname_common( 2274 mdsetname_t **spp, 2275 char *uname, 2276 int fast, 2277 md_error_t *ep 2278 ) 2279 { 2280 mddrivenamelist_t **tail; 2281 mddrivename_t *dnp; 2282 uint_t slice; 2283 mdname_t *np; 2284 char *rname = NULL; 2285 char *dname = NULL; 2286 char *cname = NULL; 2287 uint_t nparts, partno; 2288 2289 assert(uname != NULL); 2290 2291 /* check setname */ 2292 if ((cname = meta_name_getname(spp, uname, ep)) == NULL) 2293 return (NULL); 2294 2295 assert(*spp != NULL); 2296 Free(cname); 2297 2298 /* get raw name (rname) of the slice and drive (dname) we have */ 2299 if ((rname = getrawnames(spp, uname, &dname, ep)) == NULL) { 2300 return (NULL); 2301 } 2302 2303 /* look in cache first */ 2304 for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { 2305 dnp = (*tail)->drivenamep; 2306 2307 /* check to see if the drive name is already in the cache */ 2308 if ((dnp->rname != NULL) && strcmp(dnp->rname, dname) == 0) { 2309 2310 Free(rname); 2311 if (dname != NULL) 2312 Free(dname); 2313 2314 if (uname2sliceno(uname, &partno, ep) < 0) 2315 return (NULL); 2316 2317 return (metaslicename(dnp, partno, ep)); 2318 } 2319 } 2320 2321 /* 2322 * If a fast names is OK, then get one, and be done. 2323 */ 2324 if (fast) { 2325 Free(rname); 2326 if (dname != NULL) 2327 Free(dname); 2328 2329 return (metainitfastname(*spp, uname, ep)); 2330 } 2331 2332 /* allocate new list element and drive */ 2333 *tail = Zalloc(sizeof (**tail)); 2334 dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp)); 2335 2336 metainitdrivename(dnp); 2337 2338 /* get parts info */ 2339 if (getparts(dnp, rname, dname, &nparts, &partno, ep) != 0) 2340 goto out; 2341 2342 /* 2343 * libmeta needs at least V_NUMPAR partitions. 2344 * If we have an EFI partition with less than V_NUMPAR slices, 2345 * we nevertheless reserve space for V_NUMPAR 2346 */ 2347 if (nparts < V_NUMPAR) { 2348 nparts = V_NUMPAR; 2349 } 2350 2351 /* allocate and link in parts */ 2352 dnp->parts.parts_len = nparts; 2353 dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) * 2354 dnp->parts.parts_len); 2355 for (slice = 0; (slice < nparts); ++slice) { 2356 np = &dnp->parts.parts_val[slice]; 2357 metainitname(np); 2358 np->drivenamep = dnp; 2359 } 2360 2361 /* setup name_t (or slice) wanted */ 2362 if ((np = setup_slice(*spp, dnp, uname, rname, dname, partno, ep)) 2363 == NULL) 2364 goto out; 2365 2366 /* canonical disk name */ 2367 if ((dnp->cname = metadiskname(np->cname)) == NULL) 2368 dnp->cname = Strdup(np->cname); 2369 if ((dnp->rname = metadiskname(np->rname)) == NULL) 2370 dnp->rname = Strdup(np->rname); 2371 2372 /* cleanup, return success */ 2373 if (dname != NULL) 2374 Free(dname); 2375 Free(rname); 2376 return (np); 2377 2378 /* cleanup, return error */ 2379 out: 2380 if (dname != NULL) 2381 Free(dname); 2382 if (rname != NULL) 2383 Free(rname); 2384 2385 metafreedrivename(dnp); 2386 Free(dnp); 2387 Free(*tail); 2388 *tail = NULL; 2389 return (NULL); 2390 } 2391 2392 mdname_t * 2393 metaname( 2394 mdsetname_t **spp, 2395 char *uname, 2396 md_error_t *ep 2397 ) 2398 { 2399 return (metaname_common(spp, uname, 0, ep)); 2400 } 2401 2402 mdname_t * 2403 metaname_fast( 2404 mdsetname_t **spp, 2405 char *uname, 2406 md_error_t *ep 2407 ) 2408 { 2409 return (metaname_common(spp, uname, 1, ep)); 2410 } 2411 2412 /* 2413 * set up names for a drive 2414 */ 2415 mddrivename_t * 2416 metadrivename( 2417 mdsetname_t **spp, 2418 char *uname, 2419 md_error_t *ep 2420 ) 2421 { 2422 char *slicename; 2423 mdname_t *np; 2424 2425 char *cname; 2426 mddrivenamelist_t **tail; 2427 mddrivename_t *dnp; 2428 char *dname; 2429 int i; 2430 int mplen; 2431 size_t len; 2432 2433 /* check setname, get comparison name */ 2434 assert(uname != NULL); 2435 if ((cname = meta_name_getname(spp, uname, ep)) == NULL) { 2436 (void) mdsyserror(ep, ENOENT, uname); 2437 return (NULL); 2438 } 2439 2440 assert(*spp != NULL); 2441 2442 if ((dname = metadiskname(cname)) == NULL) { 2443 (void) mdsyserror(ep, ENOENT, cname); 2444 Free(cname); 2445 return (NULL); 2446 } 2447 2448 /* look in cache first */ 2449 for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { 2450 dnp = (*tail)->drivenamep; 2451 if ((dnp->cname != NULL && 2452 (strcmp(dnp->cname, dname) == 0)) || 2453 (dnp->rname != NULL && 2454 (strcmp(dnp->rname, dname) == 0))) { 2455 Free(cname); 2456 Free(dname); 2457 return (dnp); 2458 } 2459 } 2460 2461 /* Check each possible slice name based on MD_MAX_PARTS. */ 2462 2463 /* 2464 * Figure out how much string space to reserve to fit 2465 * (MD_MAX_PARTS - 1) into the name string; the loop will 2466 * increment the mplen counter once for each decimal digit in 2467 * (MD_MAX_PARTS - 1). 2468 */ 2469 for (i = MD_MAX_PARTS - 1, mplen = 0; i; i /= 10, ++mplen); 2470 len = strlen(uname) + mplen + 2; 2471 slicename = Malloc(len); 2472 2473 /* Check for each slice in turn until we find one */ 2474 for (np = NULL, i = 0; ((np == NULL) && (i < MD_MAX_PARTS)); ++i) { 2475 (void) snprintf(slicename, len, "%ss%d", uname, i); 2476 np = metaname(spp, slicename, ep); 2477 } 2478 Free(slicename); 2479 2480 if (np == NULL) { 2481 char *dname; 2482 2483 if ((mdissyserror(ep, ENOENT)) && 2484 ((dname = metadiskname(uname)) != NULL)) { 2485 Free(dname); 2486 (void) mderror(ep, MDE_NOT_DRIVENAME, uname); 2487 } 2488 return (NULL); 2489 } 2490 return (np->drivenamep); 2491 } 2492 2493 /* 2494 * FUNCTION: metaslicename() 2495 * INPUT: dnp - the drivename structure 2496 * sliceno - the slice on the drive to return 2497 * OUTPUT: ep - return error pointer 2498 * RETURNS: mdname_t- pointer the the slice name structure 2499 * PURPOSE: interface to the parts struct in the drive name struct 2500 * Since there is no guarantee that the slice name 2501 * structures are populated users should call this 2502 * function rather than accessing the structure directly 2503 * since it will populate the structure values if they 2504 * haven't already been populated before returning. 2505 */ 2506 mdname_t * 2507 metaslicename( 2508 mddrivename_t *dnp, 2509 uint_t sliceno, 2510 md_error_t *ep 2511 ) 2512 { 2513 mdsetname_t *sp = NULL; 2514 char *namep = NULL; 2515 mdname_t *np; 2516 2517 assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META); 2518 2519 if (sliceno >= dnp->parts.parts_len) { 2520 (void) mderror(ep, MDE_NOSLICE, dnp->cname); 2521 return (NULL); 2522 } 2523 2524 np = &dnp->parts.parts_val[sliceno]; 2525 2526 /* check to see if the struct is already populated */ 2527 if (np->cname) { 2528 return (np); 2529 } 2530 2531 if ((namep = meta_name_getname(&sp, dnp->cname, ep)) == NULL) 2532 return (NULL); 2533 2534 np = setup_slice(sp, dnp, NULL, NULL, dnp->rname, sliceno, ep); 2535 2536 Free(namep); 2537 2538 return (np); 2539 } 2540 2541 /* 2542 * set up metadevice name from id 2543 */ 2544 mdname_t * 2545 metamnumname( 2546 mdsetname_t **spp, 2547 minor_t mnum, 2548 int fast, 2549 md_error_t *ep 2550 ) 2551 { 2552 set_t setno = MD_MIN2SET(mnum); 2553 mdsetname_t *sp = NULL; 2554 char *uname; 2555 mdname_t *np; 2556 size_t len; 2557 2558 /* check set first */ 2559 if (spp == NULL) 2560 spp = &sp; 2561 if (chksetno(spp, setno, ep) != 0) 2562 return (NULL); 2563 assert(*spp != NULL); 2564 sp = *spp; 2565 2566 /* build corresponding device name */ 2567 if (metaislocalset(sp)) { 2568 uname = Malloc(20); 2569 (void) sprintf(uname, "d%lu", MD_MIN2UNIT(mnum)); 2570 } else { 2571 len = strlen(sp->setname) + 1 + 20; 2572 uname = Malloc(len); 2573 (void) snprintf(uname, len, "%s/d%lu", sp->setname, 2574 MD_MIN2UNIT(mnum)); 2575 } 2576 2577 /* setup name */ 2578 if (fast) { 2579 np = metaname_fast(spp, uname, ep); 2580 np->dev = metamakedev(mnum); 2581 } else 2582 np = metaname(spp, uname, ep); 2583 2584 Free(uname); 2585 return (np); 2586 } 2587 2588 /* 2589 * return metadevice name 2590 */ 2591 char * 2592 get_mdname( 2593 minor_t mnum 2594 ) 2595 { 2596 mdname_t *np; 2597 md_error_t status = mdnullerror; 2598 2599 /* get name */ 2600 if ((np = metamnumname(NULL, mnum, 0, &status)) == NULL) { 2601 mdclrerror(&status); 2602 return (NULL); 2603 } 2604 assert(meta_getminor(np->dev) == mnum); 2605 2606 /* return name */ 2607 return (np->cname); 2608 } 2609 2610 /* 2611 * check for device type 2612 */ 2613 int 2614 metaismeta( 2615 mdname_t *np 2616 ) 2617 { 2618 return (np->drivenamep->type == MDT_META || 2619 np->drivenamep->type == MDT_FAST_META); 2620 } 2621 2622 int 2623 metachkmeta( 2624 mdname_t *np, 2625 md_error_t *ep 2626 ) 2627 { 2628 if (! metaismeta(np)) { 2629 return (mddeverror(ep, MDE_NOT_META, np->dev, 2630 np->cname)); 2631 } 2632 return (0); 2633 } 2634 2635 int 2636 metachkdisk( 2637 mdname_t *np, 2638 md_error_t *ep 2639 ) 2640 { 2641 mddrivename_t *dnp = np->drivenamep; 2642 2643 assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META); 2644 2645 if ((! metaismeta(np)) && (dnp->type != MDT_COMP)) { 2646 switch (dnp->type) { 2647 case MDT_ACCES: 2648 case MDT_UNKNOWN: 2649 return (mdsyserror(ep, dnp->errnum, np->bname)); 2650 default: 2651 assert(0); 2652 return (mddeverror(ep, MDE_NOT_DISK, np->dev, 2653 np->cname)); 2654 } 2655 } 2656 return (0); 2657 } 2658 2659 int 2660 metachkcomp( 2661 mdname_t *np, 2662 md_error_t *ep 2663 ) 2664 { 2665 if (metaismeta(np)) { 2666 return (mddeverror(ep, MDE_IS_META, np->dev, 2667 np->cname)); 2668 } 2669 return (metachkdisk(np, ep)); 2670 } 2671 2672 /* 2673 * free list of names 2674 */ 2675 void 2676 metafreenamelist( 2677 mdnamelist_t *nlp 2678 ) 2679 { 2680 mdnamelist_t *next = NULL; 2681 2682 for (/* void */; (nlp != NULL); nlp = next) { 2683 next = nlp->next; 2684 Free(nlp); 2685 } 2686 } 2687 2688 /* 2689 * build list of names 2690 */ 2691 int 2692 metanamelist( 2693 mdsetname_t **spp, 2694 mdnamelist_t **nlpp, 2695 int argc, 2696 char *argv[], 2697 md_error_t *ep 2698 ) 2699 { 2700 mdnamelist_t **tailpp = nlpp; 2701 int count = 0; 2702 2703 for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 2704 mdnamelist_t *nlp = Zalloc(sizeof (*nlp)); 2705 2706 if ((nlp->namep = metaname(spp, argv[0], ep)) == NULL) { 2707 metafreenamelist(*nlpp); 2708 *nlpp = NULL; 2709 return (-1); 2710 } 2711 *tailpp = nlp; 2712 tailpp = &nlp->next; 2713 } 2714 return (count); 2715 } 2716 2717 /* 2718 * append to end of name list 2719 */ 2720 mdname_t * 2721 metanamelist_append( 2722 mdnamelist_t **nlpp, 2723 mdname_t *np 2724 ) 2725 { 2726 mdnamelist_t *nlp; 2727 2728 /* run to end of list */ 2729 for (; (*nlpp != NULL); nlpp = &(*nlpp)->next) 2730 ; 2731 2732 /* allocate new list element */ 2733 nlp = *nlpp = Zalloc(sizeof (*nlp)); 2734 2735 /* append name */ 2736 nlp->namep = np; 2737 return (np); 2738 } 2739 2740 /* 2741 * FUNCTION: meta_namelist_append_wrapper() 2742 * INPUT: tailpp - pointer to the list tail pointer 2743 * np - name node to be appended to list 2744 * OUTPUT: none 2745 * RETURNS: mdnamelist_t * - new tail of the list. 2746 * PURPOSE: wrapper to meta_namelist_append for performance. 2747 * metanamelist_append finds the tail each time which slows 2748 * down long lists. By keeping track of the tail ourselves 2749 * we can change metanamelist_append into a constant time 2750 * operation. 2751 */ 2752 mdnamelist_t ** 2753 meta_namelist_append_wrapper( 2754 mdnamelist_t **tailpp, 2755 mdname_t *np 2756 ) 2757 { 2758 (void) metanamelist_append(tailpp, np); 2759 2760 /* If it's the first item in the list, return it instead of the next */ 2761 if ((*tailpp)->next == NULL) 2762 return (tailpp); 2763 2764 return (&(*tailpp)->next); 2765 } 2766 2767 2768 /* 2769 * mdhspname_t stuff 2770 */ 2771 2772 /* 2773 * initialize hspname 2774 */ 2775 static void 2776 metainithspname( 2777 mdhspname_t *hspnamep 2778 ) 2779 { 2780 (void) memset(hspnamep, '\0', sizeof (*hspnamep)); 2781 hspnamep->hsp = MD_HSP_NONE; 2782 } 2783 2784 /* 2785 * free allocated hspname 2786 */ 2787 static void 2788 metafreehspname( 2789 mdhspname_t *hspnamep 2790 ) 2791 { 2792 if (hspnamep->hspname != NULL) 2793 Free(hspnamep->hspname); 2794 if (hspnamep->unitp != NULL) 2795 meta_invalidate_hsp(hspnamep); 2796 metainithspname(hspnamep); 2797 } 2798 2799 /* 2800 * clear the hspname cache 2801 */ 2802 static void 2803 metaflushhspnames() 2804 { 2805 mdhspnamelist_t *p, *n; 2806 2807 for (p = hsplistp, n = NULL; (p != NULL); p = n) { 2808 n = p->next; 2809 metafreehspname(p->hspnamep); 2810 Free(p->hspnamep); 2811 Free(p); 2812 } 2813 hsplistp = NULL; 2814 } 2815 2816 /* 2817 * check set and get comparison name 2818 */ 2819 static char * 2820 gethspname( 2821 mdsetname_t **spp, 2822 char *uname, 2823 hsp_t *hspp, 2824 md_error_t *ep 2825 ) 2826 { 2827 char *sname = NULL; 2828 2829 /* check setname */ 2830 assert(uname != NULL); 2831 if (parse_hsp(uname, &sname, hspp) != 0) { 2832 (void) mdsyserror(ep, ENOENT, uname); 2833 return (NULL); 2834 } 2835 if (chksetname(spp, sname, ep) != 0) { 2836 if (sname != NULL) 2837 Free(sname); 2838 return (NULL); 2839 } 2840 if (sname != NULL) 2841 Free(sname); 2842 2843 /* return comparison name */ 2844 return (canon_hsp((*spp)->setname, *hspp)); 2845 } 2846 2847 /* 2848 * set up names for a hotspare pool 2849 */ 2850 mdhspname_t * 2851 metahspname( 2852 mdsetname_t **spp, 2853 char *uname, 2854 md_error_t *ep 2855 ) 2856 { 2857 char *cname; 2858 hsp_t hsp; 2859 mdhspnamelist_t **tail; 2860 mdhspname_t *hspnp; 2861 2862 /* check setname */ 2863 assert(uname != NULL); 2864 if ((cname = gethspname(spp, uname, &hsp, ep)) == NULL) 2865 return (NULL); 2866 assert(*spp != NULL); 2867 2868 /* look in cache first */ 2869 for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) { 2870 hspnp = (*tail)->hspnamep; 2871 if (strcmp(hspnp->hspname, cname) == 0) { 2872 Free(cname); 2873 return (hspnp); 2874 } 2875 } 2876 2877 /* allocate new list element and hspname */ 2878 *tail = Zalloc(sizeof (**tail)); 2879 hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp)); 2880 metainithspname(hspnp); 2881 2882 /* save hspname and number */ 2883 hspnp->hspname = cname; 2884 hspnp->hsp = MAKE_HSP_ID((*spp)->setno, hsp); 2885 2886 /* success */ 2887 return (hspnp); 2888 2889 /* cleanup, return error */ 2890 out: 2891 metafreehspname(hspnp); 2892 Free(hspnp); 2893 Free(*tail); 2894 *tail = NULL; 2895 return (NULL); 2896 2897 2898 } 2899 2900 /* 2901 * set up hotspare pool name from id 2902 */ 2903 mdhspname_t * 2904 metahsphspname( 2905 mdsetname_t **spp, 2906 hsp_t hsp, 2907 md_error_t *ep 2908 ) 2909 { 2910 set_t setno = HSP_SET(hsp); 2911 mdsetname_t *sp = NULL; 2912 char *uname; 2913 mdhspname_t *hspnp; 2914 size_t len; 2915 2916 /* check set first */ 2917 if (spp == NULL) 2918 spp = &sp; 2919 if (chksetno(spp, setno, ep) != 0) 2920 return (NULL); 2921 assert(*spp != NULL); 2922 sp = *spp; 2923 2924 /* build corresponding hotspare pool name */ 2925 if (metaislocalset(sp)) { 2926 uname = Malloc(20); 2927 (void) sprintf(uname, "hsp%03u", HSP_ID(hsp)); 2928 } else { 2929 len = strlen(sp->setname) + 1 + 20; 2930 uname = Malloc(len); 2931 (void) snprintf(uname, len, "%s/hsp%03lu", sp->setname, 2932 HSP_ID(hsp)); 2933 } 2934 2935 /* setup name */ 2936 hspnp = metahspname(spp, uname, ep); 2937 Free(uname); 2938 return (hspnp); 2939 } 2940 2941 /* 2942 * return hotspare pool name 2943 */ 2944 char * 2945 get_hspname(hsp_t hsp) 2946 { 2947 mdhspname_t *hspnp; 2948 md_error_t status = mdnullerror; 2949 2950 /* get name */ 2951 if ((hspnp = metahsphspname(NULL, hsp, &status)) == NULL) { 2952 mdclrerror(&status); 2953 return (NULL); 2954 } 2955 2956 /* return name */ 2957 return (hspnp->hspname); 2958 } 2959 2960 /* 2961 * free hotspare pool list 2962 */ 2963 void 2964 metafreehspnamelist(mdhspnamelist_t *hspnlp) 2965 { 2966 mdhspnamelist_t *next = NULL; 2967 2968 for (/* void */; (hspnlp != NULL); hspnlp = next) { 2969 next = hspnlp->next; 2970 Free(hspnlp); 2971 } 2972 } 2973 2974 /* 2975 * build list of hotspare pool names 2976 */ 2977 int 2978 metahspnamelist( 2979 mdsetname_t **spp, 2980 mdhspnamelist_t **hspnlpp, 2981 int argc, 2982 char *argv[], 2983 md_error_t *ep 2984 ) 2985 { 2986 mdhspnamelist_t **tailpp = hspnlpp; 2987 int count = 0; 2988 2989 for (*hspnlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 2990 mdhspnamelist_t *hspnlp = Zalloc(sizeof (*hspnlp)); 2991 2992 if ((hspnlp->hspnamep = metahspname(spp, argv[0], 2993 ep)) == NULL) { 2994 metafreehspnamelist(*hspnlpp); 2995 *hspnlpp = NULL; 2996 return (-1); 2997 } 2998 *tailpp = hspnlp; 2999 tailpp = &hspnlp->next; 3000 } 3001 return (count); 3002 } 3003 3004 /* 3005 * append to end of hotspare pool list 3006 */ 3007 mdhspname_t * 3008 metahspnamelist_append(mdhspnamelist_t **hspnlpp, mdhspname_t *hspnp) 3009 { 3010 mdhspnamelist_t *hspnlp; 3011 3012 /* run to end of list */ 3013 for (; (*hspnlpp != NULL); hspnlpp = &(*hspnlpp)->next) 3014 ; 3015 3016 /* allocate new list element */ 3017 hspnlp = *hspnlpp = Zalloc(sizeof (*hspnlp)); 3018 3019 /* append hotspare pool name */ 3020 hspnlp->hspnamep = hspnp; 3021 return (hspnp); 3022 } 3023 3024 /* 3025 * get name from dev 3026 */ 3027 mdname_t * 3028 metadevname( 3029 mdsetname_t **spp, 3030 md_dev64_t dev, 3031 md_error_t *ep) 3032 { 3033 char *device_name; 3034 mdname_t *namep; 3035 mdkey_t key; 3036 3037 /* short circuit metadevices */ 3038 assert(dev != NODEV64); 3039 if (meta_dev_ismeta(dev)) 3040 return (metamnumname(spp, meta_getminor(dev), 0, ep)); 3041 3042 /* create local set, if necessary */ 3043 if (*spp == NULL) { 3044 if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) 3045 return (NULL); 3046 } 3047 3048 /* get name from namespace */ 3049 if ((device_name = meta_getnmentbydev((*spp)->setno, MD_SIDEWILD, 3050 dev, NULL, NULL, &key, ep)) == NULL) { 3051 return (NULL); 3052 } 3053 namep = metaname_fast(spp, device_name, ep); 3054 if (namep != NULL) 3055 namep->key = key; 3056 3057 Free(device_name); 3058 return (namep); 3059 } 3060 3061 /* 3062 * return cached name from md_dev64_t 3063 */ 3064 static char * 3065 metadevtocachename(md_dev64_t dev) 3066 { 3067 mddrivenamelist_t *dnlp; 3068 3069 /* look in cache */ 3070 for (dnlp = drivelistp; (dnlp != NULL); dnlp = dnlp->next) { 3071 mddrivename_t *dnp = dnlp->drivenamep; 3072 uint_t i; 3073 3074 for (i = 0; (i < dnp->parts.parts_len); ++i) { 3075 mdname_t *np = &dnp->parts.parts_val[i]; 3076 3077 if (np->dev == dev) 3078 return (np->cname); 3079 } 3080 } 3081 3082 /* not found */ 3083 return (NULL); 3084 } 3085 3086 /* 3087 * Ask the driver for the name, which has been stored in the 3088 * metadevice state database (on behalf of the utilities). 3089 * (by devno) 3090 */ 3091 char * 3092 get_devname( 3093 set_t setno, 3094 md_dev64_t dev) 3095 { 3096 mdsetname_t *sp; 3097 mdname_t *np; 3098 md_error_t status = mdnullerror; 3099 3100 /* get name */ 3101 if ((setno == MD_SET_BAD) || 3102 ((sp = metasetnosetname(setno, &status)) == NULL) || 3103 ((np = metadevname(&sp, dev, &status)) == NULL)) { 3104 mdclrerror(&status); 3105 return (metadevtocachename(dev)); 3106 } 3107 3108 /* return name */ 3109 return (np->cname); 3110 } 3111 3112 /* 3113 * get name from key 3114 */ 3115 mdname_t * 3116 metakeyname( 3117 mdsetname_t **spp, 3118 mdkey_t key, 3119 int fast, 3120 md_error_t *ep 3121 ) 3122 { 3123 char *device_name; 3124 md_dev64_t dev = NODEV64; 3125 mdname_t *namep; 3126 3127 /* create local set, if necessary */ 3128 if (*spp == NULL) { 3129 if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) 3130 return (NULL); 3131 } 3132 3133 /* get name from namespace */ 3134 if ((device_name = meta_getnmentbykey((*spp)->setno, MD_SIDEWILD, 3135 key, NULL, NULL, &dev, ep)) == NULL) { 3136 return (NULL); 3137 } 3138 if (fast) 3139 namep = metaname_fast(spp, device_name, ep); 3140 else 3141 namep = metaname(spp, device_name, ep); 3142 3143 assert(dev != NODEV64); 3144 if (namep) 3145 namep->dev = dev; 3146 Free(device_name); 3147 return (namep); 3148 } 3149 3150 /* 3151 * completely flush the caches 3152 */ 3153 void 3154 metaflushnames(int flush_sr_cache) 3155 { 3156 metaflushhspnames(); 3157 metaflushdrivenames(); 3158 metaflushsetnames(); 3159 metaflushctlrcache(); 3160 metaflushfastnames(); 3161 metaflushstatcache(); 3162 if (flush_sr_cache) 3163 sr_cache_flush(0); 3164 } 3165 3166 /* 3167 * meta_get_hotspare_names 3168 * returns an mdnamelist_t of hot spare names 3169 */ 3170 3171 int 3172 meta_get_hotspare_names( 3173 mdsetname_t *sp, 3174 mdnamelist_t **nlpp, 3175 int options, 3176 md_error_t *ep 3177 ) 3178 { 3179 mdhspnamelist_t *hspnlp = NULL; 3180 mdhspnamelist_t *hspp; 3181 int cnt = 0; 3182 3183 assert(nlpp != NULL); 3184 3185 /* get hotspare names */ 3186 if (meta_get_hsp_names(sp, &hspnlp, options, ep) < 0) { 3187 cnt = -1; 3188 goto out; 3189 } 3190 3191 /* build name list */ 3192 for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) { 3193 md_hsp_t *hsp; 3194 int i; 3195 3196 if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL) { 3197 cnt = -1; 3198 goto out; 3199 } 3200 for (i = 0; (i < hsp->hotspares.hotspares_len); i++) { 3201 md_hs_t *hs = &hsp->hotspares.hotspares_val[i]; 3202 3203 (void) metanamelist_append(nlpp, hs->hsnamep); 3204 ++cnt; 3205 } 3206 } 3207 3208 /* cleanup and return count or error */ 3209 out: 3210 metafreehspnamelist(hspnlp); 3211 if ((cnt == -1) && mdisok(ep)) { 3212 /* 3213 * At least try to give some sort of meaningful error 3214 */ 3215 (void) mderror(ep, MDE_NO_HSPS, "Generic Hotspare Error"); 3216 } 3217 3218 return (cnt); 3219 } 3220 /* 3221 * meta_create_non_dup_list 3222 * INPUT: mdnp mdname_t pointer to add to the list if a new name 3223 * ldevidp list of non-duplicate names. 3224 * OUTPUT: ldevidp list of non-duplicate names. 3225 * meta_create_non_dup_list will take a mdname_t pointer and if the device 3226 * is not in the list (ldevidp) will add it to the list. 3227 * User needs to free allocated memory. 3228 */ 3229 void 3230 meta_create_non_dup_list( 3231 mdname_t *mdnp, 3232 mddevid_t **ldevidpp 3233 ) 3234 { 3235 char *lcname; 3236 mddevid_t *tmp; 3237 mddevid_t *lastdevidp; 3238 mddevid_t *lldevidp; 3239 char *ctd, *slice; 3240 mddevid_t *ldevidp; 3241 3242 if (mdnp == NULL) 3243 return; 3244 3245 ldevidp = *ldevidpp; 3246 /* 3247 * Grab the name of the device and strip off slice information 3248 */ 3249 lcname = Strdup(mdnp->cname); 3250 if (lcname == NULL) { 3251 return; 3252 } 3253 ctd = strrchr(lcname, '/'); 3254 if (ctd != NULL) 3255 slice = strrchr(ctd, 's'); 3256 else 3257 slice = strrchr(lcname, 's'); 3258 3259 if (slice != NULL) 3260 *slice = '\0'; 3261 3262 if (ldevidp == NULL) { 3263 /* first item in list */ 3264 ldevidp = Zalloc(sizeof (mddevid_t)); 3265 ldevidp->ctdname = lcname; 3266 ldevidp->key = mdnp->key; 3267 *ldevidpp = ldevidp; 3268 } else { 3269 for (tmp = ldevidp; (tmp != NULL); tmp = tmp->next) { 3270 if (strcmp(tmp->ctdname, lcname) == 0) { 3271 /* already there so just return */ 3272 Free(lcname); 3273 return; 3274 } 3275 lastdevidp = tmp; 3276 } 3277 lldevidp = Zalloc(sizeof (mddevid_t)); 3278 lldevidp->ctdname = lcname; 3279 lldevidp->key = mdnp->key; 3280 lastdevidp->next = lldevidp; 3281 } 3282 } 3283