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
free_swapinfo(struct swaptable * swtp)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
get_swapinfo(struct swaptable ** swtpp,int * nswap,md_error_t * ep)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
meta_check_swapped(mdsetname_t * sp,mdname_t * np,md_error_t * ep)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
meta_check_driveswapped(mdsetname_t * sp,mddrivename_t * dnp,md_error_t * ep)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
meta_check_dump(mdsetname_t * sp,mdname_t * np,md_error_t * ep)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
meta_check_mounted(mdsetname_t * sp,mdname_t * np,md_error_t * ep)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
meta_check_drivemounted(mdsetname_t * sp,mddrivename_t * dnp,md_error_t * ep)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
meta_check_inuse(mdsetname_t * sp,mdname_t * np,mdinuseopts_t inuse_flags,md_error_t * ep)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
meta_check_driveinset(mdsetname_t * sp,mddrivename_t * dn,md_error_t * ep)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
add_to_devname_list(char * device_name,ddi_devid_t devid)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
meta_check_samedrive(mdname_t * np1,mdname_t * np2,md_error_t * ep)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
meta_check_overlap(char * uname,mdname_t * np1,diskaddr_t slblk1,diskaddr_t nblks1,mdname_t * np2,diskaddr_t slblk2,diskaddr_t nblks2,md_error_t * ep)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
meta_check_inmeta(mdsetname_t * sp,mdname_t * np,mdchkopts_t options,diskaddr_t slblk,diskaddr_t nblks,md_error_t * ep)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
meta_check_inset(mdsetname_t * sp,mdname_t * np,md_error_t * ep)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
meta_check_root(md_error_t * ep)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