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