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