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