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