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