1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * get dev_t list 29 */ 30 31 #include <meta.h> 32 33 #include <sys/mhd.h> 34 #include <strings.h> 35 36 /* 37 * private version of minor(), able to handle 64 bit and 32 bit devices. 38 * print a warning out in case a 32 bit dev is specified. 39 */ 40 minor_t 41 meta_getminor(md_dev64_t dev64) 42 { 43 /* check if it's a real 64 bit dev */ 44 if ((dev64 >> NBITSMAJOR64) > 0) { 45 return ((minor_t)(dev64 & MAXMIN64)); 46 } else { 47 if (getenv("META_DEBUG")) 48 (void) printf( 49 "meta_getminor called with 32 bit dev: 0x%llx\n", 50 dev64); 51 return ((minor_t)(dev64 & MAXMIN32)); 52 } 53 } 54 55 /* 56 * private version of major(), able to handle 64 bit and 32 bit devices. 57 * print a warning out in case a 32 bit dev is specified. 58 */ 59 major_t 60 meta_getmajor(md_dev64_t dev64) 61 { 62 /* check if it's a real 64 bit dev */ 63 if ((dev64 >> NBITSMAJOR64) > 0) { 64 return ((major_t)((dev64 >> NBITSMINOR64) & MAXMAJ64)); 65 } else { 66 if (getenv("META_DEBUG")) 67 (void) printf( 68 "meta_getmajor called with 32 bit dev: 0x%llx\n", 69 dev64); 70 return ((major_t)((dev64 >> NBITSMINOR32) & MAXMAJ32)); 71 } 72 } 73 74 /* 75 * private version of cmpldev(), able to handle 64 bit and 32 bit devices. 76 */ 77 dev32_t 78 meta_cmpldev(md_dev64_t dev64) 79 { 80 minor_t minor; 81 major_t major; 82 83 major = (major_t)(dev64 >> NBITSMAJOR64); 84 if (major == 0) { 85 return ((dev32_t)dev64); 86 } 87 minor = (dev32_t)dev64 & MAXMIN32; 88 return ((major << NBITSMINOR32) | minor); 89 } 90 91 /* 92 * private version of expldev(), able to handle 64 bit and 32 bit devices. 93 */ 94 md_dev64_t 95 meta_expldev(md_dev64_t dev64) 96 { 97 minor_t minor; 98 major_t major; 99 100 major = (major_t)(dev64 >> NBITSMAJOR64); 101 if (major > 0) { /* a 64 bit device was given, return unchanged */ 102 return (dev64); 103 } 104 minor = (minor_t)(dev64) & MAXMIN32; 105 major = ((major_t)dev64 >> NBITSMINOR32) & MAXMAJ32; 106 return (((md_dev64_t)major << NBITSMINOR64) | minor); 107 } 108 109 /* 110 * get underlying devices (recursively) 111 */ 112 int 113 meta_getdevs( 114 mdsetname_t *sp, 115 mdname_t *namep, 116 mdnamelist_t **nlpp, 117 md_error_t *ep 118 ) 119 { 120 char *miscname; 121 md_dev64_t *mydevs = NULL; 122 md_getdevs_params_t mgd; 123 size_t i; 124 int rval = -1; 125 md_sys_error_t *ip; 126 127 /* must have local set */ 128 assert(sp != NULL); 129 130 /* if no valid name then return an error */ 131 if (namep == NULL) 132 return (-1); 133 134 /* just add regular devices */ 135 if (! metaismeta(namep)) { 136 mdnamelist_t *p; 137 138 /* 139 * If the dev_t is in the array already 140 * then let's continue. 141 */ 142 for (p = *nlpp; (p != NULL); p = p->next) { 143 if (strcmp(namep->bname, p->namep->bname) == 0) { 144 rval = 0; 145 goto out; 146 } 147 } 148 149 /* add to list */ 150 (void) metanamelist_append(nlpp, namep); 151 rval = 0; 152 goto out; 153 } 154 155 /* get MD misc module */ 156 if ((miscname = metagetmiscname(namep, ep)) == NULL) 157 goto out; 158 159 /* get count of underlying devices */ 160 (void) memset(&mgd, '\0', sizeof (mgd)); 161 MD_SETDRIVERNAME(&mgd, miscname, sp->setno); 162 mgd.mnum = meta_getminor(namep->dev); 163 mgd.cnt = 0; 164 mgd.devs = NULL; 165 if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, namep->cname) != 0) { 166 if (mgd.mde.info.errclass == MDEC_SYS) { 167 ip = &mgd.mde.info.md_error_info_t_u.sys_error; 168 if (ip->errnum == ENODEV) { 169 rval = 0; 170 goto out; 171 } 172 } 173 (void) mdstealerror(ep, &mgd.mde); 174 goto out; 175 } else if (mgd.cnt <= 0) { 176 assert(mgd.cnt >= 0); 177 rval = 0; 178 goto out; 179 } 180 181 /* get underlying devices */ 182 mydevs = Zalloc(sizeof (*mydevs) * mgd.cnt); 183 mgd.devs = (uintptr_t)mydevs; 184 if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, namep->cname) != 0) { 185 if (mgd.mde.info.errclass == MDEC_SYS) { 186 ip = &mgd.mde.info.md_error_info_t_u.sys_error; 187 if (ip->errnum == ENODEV) { 188 rval = 0; 189 goto out; 190 } 191 } 192 (void) mdstealerror(ep, &mgd.mde); 193 goto out; 194 } else if (mgd.cnt <= 0) { 195 assert(mgd.cnt >= 0); 196 rval = 0; 197 goto out; 198 } 199 /* recurse */ 200 for (i = 0; (i < mgd.cnt); ++i) { 201 mdname_t *devnp; 202 203 if (mydevs[i] == NODEV64) { 204 continue; 205 } 206 if ((devnp = metadevname(&sp, mydevs[i], ep)) == NULL) { 207 if (mdissyserror(ep, ENOENT)) { 208 mdclrerror(ep); 209 /* 210 * If the device doesn't exist, it could be 211 * that we have a wrong dev_t/name 212 * combination in the namespace, so 213 * meta_fix_compnames try to check this 214 * with the unit structure and fix this. 215 */ 216 if (meta_fix_compnames(sp, namep, 217 mydevs[i], ep) == 0) 218 continue; 219 } 220 goto out; 221 } 222 if (meta_getdevs(sp, devnp, nlpp, ep) != 0) 223 goto out; 224 } 225 226 /* success */ 227 rval = 0; 228 229 /* cleanup, return error */ 230 out: 231 if (mydevs != NULL) 232 Free(mydevs); 233 return (rval); 234 } 235 236 /* 237 * get all dev_t for a set 238 */ 239 int 240 meta_getalldevs( 241 mdsetname_t *sp, /* set to look in */ 242 mdnamelist_t **nlpp, /* returned devices */ 243 int check_db, 244 md_error_t *ep 245 ) 246 { 247 md_replicalist_t *rlp, *rp; 248 mdnamelist_t *nlp, *np; 249 mdhspnamelist_t *hspnlp, *hspp; 250 int rval = 0; 251 252 assert(sp != NULL); 253 254 /* 255 * Get a replica namelist, 256 * and then get all the devs within the replicas. 257 */ 258 if (check_db == TRUE) { 259 rlp = NULL; 260 if (metareplicalist(sp, MD_BASICNAME_OK, &rlp, ep) < 0) 261 rval = -1; 262 for (rp = rlp; (rp != NULL); rp = rp->rl_next) { 263 if (meta_getdevs(sp, rp->rl_repp->r_namep, 264 nlpp, ep) != 0) 265 rval = -1; 266 } 267 metafreereplicalist(rlp); 268 } 269 270 /* 271 * Get a stripe namelist, 272 * and then get all the devs within the stripes. 273 */ 274 nlp = NULL; 275 if (meta_get_stripe_names(sp, &nlp, 0, ep) < 0) 276 rval = -1; 277 for (np = nlp; (np != NULL); np = np->next) { 278 if (meta_getdevs(sp, np->namep, nlpp, ep) != 0) 279 rval = -1; 280 } 281 metafreenamelist(nlp); 282 283 /* 284 * Get a mirror namelist, 285 * and then get all the devs within the mirrors. 286 */ 287 nlp = NULL; 288 if (meta_get_mirror_names(sp, &nlp, 0, ep) < 0) 289 rval = -1; 290 for (np = nlp; (np != NULL); np = np->next) { 291 if (meta_getdevs(sp, np->namep, nlpp, ep) != 0) 292 rval = -1; 293 } 294 metafreenamelist(nlp); 295 296 /* 297 * Get a trans namelist, 298 * and then get all the devs within the trans. 299 */ 300 nlp = NULL; 301 302 if (meta_get_trans_names(sp, &nlp, 0, ep) < 0) 303 rval = -1; 304 for (np = nlp; (np != NULL); np = np->next) { 305 if (meta_getdevs(sp, np->namep, nlpp, ep) != 0) 306 rval = -1; 307 } 308 metafreenamelist(nlp); 309 310 /* 311 * Get a hot spare pool namelist, 312 * and then get all the devs within the hot spare pools. 313 */ 314 hspnlp = NULL; 315 if (meta_get_hsp_names(sp, &hspnlp, 0, ep) < 0) 316 rval = -1; 317 for (hspp = hspnlp; (hspp != NULL); hspp = hspp->next) { 318 md_hsp_t *hsp; 319 uint_t i; 320 321 if ((hsp = meta_get_hsp(sp, hspp->hspnamep, ep)) == NULL) 322 rval = -1; 323 else for (i = 0; (i < hsp->hotspares.hotspares_len); ++i) { 324 md_hs_t *hs = &hsp->hotspares.hotspares_val[i]; 325 326 if (meta_getdevs(sp, hs->hsnamep, nlpp, ep) != 0) 327 rval = -1; 328 } 329 } 330 metafreehspnamelist(hspnlp); 331 332 /* 333 * Get a raid namelist, 334 * and then get all the devs within the raids. 335 */ 336 nlp = NULL; 337 if (meta_get_raid_names(sp, &nlp, 0, ep) < 0) 338 rval = -1; 339 for (np = nlp; (np != NULL); np = np->next) { 340 if (meta_getdevs(sp, np->namep, nlpp, ep) != 0) 341 rval = -1; 342 } 343 metafreenamelist(nlp); 344 345 /* 346 * Get a soft partition namelist, 347 * and then get all the devs within the softpartitions 348 */ 349 nlp = NULL; 350 if (meta_get_sp_names(sp, &nlp, 0, ep) < 0) 351 rval = -1; 352 for (np = nlp; (np != NULL); np = np->next) { 353 if (meta_getdevs(sp, np->namep, nlpp, ep) != 0) 354 rval = -1; 355 } 356 metafreenamelist(nlp); 357 358 return (rval); 359 } 360 361 /* 362 * get vtoc from a device already opened. 363 * returns 364 * 0 on success, 365 * -1 on error. If the error was ENOTSUP, partno will be set to 366 * VT_ENOTSUP if possible. 367 */ 368 int 369 meta_getvtoc( 370 int fd, /* fd for named device */ 371 char *devname, /* name of device */ 372 struct extvtoc *vtocbufp, /* vtoc buffer to fill */ 373 int *partno, /* return partno here */ 374 md_error_t *ep 375 ) 376 { 377 int part; 378 379 (void) memset(vtocbufp, 0, sizeof (*vtocbufp)); 380 if ((part = read_extvtoc(fd, vtocbufp)) < 0) { 381 int err = errno; 382 383 if (ioctl(fd, MHIOCSTATUS, NULL) == 1) 384 err = EACCES; 385 else if (part == VT_EINVAL) 386 err = EINVAL; 387 else if (part == VT_EIO) 388 err = EIO; 389 else if (part == VT_ENOTSUP) { 390 if (partno) { 391 *partno = VT_ENOTSUP; 392 return (-1); 393 } 394 } 395 return (mdsyserror(ep, err, devname)); 396 } 397 398 /* Slice number for *p0 partition (whole disk on x86) is 16 */ 399 if (part >= V_NUMPAR) 400 return (mdsyserror(ep, EINVAL, devname)); 401 402 /* Slice number for *p0 partition (whole disk on x86) is 16 */ 403 if (part >= V_NUMPAR) 404 return (mdsyserror(ep, EINVAL, devname)); 405 406 if (partno) 407 *partno = part; 408 return (0); 409 } 410 /* 411 * set mdvtoc for a meta devices 412 */ 413 int 414 meta_setmdvtoc( 415 int fd, /* fd for named device */ 416 char *devname, /* name of device */ 417 mdvtoc_t *mdvtocp, /* mdvtoc buffer to fill */ 418 md_error_t *ep 419 ) 420 { 421 uint_t i; 422 423 /* 424 * Sanity-check the mdvtoc 425 */ 426 427 if (mdvtocp->nparts > V_NUMPAR) { 428 return (-1); 429 } 430 431 /* 432 * since many drivers won't allow opening a device make sure 433 * all partitions aren't being set to zero. If all are zero then 434 * we have no way to set them to something else 435 */ 436 437 for (i = 0; i < mdvtocp->nparts; i++) 438 if (mdvtocp->parts[i].size > 0) 439 break; 440 if (i == mdvtocp->nparts) 441 return (-1); 442 443 /* 444 * Write the mdvtoc 445 */ 446 if (ioctl(fd, DKIOCSVTOC, (caddr_t)mdvtocp) == -1) { 447 return (mdsyserror(ep, errno, devname)); 448 } 449 450 return (0); 451 } 452 453 /* 454 * set vtoc 455 */ 456 int 457 meta_setvtoc( 458 int fd, /* fd for named device */ 459 char *devname, /* name of device */ 460 struct extvtoc *vtocbufp, /* vtoc buffer to fill */ 461 md_error_t *ep 462 ) 463 { 464 int part; 465 int err; 466 467 if ((part = write_extvtoc(fd, vtocbufp)) < 0) { 468 if (part == VT_EINVAL) 469 err = EINVAL; 470 else if (part == VT_EIO) 471 err = EIO; 472 else 473 err = errno; 474 return (mdsyserror(ep, err, devname)); 475 } 476 477 return (0); 478 } 479 480 /* 481 * FUNCTION: meta_get_names() 482 * INPUT: drivername - char string containing the driver name 483 * sp - the set name to get soft partitions from 484 * options - options from the command line 485 * OUTPUT: nlpp - list of all soft partition names 486 * ep - return error pointer 487 * RETURNS: int - -1 if error, 0 success 488 * PURPOSE: returns a list of all specified devices in the metadb 489 * for all devices in the specified set 490 */ 491 int 492 meta_get_names( 493 char *drivername, 494 mdsetname_t *sp, 495 mdnamelist_t **nlpp, 496 mdprtopts_t options, 497 md_error_t *ep 498 ) 499 { 500 md_i_getnum_t gn; /* MD_IOCGET_NUM params */ 501 mdnamelist_t **tailpp = nlpp; 502 minor_t *minors = NULL; 503 minor_t *m_ptr; 504 int i; 505 506 (void) memset(&gn, '\0', sizeof (gn)); 507 MD_SETDRIVERNAME(&gn, drivername, sp->setno); 508 509 /* get number of devices */ 510 if (metaioctl(MD_IOCGET_NUM, &gn, &gn.mde, NULL) != 0) { 511 if (mdiserror(&gn.mde, MDE_UNIT_NOT_FOUND)) { 512 mdclrerror(&gn.mde); 513 } else { 514 (void) mdstealerror(ep, &gn.mde); 515 return (-1); 516 } 517 } 518 519 if (gn.size > 0) { 520 /* malloc minor number buffer to be filled by ioctl */ 521 if ((minors = (minor_t *)malloc( 522 gn.size * sizeof (minor_t))) == 0) { 523 return (ENOMEM); 524 } 525 gn.minors = (uintptr_t)minors; 526 if (metaioctl(MD_IOCGET_NUM, &gn, &gn.mde, NULL) != 0) { 527 (void) mdstealerror(ep, &gn.mde); 528 free(minors); 529 return (-1); 530 } 531 m_ptr = minors; 532 for (i = 0; i < gn.size; i++) { 533 mdname_t *np; 534 535 /* get name */ 536 np = metamnumname(&sp, *m_ptr, 537 ((options & PRINT_FAST) ? 1 : 0), ep); 538 539 /* 540 * np can be NULL if the /dev/md namespace entries 541 * do not exist. This could have happened due to 542 * devfsadmd not having created them. 543 * Therefore assume devfsadmd has not run and tell 544 * it to run for the specific device that is missing. 545 * Ignore any error return from meta_update_devtree 546 * as a failure to create the device nodes will be 547 * picked up in the metamnumname() call. Note that 548 * the call to meta_update_devtree should not return 549 * until the /dev/md links have been created or if 550 * there has been a failure of some sort. 551 */ 552 if (np == NULL) { 553 (void) meta_update_devtree(*m_ptr); 554 np = metamnumname(&sp, *m_ptr, 555 ((options & PRINT_FAST) ? 1 : 0), ep); 556 } 557 558 if (np == NULL) 559 goto out; 560 561 tailpp = meta_namelist_append_wrapper(tailpp, np); 562 563 /* next device */ 564 m_ptr++; 565 } 566 free(minors); 567 } 568 return (gn.size); 569 570 out: 571 if (minors != NULL) 572 free(minors); 573 metafreenamelist(*nlpp); 574 *nlpp = NULL; 575 return (-1); 576 } 577 578 /* 579 * Wrap lib/libdevid/devid_deviceid_to_nmlist. We want to take the 580 * results from that function and filter out the c[t]dp style names that 581 * we typically see on x86 so that we never see them. 582 */ 583 int 584 meta_deviceid_to_nmlist(char *search_path, ddi_devid_t devid, char *minor_name, 585 devid_nmlist_t **retlist) 586 { 587 int res; 588 devid_nmlist_t *dp; 589 devid_nmlist_t *tmp_retlist; 590 int i = 1; 591 devid_nmlist_t *rp; 592 593 res = devid_deviceid_to_nmlist(search_path, devid, minor_name, retlist); 594 if (res != 0) { 595 return (res); 596 } 597 598 599 /* first count the number of non c[t]dp items in retlist */ 600 for (dp = *retlist; dp->dev != NODEV; dp++) { 601 uint_t s; 602 603 /* Check if this is a c[t]dp style name. */ 604 if (parse_ctd(basename(dp->devname), &s) != 1) { 605 i++; 606 } 607 } 608 609 /* create an array to hold the non c[t]dp items */ 610 tmp_retlist = Malloc(sizeof (devid_nmlist_t) * i); 611 /* copy the non c[t]dp items to the array */ 612 for (dp = *retlist, rp = tmp_retlist; dp->dev != NODEV; dp++) { 613 uint_t s; 614 615 /* Check if this is a c[t]dp style name. */ 616 if (parse_ctd(basename(dp->devname), &s) != 1) { 617 /* nope, so copy and go to the next */ 618 rp->dev = dp->dev; 619 rp->devname = Strdup(dp->devname); 620 rp++; 621 } 622 /* if it is c[t]dp, just skip the element */ 623 } 624 /* copy the list terminator */ 625 rp->dev = NODEV; 626 rp->devname = NULL; 627 devid_free_nmlist (*retlist); 628 *retlist = tmp_retlist; 629 return (res); 630 } 631 632 /* 633 * Check each real device that makes up a metadevice so that 634 * un_dev entries can be matched against the entries in the 635 * namespace. 636 * 637 * RETURN: 638 * -1 error 639 * 0 success 640 */ 641 int 642 meta_fix_compnames( 643 mdsetname_t *sp, 644 mdname_t *namep, 645 md_dev64_t dev, 646 md_error_t *ep 647 ) 648 { 649 int ret = 0; 650 char *miscname; 651 652 /* get miscname and unit */ 653 if ((miscname = metagetmiscname(namep, ep)) == NULL) 654 return (-1); 655 if (strcmp(miscname, MD_STRIPE) == 0) { 656 if (meta_stripe_check_component(sp, namep, dev, ep) < 0) { 657 ret = -1; 658 } 659 } else if (strcmp(miscname, MD_SP) == 0) { 660 if (meta_sp_check_component(sp, namep, ep) < 0) { 661 ret = -1; 662 } 663 } else if (strcmp(miscname, MD_RAID) == 0) { 664 if (meta_raid_check_component(sp, namep, dev, ep) < 0) { 665 ret = -1; 666 } 667 } else { 668 (void) mdmderror(ep, MDE_INVAL_UNIT, 0, namep->cname); 669 return (-1); 670 } 671 return (ret); 672 } 673