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