1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Just in case we're not in a build environment, make sure that 29 * TEXT_DOMAIN gets set to something. 30 */ 31 #if !defined(TEXT_DOMAIN) 32 #define TEXT_DOMAIN "SYS_TEST" 33 #endif 34 35 /* 36 * check componets 37 */ 38 39 #include <meta.h> 40 #include "meta_lib_prv.h" 41 42 #include <sys/mnttab.h> 43 #include <sys/swap.h> 44 #include <devid.h> 45 #include <sys/dumpadm.h> 46 47 /* possible returns from meta_check_samedrive */ 48 #define CANT_TELL -1 49 #define NOT_SAMEDRIVE 0 50 #define IDENTICAL_NAME_DEVT 1 51 #define IDENTICAL_DEVIDS 2 52 53 /* 54 * static list(s) 55 */ 56 typedef struct dev_list { 57 char *dev_name; 58 ddi_devid_t devid; 59 struct dev_list *dev_nxt; 60 } dev_list_t; 61 62 static dev_list_t *devnamelist = NULL; 63 64 static char *skip_these_mntents[] = { 65 "nfs", 66 "autofs", 67 "proc", 68 "tmpfs", 69 "cachefs", 70 "rfs", 71 "fd", 72 "mntfs", 73 "lofs", 74 "devfs", 75 "dev", 76 "ctfs", 77 "objfs", 78 "sharefs", 79 NULL 80 }; 81 82 /* 83 * free swap info 84 */ 85 static void 86 free_swapinfo( 87 struct swaptable *swtp 88 ) 89 { 90 int i; 91 92 if (swtp == NULL) 93 return; 94 95 for (i = 0; (i < swtp->swt_n); ++i) { 96 if (swtp->swt_ent[i].ste_path != NULL) 97 Free(swtp->swt_ent[i].ste_path); 98 } 99 100 Free(swtp); 101 } 102 103 /* 104 * get swap info 105 */ 106 static int 107 get_swapinfo( 108 struct swaptable **swtpp, 109 int *nswap, 110 md_error_t *ep 111 ) 112 { 113 int i; 114 size_t swtsize; 115 116 *swtpp = NULL; 117 118 /* get number of entries */ 119 if ((*nswap = swapctl(SC_GETNSWP, NULL)) < 0) { 120 return (mdsyserror(ep, errno, "swapctl(SC_GETNSWP)")); 121 } 122 123 /* allocate structure */ 124 swtsize = sizeof ((*swtpp)->swt_n) + 125 ((*nswap) * sizeof ((*swtpp)->swt_ent[0])); 126 *swtpp = (struct swaptable *)Zalloc(swtsize); 127 (*swtpp)->swt_n = *nswap; 128 for (i = 0; (i < (*nswap)); ++i) 129 (*swtpp)->swt_ent[i].ste_path = Zalloc(MAXPATHLEN); 130 131 /* get info */ 132 if (((*nswap) = swapctl(SC_LIST, (*swtpp))) < 0) { 133 (void) mdsyserror(ep, errno, "swapctl(SC_LIST)"); 134 free_swapinfo(*swtpp); 135 return (-1); 136 } 137 138 /* return success */ 139 return (0); 140 } 141 142 /* 143 * check whether device is swapped on 144 */ 145 static int 146 meta_check_swapped( 147 mdsetname_t *sp, 148 mdname_t *np, 149 md_error_t *ep 150 ) 151 { 152 struct swaptable *swtp; 153 int nswap; 154 int i; 155 int rval = 0; 156 157 /* should have a set */ 158 assert(sp != NULL); 159 160 /* get swap info */ 161 if (get_swapinfo(&swtp, &nswap, ep) != 0) 162 return (-1); 163 164 /* look for match */ 165 for (i = 0; ((i < nswap) && (rval == 0)); ++i) { 166 mdname_t *snp; 167 168 if ((snp = metaname(&sp, swtp->swt_ent[i].ste_path, 169 UNKNOWN, ep)) == NULL) { 170 mdclrerror(ep); 171 continue; 172 } 173 if (np->dev == snp->dev) { 174 rval = mddeverror(ep, MDE_IS_SWAPPED, 175 np->dev, np->cname); 176 } else { /* not swap - does it overlap */ 177 rval = meta_check_overlap(snp->cname, np, 0, -1, 178 snp, 0, -1, ep); 179 if (rval != 0) { 180 (void) mdoverlaperror(ep, MDE_OVERLAP_SWAP, 181 np->cname, NULL, snp->cname); 182 } 183 } 184 } 185 free_swapinfo(swtp); 186 187 /* return success */ 188 return (rval); 189 } 190 191 /* 192 * Is a driver currently swapped on? 193 */ 194 int 195 meta_check_driveswapped( 196 mdsetname_t *sp, 197 mddrivename_t *dnp, 198 md_error_t *ep 199 ) 200 { 201 struct swaptable *swtp; 202 int nswap; 203 int i; 204 int rval = 0; 205 206 /* should have a set */ 207 assert(sp != NULL); 208 209 /* get swap info */ 210 if (get_swapinfo(&swtp, &nswap, ep) != 0) 211 return (-1); 212 213 /* look for match */ 214 for (i = 0; (i < nswap); ++i) { 215 mdname_t *snp; 216 217 if ((snp = metaname(&sp, swtp->swt_ent[i].ste_path, 218 LOGICAL_DEVICE, ep)) == NULL) { 219 mdclrerror(ep); 220 continue; 221 } 222 223 if (strcmp(dnp->cname, snp->drivenamep->cname) == 0) { 224 rval = mddeverror(ep, MDE_IS_SWAPPED, NODEV64, 225 dnp->cname); 226 } 227 } 228 free_swapinfo(swtp); 229 230 /* return success */ 231 return (rval); 232 } 233 234 /* 235 * check whether device is a dump device 236 */ 237 static int 238 meta_check_dump( 239 mdsetname_t *sp, 240 mdname_t *np, 241 md_error_t *ep 242 ) 243 { 244 int rval = 0; 245 int dump_fd; 246 char device[MAXPATHLEN]; 247 248 249 if ((dump_fd = open("/dev/dump", O_RDONLY)) < 0) 250 return (mdsyserror(ep, errno, "/dev/dump")); 251 252 if (ioctl(dump_fd, DIOCGETDEV, device) != -1) { 253 mdname_t *dump_np; 254 255 if ((dump_np = metaname(&sp, device, UNKNOWN, ep)) == NULL) { 256 mdclrerror(ep); 257 (void) close(dump_fd); 258 return (0); 259 } 260 261 if (np->dev == dump_np->dev) { 262 rval = mddeverror(ep, MDE_IS_DUMP, 263 np->dev, np->cname); 264 } else { /* not a dump device - but does it overlap? */ 265 rval = meta_check_overlap(dump_np->cname, np, 0, -1, 266 dump_np, 0, -1, ep); 267 if (rval != 0) { 268 (void) mdoverlaperror(ep, MDE_OVERLAP_DUMP, 269 np->cname, NULL, dump_np->cname); 270 } 271 } 272 } 273 (void) close(dump_fd); 274 return (rval); 275 } 276 277 /* 278 * check whether device is mounted 279 */ 280 static int 281 meta_check_mounted( 282 mdsetname_t *sp, 283 mdname_t *np, 284 md_error_t *ep 285 ) 286 { 287 FILE *mfp; 288 struct mnttab m; 289 int rval = 0; 290 char mountp[MNT_LINE_MAX]; 291 char mnt_special[MNT_LINE_MAX]; 292 293 /* should have a set */ 294 assert(sp != NULL); 295 296 /* look in mnttab */ 297 if ((mfp = open_mnttab()) == NULL) 298 return (mdsyserror(ep, errno, MNTTAB)); 299 while ((getmntent(mfp, &m) == 0) && (rval == 0)) { 300 char **fstype = skip_these_mntents; 301 int skipit = 0; 302 mdname_t *mnp; 303 304 if ((m.mnt_special == NULL) || (m.mnt_mountp == NULL)) 305 continue; 306 307 if (m.mnt_mountp[0] != '/') 308 continue; 309 310 while (*fstype != NULL) 311 if (strcmp(m.mnt_fstype, *fstype++) == 0) { 312 skipit++; 313 break; 314 } 315 316 if (skipit == 1) 317 continue; 318 319 (void) strcpy(mountp, m.mnt_mountp); 320 (void) strcpy(mnt_special, m.mnt_special); 321 322 if ((mnp = metaname(&sp, mnt_special, UNKNOWN, ep)) == NULL) { 323 mdclrerror(ep); 324 continue; 325 } 326 327 if (np->dev == mnp->dev) { 328 rval = mduseerror(ep, MDE_IS_MOUNTED, 329 np->dev, mountp, np->cname); 330 } else { /* device isn't in mnttab - does it overlap? */ 331 rval = meta_check_overlap(mnp->cname, np, 0, -1, 332 mnp, 0, -1, ep); 333 if (rval != 0) { 334 (void) mdoverlaperror(ep, MDE_OVERLAP_MOUNTED, 335 np->cname, mountp, mnp->cname); 336 } 337 } 338 } 339 340 /* return success */ 341 return (rval); 342 } 343 344 345 /* 346 * Is a file system currently mounted on this disk drive? 347 */ 348 int 349 meta_check_drivemounted( 350 mdsetname_t *sp, 351 mddrivename_t *dnp, 352 md_error_t *ep 353 ) 354 { 355 FILE *mfp; 356 struct mnttab m; 357 int rval = 0; 358 char mountp[MNT_LINE_MAX]; 359 char mnt_special[MNT_LINE_MAX]; 360 361 /* should have a set */ 362 assert(sp != NULL); 363 364 /* look in mnttab */ 365 if ((mfp = open_mnttab()) == NULL) 366 return (mdsyserror(ep, errno, MNTTAB)); 367 while ((getmntent(mfp, &m) == 0) && (rval == 0)) { 368 char **fstype = skip_these_mntents; 369 int skipit = 0; 370 mdname_t *mnp; 371 372 if ((m.mnt_special == NULL) || (m.mnt_mountp == NULL)) 373 continue; 374 375 if (m.mnt_mountp[0] != '/') 376 continue; 377 378 while (*fstype != NULL) 379 if (strcmp(m.mnt_fstype, *fstype++) == 0) { 380 skipit++; 381 break; 382 } 383 384 if (skipit == 1) 385 continue; 386 387 (void) strcpy(mountp, m.mnt_mountp); 388 (void) strcpy(mnt_special, m.mnt_special); 389 if ((mnp = metaname(&sp, mnt_special, 390 LOGICAL_DEVICE, ep)) == NULL) { 391 mdclrerror(ep); 392 continue; 393 } 394 if (strcmp(dnp->cname, mnp->drivenamep->cname) == 0) { 395 rval = mduseerror(ep, MDE_IS_MOUNTED, NODEV64, 396 mountp, dnp->cname); 397 } 398 } 399 400 /* return success */ 401 return (rval); 402 } 403 404 /* 405 * Check to see if the specified name is already in use or overlaps 406 * with a device already in use. Checks are made to determine whether 407 * the device is mounted, is a swap device, or a dump device. In each 408 * case if the device is not in use then an overlap check is done to ensure 409 * that the specified slice does not overlap. 410 */ 411 int 412 meta_check_inuse( 413 mdsetname_t *sp, 414 mdname_t *np, 415 mdinuseopts_t inuse_flags, 416 md_error_t *ep 417 ) 418 { 419 int rval = 0; 420 421 if ((inuse_flags & MDCHK_MOUNTED) && 422 (rval = meta_check_mounted(sp, np, ep)) != 0) 423 return (rval); 424 425 if ((inuse_flags & MDCHK_SWAP) && 426 (rval = meta_check_swapped(sp, np, ep)) != 0) 427 return (rval); 428 429 if ((inuse_flags & MDCHK_DUMP) && 430 (rval = meta_check_dump(sp, np, ep)) != 0) 431 return (rval); 432 433 return (rval); 434 } 435 436 int 437 meta_check_driveinset(mdsetname_t *sp, mddrivename_t *dn, md_error_t *ep) 438 { 439 set_t setno; 440 set_t max_sets; 441 442 if ((max_sets = get_max_sets(ep)) == 0) 443 return (-1); 444 445 for (setno = 1; setno < max_sets; setno++) { 446 mdsetname_t *sp1; 447 int is_it; 448 449 if (setno == sp->setno) 450 continue; 451 452 if ((sp1 = metasetnosetname(setno, ep)) == NULL) { 453 if (mdismddberror(ep, MDE_DB_NODB)) { 454 mdclrerror(ep); 455 return (0); 456 } 457 if (mdiserror(ep, MDE_NO_SET)) { 458 mdclrerror(ep); 459 continue; 460 } 461 return (-1); 462 } 463 464 metaflushsetname(sp1); 465 466 if ((is_it = meta_is_drive_in_thisset(sp1, dn, FALSE, ep)) 467 == -1) 468 return (-1); 469 470 if (is_it) 471 return (mddserror(ep, MDE_DS_DRIVEINSET, sp->setno, 472 sp1->setname, dn->cname, sp->setname)); 473 } 474 475 return (0); 476 } 477 478 /* 479 * Add a device/device id tuple to the devname cache 480 */ 481 static void 482 add_to_devname_list( 483 char *device_name, /* fully qualified dev name */ 484 ddi_devid_t devid /* device id */ 485 ) 486 { 487 dev_list_t *dnlp; 488 489 dnlp = Zalloc(sizeof (*dnlp)); 490 dnlp->dev_name = Strdup(device_name); 491 dnlp->devid = devid; 492 493 /* link the node into the devname list */ 494 dnlp->dev_nxt = devnamelist; 495 devnamelist = dnlp; 496 } 497 498 /* 499 * check for same drive 500 * 501 * Differentiate between matching on name/dev_t and devid. In the latter 502 * case it is correct to fail but misleading to give the same error msg as 503 * for an overlapping slice. 504 * 505 */ 506 int 507 meta_check_samedrive( 508 mdname_t *np1, /* first comp */ 509 mdname_t *np2, /* second comp */ 510 md_error_t *ep 511 ) 512 { 513 514 mdcinfo_t *cinfop1, *cinfop2; 515 mdnmtype_t type1 = np1->drivenamep->type; 516 mdnmtype_t type2 = np2->drivenamep->type; 517 int l = 0; 518 519 char *name1 = NULL; 520 char *name2 = NULL; 521 522 int retval = CANT_TELL; 523 int fd1 = -1; 524 int fd2 = -1; 525 int rc1 = -2, rc2 = -2; 526 uint_t strl1 = 0, strl2 = 0; 527 int devid1_found = 0; 528 int devid2_found = 0; 529 530 ddi_devid_t devid1 = NULL; 531 ddi_devid_t devid2 = NULL; 532 dev_list_t *dnlp = NULL; 533 534 assert(type1 != MDT_FAST_META && type1 != MDT_FAST_COMP); 535 assert(type2 != MDT_FAST_META && type2 != MDT_FAST_COMP); 536 537 /* 538 * The process of determining if 2 names are the same drive is 539 * as follows: 540 * 541 * Case 1 - The filenames are identical 542 * 543 * Case 2 - Both devices have a devid 544 * get and compare the devids for the devices. If both 545 * devices have a devid then the compare will is all 546 * that is needed we are done. 547 * 548 * Case 3 - One or more devices does not have a devid 549 * start by doing a simple compare of the name, if they 550 * are the same just return. 551 * 552 * If the names differ then keep going and see if the 553 * may be the same underlying devic. First check to 554 * see if the sd name is the same (old code). 555 * 556 * Then check the major and minor numbers to see if 557 * they are the same. If they are then return (old code). 558 * 559 * Next compare the raw name and the component name and 560 * if they are the same then return. 561 * 562 * All else has failed so use the component name (cname) 563 * component number and unit number. If they all are 564 * equal then call them the same drive. 565 * 566 */ 567 568 if ((np1 == NULL) || (np2 == NULL)) 569 return (NOT_SAMEDRIVE); 570 571 /* if the name structs are the same then the drives must be */ 572 if (np1 == np2) 573 return (IDENTICAL_NAME_DEVT); 574 575 name1 = np1->bname; 576 name2 = np2->bname; 577 578 if ((name1 == NULL) || ((strl1 = strlen(name1)) == 0) || 579 (name2 == NULL) || ((strl2 = strlen(name2)) == 0)) 580 return (NOT_SAMEDRIVE); 581 582 if ((strl1 == strl2) && (strcmp(name1, name2) == 0)) { 583 /* names are identical */ 584 return (IDENTICAL_NAME_DEVT); 585 } 586 587 if (is_metaname(name1) || is_metaname(name2)) 588 return (NOT_SAMEDRIVE); 589 590 /* 591 * Check to see if the devicename is in the static list. If so, 592 * use its devid. Otherwise do the expensive operations 593 * of opening the device, getting the devid, and closing the 594 * device. Add the result into the static list. 595 * 596 * The case where this list will be useful is when there are soft 597 * partitions on multiple drives and a new soft partition is being 598 * created. In that situation the underlying physical device name 599 * for the new soft partition would be compared against each of the 600 * existing soft partititions. Without this static list that would 601 * involve 2 opens, closes, and devid gets for each existing soft 602 * partition 603 */ 604 for (dnlp = devnamelist; (dnlp != NULL) && 605 !(devid1_found && devid2_found); dnlp = dnlp->dev_nxt) { 606 if (!devid1_found && (strcmp(dnlp->dev_name, name1) == 0)) { 607 devid1_found = 1; 608 devid1 = dnlp->devid; 609 if (devid1 == NULL) 610 rc1 = 1; 611 else 612 rc1 = 0; 613 continue; 614 } 615 if (!devid2_found && (strcmp(dnlp->dev_name, name2) == 0)) { 616 devid2_found = 1; 617 devid2 = dnlp->devid; 618 if (devid2 == NULL) 619 rc2 = 1; 620 else 621 rc2 = 0; 622 continue; 623 } 624 } 625 626 /* 627 * Start by checking if the device has a device id, and if they 628 * are equal. If they are there is no question there is a match. 629 * 630 * The process here is open each disk, get the devid for each 631 * disk. If they both have a devid compare them and return 632 * the results. 633 */ 634 if (!devid1_found) { 635 if ((fd1 = open(name1, O_RDONLY | O_NDELAY)) < 0) { 636 return (NOT_SAMEDRIVE); 637 } 638 rc1 = devid_get(fd1, &devid1); 639 (void) close(fd1); 640 641 /* add the name and devid to the cache */ 642 add_to_devname_list(name1, devid1); 643 } 644 645 if (!devid2_found) { 646 if ((fd2 = open(name2, O_RDONLY | O_NDELAY)) < 0) { 647 return (NOT_SAMEDRIVE); 648 } 649 rc2 = devid_get(fd2, &devid2); 650 (void) close(fd2); 651 652 /* add the name and devid to the cache */ 653 add_to_devname_list(name2, devid2); 654 } 655 656 657 if ((rc1 == 0) && (rc2 == 0)) { 658 if (devid_compare(devid1, devid2) == 0) 659 retval = IDENTICAL_DEVIDS; /* same devid */ 660 else 661 retval = NOT_SAMEDRIVE; /* different drives */ 662 663 } 664 665 if (retval >= 0) { 666 return (retval); 667 } 668 669 /* 670 * At this point in time one of the two drives did not have a 671 * device ID. Do not make the assumption that is one drive 672 * did have a device id and the other did not that they are not 673 * the same. One drive could be covered by a device and still 674 * be the same drive. This is a general flaw in the system at 675 * this time. 676 */ 677 678 /* 679 * The optimization can not happen if we are given an old style name 680 * in the form /dev/XXNN[a-h], since the name caches differently and 681 * allows overlaps to happen. 682 */ 683 if (! ((sscanf(np1->bname, "/dev/%*[^0-9/]%*u%*[a-h]%n", &l) == 0 && 684 l == strlen(np1->bname)) || 685 (sscanf(np2->bname, "/dev/%*[^0-9/]%*u%*[a-h]%n", &l) == 0 && 686 l == strlen(np2->bname))) && 687 ((type1 == MDT_COMP) || (type1 == MDT_META)) && 688 ((type2 == MDT_COMP) || (type2 == MDT_META))) 689 if (np1->drivenamep == np2->drivenamep) 690 return (IDENTICAL_NAME_DEVT); 691 else 692 return (NOT_SAMEDRIVE); 693 694 /* check for same drive */ 695 if (meta_getmajor(np1->dev) != meta_getmajor(np2->dev)) 696 return (NOT_SAMEDRIVE); /* not same drive */ 697 698 if (((cinfop1 = metagetcinfo(np1, ep)) == NULL) || 699 ((cinfop2 = metagetcinfo(np2, ep)) == NULL)) { 700 if ((strcmp(np1->drivenamep->cname, 701 np2->drivenamep->cname) != 0) && 702 (strcmp(np1->drivenamep->rname, 703 np2->drivenamep->rname) != 0)) { 704 mdclrerror(ep); 705 return (NOT_SAMEDRIVE); /* not same drive */ 706 } else { 707 return (CANT_TELL); /* can't tell */ 708 } 709 } else if ((strncmp(cinfop1->cname, cinfop2->cname, 710 sizeof (cinfop1->cname)) != 0) || 711 (cinfop1->cnum != cinfop2->cnum) || 712 (cinfop1->unit != cinfop2->unit)) { 713 return (NOT_SAMEDRIVE); /* not same drive */ 714 } 715 716 /* same drive */ 717 return (IDENTICAL_NAME_DEVT); 718 } 719 720 /* 721 * check for overlap 722 */ 723 int 724 meta_check_overlap( 725 char *uname, /* user supplied name for errors */ 726 mdname_t *np1, /* first comp */ 727 diskaddr_t slblk1, /* first comp - start logical block */ 728 diskaddr_t nblks1, /* first comp - # of blocks */ 729 mdname_t *np2, /* second comp */ 730 diskaddr_t slblk2, /* second comp - start logical block */ 731 diskaddr_t nblks2, /* second comp - # of blocks */ 732 md_error_t *ep 733 ) 734 { 735 diskaddr_t sblk1, sblk2; 736 mdvtoc_t *vtocp1, *vtocp2; 737 uint_t partno1, partno2; 738 mdpart_t *partp1, *partp2; 739 int ret; 740 741 /* verify args */ 742 if (slblk1 == MD_DISKADDR_ERROR) { 743 assert(0); 744 return (mdsyserror(ep, EINVAL, np1->cname)); 745 } 746 if (slblk2 == MD_DISKADDR_ERROR) { 747 assert(0); 748 return (mdsyserror(ep, EINVAL, np2->cname)); 749 } 750 751 /* check for same drive */ 752 if ((ret = meta_check_samedrive(np1, np2, ep)) == 0) { 753 return (0); /* not same drive */ 754 } else if (ret < 0) { 755 return (-1); /* can't tell */ 756 } 757 758 /* check for overlap */ 759 if (((vtocp1 = metagetvtoc(np1, FALSE, &partno1, ep)) == NULL) || 760 ((vtocp2 = metagetvtoc(np2, FALSE, &partno2, ep)) == NULL)) { 761 return (-1); /* can't tell */ 762 } 763 partp1 = &vtocp1->parts[partno1]; 764 partp2 = &vtocp2->parts[partno2]; 765 sblk1 = partp1->start + slblk1; 766 if (nblks1 == -1) 767 nblks1 = partp1->size - slblk1; 768 sblk2 = partp2->start + slblk2; 769 if (nblks2 == -1) 770 nblks2 = partp2->size - slblk2; 771 if (((sblk1 >= sblk2) && (sblk1 < (sblk2 + nblks2))) || 772 ((sblk2 >= sblk1) && (sblk2 < (sblk1 + nblks1)))) { 773 if (np1->dev == np2->dev) { /* slice in use */ 774 return (mduseerror(ep, MDE_ALREADY, np1->dev, 775 uname, np1->cname)); 776 } 777 if (ret == IDENTICAL_NAME_DEVT) 778 return (mduseerror(ep, /* slice overlaps */ 779 MDE_OVERLAP, np1->dev, uname, np1->cname)); 780 else 781 return (mduseerror(ep, /* same devid */ 782 MDE_SAME_DEVID, np1->dev, uname, np2->cname)); 783 } 784 785 /* return success */ 786 return (0); /* no overlap */ 787 } 788 789 /* 790 * check to see if a device is in a metadevice 791 */ 792 int 793 meta_check_inmeta( 794 mdsetname_t *sp, 795 mdname_t *np, 796 mdchkopts_t options, 797 diskaddr_t slblk, 798 diskaddr_t nblks, 799 md_error_t *ep 800 ) 801 { 802 uint_t partno; 803 804 /* see if replica slice is ok, only applies to disks in sets */ 805 if (! (options & MDCHK_ALLOW_REPSLICE) && 806 ! metaislocalset(sp)) { 807 uint_t rep_slice; 808 809 if (metagetvtoc(np, FALSE, &partno, ep) == NULL) 810 return (-1); 811 if (meta_replicaslice(np->drivenamep, &rep_slice, ep) 812 != 0) 813 return (-1); 814 if (partno == rep_slice) 815 return (mddeverror(ep, MDE_REPCOMP_INVAL, np->dev, 816 np->cname)); 817 } 818 819 /* check for databases */ 820 if (meta_check_inreplica(sp, np, slblk, nblks, ep) != 0) { 821 if (mdisuseerror(ep, MDE_ALREADY)) { 822 if (options & MDCHK_ALLOW_MDDB) { 823 mdclrerror(ep); 824 } else { 825 return (mddeverror(ep, MDE_HAS_MDDB, 826 np->dev, np->cname)); 827 } 828 } else { 829 return (-1); 830 } 831 } 832 833 /* check metadevices */ 834 if (meta_check_instripe(sp, np, slblk, nblks, ep) != 0) 835 return (-1); 836 if (meta_check_inmirror(sp, np, slblk, nblks, ep) != 0) 837 return (-1); 838 if (meta_check_intrans(sp, np, options, slblk, nblks, ep) != 0) 839 return (-1); 840 if (meta_check_insp(sp, np, slblk, nblks, ep) != 0) 841 return (-1); 842 if (! (options & MDCHK_ALLOW_HS)) { 843 if (meta_check_inhsp(sp, np, slblk, nblks, ep) != 0) 844 return (-1); 845 } 846 if (meta_check_inraid(sp, np, slblk, nblks, ep) != 0) 847 return (-1); 848 849 /* return success */ 850 return (0); 851 } 852 853 /* 854 * check to see if a device is in its set 855 */ 856 int 857 meta_check_inset( 858 mdsetname_t *sp, 859 mdname_t *np, 860 md_error_t *ep 861 ) 862 { 863 mdsetname_t *npsp; 864 int bypass_daemon = FALSE; 865 866 867 /* check devices set */ 868 if (metaislocalset(sp)) 869 bypass_daemon = TRUE; 870 if ((npsp = metagetset(np, bypass_daemon, ep)) == NULL) { 871 if ((! metaismeta(np)) && 872 (metaislocalset(sp)) && 873 (mdismddberror(ep, MDE_DB_NODB))) { 874 mdclrerror(ep); 875 npsp = sp; 876 } else { 877 return (-1); 878 } 879 } 880 881 /* check set */ 882 if (metaissameset(sp, npsp)) 883 return (0); 884 885 /* return appropriate error */ 886 if (metaislocalset(sp)) 887 return (mddeverror(ep, MDE_IN_SHARED_SET, np->dev, np->cname)); 888 else 889 return (mddeverror(ep, MDE_NOT_IN_SET, np->dev, np->cname)); 890 } 891 892 /* 893 * check to see if current user is root 894 */ 895 int 896 meta_check_root(md_error_t *ep) 897 { 898 if (geteuid() != 0) { 899 (void) mderror(ep, MDE_NOPERM, ""); 900 return (-1); 901 } 902 return (0); 903 } 904