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