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  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  26  */
  27 
  28 /*
  29  * Just in case we're not in a build environment, make sure that
  30  * TEXT_DOMAIN gets set to something.
  31  */
  32 #if !defined(TEXT_DOMAIN)
  33 #define TEXT_DOMAIN "SYS_TEST"
  34 #endif
  35 
  36 /*
  37  * check componets
  38  */
  39 
  40 #include <meta.h>
  41 #include "meta_lib_prv.h"
  42 
  43 #include <sys/mnttab.h>
  44 #include <sys/swap.h>
  45 #include <devid.h>
  46 #include <sys/dumpadm.h>
  47 
  48 /* possible returns from meta_check_samedrive */
  49 #define CANT_TELL               -1
  50 #define NOT_SAMEDRIVE           0
  51 #define IDENTICAL_NAME_DEVT     1
  52 #define IDENTICAL_DEVIDS        2
  53 
  54 /*
  55  * static list(s)
  56  */
  57 typedef struct dev_list {
  58         char                    *dev_name;
  59         ddi_devid_t             devid;
  60         struct dev_list         *dev_nxt;
  61 } dev_list_t;
  62 
  63 static dev_list_t       *devnamelist = NULL;
  64 
  65 static char     *skip_these_mntents[] = {
  66         "nfs",
  67         "autofs",
  68         "proc",
  69         "tmpfs",
  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 }