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 2007 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 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 /* 2604 * metaname() 2605 * 2606 * Wrapper function for metaname_common() 2607 * If the second arg is a metadevice name then it is important that this should 2608 * be a canonical name (eg d30 rather than /dev/md/dsk/d30). If this is not the 2609 * case then a bad entry may be placed into the drivelistp cache. 2610 */ 2611 mdname_t * 2612 metaname( 2613 mdsetname_t **spp, 2614 char *uname, 2615 meta_device_type_t uname_type, 2616 md_error_t *ep 2617 ) 2618 { 2619 return (metaname_common(spp, uname, 0, uname_type, ep)); 2620 } 2621 2622 mdname_t * 2623 metaname_fast( 2624 mdsetname_t **spp, 2625 char *uname, 2626 meta_device_type_t uname_type, 2627 md_error_t *ep 2628 ) 2629 { 2630 return (metaname_common(spp, uname, 1, uname_type, ep)); 2631 } 2632 /* 2633 * Get the dnp using the device id. 2634 * 2635 * We have the potential to have more than 1 dnp with the same disk name but 2636 * have different device ids. This would happen in the case of a partial 2637 * diskset. The unavailable disk name is relative to the prior host and could 2638 * possibly be the same as a disk on this system. The only way to tell which 2639 * dnp belongs with this disk is by searching by device id. We have the 2640 * potential to have the case where 1) the disk who's device id we pass in is 2641 * in the system. In this case the name and the device id are both valid for 2642 * the disk. 2) The disk whose device id we've been passed is not in the 2643 * system and no disk with the same name has a dnp on the list. And 3) The 2644 * disk whose device id we've been passed is not on the system but there is 2645 * a disk with the same name (different devid) that is on the system. Here's 2646 * what we return for each of those cases: 2647 * 1) If disk is in system: 2648 * disk is found on drivelistp or we create a new drivename and it's 2649 * fully populated as expected. 2650 * 2) If disk not in system, no collision 2651 * Disk with the same devid is not found on drivelistp, we create a new 2652 * drivename structure and the dnp->devid is filled in not from getparts 2653 * but from the devidp passed in. No other disk in the system has the 2654 * same "name" or devid. 2655 * This situation would be caused by the import of a partial diskset. 2656 * 3) If disk not in system, collision 2657 * Disk with the same devid is not found on the drivelistp, we create a 2658 * new drivename struct but getparts will use the information from the 2659 * name which is actually in reference to another disk of the same name 2660 * in the system. getparts will fill in the dnp->devid with the value 2661 * from the other disk and we overwrite this with the value of this disk. 2662 * To get into this situation one of the disks is actually unavailable 2663 * as in the case of a partial import. 2664 */ 2665 mddrivename_t * 2666 meta_getdnp_bydevid( 2667 mdsetname_t *sp, 2668 side_t sideno, 2669 ddi_devid_t devidp, 2670 mdkey_t key, 2671 md_error_t *ep 2672 ) 2673 { 2674 ddi_devid_t dnp_devidp; 2675 char *nm; 2676 mddrivenamelist_t **tail; 2677 mddrivename_t *dnp; 2678 uint_t slice; 2679 mdname_t *np; 2680 char *rname = NULL; 2681 char *dname = NULL; 2682 uint_t nparts, partno; 2683 int ret; 2684 md_set_desc *sd = NULL; 2685 meta_device_type_t uname_type = LOGICAL_DEVICE; 2686 2687 /* look in the cache first */ 2688 for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { 2689 dnp = (*tail)->drivenamep; 2690 if (dnp->type != MDT_COMP) 2691 continue; 2692 ret = devid_str_decode(dnp->devid, &dnp_devidp, NULL); 2693 if (ret != 0) { 2694 /* unable to decode the devid */ 2695 return (NULL); 2696 } 2697 /* compare with the devid passed in. */ 2698 if (devid_compare(devidp, dnp_devidp) == 0) { 2699 /* match! We have the same disk */ 2700 devid_free(dnp_devidp); 2701 return (dnp); 2702 } 2703 devid_free(dnp_devidp); 2704 } 2705 2706 /* drive not in the cache */ 2707 2708 if ((sd = metaget_setdesc(sp, ep)) == NULL) { 2709 return (NULL); 2710 } 2711 /* get namespace info */ 2712 if (MD_MNSET_DESC(sd)) { 2713 if ((nm = meta_getnmbykey(MD_LOCAL_SET, sideno, 2714 key, ep)) == NULL) 2715 return (NULL); 2716 } else { 2717 if ((nm = meta_getnmbykey(MD_LOCAL_SET, 2718 sideno+SKEW, key, ep)) == NULL) 2719 return (NULL); 2720 } 2721 2722 /* get raw name (rname) of the slice and drive name (dname) */ 2723 if ((rname = getrawnames(&sp, nm, &dname, &uname_type, ep)) == NULL) { 2724 return (NULL); 2725 } 2726 2727 /* allocate new list element and drive */ 2728 *tail = Zalloc(sizeof (**tail)); 2729 dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp)); 2730 metainitdrivename(dnp); 2731 2732 /* get parts info */ 2733 /* 2734 * Note that if the disk is unavailable this name will point to 2735 * either a nonexistent disk and thus the part info and devid will 2736 * be empty or the name will point to the wrong disk and this 2737 * information will be invalid. Because of this, we overwrite the 2738 * dnp->devid with the correct one after getparts returns. 2739 */ 2740 if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0) 2741 goto out; 2742 2743 dnp->devid = devid_str_encode(devidp, NULL); 2744 2745 /* 2746 * libmeta needs at least V_NUMPAR partitions. 2747 * If we have an EFI partition with less than V_NUMPAR slices, 2748 * we nevertheless reserve space for V_NUMPAR 2749 */ 2750 if (nparts < V_NUMPAR) { 2751 nparts = V_NUMPAR; 2752 } 2753 2754 /* allocate and link in parts */ 2755 dnp->parts.parts_len = nparts; 2756 dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) * 2757 dnp->parts.parts_len); 2758 2759 for (slice = 0; (slice < nparts); ++slice) { 2760 np = &dnp->parts.parts_val[slice]; 2761 metainitname(np); 2762 np->drivenamep = dnp; 2763 } 2764 2765 /* setup name_t (or slice) wanted */ 2766 if ((np = setup_slice(sp, uname_type, dnp, nm, rname, 2767 dname, partno, ep)) == NULL) 2768 goto out; 2769 2770 /* canonical disk name */ 2771 if ((dnp->cname = metadiskname(np->cname)) == NULL) 2772 dnp->cname = Strdup(np->cname); 2773 if ((dnp->rname = metadiskname(np->rname)) == NULL) 2774 dnp->rname = Strdup(np->rname); 2775 2776 if (dname != NULL) 2777 Free(dname); 2778 Free(rname); 2779 return (dnp); 2780 2781 out: 2782 if (dname != NULL) 2783 Free(dname); 2784 2785 if (rname != NULL) 2786 Free(rname); 2787 2788 metafreedrivename(dnp); 2789 Free(dnp); 2790 Free(*tail); 2791 *tail = NULL; 2792 return (NULL); 2793 } 2794 2795 /* 2796 * Search the drivename list by devid instead of name. If you don't find 2797 * an entry with the same device id, create one for the uname passed in. 2798 */ 2799 mddrivename_t * 2800 metadrivenamebydevid( 2801 mdsetname_t **spp, 2802 char *devid, 2803 char *uname, 2804 md_error_t *ep 2805 ) 2806 { 2807 ddi_devid_t dnp_devidp, in_devidp; 2808 mdname_t *np; 2809 mddrivenamelist_t **tail; 2810 char *rname = NULL; 2811 mddrivename_t *dnp; 2812 char *dname; 2813 int ret; 2814 uint_t nparts, partno; 2815 uint_t slice; 2816 meta_device_type_t uname_type = LOGICAL_DEVICE; 2817 2818 /* look in the cache first */ 2819 for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { 2820 dnp = (*tail)->drivenamep; 2821 if (dnp->type != MDT_COMP) 2822 continue; 2823 2824 /* decode the dnp devid */ 2825 ret = devid_str_decode(dnp->devid, &dnp_devidp, NULL); 2826 if (ret != 0) { 2827 /* unable to decode the devid */ 2828 return (NULL); 2829 } 2830 /* decode the passed in devid */ 2831 ret = devid_str_decode(devid, &in_devidp, NULL); 2832 if (ret != 0) { 2833 /* unable to decode the devid */ 2834 devid_free(dnp_devidp); 2835 return (NULL); 2836 } 2837 /* compare with the devids */ 2838 if (devid_compare(in_devidp, dnp_devidp) == 0) { 2839 /* match! We have the same disk */ 2840 devid_free(dnp_devidp); 2841 devid_free(in_devidp); 2842 return (dnp); 2843 } 2844 } 2845 devid_free(dnp_devidp); 2846 devid_free(in_devidp); 2847 2848 /* not in the cache */ 2849 2850 /* get raw name (rname) of the slice and drive (dname) we have */ 2851 if ((rname = getrawnames(spp, uname, &dname, &uname_type, 2852 ep)) == NULL) { 2853 return (NULL); 2854 } 2855 2856 /* allocate new list element and drive */ 2857 *tail = Zalloc(sizeof (**tail)); 2858 dnp = (*tail)->drivenamep = Zalloc(sizeof (*dnp)); 2859 2860 metainitdrivename(dnp); 2861 2862 /* get parts info */ 2863 if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0) 2864 goto out; 2865 2866 /* 2867 * libmeta needs at least V_NUMPAR partitions. 2868 * If we have an EFI partition with less than V_NUMPAR slices, 2869 * we nevertheless reserve space for V_NUMPAR 2870 */ 2871 if (nparts < V_NUMPAR) { 2872 nparts = V_NUMPAR; 2873 } 2874 2875 /* allocate and link in parts */ 2876 dnp->parts.parts_len = nparts; 2877 dnp->parts.parts_val = Zalloc((sizeof (*dnp->parts.parts_val)) * 2878 dnp->parts.parts_len); 2879 for (slice = 0; (slice < nparts); ++slice) { 2880 np = &dnp->parts.parts_val[slice]; 2881 metainitname(np); 2882 np->drivenamep = dnp; 2883 } 2884 2885 /* setup name_t (or slice) wanted */ 2886 if ((np = setup_slice(*spp, uname_type, dnp, uname, rname, 2887 dname, partno, ep)) == NULL) 2888 goto out; 2889 2890 /* canonical disk name */ 2891 if ((dnp->cname = metadiskname(np->cname)) == NULL) 2892 dnp->cname = Strdup(np->cname); 2893 if ((dnp->rname = metadiskname(np->rname)) == NULL) 2894 dnp->rname = Strdup(np->rname); 2895 2896 /* cleanup, return success */ 2897 if (dname != NULL) 2898 Free(dname); 2899 Free(rname); 2900 return (dnp); 2901 2902 /* cleanup, return error */ 2903 out: 2904 if (dname != NULL) 2905 Free(dname); 2906 if (rname != NULL) 2907 Free(rname); 2908 2909 metafreedrivename(dnp); 2910 Free(dnp); 2911 Free(*tail); 2912 *tail = NULL; 2913 return (NULL); 2914 } 2915 /* 2916 * set up names for a drive 2917 */ 2918 mddrivename_t * 2919 metadrivename( 2920 mdsetname_t **spp, 2921 char *uname, 2922 md_error_t *ep 2923 ) 2924 { 2925 char *slicename; 2926 mdname_t *np; 2927 2928 mddrivenamelist_t **tail; 2929 mddrivename_t *dnp; 2930 char *dname; 2931 int i; 2932 int mplen; 2933 size_t len; 2934 2935 assert(uname != NULL); 2936 2937 if ((dname = metadiskname(uname)) == NULL) { 2938 (void) mdsyserror(ep, ENOENT, uname); 2939 return (NULL); 2940 } 2941 2942 /* look in cache first */ 2943 for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) { 2944 dnp = (*tail)->drivenamep; 2945 if ((dnp->cname != NULL && 2946 (strcmp(dnp->cname, dname) == 0)) || 2947 (dnp->rname != NULL && 2948 (strcmp(dnp->rname, dname) == 0))) { 2949 Free(dname); 2950 return (dnp); 2951 } 2952 } 2953 Free(dname); 2954 2955 /* Check each possible slice name based on MD_MAX_PARTS. */ 2956 2957 /* 2958 * Figure out how much string space to reserve to fit 2959 * (MD_MAX_PARTS - 1) into the name string; the loop will 2960 * increment the mplen counter once for each decimal digit in 2961 * (MD_MAX_PARTS - 1). 2962 */ 2963 for (i = MD_MAX_PARTS - 1, mplen = 0; i; i /= 10, ++mplen); 2964 len = strlen(uname) + mplen + 2; 2965 slicename = Malloc(len); 2966 2967 /* Check for each slice in turn until we find one */ 2968 for (np = NULL, i = 0; ((np == NULL) && (i < MD_MAX_PARTS)); ++i) { 2969 (void) snprintf(slicename, len, "%ss%d", uname, i); 2970 np = metaname(spp, slicename, LOGICAL_DEVICE, ep); 2971 } 2972 Free(slicename); 2973 2974 if (np == NULL) { 2975 if ((mdiserror(ep, MDE_UNIT_NOT_FOUND)) && 2976 ((dname = metadiskname(uname)) != NULL)) { 2977 Free(dname); 2978 (void) mderror(ep, MDE_NOT_DRIVENAME, uname); 2979 } 2980 return (NULL); 2981 } 2982 return (np->drivenamep); 2983 } 2984 2985 /* 2986 * FUNCTION: metaslicename_type() 2987 * INPUT: dnp - the drivename structure 2988 * sliceno - the slice on the drive to return 2989 * type - LOGICAL_DEVICE or META_DEVICE 2990 * OUTPUT: ep - return error pointer 2991 * RETURNS: mdname_t- pointer the the slice name structure 2992 * PURPOSE: interface to the parts struct in the drive name struct 2993 * Since there is no guarantee that the slice name 2994 * structures are populated users should call this 2995 * function rather than accessing the structure directly 2996 * since it will populate the structure values if they 2997 * haven't already been populated before returning. 2998 */ 2999 mdname_t * 3000 metaslicename_type( 3001 mddrivename_t *dnp, 3002 uint_t sliceno, 3003 meta_device_type_t uname_type, 3004 md_error_t *ep 3005 ) 3006 { 3007 mdsetname_t *sp = NULL; 3008 char *namep = NULL; 3009 mdname_t *np; 3010 3011 assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META); 3012 3013 if (sliceno >= dnp->parts.parts_len) { 3014 (void) mderror(ep, MDE_NOSLICE, dnp->cname); 3015 return (NULL); 3016 } 3017 3018 np = &dnp->parts.parts_val[sliceno]; 3019 3020 /* check to see if the struct is already populated */ 3021 if (np->cname) { 3022 return (np); 3023 } 3024 3025 if ((namep = meta_name_getname(&sp, dnp->cname, 3026 uname_type, ep)) == NULL) 3027 return (NULL); 3028 3029 np = setup_slice(sp, uname_type, dnp, NULL, NULL, dnp->rname, 3030 sliceno, ep); 3031 3032 Free(namep); 3033 3034 return (np); 3035 } 3036 3037 /* 3038 * FUNCTION: metaslicename() 3039 * INPUT: dnp - the drivename structure 3040 * sliceno - the slice on the drive to return 3041 * OUTPUT: ep - return error pointer 3042 * RETURNS: mdname_t- pointer the the slice name structure 3043 * PURPOSE: interface to the parts struct in the drive name struct 3044 * Since there is no guarantee that the slice name 3045 * structures are populated users should call this 3046 * function rather than accessing the structure directly 3047 * since it will populate the structure values if they 3048 * haven't already been populated before returning. 3049 */ 3050 mdname_t * 3051 metaslicename( 3052 mddrivename_t *dnp, 3053 uint_t sliceno, 3054 md_error_t *ep 3055 ) 3056 { 3057 return (metaslicename_type(dnp, sliceno, LOGICAL_DEVICE, ep)); 3058 } 3059 3060 /* 3061 * set up metadevice name from id 3062 */ 3063 mdname_t * 3064 metamnumname( 3065 mdsetname_t **spp, 3066 minor_t mnum, 3067 int fast, 3068 md_error_t *ep 3069 ) 3070 { 3071 set_t setno = MD_MIN2SET(mnum); 3072 mdsetname_t *sp = NULL; 3073 char *uname; 3074 mdname_t *np; 3075 md_dev64_t dev; 3076 mdkey_t key; 3077 3078 /* check set first */ 3079 if (spp == NULL) 3080 spp = &sp; 3081 if (chksetno(spp, setno, ep) != 0) 3082 return (NULL); 3083 assert(*spp != NULL); 3084 sp = *spp; 3085 3086 /* get corresponding device name */ 3087 dev = metamakedev(mnum); 3088 if ((uname = meta_getnmentbydev(sp->setno, MD_SIDEWILD, dev, 3089 NULL, NULL, &key, ep)) == NULL) 3090 return (NULL); 3091 3092 /* setup name */ 3093 if (fast) { 3094 np = metaname_fast(spp, uname, META_DEVICE, ep); 3095 if (np) { 3096 np->dev = dev; 3097 np->key = key; 3098 } 3099 } else 3100 np = metaname(spp, uname, META_DEVICE, ep); 3101 3102 Free(uname); 3103 return (np); 3104 } 3105 3106 /* 3107 * return metadevice name 3108 */ 3109 char * 3110 get_mdname( 3111 mdsetname_t *sp, 3112 minor_t mnum 3113 ) 3114 { 3115 mdname_t *np; 3116 md_error_t status = mdnullerror; 3117 mdsetname_t **spp = NULL; 3118 3119 if (sp != NULL) 3120 spp = &sp; 3121 3122 /* get name */ 3123 if ((np = metamnumname(spp, mnum, 0, &status)) == NULL) { 3124 return (NULL); 3125 } 3126 assert(meta_getminor(np->dev) == mnum); 3127 3128 /* return name */ 3129 return (np->cname); 3130 } 3131 3132 /* 3133 * check for device type 3134 */ 3135 int 3136 metaismeta( 3137 mdname_t *np 3138 ) 3139 { 3140 return (np->drivenamep->type == MDT_META || 3141 np->drivenamep->type == MDT_FAST_META); 3142 } 3143 3144 int 3145 metachkmeta( 3146 mdname_t *np, 3147 md_error_t *ep 3148 ) 3149 { 3150 if (! metaismeta(np)) { 3151 return (mddeverror(ep, MDE_NOT_META, np->dev, 3152 np->cname)); 3153 } 3154 return (0); 3155 } 3156 3157 int 3158 metachkdisk( 3159 mdname_t *np, 3160 md_error_t *ep 3161 ) 3162 { 3163 mddrivename_t *dnp = np->drivenamep; 3164 3165 assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META); 3166 3167 if ((! metaismeta(np)) && (dnp->type != MDT_COMP)) { 3168 switch (dnp->type) { 3169 case MDT_ACCES: 3170 case MDT_UNKNOWN: 3171 return (mdsyserror(ep, dnp->errnum, np->bname)); 3172 default: 3173 assert(0); 3174 return (mddeverror(ep, MDE_NOT_DISK, np->dev, 3175 np->cname)); 3176 } 3177 } 3178 return (0); 3179 } 3180 3181 int 3182 metachkcomp( 3183 mdname_t *np, 3184 md_error_t *ep 3185 ) 3186 { 3187 if (metaismeta(np)) { 3188 return (mddeverror(ep, MDE_IS_META, np->dev, 3189 np->cname)); 3190 } 3191 return (metachkdisk(np, ep)); 3192 } 3193 3194 /* 3195 * free list of names 3196 */ 3197 void 3198 metafreenamelist( 3199 mdnamelist_t *nlp 3200 ) 3201 { 3202 mdnamelist_t *next = NULL; 3203 3204 for (/* void */; (nlp != NULL); nlp = next) { 3205 next = nlp->next; 3206 Free(nlp); 3207 } 3208 } 3209 3210 /* 3211 * build list of names 3212 */ 3213 int 3214 metanamelist( 3215 mdsetname_t **spp, 3216 mdnamelist_t **nlpp, 3217 int argc, 3218 char *argv[], 3219 meta_device_type_t type, 3220 md_error_t *ep 3221 ) 3222 { 3223 mdnamelist_t **tailpp = nlpp; 3224 int count = 0; 3225 3226 for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 3227 mdnamelist_t *nlp = Zalloc(sizeof (*nlp)); 3228 3229 if ((nlp->namep = metaname(spp, argv[0], 3230 type, ep)) == NULL) { 3231 metafreenamelist(*nlpp); 3232 *nlpp = NULL; 3233 return (-1); 3234 } 3235 *tailpp = nlp; 3236 tailpp = &nlp->next; 3237 } 3238 return (count); 3239 } 3240 3241 /* 3242 * append to end of name list 3243 */ 3244 mdname_t * 3245 metanamelist_append( 3246 mdnamelist_t **nlpp, 3247 mdname_t *np 3248 ) 3249 { 3250 mdnamelist_t *nlp; 3251 3252 /* run to end of list */ 3253 for (; (*nlpp != NULL); nlpp = &(*nlpp)->next) 3254 ; 3255 3256 /* allocate new list element */ 3257 nlp = *nlpp = Zalloc(sizeof (*nlp)); 3258 3259 /* append name */ 3260 nlp->namep = np; 3261 return (np); 3262 } 3263 3264 /* 3265 * FUNCTION: meta_namelist_append_wrapper() 3266 * INPUT: tailpp - pointer to the list tail pointer 3267 * np - name node to be appended to list 3268 * OUTPUT: none 3269 * RETURNS: mdnamelist_t * - new tail of the list. 3270 * PURPOSE: wrapper to meta_namelist_append for performance. 3271 * metanamelist_append finds the tail each time which slows 3272 * down long lists. By keeping track of the tail ourselves 3273 * we can change metanamelist_append into a constant time 3274 * operation. 3275 */ 3276 mdnamelist_t ** 3277 meta_namelist_append_wrapper( 3278 mdnamelist_t **tailpp, 3279 mdname_t *np 3280 ) 3281 { 3282 (void) metanamelist_append(tailpp, np); 3283 3284 /* If it's the first item in the list, return it instead of the next */ 3285 if ((*tailpp)->next == NULL) 3286 return (tailpp); 3287 3288 return (&(*tailpp)->next); 3289 } 3290 3291 3292 /* 3293 * mdhspname_t stuff 3294 */ 3295 3296 /* 3297 * initialize hspname 3298 */ 3299 static void 3300 metainithspname( 3301 mdhspname_t *hspnamep 3302 ) 3303 { 3304 (void) memset(hspnamep, '\0', sizeof (*hspnamep)); 3305 hspnamep->hsp = MD_HSP_NONE; 3306 } 3307 3308 /* 3309 * free allocated hspname 3310 */ 3311 static void 3312 metafreehspname( 3313 mdhspname_t *hspnamep 3314 ) 3315 { 3316 if (hspnamep->hspname != NULL) 3317 Free(hspnamep->hspname); 3318 if (hspnamep->unitp != NULL) 3319 meta_invalidate_hsp(hspnamep); 3320 metainithspname(hspnamep); 3321 } 3322 3323 /* 3324 * clear the hspname cache 3325 */ 3326 static void 3327 metaflushhspnames() 3328 { 3329 mdhspnamelist_t *p, *n; 3330 3331 for (p = hsplistp, n = NULL; (p != NULL); p = n) { 3332 n = p->next; 3333 metafreehspname(p->hspnamep); 3334 Free(p->hspnamep); 3335 Free(p); 3336 } 3337 hsplistp = NULL; 3338 } 3339 3340 /* 3341 * check set and get comparison name 3342 */ 3343 static char * 3344 gethspname( 3345 mdsetname_t **spp, 3346 char *uname, 3347 md_error_t *ep 3348 ) 3349 { 3350 char *cname = NULL; 3351 3352 cname = meta_canonicalize(*spp, uname); 3353 /* if it is not a meta/hsp name then flag an error */ 3354 if (cname == NULL) { 3355 (void) mdsyserror(ep, ENOENT, uname); 3356 return (NULL); 3357 } 3358 return (cname); 3359 } 3360 3361 /* 3362 * set up a hotspare pool name structure using both the name 3363 * and the self id 3364 */ 3365 static mdhspname_t * 3366 metahspname_hsp( 3367 mdsetname_t **spp, 3368 char *uname, 3369 hsp_t hsp, 3370 md_error_t *ep 3371 ) 3372 { 3373 char *cname; 3374 mdhspnamelist_t **tail; 3375 mdhspname_t *hspnp; 3376 3377 /* check setname */ 3378 assert(uname != NULL); 3379 if ((cname = gethspname(spp, uname, ep)) == NULL) 3380 return (NULL); 3381 assert(*spp != NULL); 3382 3383 /* look in cache first */ 3384 for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) { 3385 hspnp = (*tail)->hspnamep; 3386 if (strcmp(hspnp->hspname, cname) == 0) { 3387 Free(cname); 3388 /* if the hsp value has not been set then set it now */ 3389 if (hspnp->hsp == MD_HSP_NONE) 3390 hspnp->hsp = hsp; 3391 return (hspnp); 3392 } 3393 } 3394 3395 /* if the hsp number isn't specified then attempt to get it */ 3396 if (hsp == MD_HSP_NONE && (hsp = meta_gethspnmentbyname((*spp)->setno, 3397 MD_SIDEWILD, cname, ep)) == MD_HSP_NONE) { 3398 if (! mdisok(ep)) { 3399 /* 3400 * If the error is ENOENT, then we will continue on, 3401 * because the device does not yet exist. 3402 * For other types of errors, however, we'll bail out. 3403 */ 3404 if (! mdissyserror(ep, ENOENT)) { 3405 Free(cname); 3406 return (NULL); 3407 } 3408 mdclrerror(ep); 3409 } 3410 } 3411 3412 /* allocate new list element and hspname */ 3413 *tail = Zalloc(sizeof (**tail)); 3414 hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp)); 3415 metainithspname(hspnp); 3416 3417 /* save hspname and number */ 3418 hspnp->hspname = cname; 3419 hspnp->hsp = hsp; 3420 3421 /* success */ 3422 return (hspnp); 3423 } 3424 3425 /* 3426 * set up names for a hotspare pool 3427 */ 3428 mdhspname_t * 3429 metahspname( 3430 mdsetname_t **spp, 3431 char *uname, 3432 md_error_t *ep 3433 ) 3434 { 3435 return (metahspname_hsp(spp, uname, MD_HSP_NONE, ep)); 3436 } 3437 3438 /* 3439 * set up hotspare pool name from key 3440 */ 3441 mdhspname_t * 3442 metahsphspname( 3443 mdsetname_t **spp, 3444 hsp_t hsp, 3445 md_error_t *ep 3446 ) 3447 { 3448 set_t setno = HSP_SET(hsp); 3449 mdsetname_t *sp = NULL; 3450 char *uname; 3451 mdhspname_t *hspnp; 3452 3453 /* check set first */ 3454 if (spp == NULL) 3455 spp = &sp; 3456 if (chksetno(spp, setno, ep) != 0) 3457 return (NULL); 3458 assert(*spp != NULL); 3459 sp = *spp; 3460 3461 /* get corresponding hotspare pool name */ 3462 if ((uname = meta_gethspnmentbyid(sp->setno, 3463 MD_SIDEWILD, hsp, ep)) == NULL) 3464 return (NULL); 3465 3466 /* setup name */ 3467 hspnp = metahspname_hsp(spp, uname, hsp, ep); 3468 Free(uname); 3469 return (hspnp); 3470 } 3471 3472 /* 3473 * return hotspare pool name 3474 */ 3475 char * 3476 get_hspname(mdsetname_t *sp, hsp_t hsp) 3477 { 3478 mdhspname_t *hspnp; 3479 md_error_t status = mdnullerror; 3480 mdsetname_t **spp = NULL; 3481 3482 if (sp != NULL) 3483 spp = &sp; 3484 3485 /* get name */ 3486 if ((hspnp = metahsphspname(spp, hsp, &status)) == NULL) { 3487 mdclrerror(&status); 3488 return (NULL); 3489 } 3490 3491 /* return name */ 3492 return (hspnp->hspname); 3493 } 3494 3495 /* 3496 * free hotspare pool list 3497 */ 3498 void 3499 metafreehspnamelist(mdhspnamelist_t *hspnlp) 3500 { 3501 mdhspnamelist_t *next = NULL; 3502 3503 for (/* void */; (hspnlp != NULL); hspnlp = next) { 3504 next = hspnlp->next; 3505 Free(hspnlp); 3506 } 3507 } 3508 3509 /* 3510 * build list of hotspare pool names 3511 */ 3512 int 3513 metahspnamelist( 3514 mdsetname_t **spp, 3515 mdhspnamelist_t **hspnlpp, 3516 int argc, 3517 char *argv[], 3518 md_error_t *ep 3519 ) 3520 { 3521 mdhspnamelist_t **tailpp = hspnlpp; 3522 int count = 0; 3523 3524 for (*hspnlpp = NULL; (argc > 0); ++count, --argc, ++argv) { 3525 mdhspnamelist_t *hspnlp = Zalloc(sizeof (*hspnlp)); 3526 3527 if ((hspnlp->hspnamep = metahspname(spp, argv[0], 3528 ep)) == NULL) { 3529 metafreehspnamelist(*hspnlpp); 3530 *hspnlpp = NULL; 3531 return (-1); 3532 } 3533 *tailpp = hspnlp; 3534 tailpp = &hspnlp->next; 3535 } 3536 return (count); 3537 } 3538 3539 /* 3540 * append to end of hotspare pool list 3541 */ 3542 mdhspname_t * 3543 metahspnamelist_append(mdhspnamelist_t **hspnlpp, mdhspname_t *hspnp) 3544 { 3545 mdhspnamelist_t *hspnlp; 3546 3547 /* run to end of list */ 3548 for (; (*hspnlpp != NULL); hspnlpp = &(*hspnlpp)->next) 3549 ; 3550 3551 /* allocate new list element */ 3552 hspnlp = *hspnlpp = Zalloc(sizeof (*hspnlp)); 3553 3554 /* append hotspare pool name */ 3555 hspnlp->hspnamep = hspnp; 3556 return (hspnp); 3557 } 3558 3559 /* 3560 * get name from dev 3561 */ 3562 mdname_t * 3563 metadevname( 3564 mdsetname_t **spp, 3565 md_dev64_t dev, 3566 md_error_t *ep) 3567 { 3568 char *device_name; 3569 mdname_t *namep; 3570 mdkey_t key; 3571 3572 /* short circuit metadevices */ 3573 assert(dev != NODEV64); 3574 if (meta_dev_ismeta(dev)) 3575 return (metamnumname(spp, meta_getminor(dev), 0, ep)); 3576 3577 /* create local set, if necessary */ 3578 if (*spp == NULL) { 3579 if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) 3580 return (NULL); 3581 } 3582 3583 /* get name from namespace */ 3584 if ((device_name = meta_getnmentbydev((*spp)->setno, MD_SIDEWILD, 3585 dev, NULL, NULL, &key, ep)) == NULL) { 3586 return (NULL); 3587 } 3588 namep = metaname_fast(spp, device_name, LOGICAL_DEVICE, ep); 3589 if (namep != NULL) 3590 namep->key = key; 3591 3592 Free(device_name); 3593 return (namep); 3594 } 3595 3596 /* 3597 * return cached name from md_dev64_t 3598 */ 3599 static char * 3600 metadevtocachename(md_dev64_t dev) 3601 { 3602 mddrivenamelist_t *dnlp; 3603 3604 /* look in cache */ 3605 for (dnlp = drivelistp; (dnlp != NULL); dnlp = dnlp->next) { 3606 mddrivename_t *dnp = dnlp->drivenamep; 3607 uint_t i; 3608 3609 for (i = 0; (i < dnp->parts.parts_len); ++i) { 3610 mdname_t *np = &dnp->parts.parts_val[i]; 3611 3612 if (np->dev == dev) 3613 return (np->cname); 3614 } 3615 } 3616 3617 /* not found */ 3618 return (NULL); 3619 } 3620 3621 /* 3622 * Ask the driver for the name, which has been stored in the 3623 * metadevice state database (on behalf of the utilities). 3624 * (by devno) 3625 */ 3626 char * 3627 get_devname( 3628 set_t setno, 3629 md_dev64_t dev) 3630 { 3631 mdsetname_t *sp; 3632 mdname_t *np; 3633 md_error_t status = mdnullerror; 3634 3635 /* get name */ 3636 if ((setno == MD_SET_BAD) || 3637 ((sp = metasetnosetname(setno, &status)) == NULL) || 3638 ((np = metadevname(&sp, dev, &status)) == NULL)) { 3639 mdclrerror(&status); 3640 return (metadevtocachename(dev)); 3641 } 3642 3643 /* return name */ 3644 return (np->cname); 3645 } 3646 3647 /* 3648 * get name from key 3649 */ 3650 mdname_t * 3651 metakeyname( 3652 mdsetname_t **spp, 3653 mdkey_t key, 3654 int fast, 3655 md_error_t *ep 3656 ) 3657 { 3658 char *device_name; 3659 md_dev64_t dev = NODEV64; 3660 mdname_t *namep; 3661 3662 /* create local set, if necessary */ 3663 if (*spp == NULL) { 3664 if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) 3665 return (NULL); 3666 } 3667 3668 /* get name from namespace */ 3669 if ((device_name = meta_getnmentbykey((*spp)->setno, MD_SIDEWILD, 3670 key, NULL, NULL, &dev, ep)) == NULL) { 3671 return (NULL); 3672 } 3673 if (fast) 3674 namep = metaname_fast(spp, device_name, UNKNOWN, ep); 3675 else 3676 namep = metaname(spp, device_name, UNKNOWN, ep); 3677 3678 assert(dev != NODEV64); 3679 if (namep) 3680 namep->dev = dev; 3681 Free(device_name); 3682 return (namep); 3683 } 3684 3685 /* 3686 * completely flush metadev/hsp caches 3687 */ 3688 void 3689 metaflushmetanames() 3690 { 3691 metaflushhspnames(); 3692 metaflushdrivenames(); 3693 metaflushfastnames(); 3694 metaflushstatcache(); 3695 } 3696 3697 /* 3698 * completely flush the caches 3699 */ 3700 void 3701 metaflushnames(int flush_sr_cache) 3702 { 3703 metaflushhspnames(); 3704 metaflushdrivenames(); 3705 metaflushsetnames(); 3706 metaflushctlrcache(); 3707 metaflushfastnames(); 3708 metaflushstatcache(); 3709 if (flush_sr_cache) 3710 sr_cache_flush(0); 3711 } 3712 3713 /* 3714 * meta_get_hotspare_names 3715 * returns an mdnamelist_t of hot spare names 3716 */ 3717 3718 int 3719 meta_get_hotspare_names( 3720 mdsetname_t *sp, 3721 mdnamelist_t **nlpp, 3722 int options, 3723 md_error_t *ep 3724 ) 3725 { 3726 mdhspnamelist_t *hspnlp = NULL; 3727 mdhspnamelist_t *hspp; 3728 int cnt = 0; 3729 3730 assert(nlpp != NULL); 3731 3732 /* get hotspare names */ 3733 if (meta_get_hsp_names(sp, &hspnlp, options, ep) < 0) { 3734 cnt = -1; 3735 goto out; 3736 } 3737 3738 /* build name list */ 3739 for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) { 3740 md_hsp_t *hsp; 3741 int i; 3742 3743 if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL) { 3744 cnt = -1; 3745 goto out; 3746 } 3747 for (i = 0; (i < hsp->hotspares.hotspares_len); i++) { 3748 md_hs_t *hs = &hsp->hotspares.hotspares_val[i]; 3749 3750 (void) metanamelist_append(nlpp, hs->hsnamep); 3751 ++cnt; 3752 } 3753 } 3754 3755 /* cleanup and return count or error */ 3756 out: 3757 metafreehspnamelist(hspnlp); 3758 if ((cnt == -1) && mdisok(ep)) { 3759 /* 3760 * At least try to give some sort of meaningful error 3761 */ 3762 (void) mderror(ep, MDE_NO_HSPS, "Generic Hotspare Error"); 3763 } 3764 3765 return (cnt); 3766 } 3767 /* 3768 * meta_create_non_dup_list 3769 * INPUT: mdnp mdname_t pointer to add to the list if a new name 3770 * ldevidp list of non-duplicate names. 3771 * OUTPUT: ldevidp list of non-duplicate names. 3772 * meta_create_non_dup_list will take a mdname_t pointer and if the device 3773 * is not in the list (ldevidp) will add it to the list. 3774 * User needs to free allocated memory. 3775 */ 3776 void 3777 meta_create_non_dup_list( 3778 mdname_t *mdnp, 3779 mddevid_t **ldevidpp 3780 ) 3781 { 3782 char *lcname; 3783 mddevid_t *tmp; 3784 mddevid_t *lastdevidp; 3785 mddevid_t *lldevidp; 3786 char *ctd, *slice; 3787 mddevid_t *ldevidp; 3788 3789 if (mdnp == NULL) 3790 return; 3791 3792 ldevidp = *ldevidpp; 3793 /* 3794 * Grab the name of the device and strip off slice information 3795 */ 3796 lcname = Strdup(mdnp->cname); 3797 if (lcname == NULL) { 3798 return; 3799 } 3800 ctd = strrchr(lcname, '/'); 3801 if (ctd != NULL) 3802 slice = strrchr(ctd, 's'); 3803 else 3804 slice = strrchr(lcname, 's'); 3805 3806 if (slice != NULL) 3807 *slice = '\0'; 3808 3809 if (ldevidp == NULL) { 3810 /* first item in list */ 3811 ldevidp = Zalloc(sizeof (mddevid_t)); 3812 ldevidp->ctdname = lcname; 3813 ldevidp->key = mdnp->key; 3814 *ldevidpp = ldevidp; 3815 } else { 3816 for (tmp = ldevidp; (tmp != NULL); tmp = tmp->next) { 3817 if (strcmp(tmp->ctdname, lcname) == 0) { 3818 /* already there so just return */ 3819 Free(lcname); 3820 return; 3821 } 3822 lastdevidp = tmp; 3823 } 3824 lldevidp = Zalloc(sizeof (mddevid_t)); 3825 lldevidp->ctdname = lcname; 3826 lldevidp->key = mdnp->key; 3827 lastdevidp->next = lldevidp; 3828 } 3829 } 3830