xref: /onnv-gate/usr/src/uts/common/io/lvm/md/md_ioctl.c (revision 5428:a49c9c44830e)
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 2007 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  * Driver for Virtual Disk.
30  */
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/buf.h>
34 #include <sys/conf.h>
35 #include <sys/user.h>
36 #include <sys/uio.h>
37 #include <sys/proc.h>
38 #include <sys/t_lock.h>
39 #include <sys/dkio.h>
40 #include <sys/kmem.h>
41 #include <sys/utsname.h>
42 #include <sys/debug.h>
43 #include <sys/sysmacros.h>
44 #include <sys/types.h>
45 #include <sys/mkdev.h>
46 #include <sys/vtoc.h>
47 #include <sys/efi_partition.h>
48 #include <sys/open.h>
49 #include <sys/file.h>
50 #include <sys/ddi.h>
51 #include <sys/sunddi.h>
52 #include <sys/lvm/mdmn_commd.h>
53 
54 #include <sys/lvm/mdvar.h>
55 #include <sys/lvm/md_rename.h>
56 #include <sys/lvm/md_names.h>
57 #include <sys/lvm/md_hotspares.h>
58 
59 extern md_ops_t		**md_ops;
60 extern unit_t		md_nunits;
61 extern set_t		md_nsets;
62 extern int		md_nmedh;
63 extern md_set_t		md_set[];
64 extern md_set_io_t	md_set_io[];
65 extern int		md_status;
66 extern int		md_ioctl_cnt;
67 extern int		md_in_upgrade;
68 extern major_t		md_major;
69 
70 /* md.c */
71 extern kmutex_t		md_mx;
72 extern kcondvar_t	md_cv;
73 
74 /* md_hotspares.c */
75 extern	hot_spare_pool_t *find_hot_spare_pool(set_t setno, int hsp_id);
76 
77 /* md_med.c */
78 extern int		med_addr_tab_nents;
79 extern int		med_get_t_size_ioctl(mddb_med_t_parm_t *tpp, int mode);
80 extern int		med_get_t_ioctl(mddb_med_t_parm_t *tpp, int mode);
81 extern int		med_set_t_ioctl(mddb_med_t_parm_t *tpp, int mode);
82 extern unit_t		md_get_nextunit(set_t setno);
83 
84 static int		md_mn_commd_present;
85 
86 /* md_mddb.c */
87 extern mddb_set_t	*mddb_setenter(set_t setno, int flag, int *errorcodep);
88 extern void		mddb_setexit(mddb_set_t *s);
89 extern md_krwlock_t	nm_lock;
90 
91 /*
92  * md_mn_is_commd_present:
93  * ----------------------
94  * Determine if commd is running on this node.
95  *
96  * Returns:
97  *	1	if commd has been started
98  *	0	if commd has not been started or has exited
99  */
100 int
101 md_mn_is_commd_present(void)
102 {
103 	return (md_mn_commd_present ? 1 : 0);
104 }
105 
106 /*
107  * md_mn_clear_commd_present:
108  * -------------------------
109  * Clear the commd_present flag. Called only from a CPR request to suspend /
110  * terminate a resync thread. We clear the md_mn_commd_present flag so that
111  * any RPC request that was in transit can complete with a failure and _not_
112  * result in an unexpected system panic.
113  */
114 void
115 md_mn_clear_commd_present()
116 {
117 	md_mn_commd_present = 0;
118 }
119 
120 /*
121  * It is possible to pass in a minor number via the ioctl interface
122  * and this minor number is used to reference elements in arrays.
123  * Therefore we need to make sure that the value passed in is
124  * correct within the array sizes, and array dereference. Not
125  * doing so allows for incorrect values which may result in panics.
126  */
127 static int
128 verify_minor(minor_t mnum)
129 {
130 	set_t	setno = MD_MIN2SET(mnum);
131 
132 	/*
133 	 * Check the bounds.
134 	 */
135 	if (setno >= md_nsets || (MD_MIN2UNIT(mnum) >= md_nunits)) {
136 		return (EINVAL);
137 	}
138 
139 	/* has the set been initialised ? */
140 	if ((md_get_setstatus(setno) & MD_SET_SNARFED) == 0)
141 		return (ENODEV);
142 
143 	return (0);
144 }
145 
146 static int
147 get_lb_inittime_ioctl(
148 	mddb_config_t	*cp
149 )
150 {
151 	set_t		setno = cp->c_setno;
152 	int		err;
153 	mddb_set_t	*s;
154 
155 	if (setno >= md_nsets)
156 		return (-1);
157 
158 	if ((s = mddb_setenter(setno, MDDB_MUSTEXIST, &err)) == NULL)
159 		return (-1);
160 
161 	if (s->s_lbp == NULL) {
162 		mddb_setexit(s);
163 		return (-1);
164 	}
165 
166 	cp->c_timestamp = s->s_lbp->lb_inittime;
167 
168 	mddb_setexit(s);
169 	return (0);
170 }
171 
172 static int
173 setnm_ioctl(mdnm_params_t *nm, int mode)
174 {
175 	char 	*name, *minorname = NULL;
176 	side_t	side;
177 	int	err = 0;
178 	void	*devid = NULL;
179 	int	devid_sz;
180 
181 	/*
182 	 * Don't allow addition of new names to namespace during upgrade.
183 	 */
184 	if (MD_UPGRADE)  {
185 		return (EAGAIN);
186 	}
187 
188 	mdclrerror(&nm->mde);
189 
190 	if ((mode & FWRITE) == 0)
191 		return (EACCES);
192 
193 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
194 		return (0);
195 
196 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
197 		return (ENODEV);
198 
199 	if (md_get_setstatus(nm->setno) & MD_SET_STALE)
200 		return (mdmddberror(&nm->mde, MDE_DB_STALE, NODEV32,
201 		    nm->setno));
202 
203 	name = kmem_alloc(MAXPATHLEN, KM_SLEEP);
204 
205 	err = ddi_copyin((caddr_t)(uintptr_t)nm->devname, name,
206 	    (size_t)nm->devname_len, mode);
207 	if (err) {
208 		err = EFAULT;
209 		goto out;
210 	}
211 
212 	if (nm->imp_flag) {
213 		if ((nm->devid == NULL) || (nm->minorname == NULL)) {
214 			err = EINVAL;
215 			goto out;
216 		}
217 		if (nm->devid) {
218 			devid_sz = nm->devid_size;
219 			devid = kmem_zalloc(devid_sz, KM_SLEEP);
220 			err = ddi_copyin((caddr_t)(uintptr_t)nm->devid,
221 			    devid, devid_sz, mode);
222 			if (err) {
223 				err = EFAULT;
224 				goto out;
225 			}
226 		}
227 		if (nm->minorname) {
228 			if (nm->minorname_len > MAXPATHLEN) {
229 				err = EINVAL;
230 				goto out;
231 			}
232 			minorname = kmem_zalloc(nm->minorname_len, KM_SLEEP);
233 			err = ddi_copyin((caddr_t)(uintptr_t)nm->minorname,
234 			    minorname, (size_t)nm->minorname_len, mode);
235 			if (err) {
236 				err = EFAULT;
237 				goto out;
238 			}
239 		}
240 	}
241 
242 	if (nm->side == -1)
243 		side = mddb_getsidenum(nm->setno);
244 	else
245 		side = nm->side;
246 
247 	if (strcmp(nm->drvnm, "") == 0) {
248 		char *drvnm;
249 		drvnm = ddi_major_to_name(nm->major);
250 		(void) strncpy(nm->drvnm, drvnm, sizeof (nm->drvnm));
251 	}
252 
253 	nm->key = md_setdevname(nm->setno, side, nm->key, nm->drvnm,
254 	    nm->mnum, name, nm->imp_flag, (ddi_devid_t)devid, minorname,
255 	    0, &nm->mde);
256 	/*
257 	 * If we got an error from md_setdevname & md_setdevname did not
258 	 * set the error code, we'll default to MDE_DB_NOSPACE.
259 	 */
260 	if ((((int)nm->key) < 0) && mdisok(&nm->mde)) {
261 		err = mdmddberror(&nm->mde, MDE_DB_NOSPACE, NODEV32, nm->setno);
262 		goto out;
263 	}
264 
265 out:
266 	kmem_free(name, MAXPATHLEN);
267 	if (devid) {
268 		kmem_free(devid, devid_sz);
269 	}
270 	if (minorname)
271 		kmem_free(minorname, nm->minorname_len);
272 	return (err);
273 }
274 
275 static int
276 getnm_ioctl(
277 	mdnm_params_t	*nm,
278 	int		mode
279 )
280 {
281 	char		*name;
282 	side_t		side;
283 	md_dev64_t	dev = NODEV64;
284 	mdc_unit_t	*un;
285 	uint_t		id;
286 	char		*setname;
287 	int		err = 0;
288 
289 	mdclrerror(&nm->mde);
290 
291 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
292 		return (0);
293 
294 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
295 		return (ENODEV);
296 
297 
298 	name = kmem_alloc(MAXPATHLEN, KM_SLEEP);
299 
300 	if (nm->side == -1)
301 		side = mddb_getsidenum(nm->setno);
302 	else
303 		side = nm->side;
304 
305 	if (nm->drvnm[0] == '\0') {
306 		char *drvnm;
307 
308 		if (MD_UPGRADE)
309 			drvnm = md_targ_major_to_name(nm->major);
310 		else
311 			drvnm = ddi_major_to_name(nm->major);
312 		if (drvnm != NULL)
313 			(void) strncpy(nm->drvnm, drvnm, sizeof (nm->drvnm));
314 	}
315 
316 	if (nm->drvnm[0] != '\0') {
317 		if (MD_UPGRADE)
318 			dev = md_makedevice(md_targ_name_to_major(nm->drvnm),
319 			    nm->mnum);
320 		else
321 			dev = md_makedevice(ddi_name_to_major(nm->drvnm),
322 			    nm->mnum);
323 	}
324 
325 	/*
326 	 * With the introduction of friendly names, all friendly named
327 	 * metadevices will have an entry in the name space. However,
328 	 * systems upgraded from pre-friendly name to a friendly name
329 	 * release won't have name space entries for pre-friendly name
330 	 * top level metadevices.
331 	 *
332 	 * So we search the name space for the our entry with either the
333 	 * given dev_t or key. If we can't find the entry, we'll try the
334 	 * un array to get information for our target metadevice. Note
335 	 * we only use the un array when searching by dev_t since a
336 	 * key implies an existing device which should have been
337 	 * found in the name space with the call md_getdevname.
338 	 */
339 	if (md_getdevname(nm->setno, side, nm->key, dev, name,
340 	    MAXPATHLEN) == 0) {
341 		err = md_getnment(nm->setno, side, nm->key, dev, nm->drvnm,
342 		    sizeof (nm->drvnm), &nm->major, &nm->mnum, &nm->retkey);
343 		if (err) {
344 			if (err < 0)
345 				err = EINVAL;
346 			goto out;
347 		}
348 	} else {
349 		if ((nm->key != MD_KEYWILD) ||
350 		    (md_set[MD_MIN2SET(nm->mnum)].s_un == NULL) ||
351 		    (MD_UNIT(nm->mnum) == NULL)) {
352 			err = ENOENT;
353 			goto out;
354 		}
355 
356 		/*
357 		 * We're here because the mnum is of a pre-friendly
358 		 * name device. Make sure the major value is for
359 		 * metadevices.
360 		 */
361 		if (nm->major != md_major) {
362 			err = ENOENT;
363 			goto out;
364 		}
365 
366 		/*
367 		 * get the unit number and setname to construct the
368 		 * fully qualified name for the metadevice.
369 		 */
370 		un = MD_UNIT(nm->mnum);
371 		id =  MD_MIN2UNIT(un->un_self_id);
372 		if (nm->setno != MD_LOCAL_SET) {
373 			setname = mddb_getsetname(nm->setno);
374 			(void) snprintf(name, MAXPATHLEN,
375 			    "/dev/md/%s/dsk/d%u", setname, id);
376 		} else {
377 			(void) snprintf(name, MAXPATHLEN,
378 			    "/dev/md/dsk/d%u", id);
379 		}
380 	}
381 
382 	err = ddi_copyout(name, (caddr_t)(uintptr_t)nm->devname,
383 	    strlen(name) + 1, mode);
384 	if (err) {
385 		err = EFAULT;
386 		goto out;
387 	}
388 
389 out:
390 	kmem_free(name, MAXPATHLEN);
391 	return (err);
392 }
393 
394 static int
395 gethspnm_ioctl(
396 	mdhspnm_params_t	*nm,
397 	int			mode
398 )
399 {
400 	char			*name;
401 	char			*tmpname;
402 	char			*setname = NULL;
403 	side_t			side;
404 	hot_spare_pool_t	*hsp = NULL;
405 	mdkey_t			key = MD_KEYWILD;
406 	int			err = 0;
407 
408 	mdclrerror(&nm->mde);
409 
410 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
411 		return (0);
412 
413 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
414 		return (ENODEV);
415 
416 	name = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
417 
418 	if (nm->side == -1)
419 		side = mddb_getsidenum(nm->setno);
420 	else
421 		side = nm->side;
422 
423 	/*
424 	 * Get the key from input hspid, use different macros
425 	 * since the hspid could be either a FN or pre-FN hspid.
426 	 */
427 	if (nm->hspid != MD_HSPID_WILD) {
428 		if (HSP_ID_IS_FN(nm->hspid))
429 			key = HSP_ID_TO_KEY(nm->hspid);
430 		else
431 			key = HSP_ID(nm->hspid);
432 	}
433 
434 	/*
435 	 * Get the input name if we're searching by hsp name. Check
436 	 * that the input name length is less than MAXPATHLEN.
437 	 */
438 	if ((nm->hspid == MD_HSPID_WILD) &&
439 	    (nm->hspname_len <= MAXPATHLEN)) {
440 		err = ddi_copyin((caddr_t)(uintptr_t)nm->hspname,
441 		    name, (sizeof (char)) * nm->hspname_len, mode);
442 
443 		/* Stop if ddi_copyin failed. */
444 		if (err) {
445 			err = EFAULT;
446 			goto out;
447 		}
448 	}
449 
450 	/* Must have either a valid hspid or a name to continue */
451 	if ((nm->hspid == MD_HSPID_WILD) && (name[0] == '\0')) {
452 		err = EINVAL;
453 		goto out;
454 	}
455 
456 	/*
457 	 * Try to find the hsp namespace entry corresponds to either
458 	 * the given hspid or name. If we can't find it, the hsp maybe
459 	 * a pre-friendly name hsp so we'll try to find it in the
460 	 * s_hsp array.
461 	 */
462 	if ((nm->hspid == MD_HSPID_WILD) || (HSP_ID_IS_FN(nm->hspid))) {
463 
464 		if (md_gethspinfo(nm->setno, side, key, nm->drvnm,
465 		    &nm->ret_hspid, name) != 0) {
466 			/*
467 			 * If we were given a key for a FN hsp and
468 			 * couldn't find its entry, simply errored
469 			 * out.
470 			 */
471 			if (HSP_ID_IS_FN(nm->hspid)) {
472 				err = ENOENT;
473 				goto out;
474 			}
475 
476 			/*
477 			 * Since md_gethspinfo failed and the hspid is
478 			 * not a FN hspid,  we must have a name for a
479 			 * pre-FN hotspare pool
480 			 */
481 			if (name[0] == '\0') {
482 				err = EINVAL;
483 				goto out;
484 			}
485 
486 			tmpname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
487 			if (nm->setno != MD_LOCAL_SET)
488 				setname = mddb_getsetname(nm->setno);
489 
490 			hsp = (hot_spare_pool_t *)md_set[nm->setno].s_hsp;
491 			while (hsp != NULL) {
492 				/* Only use the pre-friendly name hsp */
493 				if (!(hsp->hsp_revision & MD_FN_META_DEV)) {
494 
495 					if (setname != NULL) {
496 						(void) snprintf(tmpname,
497 						    MAXPATHLEN,
498 						    "%s/hsp%03u", setname,
499 						    HSP_ID(hsp->hsp_self_id));
500 					} else {
501 						(void) snprintf(tmpname,
502 						    MAXPATHLEN, "hsp%03u",
503 						    HSP_ID(hsp->hsp_self_id));
504 					}
505 
506 					if (strcmp(name, tmpname) == 0)
507 						break;
508 				}
509 
510 				hsp = hsp->hsp_next;
511 			}
512 			kmem_free(tmpname, MAXPATHLEN);
513 
514 			if (hsp == NULL) {
515 				err = ENOENT;
516 				goto out;
517 			}
518 
519 			/* Return hsp_self_id */
520 			nm->ret_hspid = hsp->hsp_self_id;
521 		}
522 
523 	} else {
524 		/*
525 		 * We have a hspid for a pre-FN hotspare pool. Let's
526 		 * try to find the matching hsp using the given
527 		 * hspid.
528 		 */
529 		if (nm->hspid == MD_HSPID_WILD) {
530 			err = ENOENT;
531 			goto out;
532 		}
533 
534 		hsp = (hot_spare_pool_t *)md_set[nm->setno].s_hsp;
535 		while (hsp != NULL) {
536 			if (hsp->hsp_self_id == nm->hspid)
537 				break;
538 			hsp = hsp->hsp_next;
539 		}
540 
541 		if (hsp == NULL) {
542 			err = ENOENT;
543 			goto out;
544 		}
545 
546 		/* Prepare a name to return */
547 		if (nm->setno != MD_LOCAL_SET)
548 			setname = mddb_getsetname(nm->setno);
549 
550 		if (setname != NULL) {
551 			(void) snprintf(name, MAXPATHLEN, "%s/hsp%03u",
552 			    setname, HSP_ID(hsp->hsp_self_id));
553 		} else {
554 			(void) snprintf(name, MAXPATHLEN, "hsp%03u",
555 			    HSP_ID(hsp->hsp_self_id));
556 		}
557 
558 		nm->ret_hspid = hsp->hsp_self_id;
559 	}
560 
561 	if (nm->hspid != MD_HSPID_WILD) {
562 		if ((strlen(name) + 1) > nm->hspname_len) {
563 			err = EINVAL;
564 			goto out;
565 		}
566 		err = ddi_copyout(name, (caddr_t)
567 		    (uintptr_t)nm->hspname, strlen(name)+1, mode);
568 	}
569 
570 	if (err) {
571 		if (err < 0)
572 			err = EINVAL;
573 	}
574 
575 out:
576 	kmem_free(name, MAXPATHLEN);
577 	return (err);
578 }
579 
580 
581 /*ARGSUSED*/
582 static int
583 update_loc_namespace_ioctl(
584 	mdnm_params_t	*nm,
585 	char		*dname,
586 	char		*pname,
587 	int		mode
588 )
589 {
590 
591 	side_t		side;
592 
593 	mdclrerror(&nm->mde);
594 
595 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
596 		return (0);
597 
598 	if (MD_MNSET_SETNO(nm->setno))
599 		return (0);
600 
601 	if ((md_get_setstatus(nm->setno) & MD_SET_STALE))
602 		return (0);
603 
604 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
605 		return (ENODEV);
606 
607 	if (nm->side == -1)
608 		side = mddb_getsidenum(nm->setno);
609 	else
610 		side = nm->side;
611 
612 	return (md_update_locator_namespace(nm->setno, side, dname,
613 	    pname, nm->devt));
614 }
615 
616 /*ARGSUSED*/
617 static int
618 update_namespace_did_ioctl(
619 	mdnm_params_t	*nm,
620 	int		mode
621 )
622 {
623 	side_t		side;
624 
625 	mdclrerror(&nm->mde);
626 
627 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
628 		return (0);
629 
630 	if (MD_MNSET_SETNO(nm->setno))
631 		return (0);
632 
633 	if ((md_get_setstatus(nm->setno) & MD_SET_STALE))
634 		return (0);
635 
636 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
637 		return (ENODEV);
638 
639 	if (nm->side == -1)
640 		side = mddb_getsidenum(nm->setno);
641 	else
642 		side = nm->side;
643 
644 	return (md_update_namespace_did(nm->setno, side, nm->key, &nm->mde));
645 }
646 
647 /*ARGSUSED*/
648 static int
649 update_namespace_ioctl(
650 	mdnm_params_t	*nm,
651 	char		*dname,
652 	char		*pname,
653 	int		mode
654 )
655 {
656 	side_t		side;
657 
658 	mdclrerror(&nm->mde);
659 
660 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
661 		return (0);
662 
663 	if (MD_MNSET_SETNO(nm->setno))
664 		return (0);
665 
666 	if ((md_get_setstatus(nm->setno) & MD_SET_STALE))
667 		return (0);
668 
669 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
670 		return (ENODEV);
671 
672 	if (nm->side == -1)
673 		side = mddb_getsidenum(nm->setno);
674 	else
675 		side = nm->side;
676 
677 	return (md_update_namespace(nm->setno, side, nm->key,
678 	    dname, pname, nm->mnum));
679 
680 }
681 
682 /*ARGSUSED*/
683 static int
684 getnextkey_ioctl(
685 	mdnm_params_t	*nm,
686 	int		mode
687 )
688 {
689 	side_t		side;
690 
691 	mdclrerror(&nm->mde);
692 
693 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
694 		return (0);
695 
696 	if (nm->setno >= md_nsets)
697 		return (EINVAL);
698 
699 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
700 		return (ENODEV);
701 
702 	if (nm->side == -1)
703 		side = mddb_getsidenum(nm->setno);
704 	else
705 		side = nm->side;
706 
707 	nm->key = md_getnextkey(nm->setno, side, nm->key, &nm->ref_count);
708 	return (0);
709 }
710 
711 /*ARGSUSED*/
712 static int
713 remnm_ioctl(mdnm_params_t *nm, int mode)
714 {
715 	side_t	side;
716 
717 	mdclrerror(&nm->mde);
718 
719 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
720 		return (0);
721 
722 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
723 		return (ENODEV);
724 
725 	if (nm->side == -1)
726 		side = mddb_getsidenum(nm->setno);
727 	else
728 		side = nm->side;
729 
730 	return (md_remdevname(nm->setno, side, nm->key));
731 }
732 
733 
734 /*ARGSUSED*/
735 static int
736 getdrvnm_ioctl(md_dev64_t dev, md_i_driverinfo_t *di, int mode)
737 {
738 	mdi_unit_t 	*ui;
739 	minor_t		mnum = di->mnum;
740 	set_t		setno = MD_MIN2SET(mnum);
741 
742 	mdclrerror(&di->mde);
743 
744 	if (md_snarf_db_set(MD_LOCAL_SET, &di->mde) != 0)
745 		return (0);
746 
747 	ui = MDI_UNIT(mnum);
748 	if (ui == NULL) {
749 		return (mdmderror(&di->mde, MDE_UNIT_NOT_SETUP, mnum));
750 	}
751 
752 	MD_SETDRIVERNAME(di, md_ops[ui->ui_opsindex]->md_driver.md_drivername,
753 	    setno);
754 
755 	return (0);
756 }
757 
758 /*ARGSUSED*/
759 static int
760 getnext_ioctl(md_i_getnext_t *gn, int mode)
761 {
762 	int		modindex;
763 	md_link_t	*next;
764 	uint_t		id;
765 	int		found = 0;
766 	set_t		setno = gn->md_driver.md_setno;
767 
768 	mdclrerror(&gn->mde);
769 
770 	if (md_snarf_db_set(MD_LOCAL_SET, &gn->mde) != 0)
771 		return (0);
772 
773 	if ((md_get_setstatus(setno) & MD_SET_SNARFED) == 0) {
774 		if (md_get_setstatus(setno) & MD_SET_TAGDATA)
775 			return (mdmddberror(&gn->mde, MDE_DB_TAGDATA,
776 			    NODEV32, setno));
777 		else
778 			return (mderror(&gn->mde, MDE_UNIT_NOT_FOUND));
779 	}
780 
781 	modindex = md_getmodindex((md_driver_t *)gn, 1, 0);
782 	if (modindex == -1) {
783 		return (mderror(&gn->mde, MDE_UNIT_NOT_FOUND));
784 	}
785 
786 	rw_enter(&md_ops[modindex]->md_link_rw.lock, RW_READER);
787 	id = gn->id;
788 	next = md_ops[modindex]->md_head;
789 	while (next) {
790 		if ((next->ln_setno == setno) && (next->ln_id == id)) {
791 			gn->id = id;
792 			found = 1;
793 			break;
794 		}
795 
796 		if ((next->ln_setno == setno) &&(next->ln_id > id) &&
797 		    (! found || (next->ln_id < gn->id))) {
798 			gn->id = next->ln_id;
799 			found = 1;
800 			/* continue looking for smallest */
801 		}
802 		next = next->ln_next;
803 	}
804 	rw_exit(&md_ops[modindex]->md_link_rw.lock);
805 
806 	if (! found)
807 		return (mderror(&gn->mde, MDE_UNIT_NOT_FOUND));
808 
809 	return (0);
810 }
811 
812 /*ARGSUSED*/
813 static int
814 getnum_ioctl(void *d, int mode)
815 {
816 	int		modindex;
817 	md_link_t	*next;
818 	int		sz;
819 	minor_t		*minors;
820 	minor_t		*m_ptr;
821 	set_t		setno;
822 	int		err = 0;
823 	md_error_t	*mdep;
824 	int		minor_array_length;
825 	md_driver_t	*driver;
826 	int		count = 0;
827 	struct md_i_getnum	*gn = d;
828 
829 
830 	/* number of specified devices in specified set - if 0 return count */
831 	minor_array_length = gn->size;
832 	if (minor_array_length > md_nunits)
833 		return (EINVAL);
834 
835 	mdep = &gn->mde;
836 	driver = &gn->md_driver;
837 	setno = driver->md_setno;
838 
839 	mdclrerror(mdep);
840 
841 	if (md_snarf_db_set(MD_LOCAL_SET, mdep) != 0)
842 		return (0);
843 
844 	if ((md_get_setstatus(setno) & MD_SET_SNARFED) == 0) {
845 		if (md_get_setstatus(setno) & MD_SET_TAGDATA) {
846 			return (mdmddberror(mdep, MDE_DB_TAGDATA,
847 			    NODEV32, setno));
848 		} else {
849 			return (mderror(mdep, MDE_UNIT_NOT_FOUND));
850 		}
851 	}
852 
853 	modindex = md_getmodindex(driver, 0, 0);
854 	if (modindex == -1) {
855 
856 		return (mderror(mdep, MDE_UNIT_NOT_FOUND));
857 	}
858 
859 	rw_enter(&md_ops[modindex]->md_link_rw.lock, RW_READER);
860 	/* if array length is not 0 then allocate the output buffers */
861 	if (minor_array_length != 0) {
862 		sz = minor_array_length * ((int)sizeof (minor_t));
863 		minors = kmem_zalloc(sz, KM_SLEEP);
864 		m_ptr = minors;
865 	}
866 
867 	next = md_ops[modindex]->md_head;
868 	count = 0;
869 	while (next) {
870 		if (next->ln_setno == setno) {
871 			if ((minor_array_length > 0) &&
872 			    (count < minor_array_length)) {
873 				*m_ptr = next->ln_id;
874 				m_ptr++;
875 			}
876 			count++;
877 		}
878 		next = next->ln_next;
879 	}
880 	rw_exit(&md_ops[modindex]->md_link_rw.lock);
881 
882 	gn->size = count;
883 	/* now copy the array back */
884 	if (minor_array_length > 0) {
885 		err = ddi_copyout(minors,
886 		    (caddr_t)(uintptr_t)gn->minors, sz, mode);
887 		kmem_free(minors, sz);
888 	}
889 
890 	return (err);
891 }
892 
893 /*ARGSUSED*/
894 static int
895 didstat_ioctl(
896 	md_i_didstat_t	*ds
897 )
898 {
899 	int		cnt = 0;
900 	int		err = 0;
901 
902 	mdclrerror(&ds->mde);
903 
904 	if (md_snarf_db_set(MD_LOCAL_SET, &ds->mde) != 0)
905 		return (0);
906 
907 	if (ds->setno >= md_nsets) {
908 		return (EINVAL);
909 	}
910 
911 	if ((md_get_setstatus(ds->setno) & MD_SET_SNARFED) == 0)
912 		return (ENODEV);
913 
914 	if (ds->mode == MD_FIND_INVDID) {
915 		cnt = md_validate_devid(ds->setno, ds->side, &ds->maxsz);
916 		if (cnt == -1)
917 			err = -1;
918 		ds->cnt = cnt;
919 	} else if (ds->mode == MD_GET_INVDID) {
920 		if (md_get_invdid(ds->setno, ds->side, ds->cnt, ds->maxsz,
921 		    (caddr_t)(uintptr_t)ds->ctdp) == -1) {
922 			err = -1;
923 		}
924 	} else {
925 		/* invalid mode */
926 		err = EINVAL;
927 	}
928 
929 	return (err);
930 }
931 
932 /*ARGSUSED*/
933 static int
934 getdid_ioctl(
935 	mdnm_params_t	*nm,
936 	int		mode
937 )
938 {
939 	int		err = 0;
940 	ddi_devid_t	did = NULL;
941 
942 	mdclrerror(&nm->mde);
943 
944 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
945 		return (0);
946 
947 	if (nm->setno >= md_nsets) {
948 		return (EINVAL);
949 	}
950 
951 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
952 		return (ENODEV);
953 
954 	/*
955 	 * Tell user that replica is not in devid mode
956 	 */
957 	if (!(((mddb_set_t *)md_set[nm->setno].s_db)->s_lbp->lb_flags
958 	    & MDDB_DEVID_STYLE) && md_keep_repl_state) {
959 		return (mdsyserror(&nm->mde, MDDB_F_NODEVID));
960 	}
961 
962 	/*
963 	 * If user is prepared to receive the devid allocate a kernel buffer.
964 	 */
965 	if (nm->devid_size != 0) {
966 		/* check for bogus value of devid_size */
967 		if (nm->devid_size > MAXPATHLEN) {
968 			return (EINVAL);
969 		}
970 		did = kmem_alloc(nm->devid_size, KM_SLEEP);
971 	}
972 
973 	err = md_getdevid(nm->setno, nm->side, nm->key, did, &nm->devid_size);
974 
975 	if (err) {
976 		if (err < 0)
977 			err = EINVAL;
978 		goto out;
979 	}
980 
981 	/*
982 	 * If devid size was already known to user then give them the devid.
983 	 */
984 	if (did != NULL)
985 		err = ddi_copyout(did,
986 		    (caddr_t)(uintptr_t)nm->devid, nm->devid_size, mode);
987 
988 out:
989 	if (did != NULL)
990 		kmem_free(did, nm->devid_size);
991 	return (err);
992 }
993 
994 int
995 mddb_setmaster_ioctl(mddb_setmaster_config_t *info)
996 {
997 	/* Verify that setno is in valid range */
998 	if (info->c_setno >= md_nsets)
999 		return (EINVAL);
1000 
1001 	/*
1002 	 * When adding the first disk to a MN diskset, the master
1003 	 * needs to be set (in order to write out the mddb)
1004 	 * before the set is snarfed or even before the set
1005 	 * is marked as a MNset in the md_set structure.
1006 	 * So, don't check for MNset or SNARFED and don't call
1007 	 * mddb_setenter. In order to discourage bad ioctl calls,
1008 	 * verify that magic field in structure is set correctly.
1009 	 */
1010 	if (info->c_magic != MDDB_SETMASTER_MAGIC)
1011 		return (EINVAL);
1012 
1013 	if (info->c_current_host_master)
1014 		md_set[info->c_setno].s_am_i_master = 1;
1015 	else
1016 		md_set[info->c_setno].s_am_i_master = 0;
1017 
1018 	return (0);
1019 }
1020 
1021 /*
1022  * Set the devid for the namespace record identified by the tuple
1023  * [setno, sideno, key]. The key is the namespace key. The md_getdevnum()
1024  * function is used to actually regenerate the devid.
1025  */
1026 /*ARGSUSED*/
1027 static int
1028 setdid_ioctl(
1029 	mdnm_params_t	*nm,
1030 	int		mode
1031 )
1032 {
1033 	dev_t		devt;
1034 
1035 	/*
1036 	 * If upgrading do not allow modification of the namespace.
1037 	 */
1038 	if (MD_UPGRADE)
1039 		return (EAGAIN);
1040 
1041 	mdclrerror(&nm->mde);
1042 
1043 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
1044 		return (0);
1045 
1046 	if (nm->setno >= md_nsets)
1047 		return (EINVAL);
1048 
1049 	if (MD_MNSET_SETNO(nm->setno))
1050 		return (0);
1051 
1052 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
1053 		return (ENODEV);
1054 
1055 	devt = md_dev64_to_dev(
1056 	    md_getdevnum(nm->setno, nm->side, nm->key, MD_TRUST_DEVT));
1057 
1058 	if (devt == NODEV)
1059 		return (ENODEV);
1060 
1061 	return (0);
1062 }
1063 
1064 /*ARGSUSED*/
1065 static int
1066 getdidmin_ioctl(
1067 	mdnm_params_t   *nm,
1068 	int		mode
1069 )
1070 {
1071 	int	err = 0;
1072 	char	*minorname = NULL;
1073 
1074 	mdclrerror(&nm->mde);
1075 
1076 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
1077 		return (0);
1078 
1079 	if (nm->setno >= md_nsets)
1080 		return (EINVAL);
1081 
1082 	if (MD_MNSET_SETNO(nm->setno))
1083 		return (0);
1084 
1085 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
1086 		return (ENODEV);
1087 
1088 	minorname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1089 
1090 	if (nm->side == -1) {
1091 		err = EINVAL;
1092 		goto out;
1093 	}
1094 
1095 	err = md_getdevidminor(nm->setno, nm->side, nm->key, minorname,
1096 	    MAXPATHLEN);
1097 
1098 	if (err) {
1099 		if (err < 0)
1100 			err = EINVAL;
1101 		goto out;
1102 	}
1103 
1104 	err = ddi_copyout(minorname, (caddr_t)(uintptr_t)nm->minorname,
1105 	    strlen(minorname) + 1, mode);
1106 
1107 out:
1108 
1109 	kmem_free(minorname, MAXPATHLEN);
1110 	return (err);
1111 }
1112 
1113 static int
1114 mddb_userreq_ioctl(mddb_userreq_t *ur, int mode)
1115 {
1116 	void			*data;
1117 	int			status;
1118 	mddb_recid_t		*recids;
1119 	int			flags;
1120 
1121 	if (ur->ur_setno >= md_nsets)
1122 		return (EINVAL);
1123 
1124 	mdclrerror(&ur->ur_mde);
1125 
1126 	if (md_snarf_db_set(MD_LOCAL_SET, &ur->ur_mde) != 0)
1127 		return (0);
1128 
1129 	if ((md_get_setstatus(ur->ur_setno) & MD_SET_SNARFED) == 0)
1130 		return (ENODEV);
1131 
1132 	switch (ur->ur_cmd) {
1133 	case MD_DB_GETNEXTREC:
1134 		if (ur->ur_recid == 0)
1135 			ur->ur_recid = mddb_makerecid(ur->ur_setno, 0);
1136 		/*
1137 		 * Is ur_recid a valid one ?
1138 		 */
1139 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
1140 			return (EINVAL);
1141 
1142 		ur->ur_recid = mddb_getnextrec(ur->ur_recid, ur->ur_type,
1143 		    ur->ur_type2);
1144 		if (ur->ur_recid > 0) {
1145 			ur->ur_type = mddb_getrectype1(ur->ur_recid);
1146 			ur->ur_type2 = mddb_getrectype2(ur->ur_recid);
1147 			ur->ur_recstat = mddb_getrecstatus(ur->ur_recid);
1148 		}
1149 		break;
1150 
1151 	case MD_DB_COMMIT_ONE:
1152 		/*
1153 		 * Is ur_recid a valid one?
1154 		 */
1155 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
1156 			return (EINVAL);
1157 
1158 		ur->ur_recstat = mddb_getrecstatus(ur->ur_recid);
1159 		if (ur->ur_recstat == MDDB_NORECORD)
1160 			return (ENXIO);
1161 		status = mddb_commitrec(ur->ur_recid);
1162 		/*
1163 		 * For MN sets we panic if there are too few database replicas
1164 		 * and we're attempting to add entries to the log.
1165 		 */
1166 		if (status != 0) {
1167 			if ((MD_MNSET_SETNO(ur->ur_setno) &&
1168 			    (ur->ur_type2 == MDDB_UR_LR)) &&
1169 			    (md_get_setstatus(ur->ur_setno) & MD_SET_TOOFEW)) {
1170 				cmn_err(CE_PANIC,
1171 				    "md: Panic due to lack of DiskSuite state\n"
1172 				    " database replicas. Fewer than 50%% of "
1173 				    "the total were available,\n so panic to "
1174 				    "ensure data integrity.");
1175 			}
1176 			return (mddbstatus2error(&ur->ur_mde, status, NODEV32,
1177 			    ur->ur_setno));
1178 		}
1179 		break;
1180 
1181 	case MD_DB_COMMIT_MANY:
1182 		if (ur->ur_size <= 0)
1183 			return (EINVAL);
1184 
1185 		data = kmem_alloc(ur->ur_size, KM_SLEEP);
1186 
1187 		if (ddi_copyin((caddr_t)(uintptr_t)ur->ur_data, data,
1188 		    (size_t)ur->ur_size, mode)) {
1189 			kmem_free(data, ur->ur_size);
1190 			return (EFAULT);
1191 		}
1192 
1193 		recids = (mddb_recid_t *)data;
1194 		while (*recids != 0) {
1195 			/*
1196 			 * Is recid a valid ?
1197 			 */
1198 			if (DBSET(*recids) < 0 || DBSET(*recids) >= md_nsets) {
1199 				kmem_free(data, ur->ur_size);
1200 				return (EINVAL);
1201 			}
1202 			ur->ur_recstat = mddb_getrecstatus(*recids++);
1203 			if (ur->ur_recstat == MDDB_NORECORD) {
1204 				kmem_free(data, ur->ur_size);
1205 				return (ENXIO);
1206 			}
1207 		}
1208 		status = mddb_commitrecs(data);
1209 		kmem_free(data, ur->ur_size);
1210 		/*
1211 		 * For MN sets we panic if there are too few database replicas
1212 		 * and we're attempting to add entries to the log.
1213 		 */
1214 		if (status != 0) {
1215 			if ((MD_MNSET_SETNO(ur->ur_setno) &&
1216 			    (ur->ur_type2 == MDDB_UR_LR)) &&
1217 			    (md_get_setstatus(ur->ur_setno) & MD_SET_TOOFEW)) {
1218 				cmn_err(CE_PANIC,
1219 				    "md: Panic due to lack of DiskSuite state\n"
1220 				    " database replicas. Fewer than 50%% of "
1221 				    "the total were available,\n so panic to "
1222 				    "ensure data integrity.");
1223 			}
1224 			return (mddbstatus2error(&ur->ur_mde, status, NODEV32,
1225 			    ur->ur_setno));
1226 		}
1227 		break;
1228 
1229 	case MD_DB_GETDATA:
1230 		/*
1231 		 * Check ur_recid
1232 		 */
1233 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
1234 			return (EINVAL);
1235 
1236 		ur->ur_recstat = mddb_getrecstatus(ur->ur_recid);
1237 		if (ur->ur_recstat == MDDB_NORECORD ||
1238 		    ur->ur_recstat == MDDB_NODATA)
1239 			return (ENXIO);
1240 
1241 		if (ur->ur_size > mddb_getrecsize(ur->ur_recid))
1242 			return (EINVAL);
1243 
1244 		data = mddb_getrecaddr(ur->ur_recid);
1245 		if (ddi_copyout(data, (caddr_t)(uintptr_t)ur->ur_data,
1246 		    (size_t)ur->ur_size, mode)) {
1247 			return (EFAULT);
1248 		}
1249 		break;
1250 
1251 	case MD_DB_SETDATA:
1252 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
1253 			return (EINVAL);
1254 
1255 		ur->ur_recstat = mddb_getrecstatus(ur->ur_recid);
1256 		if (ur->ur_recstat == MDDB_NORECORD)
1257 			return (ENXIO);
1258 
1259 		if (ur->ur_size > mddb_getrecsize(ur->ur_recid))
1260 			return (EINVAL);
1261 
1262 		data = mddb_getrecaddr(ur->ur_recid);
1263 		if (ddi_copyin((caddr_t)(uintptr_t)ur->ur_data, data,
1264 		    (size_t)ur->ur_size, mode)) {
1265 			return (EFAULT);
1266 		}
1267 		break;
1268 
1269 	case MD_DB_DELETE:
1270 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
1271 			return (EINVAL);
1272 
1273 		ur->ur_recstat = mddb_getrecstatus(ur->ur_recid);
1274 		if (ur->ur_recstat == MDDB_NORECORD)
1275 			return (ENXIO);
1276 		status = mddb_deleterec(ur->ur_recid);
1277 		if (status < 0)
1278 			return (mddbstatus2error(&ur->ur_mde, status, NODEV32,
1279 			    ur->ur_setno));
1280 		break;
1281 
1282 	case MD_DB_CREATE:
1283 	{
1284 		int	mn_set = 0;
1285 
1286 		if (md_get_setstatus(ur->ur_setno) & MD_SET_MNSET)
1287 			mn_set = 1;
1288 
1289 		if (ur->ur_setno >= md_nsets)
1290 			return (EINVAL);
1291 		if ((mn_set) && (ur->ur_type2 == MDDB_UR_LR))
1292 			flags = MD_CRO_32BIT | MD_CRO_CHANGELOG;
1293 		else
1294 			flags = MD_CRO_32BIT;
1295 		ur->ur_recid = mddb_createrec(ur->ur_size, ur->ur_type,
1296 		    ur->ur_type2, flags, ur->ur_setno);
1297 		if (ur->ur_recid < 0)
1298 			return (mddbstatus2error(&ur->ur_mde, ur->ur_recid,
1299 			    NODEV32, ur->ur_setno));
1300 		break;
1301 	}
1302 
1303 	case MD_DB_GETSTATUS:
1304 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
1305 			return (EINVAL);
1306 		ur->ur_recstat = mddb_getrecstatus(ur->ur_recid);
1307 		break;
1308 
1309 	case MD_DB_GETSIZE:
1310 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
1311 			return (EINVAL);
1312 		ur->ur_size = mddb_getrecsize(ur->ur_recid);
1313 		break;
1314 
1315 	case MD_DB_MAKEID:
1316 		if (ur->ur_setno >= md_nsets)
1317 			return (EINVAL);
1318 		ur->ur_recid = mddb_makerecid(ur->ur_setno, ur->ur_recid);
1319 		break;
1320 
1321 	default:
1322 		return (EINVAL);
1323 	}
1324 	return (0);
1325 }
1326 
1327 static int
1328 setuserflags(
1329 	md_set_userflags_t	*msu,
1330 	IOLOCK			*lock
1331 )
1332 {
1333 	minor_t			mnum = msu->mnum;
1334 	set_t			setno = MD_MIN2SET(mnum);
1335 	md_unit_t		*un;
1336 	mdi_unit_t		*ui;
1337 
1338 	mdclrerror(&msu->mde);
1339 
1340 	if (md_get_setstatus(setno) & MD_SET_STALE)
1341 		return (mdmddberror(&msu->mde, MDE_DB_STALE, mnum, setno));
1342 
1343 	if ((ui = MDI_UNIT(mnum)) == NULL) {
1344 		return (mdmderror(&msu->mde, MDE_UNIT_NOT_SETUP, mnum));
1345 	}
1346 
1347 	un = (md_unit_t *)md_ioctl_writerlock(lock, ui);
1348 
1349 	un->c.un_user_flags = msu->userflags;
1350 	mddb_commitrec_wrapper(un->c.un_record_id);
1351 
1352 	return (0);
1353 }
1354 
1355 /*
1356  * mddb_didstat_from_user -- called for DIDSTAT ioctl. 2 different calling
1357  * 	scenarios.
1358  * 	1) data->mode == MD_FIND_INVDID
1359  *	   when user is inquiring about the existence of invalid device id's.
1360  *	   Upon return to the user d->cnt may have a value in it.
1361  *	2) data->mode == MD_GET_INVDID
1362  *	   when the user wants a list of the invalid device id's.
1363  *	   In this case d->ctdp is non Null and cnt has	a value in it.
1364  *
1365  * Basically this routine along with mddb_didstat_to_user can be eliminated
1366  * by pushing ddi_copyout down to lower level interfaces.  To minimize impact
1367  * just keep the current implementation intact.
1368  */
1369 static int
1370 mddb_didstat_from_user(
1371 	void		**d,
1372 	caddr_t		data,
1373 	int		mode,
1374 	caddr_t		*ds_ctd_addr
1375 )
1376 {
1377 	size_t		sz1 = 0, sz2 = 0;
1378 	md_i_didstat_t	*d1;
1379 	void		*d2;
1380 	*ds_ctd_addr	= 0;
1381 
1382 	sz1 = sizeof (md_i_didstat_t);
1383 	d1 = (md_i_didstat_t *)kmem_zalloc(sz1, KM_SLEEP);
1384 
1385 	if (ddi_copyin(data, (void *)d1, sz1, mode) != 0) {
1386 		kmem_free((void *)d1, sz1);
1387 		return (EFAULT);
1388 	}
1389 
1390 	/*
1391 	 * ds_ctd_addr has actual user ctdp
1392 	 */
1393 	*ds_ctd_addr = (caddr_t)(uintptr_t)d1->ctdp;
1394 	if (d1->mode == MD_GET_INVDID) {
1395 		sz2 = (d1->cnt * d1->maxsz) + 1;
1396 		if (sz2 <= 0) {
1397 			kmem_free(d1, sz1);
1398 			return (EINVAL);
1399 		}
1400 		d2 = kmem_zalloc(sz2, KM_SLEEP);
1401 		d1->ctdp = (uint64_t)(uintptr_t)d2;
1402 	} else if (d1->mode != MD_FIND_INVDID) {
1403 		kmem_free(d1, sz1);
1404 		return (EINVAL);
1405 	}
1406 	*d = (void *)d1;
1407 	return (0);
1408 }
1409 
1410 /*
1411  * mddb_didstat_to_user -- see comment for mddb_didstat_from_user. In this
1412  * 		case d->cnt could have a value in it for either usage of
1413  *		the ioctl.
1414  */
1415 /*ARGSUSED*/
1416 static int
1417 mddb_didstat_to_user(
1418 	void 		*d,
1419 	caddr_t		data,
1420 	int		mode,
1421 	caddr_t		ds_ctd_addr
1422 )
1423 {
1424 	size_t		sz1 = 0, sz2 = 0;
1425 	md_i_didstat_t		*d1;
1426 	void			*d2;
1427 
1428 
1429 	d1 = (md_i_didstat_t *)d;
1430 	sz1 = sizeof (md_i_didstat_t);
1431 
1432 	sz2 = (d1->cnt * d1->maxsz) + 1;
1433 	d2 = (caddr_t)(uintptr_t)d1->ctdp;
1434 	if (d2 && sz2) {
1435 		/*
1436 		 * Copy out from kernel ctdp to user ctdp area
1437 		 */
1438 		if (ddi_copyout(d2, (caddr_t)ds_ctd_addr, sz2, mode) != 0) {
1439 			kmem_free(d1, sz1);
1440 			kmem_free(d2, sz2);
1441 			return (EFAULT);
1442 		}
1443 		d1->ctdp = (uint64_t)(uintptr_t)ds_ctd_addr;
1444 	}
1445 	if (ddi_copyout(d1, data, sz1, mode) != 0) {
1446 		kmem_free(d1, sz1);
1447 		if (sz2 && d2)
1448 			kmem_free(d2, sz2);
1449 		return (EFAULT);
1450 	}
1451 	kmem_free(d1, sz1);
1452 	if (sz2 && d2)
1453 		kmem_free(d2, sz2);
1454 	return (0);
1455 }
1456 
1457 
1458 static int
1459 mddb_config_from_user(
1460 	void 		**d,
1461 	caddr_t 	data,
1462 	int 		mode,
1463 	caddr_t 	*c_devid_addr,
1464 	caddr_t		*c_old_devid_addr
1465 )
1466 {
1467 	size_t		sz1 = 0, sz2 = 0, sz3 = 0;
1468 	mddb_config_t	*d1;
1469 	void		*d2;
1470 	void 		*d3;
1471 
1472 	*c_devid_addr = 0;
1473 
1474 	sz1 = sizeof (mddb_config_t);
1475 	d1 = (mddb_config_t *)kmem_zalloc(sz1, KM_SLEEP);
1476 
1477 	if (ddi_copyin(data, (void *)d1, sz1, mode) != 0) {
1478 		kmem_free((void *)d1, sz1);
1479 		return (EFAULT);
1480 	}
1481 	*c_devid_addr = (caddr_t)(uintptr_t)d1->c_locator.l_devid;
1482 
1483 	if (d1->c_locator.l_devid_flags & MDDB_DEVID_SPACE) {
1484 		sz2 = d1->c_locator.l_devid_sz;
1485 		if (d1->c_locator.l_devid_sz <= 0 ||
1486 		    d1->c_locator.l_devid_sz > MAXPATHLEN) {
1487 			kmem_free((void *)d1, sz1);
1488 			return (EINVAL);
1489 		}
1490 		d2 = kmem_zalloc(sz2, KM_SLEEP);
1491 		if (ddi_copyin((caddr_t)(uintptr_t)d1->c_locator.l_devid,
1492 		    d2, sz2, mode) != 0) {
1493 			kmem_free(d1, sz1);
1494 			kmem_free(d2, sz2);
1495 			return (EFAULT);
1496 		}
1497 		d1->c_locator.l_devid = (uint64_t)(uintptr_t)d2;
1498 
1499 		if ((caddr_t)(uintptr_t)d1->c_locator.l_old_devid) {
1500 			*c_old_devid_addr = (caddr_t)(uintptr_t)
1501 			    d1->c_locator.l_old_devid;
1502 
1503 			sz3 = d1->c_locator.l_old_devid_sz;
1504 			if (d1->c_locator.l_old_devid_sz <= 0 ||
1505 			    d1->c_locator.l_old_devid_sz > MAXPATHLEN) {
1506 				kmem_free((void *)d1, sz1);
1507 				kmem_free(d2, sz2);
1508 				return (EINVAL);
1509 			}
1510 			d3 = kmem_zalloc(sz3, KM_SLEEP);
1511 			if (ddi_copyin(
1512 			    (caddr_t)(uintptr_t)d1->c_locator.l_old_devid,
1513 			    d3, sz3, mode) != 0) {
1514 				kmem_free((void *)d1, sz1);
1515 				kmem_free(d2, sz2);
1516 				kmem_free(d3, sz3);
1517 				return (EFAULT);
1518 			}
1519 			d1->c_locator.l_old_devid = (uintptr_t)d3;
1520 		}
1521 	} else {
1522 		d1->c_locator.l_devid = (uint64_t)0;
1523 		d1->c_locator.l_old_devid = (uint64_t)0;
1524 	}
1525 
1526 	*d = (void *)d1;
1527 	return (0);
1528 }
1529 
1530 /*ARGSUSED*/
1531 static int
1532 mddb_config_to_user(
1533 	void 		*d,
1534 	caddr_t 	data,
1535 	int 		mode,
1536 	caddr_t 	c_devid_addr,
1537 	caddr_t		c_old_devid_addr
1538 )
1539 {
1540 	size_t		sz1 = 0, sz2 = 0, sz3 = 0;
1541 	mddb_config_t		*d1;
1542 	void			*d2;
1543 	void			*d3;
1544 
1545 	d1 = (mddb_config_t *)d;
1546 	sz1 = sizeof (mddb_config_t);
1547 
1548 	if (d1->c_locator.l_devid_flags & MDDB_DEVID_SPACE) {
1549 		sz2 = d1->c_locator.l_devid_sz;
1550 		d2 = (caddr_t)(uintptr_t)d1->c_locator.l_devid;
1551 		/* Only copyout devid if valid */
1552 		if (d1->c_locator.l_devid_flags & MDDB_DEVID_VALID) {
1553 			if (ddi_copyout(d2, (caddr_t)c_devid_addr,
1554 			    sz2, mode) != 0) {
1555 				kmem_free(d1, sz1);
1556 				kmem_free(d2, sz2);
1557 				return (EFAULT);
1558 			}
1559 		}
1560 	}
1561 
1562 	d1->c_locator.l_devid = (uint64_t)(uintptr_t)c_devid_addr;
1563 
1564 	if (d1->c_locator.l_old_devid) {
1565 		sz3 = d1->c_locator.l_old_devid_sz;
1566 		d3 = (caddr_t)(uintptr_t)d1->c_locator.l_old_devid;
1567 		if (ddi_copyout(d3, (caddr_t)c_old_devid_addr,
1568 		    sz3, mode) != 0) {
1569 			kmem_free(d1, sz1);
1570 			kmem_free(d2, sz2);
1571 			kmem_free(d3, sz3);
1572 		}
1573 	}
1574 	d1->c_locator.l_old_devid = (uintptr_t)c_old_devid_addr;
1575 
1576 	if (ddi_copyout(d1, data, sz1, mode) != 0) {
1577 		kmem_free(d1, sz1);
1578 		if (sz2)
1579 			kmem_free(d2, sz2);
1580 		if (sz3)
1581 			kmem_free(d3, sz3);
1582 		return (EFAULT);
1583 	}
1584 
1585 	if (d1)
1586 		kmem_free(d1, sz1);
1587 	if (sz2)
1588 		kmem_free(d2, sz2);
1589 	if (sz3)
1590 		kmem_free(d3, sz3);
1591 
1592 	return (0);
1593 }
1594 
1595 /*
1596  * NAME:	get_tstate
1597  * PURPOSE:	Return unit's transient error state to user.
1598  * INPUT:	device node (set + metadevice number)
1599  * OUTPUT:	gu->tstate
1600  * RETURNS:	0 on success
1601  *		EINVAL on failure
1602  */
1603 static int
1604 get_tstate(md_i_get_tstate_t *gu, IOLOCK *lock)
1605 {
1606 	mdi_unit_t	*ui;
1607 
1608 	ui = MDI_UNIT(gu->id);
1609 	if (ui == (mdi_unit_t *)NULL) {
1610 		(void) mdmderror(&gu->mde, MDE_UNIT_NOT_SETUP, gu->id);
1611 		return (EINVAL);
1612 	}
1613 
1614 	(void) md_ioctl_readerlock(lock, ui);
1615 	gu->tstate = ui->ui_tstate;
1616 	md_ioctl_readerexit(lock);
1617 
1618 	return (0);
1619 }
1620 
1621 /*
1622  * NAME:	md_clu_ioctl
1623  * PURPOSE:	depending on clu_cmd:
1624  *		- Check open state,
1625  *		- lock opens and check open state
1626  *		- unlock opens again
1627  * INPUT:	metadevice and clu_cmd
1628  * OUTPUT:	open state (for MD_MN_LCU_UNLOCK always 0)
1629  * RETURNS:	0 on success
1630  *		EINVAL on failure
1631  */
1632 int
1633 md_clu_ioctl(md_clu_open_t *clu)
1634 {
1635 	mdi_unit_t	*ui;
1636 	minor_t		mnum;
1637 
1638 	if ((clu->clu_dev <= 0) ||
1639 	    (md_getmajor(clu->clu_dev)) != md_major) {
1640 		return (EINVAL);
1641 	}
1642 
1643 	mnum = md_getminor(clu->clu_dev);
1644 	if ((ui = MDI_UNIT(mnum)) == NULL) {
1645 		return (mdmderror(&clu->clu_mde, MDE_UNIT_NOT_SETUP, mnum));
1646 	}
1647 
1648 	switch (clu->clu_cmd) {
1649 	case MD_MN_LCU_CHECK:
1650 		/* No lock here, just checking */
1651 		clu->clu_isopen = md_unit_isopen(ui);
1652 		break;
1653 	case MD_MN_LCU_LOCK:
1654 		/* This inhibits later opens to succeed */
1655 		ui->ui_tstate |= MD_OPENLOCKED;
1656 		clu->clu_isopen = md_unit_isopen(ui);
1657 		/* In case the md is opened, reset the lock immediately */
1658 		if (clu->clu_isopen != 0) {
1659 			ui->ui_tstate &= ~MD_OPENLOCKED;
1660 		}
1661 		break;
1662 	case MD_MN_LCU_UNLOCK:
1663 		ui->ui_tstate &= ~MD_OPENLOCKED;
1664 		clu->clu_isopen = 0;	/* always sucess */
1665 		break;
1666 	}
1667 	return (0);
1668 }
1669 
1670 /*
1671  * NAME:	mkdev_ioctl
1672  * PURPOSE:	Create device node for specified set / metadevice tuple
1673  * INPUT:	device tuple (set number + metadevice number)
1674  * OUTPUT:	None
1675  * RETURNS:	0 on success
1676  *		EINVAL on failure
1677  */
1678 static int
1679 mkdev_ioctl(md_mkdev_params_t *p)
1680 {
1681 	set_t	setno = p->md_driver.md_setno;
1682 	unit_t	un;
1683 
1684 	mdclrerror(&p->mde);
1685 
1686 	/* Validate arguments passed in to ioctl */
1687 	if (setno >= MD_MAXSETS) {
1688 		(void) mderror(&p->mde, MDE_NO_SET);
1689 		return (EINVAL);
1690 	}
1691 
1692 	/*
1693 	 * Get the next available unit number in this set
1694 	 */
1695 	un = md_get_nextunit(setno);
1696 	if (un == MD_UNITBAD) {
1697 		(void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, un);
1698 		return (ENODEV);
1699 	}
1700 
1701 	/* Create the device node */
1702 	if (md_create_minor_node(setno, un)) {
1703 		(void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, un);
1704 		return (ENODEV);
1705 	}
1706 
1707 	/* Return the minor number */
1708 	p->un = un;
1709 
1710 	return (0);
1711 }
1712 
1713 /*
1714  * admin device ioctls
1715  */
1716 static int
1717 md_base_ioctl(md_dev64_t dev, int cmd, caddr_t data, int mode, IOLOCK *lockp)
1718 {
1719 	size_t		sz = 0;
1720 	void		*d = NULL;
1721 	mddb_config_t	*cp;
1722 	set_t		setno;
1723 	int		err = 0;
1724 	int		err_to_user = 0;
1725 	int		mddb_config_case = 0;
1726 	int		mddb_didstat_case = 0;
1727 	caddr_t		c_devid_addr = 0;
1728 	caddr_t		c_old_devid_addr = 0;
1729 	caddr_t		ds_ctd_addr = 0;
1730 	mddb_set_node_params_t	*snp;
1731 
1732 	/* For now we can only handle 32-bit clients for internal commands */
1733 	if ((cmd != DKIOCINFO) &&
1734 	    ((mode & DATAMODEL_MASK) != DATAMODEL_ILP32)) {
1735 		return (EINVAL);
1736 	}
1737 
1738 	switch (cmd) {
1739 
1740 	case DKIOCINFO:
1741 	{
1742 		if (! (mode & FREAD))
1743 			return (EACCES);
1744 
1745 		sz = sizeof (struct dk_cinfo);
1746 		d = kmem_alloc(sz, KM_SLEEP);
1747 
1748 		get_info((struct dk_cinfo *)d, md_getminor(dev));
1749 		break;
1750 	}
1751 
1752 	case MD_DB_USEDEV:
1753 	{
1754 		if (! (mode & FWRITE))
1755 			return (EACCES);
1756 
1757 		mddb_config_case = 1;
1758 
1759 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
1760 		    &c_old_devid_addr);
1761 
1762 		if (err)
1763 			return (err);
1764 
1765 		err = mddb_configure(MDDB_USEDEV, (mddb_config_t *)d);
1766 		break;
1767 	}
1768 
1769 	case MD_DB_GETDEV:
1770 	{
1771 		if (! (mode & FREAD))
1772 			return (EACCES);
1773 
1774 		mddb_config_case = 1;
1775 
1776 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
1777 		    &c_old_devid_addr);
1778 
1779 		if (err)
1780 			return (err);
1781 
1782 		err = mddb_configure(MDDB_GETDEV, (mddb_config_t *)d);
1783 		break;
1784 	}
1785 
1786 	case MD_DB_GETDRVNM:
1787 	{
1788 		if (! (mode & FREAD))
1789 			return (EACCES);
1790 
1791 		mddb_config_case = 1;
1792 
1793 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
1794 		    &c_old_devid_addr);
1795 
1796 		if (err)
1797 			return (err);
1798 
1799 		err = mddb_configure(MDDB_GETDRVRNAME, (mddb_config_t *)d);
1800 		break;
1801 	}
1802 
1803 	case MD_DB_ENDDEV:
1804 	{
1805 		if (! (mode & FREAD))
1806 			return (EACCES);
1807 
1808 		mddb_config_case = 1;
1809 
1810 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
1811 		    &c_old_devid_addr);
1812 
1813 		if (err)
1814 			return (err);
1815 
1816 		err = mddb_configure(MDDB_ENDDEV, (mddb_config_t *)d);
1817 		break;
1818 	}
1819 
1820 	case MD_DB_DELDEV:
1821 	{
1822 		if (! (mode & FWRITE))
1823 			return (EACCES);
1824 
1825 		mddb_config_case = 1;
1826 
1827 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
1828 		    &c_old_devid_addr);
1829 
1830 		if (err)
1831 			return (err);
1832 
1833 		cp = (mddb_config_t *)d;
1834 		setno = cp->c_setno;
1835 		err = mddb_configure(MDDB_DELDEV, cp);
1836 		if (! mdisok(&cp->c_mde))
1837 			break;
1838 
1839 		if (setno == MD_LOCAL_SET)
1840 			break;
1841 
1842 		if (cp->c_dbcnt != 0)
1843 			break;
1844 
1845 		/*
1846 		 * if the last db replica of a diskset is deleted
1847 		 * unload everything.
1848 		 */
1849 
1850 		/* Requesting a release, clean up everything */
1851 		md_clr_setstatus(setno, MD_SET_KEEPTAG);
1852 
1853 		err = release_set(cp, mode);
1854 
1855 		break;
1856 	}
1857 
1858 	case MD_DB_NEWDEV:
1859 	{
1860 		if (! (mode & FWRITE))
1861 			return (EACCES);
1862 
1863 		mddb_config_case = 1;
1864 
1865 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
1866 		    &c_old_devid_addr);
1867 
1868 		if (err)
1869 			return (err);
1870 
1871 		cp = (mddb_config_t *)d;
1872 		setno = cp->c_setno;
1873 		err = mddb_configure(MDDB_NEWDEV, cp);
1874 		if (! err && mdisok(&cp->c_mde))
1875 			(void) md_snarf_db_set(setno, &cp->c_mde);
1876 		break;
1877 	}
1878 
1879 	case MD_DB_NEWSIDE:
1880 	{
1881 		if (! (mode & FWRITE))
1882 			return (EACCES);
1883 
1884 		mddb_config_case = 1;
1885 
1886 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
1887 		    &c_old_devid_addr);
1888 
1889 		if (err)
1890 			return (err);
1891 
1892 		err = mddb_configure(MDDB_NEWSIDE, (mddb_config_t *)d);
1893 		break;
1894 	}
1895 
1896 	case MD_DB_DELSIDE:
1897 	{
1898 		if (! (mode & FWRITE))
1899 			return (EACCES);
1900 
1901 		mddb_config_case = 1;
1902 
1903 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
1904 		    &c_old_devid_addr);
1905 
1906 		if (err)
1907 			return (err);
1908 
1909 		err = mddb_configure(MDDB_DELSIDE, (mddb_config_t *)d);
1910 		break;
1911 	}
1912 
1913 	case MD_DB_SETDID:
1914 	{
1915 		if (!(mode & FWRITE)) {
1916 			return (EACCES);
1917 		}
1918 
1919 		mddb_config_case = 1;
1920 
1921 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
1922 		    &c_old_devid_addr);
1923 
1924 		if (err) {
1925 			return (err);
1926 		}
1927 
1928 		err = mddb_configure(MDDB_SETDID, (mddb_config_t *)d);
1929 
1930 		break;
1931 	}
1932 
1933 	case MD_GRAB_SET:
1934 	{
1935 		if (! (mode & FWRITE))
1936 			return (EACCES);
1937 
1938 		mddb_config_case = 1;
1939 
1940 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
1941 		    &c_old_devid_addr);
1942 
1943 		if (err)
1944 			return (err);
1945 
1946 		cp = (mddb_config_t *)d;
1947 		setno = cp->c_setno;
1948 
1949 		err = take_set(cp, mode);
1950 
1951 		if (err || ! mdisok(&cp->c_mde))
1952 			break;
1953 
1954 		if (md_get_setstatus(setno) & MD_SET_ACCOK)
1955 			err = mdmddberror(&cp->c_mde, MDE_DB_ACCOK, NODEV32,
1956 			    setno);
1957 
1958 		md_unblock_setio(setno);
1959 		break;
1960 	}
1961 
1962 	case MD_RELEASE_SET:
1963 	{
1964 		if (! (mode & FWRITE))
1965 			return (EACCES);
1966 
1967 		mddb_config_case = 1;
1968 
1969 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
1970 		    &c_old_devid_addr);
1971 
1972 		if (err)
1973 			return (err);
1974 
1975 		/* shorthand */
1976 		cp = (mddb_config_t *)d;
1977 		setno = cp->c_setno;
1978 
1979 		/* If the user requests a release, clean up everything */
1980 		md_clr_setstatus(setno, MD_SET_KEEPTAG);
1981 
1982 		/* Block incoming I/Os during release_set operation */
1983 		if (MD_MNSET_SETNO(setno)) {
1984 			/*
1985 			 * md_tas_block_setio will block the set if
1986 			 * there are no outstanding I/O requests,
1987 			 * otherwise it returns -1.
1988 			 */
1989 			if (md_tas_block_setio(setno) != 1) {
1990 				err = EBUSY;
1991 				break;
1992 			}
1993 		} else {
1994 			/*
1995 			 * Should not return something other than 1
1996 			 */
1997 			if (md_block_setio(setno) != 1) {
1998 				md_clearblock_setio(setno);
1999 				err = EACCES;
2000 				break;
2001 			}
2002 		}
2003 
2004 		err = release_set(cp, mode);
2005 
2006 		/* Unblock I/O state only if release_set failed */
2007 		if (err)
2008 			md_clearblock_setio(setno);
2009 
2010 		break;
2011 	}
2012 
2013 	case MD_DB_GETOPTLOC:
2014 	{
2015 		if (! (mode & FREAD))
2016 			return (EACCES);
2017 
2018 		sz = sizeof (mddb_optloc_t);
2019 		d = kmem_alloc(sz, KM_SLEEP);
2020 
2021 		if (ddi_copyin(data, d, sz, mode) != 0) {
2022 			err = EFAULT;
2023 			break;
2024 		}
2025 
2026 		err = mddb_getoptloc((mddb_optloc_t *)d);
2027 		break;
2028 	}
2029 
2030 	case MD_HALT:
2031 	{
2032 		if (! (mode & FWRITE))
2033 			return (EACCES);
2034 
2035 		/* already have the ioctl lock */
2036 		return (md_halt(MD_GBL_IOCTL_LOCK));
2037 	}
2038 
2039 	case MD_IOCSET_NM:
2040 	{
2041 		if (! (mode & FREAD))
2042 			return (EACCES);
2043 
2044 		sz = sizeof (mdnm_params_t);
2045 		d = kmem_alloc(sz, KM_SLEEP);
2046 
2047 		if (ddi_copyin(data, d, sz, mode) != 0) {
2048 			err = EFAULT;
2049 			break;
2050 		}
2051 
2052 		/* check data integrity */
2053 		if (((mdnm_params_t *)d)->setno >= md_nsets) {
2054 			err = EINVAL;
2055 			break;
2056 		}
2057 
2058 		if ((((mdnm_params_t *)d)->devname_len == 0) ||
2059 		    (((mdnm_params_t *)d)->devname_len > MAXPATHLEN)) {
2060 			err = EINVAL;
2061 			break;
2062 		}
2063 
2064 		if (((mdnm_params_t *)d)->devname == NULL) {
2065 			err = EINVAL;
2066 			break;
2067 		}
2068 
2069 		err = setnm_ioctl((mdnm_params_t *)d, mode);
2070 		break;
2071 	}
2072 
2073 	case MD_IOCGET_NM:
2074 	{
2075 		if (! (mode & FREAD))
2076 			return (EACCES);
2077 
2078 		sz = sizeof (mdnm_params_t);
2079 		d = kmem_alloc(sz, KM_SLEEP);
2080 
2081 		if (ddi_copyin(data, d, sz, mode) != 0) {
2082 			err = EFAULT;
2083 			break;
2084 		}
2085 
2086 		/* check data integrity */
2087 		if (((mdnm_params_t *)d)->setno >= md_nsets) {
2088 			err = EINVAL;
2089 			break;
2090 		}
2091 		if (((mdnm_params_t *)d)->devname == NULL) {
2092 			err = EINVAL;
2093 			break;
2094 		}
2095 
2096 		err = getnm_ioctl((mdnm_params_t *)d, mode);
2097 		break;
2098 	}
2099 
2100 	case MD_IOCGET_HSP_NM:
2101 	{
2102 		if (! (mode & FREAD))
2103 			return (EACCES);
2104 
2105 		sz = sizeof (mdhspnm_params_t);
2106 		d = kmem_alloc(sz, KM_SLEEP);
2107 
2108 		if (ddi_copyin(data, d, sz, mode) != 0) {
2109 			err = EFAULT;
2110 			break;
2111 		}
2112 
2113 		/* check data integrity */
2114 		if (((mdhspnm_params_t *)d)->setno >= md_nsets) {
2115 			err = EINVAL;
2116 			break;
2117 		}
2118 		if (((mdhspnm_params_t *)d)->hspname == NULL) {
2119 			err = EINVAL;
2120 			break;
2121 		}
2122 
2123 		err = gethspnm_ioctl((mdhspnm_params_t *)d, mode);
2124 		break;
2125 	}
2126 
2127 	case MD_IOCNXTKEY_NM:
2128 	{
2129 		if (! (mode & FREAD))
2130 			return (EACCES);
2131 
2132 		sz = sizeof (mdnm_params_t);
2133 		d = kmem_alloc(sz, KM_SLEEP);
2134 
2135 		if (ddi_copyin(data, d, sz, mode) != 0) {
2136 			err = EFAULT;
2137 			break;
2138 		}
2139 
2140 		err = getnextkey_ioctl((mdnm_params_t *)d, mode);
2141 		break;
2142 	}
2143 
2144 	case MD_IOCREM_NM:
2145 	{
2146 		if (! (mode & FREAD))
2147 			return (EACCES);
2148 
2149 		sz = sizeof (mdnm_params_t);
2150 		d = kmem_alloc(sz, KM_SLEEP);
2151 
2152 		if (ddi_copyin(data, d, sz, mode) != 0) {
2153 			err = EFAULT;
2154 			break;
2155 		}
2156 
2157 		/* check data integrity */
2158 		if (((mdnm_params_t *)d)->setno >= md_nsets) {
2159 			err = EINVAL;
2160 			break;
2161 		}
2162 
2163 		err = remnm_ioctl((mdnm_params_t *)d, mode);
2164 		break;
2165 	}
2166 
2167 	case MD_IOCGET_TSTATE:
2168 	{
2169 		md_i_get_tstate_t	*p;
2170 
2171 		if (! (mode & FREAD))
2172 			return (EACCES);
2173 
2174 		sz = sizeof (md_i_get_tstate_t);
2175 		d = kmem_alloc(sz, KM_SLEEP);
2176 
2177 		if (ddi_copyin(data, d, sz, mode) != 0) {
2178 			err = EFAULT;
2179 			break;
2180 		}
2181 
2182 		p = (md_i_get_tstate_t *)d;
2183 
2184 		if ((err = verify_minor(p->id)) != 0) {
2185 			if (err == EINVAL)
2186 				(void) mdmderror(&p->mde, MDE_INVAL_UNIT,
2187 				    p->id);
2188 			break;
2189 		}
2190 
2191 		err = get_tstate(p, lockp);
2192 		break;
2193 	}
2194 
2195 	case MD_IOCGET_DRVNM:
2196 	{
2197 		md_i_driverinfo_t	*p;
2198 
2199 		if (! (mode & FREAD))
2200 			return (EACCES);
2201 
2202 		sz = sizeof (md_i_driverinfo_t);
2203 		d = kmem_alloc(sz, KM_SLEEP);
2204 
2205 		if (ddi_copyin(data, d, sz, mode) != 0) {
2206 			err = EFAULT;
2207 			break;
2208 		}
2209 
2210 		p = (md_i_driverinfo_t *)d;
2211 
2212 		/* check data integrity */
2213 		if (p->md_driver.md_drivername == NULL) {
2214 			err = EINVAL;
2215 			break;
2216 		}
2217 
2218 		if ((err = verify_minor(p->mnum)) != 0) {
2219 			if (err == EINVAL)
2220 				(void) mdmderror(&p->mde, MDE_INVAL_UNIT,
2221 				    p->mnum);
2222 			break;
2223 		}
2224 
2225 		err = getdrvnm_ioctl(dev, p, mode);
2226 		break;
2227 	}
2228 
2229 	case MD_IOCGET_NEXT:
2230 	{
2231 		if (! (mode & FREAD))
2232 			return (EACCES);
2233 
2234 		sz = sizeof (md_i_getnext_t);
2235 		d = kmem_alloc(sz, KM_SLEEP);
2236 
2237 		if (ddi_copyin(data, d, sz, mode) != 0) {
2238 			err = EFAULT;
2239 			break;
2240 		}
2241 
2242 		/* check data integrity */
2243 		if (((md_i_getnext_t *)d)->md_driver.md_setno >= md_nsets) {
2244 			err = EINVAL;
2245 			break;
2246 		}
2247 
2248 		err = getnext_ioctl((md_i_getnext_t *)d, mode);
2249 		break;
2250 	}
2251 
2252 	case MD_DB_USERREQ:
2253 	case MD_MN_DB_USERREQ:
2254 	{
2255 		if (! (mode & FREAD))
2256 			return (EACCES);
2257 
2258 		sz = sizeof (mddb_userreq_t);
2259 		d = kmem_alloc(sz, KM_SLEEP);
2260 
2261 		if (ddi_copyin(data, d, sz, mode) != 0) {
2262 			err = EFAULT;
2263 			break;
2264 		}
2265 		err = mddb_userreq_ioctl((mddb_userreq_t *)d, mode);
2266 		break;
2267 	}
2268 
2269 	case MD_IOCGET_NUM:
2270 	{
2271 		if (! (mode & FREAD))
2272 			return (EACCES);
2273 
2274 		sz = sizeof (md_i_getnum_t);
2275 		d = kmem_alloc(sz, KM_SLEEP);
2276 
2277 		if (ddi_copyin(data, d, sz, mode) != 0) {
2278 			err = EFAULT;
2279 			break;
2280 		}
2281 
2282 		err = getnum_ioctl(d, mode);
2283 		break;
2284 	}
2285 
2286 	case MD_DB_OWNSET:
2287 	{
2288 		if (! (mode & FREAD))
2289 			return (EACCES);
2290 
2291 		sz = sizeof (mddb_ownset_t);
2292 		d = kmem_alloc(sz, KM_SLEEP);
2293 
2294 		if (ddi_copyin(data, d, sz, mode) != 0) {
2295 			err = EFAULT;
2296 			break;
2297 		}
2298 
2299 		if (((mddb_ownset_t *)d)->setno >= md_nsets) {
2300 			err = EINVAL;
2301 			break;
2302 		}
2303 
2304 		((mddb_ownset_t *)d)->owns_set =
2305 		    mddb_ownset(((mddb_ownset_t *)d)->setno);
2306 
2307 		break;
2308 	}
2309 
2310 	case MD_IOCGETNSET:
2311 	{
2312 		if (! (mode & FREAD))
2313 			return (EACCES);
2314 
2315 		if (ddi_copyout((caddr_t)&md_nsets, data,
2316 		    sizeof (set_t), mode) != 0) {
2317 			err = EFAULT;
2318 			break;
2319 		}
2320 		break;
2321 	}
2322 
2323 	case MD_IOCGETNUNITS:
2324 	{
2325 		if (! (mode & FREAD))
2326 			return (EACCES);
2327 
2328 		if (ddi_copyout((caddr_t)&md_nunits, data,
2329 		    sizeof (set_t), mode) != 0) {
2330 			err = EFAULT;
2331 			break;
2332 		}
2333 		break;
2334 	}
2335 
2336 	case MD_IOCGVERSION:
2337 	{
2338 		uint_t	dversion = MD_DVERSION;
2339 
2340 		if (! (mode & FREAD))
2341 			return (EACCES);
2342 
2343 		if (ddi_copyout((caddr_t)&dversion, data,
2344 		    sizeof (dversion), mode) != 0) {
2345 			err = EFAULT;
2346 			break;
2347 		}
2348 		break;
2349 	}
2350 
2351 	case MD_IOCSET_FLAGS:
2352 	{
2353 		md_set_userflags_t	*p;
2354 
2355 		if (! (mode & FWRITE))
2356 			return (EACCES);
2357 
2358 		sz = sizeof (md_set_userflags_t);
2359 		d = kmem_alloc(sz, KM_SLEEP);
2360 
2361 		if (ddi_copyin(data, d, sz, mode)) {
2362 			err = EFAULT;
2363 			break;
2364 		}
2365 
2366 		p = (md_set_userflags_t *)d;
2367 
2368 		if ((err = verify_minor(p->mnum)) != 0) {
2369 			if (err == EINVAL)
2370 				(void) mdmderror(&p->mde, MDE_INVAL_UNIT,
2371 				    p->mnum);
2372 			break;
2373 		}
2374 
2375 		err = setuserflags(p, lockp);
2376 		break;
2377 	}
2378 
2379 	case MD_IOCRENAME:
2380 	{
2381 		md_rename_t	*p;
2382 
2383 		if (! (mode & FWRITE)) {
2384 			return (EACCES);
2385 		}
2386 
2387 		sz = sizeof (md_rename_t);
2388 		d = kmem_alloc(sz, KM_SLEEP);
2389 
2390 		if (ddi_copyin(data, d, sz, mode)) {
2391 			err = EFAULT;
2392 			break;
2393 		}
2394 
2395 		p = (md_rename_t *)d;
2396 
2397 		if ((err = verify_minor(p->to.mnum)) != 0) {
2398 			if (err == EINVAL)
2399 				(void) mdmderror(&p->mde, MDE_INVAL_UNIT,
2400 				    p->to.mnum);
2401 			break;
2402 		}
2403 
2404 		if ((err = verify_minor(p->from.mnum)) != 0) {
2405 			if (err == EINVAL)
2406 				(void) mdmderror(&p->mde, MDE_INVAL_UNIT,
2407 				    p->from.mnum);
2408 			break;
2409 		}
2410 
2411 		err = md_rename(p, lockp);
2412 		break;
2413 	}
2414 
2415 	case MD_IOCISOPEN:
2416 	{
2417 		md_isopen_t	*p;
2418 		mdi_unit_t	*ui;
2419 		minor_t		mnum;
2420 
2421 		if (! (mode & FREAD))
2422 			return (EACCES);
2423 
2424 		sz = sizeof (md_isopen_t);
2425 		d = kmem_alloc(sz, KM_SLEEP);
2426 
2427 		if (ddi_copyin(data, d, sz, mode)) {
2428 			err = EFAULT;
2429 			break;
2430 		}
2431 
2432 		p = (md_isopen_t *)d;
2433 		if ((p->dev <= 0) || (md_getmajor(p->dev)) != md_major) {
2434 			err = EINVAL;
2435 			break;
2436 		}
2437 
2438 		mnum = md_getminor(p->dev);
2439 
2440 		if ((err = verify_minor(mnum)) != 0) {
2441 			if (err == EINVAL)
2442 				(void) mdmderror(&p->mde, MDE_INVAL_UNIT, mnum);
2443 			break;
2444 		}
2445 
2446 		if ((ui = MDI_UNIT(mnum)) == NULL) {
2447 			(void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, mnum);
2448 			err = EINVAL;
2449 			break;
2450 		}
2451 
2452 		p->isopen = md_unit_isopen(ui);
2453 		break;
2454 	}
2455 
2456 	case MD_MED_GET_LST:
2457 	{
2458 		mddb_med_parm_t		*medpp;
2459 
2460 		if (! (mode & FREAD))
2461 			return (EACCES);
2462 
2463 		sz = sizeof (mddb_med_parm_t);
2464 		d = kmem_alloc(sz, KM_SLEEP);
2465 
2466 		if (ddi_copyin(data, d, sz, mode) != 0) {
2467 			err = EFAULT;
2468 			break;
2469 		}
2470 
2471 		medpp = (mddb_med_parm_t *)d;
2472 
2473 		err = getmed_ioctl(medpp, mode);
2474 		break;
2475 	}
2476 
2477 	case MD_MED_SET_LST:
2478 	{
2479 		mddb_med_parm_t		*medpp;
2480 
2481 		if (! (mode & FWRITE))
2482 			return (EACCES);
2483 
2484 		sz = sizeof (mddb_med_parm_t);
2485 		d = kmem_alloc(sz, KM_SLEEP);
2486 
2487 		if (ddi_copyin(data, d, sz, mode) != 0) {
2488 			err = EFAULT;
2489 			break;
2490 		}
2491 
2492 		medpp = (mddb_med_parm_t *)d;
2493 
2494 		err = setmed_ioctl(medpp, mode);
2495 
2496 		break;
2497 	}
2498 
2499 	case MD_MED_UPD_MED:
2500 	{
2501 		if (! (mode & FWRITE))
2502 			return (EACCES);
2503 
2504 		sz = sizeof (mddb_med_upd_parm_t);
2505 		d = kmem_alloc(sz, KM_SLEEP);
2506 
2507 		if (ddi_copyin(data, d, sz, mode) != 0) {
2508 			err = EFAULT;
2509 			break;
2510 		}
2511 
2512 		err = updmed_ioctl((mddb_med_upd_parm_t *)d, mode);
2513 
2514 		break;
2515 	}
2516 
2517 	case MD_MED_GET_NMED:
2518 	{
2519 		if (! (mode & FREAD))
2520 			return (EACCES);
2521 
2522 		if (ddi_copyout((caddr_t)&md_nmedh, data,
2523 		    sizeof (int), mode) != 0) {
2524 			err = EFAULT;
2525 			break;
2526 		}
2527 		break;
2528 	}
2529 
2530 	case MD_MED_GET_TAG:
2531 	{
2532 		if (! (mode & FREAD))
2533 			return (EACCES);
2534 
2535 		sz = sizeof (mddb_dtag_get_parm_t);
2536 		d = kmem_alloc(sz, KM_SLEEP);
2537 
2538 		if (ddi_copyin(data, d, sz, mode) != 0) {
2539 			err = EFAULT;
2540 			break;
2541 		}
2542 
2543 		err = gettag_ioctl((mddb_dtag_get_parm_t *)d, mode);
2544 
2545 		break;
2546 	}
2547 
2548 	case MD_MED_USE_TAG:
2549 	{
2550 		if (! (mode & FWRITE))
2551 			return (EACCES);
2552 
2553 		sz = sizeof (mddb_dtag_use_parm_t);
2554 		d = kmem_alloc(sz, KM_SLEEP);
2555 
2556 		if (ddi_copyin(data, d, sz, mode) != 0) {
2557 			err = EFAULT;
2558 			break;
2559 		}
2560 
2561 		err = usetag_ioctl((mddb_dtag_use_parm_t *)d, mode);
2562 
2563 		break;
2564 	}
2565 
2566 	case MD_MED_ACCEPT:
2567 	{
2568 		if (! (mode & FWRITE))
2569 			return (EACCES);
2570 
2571 		sz = sizeof (mddb_accept_parm_t);
2572 		d = kmem_alloc(sz, KM_SLEEP);
2573 
2574 		if (ddi_copyin(data, d, sz, mode) != 0) {
2575 			err = EFAULT;
2576 			break;
2577 		}
2578 
2579 		err = accept_ioctl((mddb_accept_parm_t *)d, mode);
2580 
2581 		break;
2582 	}
2583 
2584 	case MD_MED_GET_TLEN:
2585 	{
2586 		if (! (mode & FREAD))
2587 			return (EACCES);
2588 
2589 		sz = sizeof (mddb_med_t_parm_t);
2590 		d = kmem_alloc(sz, KM_SLEEP);
2591 
2592 		if (ddi_copyin(data, d, sz, mode) != 0) {
2593 			err = EFAULT;
2594 			break;
2595 		}
2596 
2597 		err = med_get_t_size_ioctl((mddb_med_t_parm_t *)d, mode);
2598 
2599 		break;
2600 	}
2601 
2602 	case MD_MED_GET_T:
2603 	{
2604 		if (! (mode & FREAD))
2605 			return (EACCES);
2606 
2607 		sz = (sizeof (mddb_med_t_parm_t) - sizeof (mddb_med_t_ent_t)) +
2608 		    (sizeof (mddb_med_t_ent_t) * med_addr_tab_nents);
2609 		d = kmem_alloc(sz, KM_SLEEP);
2610 
2611 		if (ddi_copyin(data, d, sz, mode) != 0) {
2612 			err = EFAULT;
2613 			break;
2614 		}
2615 
2616 		err = med_get_t_ioctl((mddb_med_t_parm_t *)d, mode);
2617 
2618 		break;
2619 	}
2620 
2621 	case MD_MED_SET_T:
2622 	{
2623 		if (! (mode & FWRITE))
2624 			return (EACCES);
2625 
2626 		sz = (sizeof (mddb_med_t_parm_t) - sizeof (mddb_med_t_ent_t)) +
2627 		    (sizeof (mddb_med_t_ent_t) * med_addr_tab_nents);
2628 		d = kmem_alloc(sz, KM_SLEEP);
2629 
2630 		if (ddi_copyin(data, d, sz, mode) != 0) {
2631 			err = EFAULT;
2632 			break;
2633 		}
2634 
2635 		err = med_set_t_ioctl((mddb_med_t_parm_t *)d, mode);
2636 
2637 		break;
2638 	}
2639 
2640 	case  MD_GET_SETSTAT:
2641 	{
2642 		md_gs_stat_parm_t	*gsp;
2643 
2644 		if (! (mode & FREAD))
2645 			return (EACCES);
2646 
2647 		sz = sizeof (md_gs_stat_parm_t);
2648 		d = kmem_alloc(sz, KM_SLEEP);
2649 
2650 		if (ddi_copyin(data, d, sz, mode) != 0) {
2651 			err = EFAULT;
2652 			break;
2653 		}
2654 
2655 		gsp = (md_gs_stat_parm_t *)d;
2656 
2657 		if (gsp->gs_setno > (md_nsets - 1)) {
2658 			err = EINVAL;
2659 			break;
2660 		}
2661 
2662 		gsp->gs_status = md_set[gsp->gs_setno].s_status;
2663 
2664 		break;
2665 	}
2666 
2667 	case  MD_SETNMDID:
2668 	{
2669 		if (!(mode & FREAD))
2670 			return (EACCES);
2671 
2672 		sz = sizeof (mdnm_params_t);
2673 		d = kmem_alloc(sz, KM_SLEEP);
2674 
2675 		if (ddi_copyin(data, d, sz, mode) != 0) {
2676 			err = EFAULT;
2677 			break;
2678 		}
2679 
2680 		err = update_namespace_did_ioctl((mdnm_params_t *)d, mode);
2681 		break;
2682 
2683 	}
2684 	case  MD_IOCUPD_NM:
2685 	{
2686 		char *dname;
2687 		char *pname;
2688 		uint_t	devnamelen, pathnamelen;
2689 
2690 		if (!(mode & FREAD))
2691 			return (EACCES);
2692 
2693 		sz = sizeof (mdnm_params_t);
2694 		d = kmem_alloc(sz, KM_SLEEP);
2695 
2696 		if (ddi_copyin(data, d, sz, mode) != 0) {
2697 			err = EFAULT;
2698 			break;
2699 		}
2700 
2701 		devnamelen = ((mdnm_params_t *)d)->devname_len;
2702 		pathnamelen = ((mdnm_params_t *)d)->pathname_len;
2703 
2704 		if ((devnamelen > MAXPATHLEN) || (pathnamelen > MAXPATHLEN) ||
2705 		    (devnamelen == 0) || (pathnamelen == 0)) {
2706 			kmem_free(d, sz);
2707 			return (EINVAL);
2708 		}
2709 
2710 		/* alloc memory for devname */
2711 		dname = kmem_alloc(devnamelen + 1, KM_SLEEP);
2712 
2713 		if (ddi_copyin(
2714 		    (void *)(uintptr_t)((mdnm_params_t *)d)->devname,
2715 		    (void *)dname, devnamelen + 1, mode) != 0) {
2716 			err = EFAULT;
2717 			kmem_free(dname, devnamelen + 1);
2718 			break;
2719 		}
2720 
2721 		pname = kmem_alloc(pathnamelen + 1, KM_SLEEP);
2722 
2723 		if (ddi_copyin(
2724 		    (void *)(uintptr_t)((mdnm_params_t *)d)->pathname,
2725 		    (void *)pname, pathnamelen + 1, mode) != 0) {
2726 			err = EFAULT;
2727 			kmem_free(dname, devnamelen + 1);
2728 			kmem_free(pname, pathnamelen + 1);
2729 			break;
2730 		}
2731 
2732 		err = update_namespace_ioctl((mdnm_params_t *)d, dname, pname,
2733 		    mode);
2734 
2735 		kmem_free(dname, devnamelen + 1);
2736 		kmem_free(pname, pathnamelen + 1);
2737 		break;
2738 	}
2739 
2740 	case	MD_IOCUPD_LOCNM:
2741 	{
2742 		char *dname;
2743 		char *pname;
2744 		uint_t	devnamelen, pathnamelen;
2745 
2746 		if (!(mode & FREAD))
2747 			return (EACCES);
2748 
2749 		sz = sizeof (mdnm_params_t);
2750 		d = kmem_alloc(sz, KM_SLEEP);
2751 
2752 		if (ddi_copyin(data, d, sz, mode) != 0) {
2753 			err = EFAULT;
2754 			break;
2755 		}
2756 
2757 		devnamelen = ((mdnm_params_t *)d)->devname_len;
2758 		pathnamelen = ((mdnm_params_t *)d)->pathname_len;
2759 
2760 		if ((devnamelen > MAXPATHLEN) || (pathnamelen > MAXPATHLEN) ||
2761 		    (devnamelen == 0) || (pathnamelen == 0)) {
2762 			kmem_free(d, sz);
2763 			return (EINVAL);
2764 		}
2765 
2766 		/* alloc memory for devname */
2767 		dname = kmem_alloc(devnamelen + 1, KM_SLEEP);
2768 
2769 		if (ddi_copyin(
2770 		    (void *)(uintptr_t)((mdnm_params_t *)d)->devname,
2771 		    (void *)dname, devnamelen + 1, mode) != 0) {
2772 			err = EFAULT;
2773 			kmem_free(dname, devnamelen + 1);
2774 			break;
2775 		}
2776 
2777 		pname = kmem_alloc(pathnamelen + 1, KM_SLEEP);
2778 
2779 		if (ddi_copyin(
2780 		    (void *)(uintptr_t)((mdnm_params_t *)d)->pathname,
2781 		    (void *)pname, pathnamelen + 1, mode) != 0) {
2782 			err = EFAULT;
2783 			kmem_free(dname, devnamelen + 1);
2784 			kmem_free(pname, pathnamelen + 1);
2785 			break;
2786 		}
2787 
2788 		err = update_loc_namespace_ioctl((mdnm_params_t *)d, dname,
2789 		    pname, mode);
2790 
2791 		kmem_free(dname, devnamelen + 1);
2792 		kmem_free(pname, pathnamelen + 1);
2793 		break;
2794 	}
2795 
2796 	case  MD_SET_SETSTAT:
2797 	{
2798 #ifdef DEBUG
2799 		/* Can be used to set the s_status flags from user code */
2800 		md_gs_stat_parm_t	*gsp;
2801 
2802 		if (! (mode & FWRITE))
2803 			return (EACCES);
2804 
2805 		sz = sizeof (md_gs_stat_parm_t);
2806 		d = kmem_alloc(sz, KM_SLEEP);
2807 
2808 		if (ddi_copyin(data, d, sz, mode) != 0) {
2809 			err = EFAULT;
2810 			break;
2811 		}
2812 
2813 		gsp = (md_gs_stat_parm_t *)d;
2814 
2815 		if (gsp->gs_setno > (md_nsets - 1)) {
2816 			err = EINVAL;
2817 			break;
2818 		}
2819 
2820 		md_set[gsp->gs_setno].s_status = gsp->gs_status;
2821 
2822 #endif	/* DEBUG */
2823 		break;
2824 	}
2825 
2826 	case MD_IOCGET_DID:
2827 	{
2828 		if (! (mode & FREAD))
2829 			return (EACCES);
2830 
2831 		sz = sizeof (mdnm_params_t);
2832 		d = kmem_alloc(sz, KM_SLEEP);
2833 
2834 		if (ddi_copyin(data, d, sz, mode) != 0) {
2835 			err = EFAULT;
2836 			break;
2837 		}
2838 
2839 		err = getdid_ioctl((mdnm_params_t *)d, mode);
2840 		break;
2841 	}
2842 
2843 	case MD_IOCSET_DID:
2844 	{
2845 		if (! (mode & FWRITE))
2846 			return (EACCES);
2847 
2848 		sz = sizeof (mdnm_params_t);
2849 		d = kmem_alloc(sz, KM_SLEEP);
2850 
2851 		if (ddi_copyin(data, d, sz, mode) != 0) {
2852 			err = EFAULT;
2853 			break;
2854 		}
2855 
2856 		err = setdid_ioctl((mdnm_params_t *)d, mode);
2857 		break;
2858 	}
2859 
2860 	case MD_IOCGET_DIDMIN:
2861 	{
2862 		if (! (mode & FREAD))
2863 			return (EACCES);
2864 
2865 		sz = sizeof (mdnm_params_t);
2866 		d = kmem_alloc(sz, KM_SLEEP);
2867 
2868 		if (ddi_copyin(data, d, sz, mode) != 0) {
2869 			err = EFAULT;
2870 			break;
2871 		}
2872 
2873 		if (((mdnm_params_t *)d)->setno >= md_nsets) {
2874 			err = EINVAL;
2875 			break;
2876 		}
2877 
2878 		err = getdidmin_ioctl((mdnm_params_t *)d, mode);
2879 		break;
2880 	}
2881 
2882 	case MD_IOCDID_STAT:
2883 	{
2884 		if (!(mode & FREAD))
2885 			return (EACCES);
2886 
2887 		mddb_didstat_case = 1;
2888 
2889 		err = mddb_didstat_from_user(&d, data, mode, &ds_ctd_addr);
2890 
2891 		if (err) {
2892 			return (err);
2893 		}
2894 
2895 		err = didstat_ioctl((md_i_didstat_t *)d);
2896 		break;
2897 	}
2898 
2899 	case MD_UPGRADE_STAT:
2900 	{
2901 		if (! (mode & FREAD))
2902 			return (EACCES);
2903 
2904 		if (ddi_copyout((caddr_t)&md_in_upgrade, data,
2905 		    sizeof (int), mode) != 0) {
2906 			err = EFAULT;
2907 			break;
2908 		}
2909 		break;
2910 	}
2911 
2912 	case MD_SETMASTER:
2913 	{
2914 		if (! (mode & FREAD))
2915 			return (EACCES);
2916 
2917 		sz = sizeof (mddb_setmaster_config_t);
2918 		d = kmem_alloc(sz, KM_SLEEP);
2919 
2920 		if (ddi_copyin(data, d, sz, mode) != 0) {
2921 			err = EFAULT;
2922 			break;
2923 		}
2924 
2925 		err = mddb_setmaster_ioctl((mddb_setmaster_config_t *)d);
2926 		break;
2927 	}
2928 
2929 	case MD_MN_SET_DOORH:
2930 	{
2931 	/* This ioctl sets the global kernel variable mdmn_door_handle */
2932 		if (ddi_copyin(data, &mdmn_door_did, sizeof (int), mode) != 0) {
2933 			err = EFAULT;
2934 		} else {
2935 			err = 0;
2936 		}
2937 		mdmn_door_handle = door_ki_lookup(mdmn_door_did);
2938 
2939 		break;
2940 	}
2941 
2942 #ifdef DEBUG
2943 	case MD_MN_CHECK_DOOR1:
2944 	{
2945 	/* This ioctl sends a message through a previously opened door */
2946 		int		ret;
2947 		int		msg_test = 11111111;
2948 		int		nloops = 0;
2949 		set_t		setno;
2950 		md_mn_kresult_t	*result;
2951 		uint_t		flags = MD_MSGF_NO_LOG | MD_MSGF_NO_BCAST;
2952 
2953 		result = kmem_zalloc(sizeof (md_mn_kresult_t), KM_SLEEP);
2954 		if (ddi_copyin(data, &nloops, sizeof (int), mode) != 0) {
2955 			err = EFAULT;
2956 		} else {
2957 			err = 0;
2958 		}
2959 
2960 		/*
2961 		 * This is a way to tell ksend_message() to use different sets.
2962 		 * Odd numbers go to set 1 even numbers go to set 2
2963 		 */
2964 		if (nloops & 0x1) {
2965 			setno = 1;
2966 		} else {
2967 			setno = 2;
2968 		}
2969 		while (nloops--)  {
2970 			ret = mdmn_ksend_message(
2971 			    setno,
2972 			    MD_MN_MSG_TEST1,
2973 			    flags,
2974 			    (char *)&msg_test,
2975 			    sizeof (msg_test),
2976 			    result);
2977 
2978 			if (ret != 0) {
2979 				printf("mdmn_ksend_message failed (%d)\n", ret);
2980 			}
2981 		}
2982 		kmem_free(result, sizeof (md_mn_kresult_t));
2983 
2984 		break;
2985 	}
2986 
2987 	case MD_MN_CHECK_DOOR2:
2988 	{
2989 	/* This ioctl sends a message through a previously opened door */
2990 		int		ret;
2991 		int		msg_test = 22222222;
2992 		int		nloops = 0;
2993 		md_mn_kresult_t	*result;
2994 		set_t		setno;
2995 		uint_t		flags = MD_MSGF_NO_LOG;
2996 
2997 		result = kmem_zalloc(sizeof (md_mn_kresult_t), KM_SLEEP);
2998 		if (ddi_copyin(data, &nloops, sizeof (int), mode) != 0) {
2999 			err = EFAULT;
3000 		} else {
3001 			err = 0;
3002 		}
3003 		/*
3004 		 * This is a way to tell ksend_message() to use different sets.
3005 		 * Odd numbers go to set 1 even numbers go to set 2
3006 		 */
3007 		if (nloops & 0x1) {
3008 			setno = 1;
3009 		} else {
3010 			setno = 2;
3011 		}
3012 		while (nloops--)  {
3013 			ret = mdmn_ksend_message(
3014 			    setno,
3015 			    MD_MN_MSG_TEST2,
3016 			    flags,
3017 			    (char *)&msg_test,
3018 			    sizeof (msg_test),
3019 			    result);
3020 
3021 			if (ret != 0) {
3022 				printf("mdmn_ksend_message failed (%d)\n", ret);
3023 			}
3024 		}
3025 		kmem_free(result, sizeof (md_mn_kresult_t));
3026 
3027 		break;
3028 	}
3029 #endif
3030 
3031 	case MD_MN_OPEN_TEST:
3032 	{
3033 		md_clu_open_t	*p;
3034 		minor_t		mnum;
3035 
3036 		sz = sizeof (md_clu_open_t);
3037 		d = kmem_alloc(sz, KM_SLEEP);
3038 
3039 		if (ddi_copyin(data, d, sizeof (md_clu_open_t), mode) != 0) {
3040 			err = EFAULT;
3041 			break;
3042 		}
3043 
3044 		p = (md_clu_open_t *)d;
3045 		mnum = md_getminor(p->clu_dev);
3046 
3047 		if ((err = verify_minor(mnum)) != 0) {
3048 			if (err == EINVAL)
3049 				(void) mdmderror(&p->clu_mde, MDE_INVAL_UNIT,
3050 				    mnum);
3051 			break;
3052 		}
3053 		err = md_clu_ioctl(p);
3054 		break;
3055 	}
3056 
3057 	case MD_MN_SET_NODEID:
3058 	{
3059 		if (! (mode & FWRITE))
3060 			return (EACCES);
3061 
3062 		sz = sizeof (mddb_set_node_params_t);
3063 		d = kmem_alloc(sz, KM_SLEEP);
3064 
3065 		if (ddi_copyin(data, d, sz, mode) != 0) {
3066 			err = EFAULT;
3067 			break;
3068 		}
3069 		snp = (mddb_set_node_params_t *)d;
3070 
3071 		if (snp->sn_setno >= md_nsets) {
3072 			err = EINVAL;
3073 			break;
3074 		}
3075 
3076 		md_set[snp->sn_setno].s_nodeid = snp->sn_nodeid;
3077 
3078 		if (md_mn_mynode_id == MD_MN_INVALID_NID)
3079 			md_mn_mynode_id = snp->sn_nodeid;
3080 #ifdef DEBUG
3081 		else if (md_mn_mynode_id != snp->sn_nodeid)
3082 			cmn_err(CE_WARN, "Previously set nodeid 0x%x for this"
3083 			    "node doesn't match nodeid being set 0x%x\n",
3084 			    md_mn_mynode_id, snp->sn_nodeid);
3085 #endif /* DEBUG */
3086 		err = 0;
3087 		break;
3088 	}
3089 	case MD_IOCGUNIQMSGID:
3090 	{
3091 		md_mn_msgid_t msgid;
3092 		struct timeval32 tv;
3093 
3094 		if (! (mode & FREAD))
3095 			return (EACCES);
3096 
3097 		uniqtime32(&tv);
3098 
3099 		/* high 32 bits are the seconds */
3100 		msgid.mid_time = (u_longlong_t)tv.tv_sec << 32;
3101 		/* low 32 bits are the micro secs */
3102 		msgid.mid_time |= tv.tv_usec;
3103 
3104 		msgid.mid_nid = md_mn_mynode_id;
3105 		/*
3106 		 * This is never called for submessages, so we better
3107 		 * null out the submessage ID
3108 		 */
3109 		msgid.mid_smid = 0;
3110 
3111 		if (ddi_copyout((caddr_t)&msgid, data, sizeof (msgid), mode)
3112 		    != 0) {
3113 			err = EFAULT;
3114 			break;
3115 		}
3116 		break;
3117 	}
3118 
3119 	/*
3120 	 * suspend the IO's for a given set number.
3121 	 *
3122 	 * If setno = 0 is specified, try operation on all snarfed MN disksets.
3123 	 * If there are no snarfed MN disksets, then return success.
3124 	 *
3125 	 * If a specific set number is given, then return EINVAL if unable
3126 	 * to perform operation.
3127 	 */
3128 	case MD_MN_SUSPEND_SET:
3129 	{
3130 		set_t	setno;
3131 		int	rval = 0;
3132 		int	i;
3133 
3134 		if (! (mode & FWRITE))
3135 			return (EACCES);
3136 
3137 		if (ddi_copyin(data, &setno, sizeof (set_t), mode) != 0) {
3138 			return (EFAULT);
3139 		}
3140 		if (setno >= MD_MAXSETS) {
3141 			return (EINVAL);
3142 		}
3143 
3144 		mutex_enter(&md_mx);
3145 		if (setno == 0) {
3146 			/* if set number is 0, we walk all sets */
3147 			for (i = 1; i <= (MD_MAXSETS - 1); i++) {
3148 				if ((md_set[i].s_status &
3149 				    (MD_SET_SNARFED|MD_SET_MNSET)) ==
3150 				    (MD_SET_SNARFED|MD_SET_MNSET)) {
3151 					md_set[i].s_status |= MD_SET_HALTED;
3152 				}
3153 			}
3154 		} else {
3155 			/* If unable to halt specified set, set EINVAL */
3156 			if ((md_set[setno].s_status &
3157 			    (MD_SET_SNARFED|MD_SET_MNSET)) ==
3158 			    (MD_SET_SNARFED|MD_SET_MNSET)) {
3159 				md_set[setno].s_status |= MD_SET_HALTED;
3160 			} else {
3161 				rval = EINVAL;
3162 			}
3163 		}
3164 		mutex_exit(&md_mx);
3165 		return (rval);
3166 	}
3167 
3168 	/*
3169 	 * resume the IO's for a given set number.
3170 	 *
3171 	 * If setno = 0 is specified, try operation on all snarfed MN disksets.
3172 	 * If there are no snarfed MN disksets, then return success.
3173 	 *
3174 	 * If a specific set number is given, then return EINVAL if unable
3175 	 * to perform operation.
3176 	 */
3177 	case MD_MN_RESUME_SET:
3178 	{
3179 		set_t	setno;
3180 		int	resumed_set = 0;
3181 		int	rval = 0;
3182 		int	i;
3183 
3184 		if (! (mode & FWRITE))
3185 			return (EACCES);
3186 
3187 		if (ddi_copyin(data, &setno, sizeof (set_t), mode) != 0) {
3188 			return (EFAULT);
3189 		}
3190 		if (setno >= MD_MAXSETS) {
3191 			return (EINVAL);
3192 		}
3193 
3194 		/* if 0 is specified as the set number, we walk all sets */
3195 		mutex_enter(&md_mx);
3196 		if (setno == 0) {
3197 			/* if set number is 0, we walk all sets */
3198 			for (i = 1; i <= (MD_MAXSETS - 1); i++) {
3199 				if ((md_set[i].s_status &
3200 				    (MD_SET_SNARFED|MD_SET_MNSET)) ==
3201 				    (MD_SET_SNARFED|MD_SET_MNSET)) {
3202 					md_set[i].s_status &= ~MD_SET_HALTED;
3203 					resumed_set = 1;
3204 				}
3205 			}
3206 		} else {
3207 			/* If unable to resume specified set, set EINVAL */
3208 			if ((md_set[setno].s_status &
3209 			    (MD_SET_SNARFED|MD_SET_MNSET)) ==
3210 			    (MD_SET_SNARFED|MD_SET_MNSET)) {
3211 				md_set[setno].s_status &= ~MD_SET_HALTED;
3212 				resumed_set = 1;
3213 			} else {
3214 				rval = EINVAL;
3215 			}
3216 		}
3217 
3218 		/*
3219 		 * In case we actually resumed at least one set,
3220 		 * Inform all threads waiting for this change
3221 		 */
3222 		if (resumed_set == 1) {
3223 			cv_broadcast(&md_cv);
3224 		}
3225 
3226 		mutex_exit(&md_mx);
3227 		return (rval);
3228 	}
3229 
3230 	case MD_MN_MDDB_PARSE:
3231 	{
3232 		if (! (mode & FWRITE))
3233 			return (EACCES);
3234 
3235 		sz = sizeof (mddb_parse_parm_t);
3236 		d = kmem_alloc(sz, KM_SLEEP);
3237 
3238 		if (ddi_copyin(data, d, sz, mode) != 0) {
3239 			err = EFAULT;
3240 			break;
3241 		}
3242 		err = mddb_parse((mddb_parse_parm_t *)d);
3243 		break;
3244 
3245 	}
3246 
3247 	case MD_MN_MDDB_BLOCK:
3248 	{
3249 		if (! (mode & FWRITE))
3250 			return (EACCES);
3251 
3252 		sz = sizeof (mddb_block_parm_t);
3253 		d = kmem_alloc(sz, KM_SLEEP);
3254 
3255 		if (ddi_copyin(data, d, sz, mode) != 0) {
3256 			err = EFAULT;
3257 			break;
3258 		}
3259 		err = mddb_block((mddb_block_parm_t *)d);
3260 		break;
3261 
3262 	}
3263 
3264 	case MD_MN_MDDB_OPTRECFIX:
3265 	{
3266 		if (! (mode & FWRITE))
3267 			return (EACCES);
3268 
3269 		sz = sizeof (mddb_optrec_parm_t);
3270 		d = kmem_alloc(sz, KM_SLEEP);
3271 
3272 		if (ddi_copyin(data, d, sz, mode) != 0) {
3273 			err = EFAULT;
3274 			break;
3275 		}
3276 		err = mddb_optrecfix((mddb_optrec_parm_t *)d);
3277 		break;
3278 
3279 	}
3280 
3281 	case MD_MN_CHK_WRT_MDDB:
3282 	{
3283 		if (! (mode & FWRITE))
3284 			return (EACCES);
3285 
3286 		sz = sizeof (mddb_config_t);
3287 		d = kmem_alloc(sz, KM_SLEEP);
3288 
3289 		if (ddi_copyin(data, d, sz, mode) != 0) {
3290 			err = EFAULT;
3291 			break;
3292 		}
3293 
3294 		err = mddb_check_write_ioctl((mddb_config_t *)d);
3295 		break;
3296 	}
3297 
3298 	case MD_MN_SET_SETFLAGS:
3299 	case MD_MN_GET_SETFLAGS:
3300 	{
3301 		if (! (mode & FREAD))
3302 			return (EACCES);
3303 
3304 		sz = sizeof (mddb_setflags_config_t);
3305 		d = kmem_alloc(sz, KM_SLEEP);
3306 
3307 		if (ddi_copyin(data, d, sz, mode) != 0) {
3308 			err = EFAULT;
3309 			break;
3310 		}
3311 
3312 		err = mddb_setflags_ioctl((mddb_setflags_config_t *)d);
3313 		break;
3314 	}
3315 
3316 	case MD_MN_COMMD_ERR:
3317 	{
3318 		md_mn_commd_err_t *cmp;
3319 		char *msg;
3320 
3321 		sz = sizeof (md_mn_commd_err_t);
3322 		d = kmem_zalloc(sz, KM_SLEEP);
3323 
3324 		if (ddi_copyin(data, d, sz, mode) != 0) {
3325 			err = EFAULT;
3326 			break;
3327 		}
3328 
3329 		cmp = (md_mn_commd_err_t *)d;
3330 		if (cmp->size > MAXPATHLEN) {
3331 			err = EINVAL;
3332 			break;
3333 		}
3334 
3335 		msg = (char *)kmem_zalloc(cmp->size + 1, KM_SLEEP);
3336 		if (ddi_copyin((caddr_t)(uintptr_t)cmp->md_message, msg,
3337 		    cmp->size, mode) != 0) {
3338 			kmem_free(msg, cmp->size + 1);
3339 			err = EFAULT;
3340 			break;
3341 		}
3342 		cmn_err(CE_WARN, "%s\n", msg);
3343 		kmem_free(msg, cmp->size + 1);
3344 		break;
3345 	}
3346 
3347 	case MD_IOCMAKE_DEV:
3348 	{
3349 		if (! (mode & FWRITE))
3350 			return (EACCES);
3351 
3352 		sz = sizeof (md_mkdev_params_t);
3353 
3354 		if ((d = kmem_alloc(sz, KM_NOSLEEP)) == NULL)
3355 			return (ENOMEM);
3356 
3357 		if (ddi_copyin(data, d, sz, mode) != 0) {
3358 			err = EFAULT;
3359 			break;
3360 		}
3361 
3362 		err = mkdev_ioctl((md_mkdev_params_t *)d);
3363 		break;
3364 	}
3365 
3366 	case MD_IOCREM_DEV:
3367 	{
3368 		set_t	setno;
3369 
3370 		if (! (mode & FWRITE))
3371 			return (EACCES);
3372 
3373 		sz = sizeof (minor_t);
3374 
3375 		d = kmem_zalloc(sz, KM_SLEEP);
3376 
3377 		if (ddi_copyin(data, d, sz, mode) != 0) {
3378 			err = EFAULT;
3379 			break;
3380 		}
3381 
3382 		/*
3383 		 * This ioctl is called to cleanup the device name
3384 		 * space when metainit fails or -n is invoked
3385 		 * In this case, reclaim the dispatched un slot
3386 		 */
3387 		setno = MD_MIN2SET(*(minor_t *)d);
3388 		if (setno >= md_nsets) {
3389 			err = EINVAL;
3390 			break;
3391 		} else if (md_set[setno].s_un_next <= 0) {
3392 			err = EFAULT;
3393 			break;
3394 		} else {
3395 			md_set[setno].s_un_next--;
3396 		}
3397 
3398 		/*
3399 		 * Attempt to remove the assocated device node
3400 		 */
3401 		md_remove_minor_node(*(minor_t *)d);
3402 		break;
3403 	}
3404 
3405 	/*
3406 	 * Update md_mn_commd_present global to reflect presence or absence of
3407 	 * /usr/sbin/rpc.mdcommd. This allows us to determine if an RPC failure
3408 	 * is expected during a mdmn_ksend_message() handshake. If the commd is
3409 	 * not present then an RPC failure is acceptable. If the commd _is_
3410 	 * present then an RPC failure means we have an inconsistent view across
3411 	 * the cluster.
3412 	 */
3413 	case MD_MN_SET_COMMD_RUNNING:
3414 	{
3415 		if (! (mode & FWRITE))
3416 			return (EACCES);
3417 
3418 		md_mn_commd_present = (int)(intptr_t)data;
3419 		err = 0;
3420 		break;
3421 	}
3422 
3423 	case MD_IOCIMP_LOAD:
3424 	{
3425 		if (! (mode & FWRITE))
3426 			return (EACCES);
3427 
3428 		mddb_config_case = 1;
3429 
3430 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
3431 		    &c_old_devid_addr);
3432 
3433 		if (err) {
3434 			return (err);
3435 		}
3436 
3437 		err = md_imp_snarf_set((mddb_config_t *)d);
3438 		break;
3439 
3440 	}
3441 
3442 	case MD_DB_LBINITTIME:
3443 	{
3444 		if (! (mode & FWRITE))
3445 			return (EACCES);
3446 
3447 		mddb_config_case = 1;
3448 
3449 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
3450 		    &c_old_devid_addr);
3451 
3452 		if (err)
3453 			return (err);
3454 
3455 		err = get_lb_inittime_ioctl((mddb_config_t *)d);
3456 		break;
3457 	}
3458 	case MD_IOCUPDATE_NM_RR_DID:
3459 	{
3460 		if (! (mode & FWRITE))
3461 			return (EACCES);
3462 
3463 		mddb_config_case = 1;
3464 
3465 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
3466 		    &c_old_devid_addr);
3467 
3468 		if (err)
3469 			return (err);
3470 
3471 		err = md_update_nm_rr_did_ioctl((mddb_config_t *)d);
3472 		break;
3473 	}
3474 	default:
3475 		return (ENOTTY);	/* used by next level up */
3476 	}
3477 
3478 	/*
3479 	 * copyout and free any args
3480 	 */
3481 	if (mddb_config_case) {
3482 		err_to_user = mddb_config_to_user(d, data, mode, c_devid_addr,
3483 		    c_old_devid_addr);
3484 	} else if (mddb_didstat_case) {
3485 		err_to_user = mddb_didstat_to_user(d, data, mode, ds_ctd_addr);
3486 	} else if (sz != 0) {
3487 		if (ddi_copyout(d, data, sz, mode) != 0) {
3488 			err = EFAULT;
3489 		}
3490 		kmem_free(d, sz);
3491 	}
3492 
3493 	if (err)
3494 		return (err);
3495 	return (err_to_user);
3496 }
3497 
3498 int
3499 md_admin_ioctl(md_dev64_t dev, int cmd, caddr_t data, int mode, IOLOCK *lockp)
3500 {
3501 	md_driver_t	drv;
3502 	int		modindex;
3503 	int		err;
3504 
3505 	/*
3506 	 * see if we can do this without involving the subdriver
3507 	 */
3508 	if ((err = md_base_ioctl(dev, cmd, data, mode, lockp)) != ENOTTY)
3509 		return (err);
3510 
3511 	/*
3512 	 * see what subdriver we need
3513 	 */
3514 	if (! ISMDIOC(cmd))
3515 		return (ENOTTY);
3516 
3517 	if ((!NODBNEEDED(cmd)) && md_snarf_db_set(MD_LOCAL_SET, NULL) != 0)
3518 		return (ENODEV);
3519 
3520 	if (ddi_copyin(data, (caddr_t)&drv, sizeof (drv), mode) != 0)
3521 		return (EFAULT);
3522 
3523 	/*
3524 	 * load subdriver if not already loaded
3525 	 */
3526 	if (((modindex = md_getmodindex(&drv, 0, NODBNEEDED(cmd))) == -1) ||
3527 	    (md_ops[modindex]->md_ioctl == NULL))
3528 		return (ENOTTY);
3529 
3530 	/*
3531 	 * dispatch to subdriver
3532 	 */
3533 	return ((*md_ops[modindex]->md_ioctl)(md_dev64_to_dev(dev), cmd, data,
3534 	    mode, lockp));
3535 }
3536 
3537 void
3538 md_get_geom(
3539 	md_unit_t	*un,
3540 	struct dk_geom	*gp
3541 )
3542 {
3543 	diskaddr_t		tb = un->c.un_total_blocks;
3544 	uint_t			cylsize = un->c.un_nhead * un->c.un_nsect;
3545 
3546 	bzero((caddr_t)gp, sizeof (*gp));
3547 	gp->dkg_nhead = un->c.un_nhead;
3548 	gp->dkg_nsect = un->c.un_nsect;
3549 	gp->dkg_rpm = un->c.un_rpm;
3550 	gp->dkg_write_reinstruct = un->c.un_wr_reinstruct;
3551 	gp->dkg_read_reinstruct = un->c.un_rd_reinstruct;
3552 	gp->dkg_ncyl = (ushort_t)(tb / cylsize);
3553 	if (! (un->c.un_flag & MD_LABELED))	/* skip first cyl */
3554 		gp->dkg_ncyl += 1;
3555 	gp->dkg_pcyl = gp->dkg_ncyl;
3556 }
3557 
3558 void
3559 md_get_vtoc(md_unit_t *un, struct vtoc *vtoc)
3560 {
3561 	caddr_t			v;
3562 	mddb_recstatus_t	status;
3563 	struct vtoc32		*vt32;
3564 
3565 	/*
3566 	 * Return vtoc structure fields in the provided VTOC area, addressed
3567 	 * by *vtoc.
3568 	 *
3569 	 */
3570 
3571 	if (un->c.un_vtoc_id) {
3572 		status = mddb_getrecstatus(un->c.un_vtoc_id);
3573 		if (status == MDDB_OK) {
3574 			v = mddb_getrecaddr(un->c.un_vtoc_id);
3575 			/* if this seems to be a sane vtoc, just copy it ... */
3576 			if (((struct vtoc *)v)->v_sanity == VTOC_SANE) {
3577 				bcopy(v, (caddr_t)vtoc, sizeof (struct vtoc));
3578 			} else {
3579 				/* ... else assume a vtoc32 was stored here */
3580 				vt32 = (struct vtoc32 *)v;
3581 				vtoc32tovtoc((*vt32), (*vtoc));
3582 			}
3583 			if (un->c.un_flag & MD_LABELED)
3584 				vtoc->v_part[0].p_start = 0;
3585 			else
3586 				vtoc->v_part[0].p_start =
3587 				    un->c.un_nhead * un->c.un_nsect;
3588 			vtoc->v_part[0].p_size = un->c.un_total_blocks;
3589 			vtoc->v_version = V_VERSION;
3590 			vtoc->v_sectorsz = DEV_BSIZE;
3591 			return;
3592 		}
3593 
3594 		un->c.un_vtoc_id = 0;
3595 		mddb_commitrec_wrapper(un->c.un_record_id);
3596 	}
3597 
3598 	bzero((caddr_t)vtoc, sizeof (struct vtoc));
3599 	vtoc->v_sanity = VTOC_SANE;
3600 	vtoc->v_nparts = 1;
3601 	vtoc->v_version = V_VERSION;
3602 	vtoc->v_sectorsz = DEV_BSIZE;
3603 	if (un->c.un_flag & MD_LABELED)
3604 		vtoc->v_part[0].p_start = 0;
3605 	else
3606 		vtoc->v_part[0].p_start = un->c.un_nhead * un->c.un_nsect;
3607 	vtoc->v_part[0].p_size = un->c.un_total_blocks;
3608 }
3609 
3610 int
3611 md_set_vtoc(md_unit_t *un, struct vtoc *vtoc)
3612 {
3613 
3614 	struct partition	*vpart;
3615 	int			i;
3616 	mddb_recid_t		recid;
3617 	mddb_recid_t		recids[3];
3618 	mddb_recstatus_t	status;
3619 	caddr_t			v;
3620 	daddr_t			sb;
3621 
3622 	/*
3623 	 * Sanity-check the vtoc
3624 	 */
3625 	if (vtoc->v_sanity != VTOC_SANE || vtoc->v_nparts != 1)
3626 		return (EINVAL);
3627 
3628 	/* don't allow to create a vtoc for a big metadevice */
3629 	if (un->c.un_revision & MD_64BIT_META_DEV)
3630 		return (ENOTSUP);
3631 	/*
3632 	 * Validate the partition table
3633 	 */
3634 	vpart = vtoc->v_part;
3635 	for (i = 0; i < V_NUMPAR; i++, vpart++) {
3636 		if (i == 0) {
3637 			if (un->c.un_flag & MD_LABELED)
3638 				sb = 0;
3639 			else
3640 				sb = un->c.un_nhead * un->c.un_nsect;
3641 			if (vpart->p_start != sb)
3642 				return (EINVAL);
3643 			if (vpart->p_size != (long)un->c.un_total_blocks)
3644 				return (EINVAL);
3645 			continue;
3646 		}
3647 		/* all other partitions must be zero */
3648 		if (vpart->p_start != 0)
3649 			return (EINVAL);
3650 		if (vpart->p_size != 0)
3651 			return (EINVAL);
3652 	}
3653 
3654 	if (un->c.un_vtoc_id) {
3655 		recid = un->c.un_vtoc_id;
3656 		status = mddb_getrecstatus(recid);
3657 		if (status == MDDB_OK) {
3658 			/*
3659 			 * If there's enough space in the record, and the
3660 			 * existing record is a vtoc record (not EFI),
3661 			 * we just can use the existing space.
3662 			 * Otherwise, we create a new MDDB_VTOC record for
3663 			 * this unit.
3664 			 */
3665 			if ((mddb_getrecsize(recid) >= sizeof (struct vtoc)) &&
3666 			    ((un->c.un_flag & MD_EFILABEL) == 0)) {
3667 				v = mddb_getrecaddr(recid);
3668 				bcopy((caddr_t)vtoc, v, sizeof (struct vtoc));
3669 				mddb_commitrec_wrapper(recid);
3670 				recids[0] = recid;
3671 				recids[1] = un->c.un_record_id;
3672 				recids[2] = 0;
3673 				un->c.un_flag &= ~MD_EFILABEL;
3674 				mddb_commitrecs_wrapper(recids);
3675 				return (0);
3676 			}
3677 
3678 			un->c.un_vtoc_id = 0;
3679 			mddb_commitrec_wrapper(un->c.un_record_id);
3680 			mddb_deleterec_wrapper(recid);
3681 		}
3682 	}
3683 
3684 	recid = mddb_createrec(sizeof (struct vtoc), MDDB_VTOC, 0,
3685 	    MD_CRO_32BIT, MD_UN2SET(un));
3686 
3687 	if (recid < 0) {
3688 		return (ENOSPC);
3689 	}
3690 
3691 	recids[0] = recid;
3692 	recids[1] = un->c.un_record_id;
3693 	recids[2] = 0;
3694 	v = mddb_getrecaddr(recid);
3695 	bcopy((caddr_t)vtoc, v, sizeof (struct vtoc));
3696 
3697 	un->c.un_vtoc_id = recid;
3698 	un->c.un_flag &= ~MD_EFILABEL;
3699 	mddb_commitrecs_wrapper(recids);
3700 	return (0);
3701 }
3702 
3703 
3704 void
3705 md_get_cgapart(md_unit_t *un, struct dk_map *dkmapp)
3706 {
3707 
3708 	/* skip the first cyl */
3709 	dkmapp->dkl_cylno = 1;
3710 
3711 	dkmapp->dkl_nblk = (daddr_t)un->c.un_total_blocks;
3712 }
3713 
3714 static struct uuid md_efi_reserved = EFI_RESERVED;
3715 
3716 /*
3717  * md_get_efi
3718  * INPUT:
3719  *	un; the md_unit
3720  *	buf; the buffer that is preallocated by the calling routine and
3721  *		capable of taking the EFI label for this unit
3722  * OUTPUT:
3723  *	A filled buffer, containing one struct efi_gpt followed by one
3724  *		struct efi_gpe, because a md efi only has one valid partition
3725  *		We fetch that date either from the mddb (like vtoc)
3726  *		or we a fake an EFI label.
3727  *
3728  * NOTES:
3729  *	We do not provide for any global unique identifiers,
3730  *	We also use the field c.un_vtoc_id, as the semantic is very similar
3731  *	When we are called, it's already checked, that this unit has an EFI
3732  *		label and not a vtoc
3733  */
3734 
3735 void
3736 md_get_efi(md_unit_t *un, char *buf)
3737 {
3738 	caddr_t		v;
3739 	efi_gpt_t	*efi_header = (efi_gpt_t *)buf;
3740 	efi_gpe_t	*efi_part = (efi_gpe_t *)(buf + sizeof (efi_gpt_t));
3741 	mddb_recstatus_t	status;
3742 
3743 	/* first comes the header */
3744 	efi_header->efi_gpt_Signature = LE_64(EFI_SIGNATURE);
3745 	efi_header->efi_gpt_HeaderSize = LE_32(sizeof (efi_gpt_t));
3746 	efi_header->efi_gpt_NumberOfPartitionEntries = LE_32(1);
3747 	efi_header->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (efi_gpe_t));
3748 	efi_header->efi_gpt_LastUsableLBA = LE_64(un->c.un_total_blocks - 1);
3749 	efi_header->efi_gpt_FirstUsableLBA = 0;
3750 	efi_header->efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT);
3751 
3752 	/*
3753 	 * We don't fill out any of these:
3754 	 *
3755 	 * efi_header->efi_gpt_HeaderCRC32;
3756 	 * efi_header->efi_gpt_DiskGUID;
3757 	 * efi_header->efi_gpt_PartitionEntryArrayCRC32;
3758 	 * efi_header->efi_gpt_Reserved1;
3759 	 * efi_header->efi_gpt_MyLBA;
3760 	 * efi_header->efi_gpt_AlternateLBA;
3761 	 * efi_header->efi_gpt_Reserved2[LEN_EFI_PAD];
3762 	 * efi_header->efi_gpt_PartitionEntryLBA;
3763 	 */
3764 
3765 	/*
3766 	 * We copy back one partition, of type reserved,
3767 	 * which may contain the name of the metadevice
3768 	 * (this is what was used to be v_volume for a vtoc device)
3769 	 * if no name is stored in the vtoc record, we hand an empty name
3770 	 * to the user
3771 	 */
3772 
3773 	UUID_LE_CONVERT(efi_part->efi_gpe_PartitionTypeGUID, md_efi_reserved);
3774 	if (un->c.un_flag & MD_LABELED)
3775 		efi_part->efi_gpe_StartingLBA = LE_64(1ULL);
3776 	else
3777 		efi_part->efi_gpe_StartingLBA = 0;
3778 
3779 	efi_part->efi_gpe_EndingLBA = LE_64(un->c.un_total_blocks - 1);
3780 
3781 	if (un->c.un_vtoc_id) {
3782 		status = mddb_getrecstatus(un->c.un_vtoc_id);
3783 		if (status == MDDB_OK) {
3784 			v = mddb_getrecaddr(un->c.un_vtoc_id);
3785 			bcopy(v, (caddr_t)&(efi_part->efi_gpe_PartitionName),
3786 			    MD_EFI_PARTNAME_BYTES);
3787 			return;
3788 		}
3789 		un->c.un_vtoc_id = 0;
3790 		mddb_commitrec_wrapper(un->c.un_record_id);
3791 	}
3792 
3793 	/*
3794 	 * We don't fill out any of these
3795 	 * efi_part->efi_gpe_UniquePartitionGUID
3796 	 * efi_part->efi_gpe_Attributes
3797 	 */
3798 }
3799 
3800 
3801 /*
3802  * md_set_efi
3803  * INPUT:
3804  *	un; a md_unit
3805  *	buf; a buffer that is holding an EFI label for this unit
3806  *
3807  * PURPOSE:
3808  *	Perform some sanity checks on the EFI label provided,
3809  *	Then store efi_gpe_PartitionName in the mddb
3810  *	and link the unit's c.un_vtoc_id field to it.
3811  *
3812  * RETURN:
3813  *	EINVAL if any of the sanity checks fail
3814  *	0 on succes
3815  *
3816  * NOTES:
3817  *	We do not provide for any global unique identifiers,
3818  *	We also use the field c.un_vtoc_id, as the semantic is very similar
3819  *	When we are called, it's already checked, that this unit has an EFI
3820  *		label and not a vtoc
3821  */
3822 
3823 
3824 int
3825 md_set_efi(md_unit_t *un, char *buf)
3826 {
3827 
3828 	mddb_recid_t		recid;
3829 	mddb_recid_t		recids[3];
3830 	mddb_recstatus_t	status;
3831 	caddr_t			v;
3832 	efi_gpt_t	*efi_header = (efi_gpt_t *)buf;
3833 	efi_gpe_t	*efi_part = (efi_gpe_t *)(buf + sizeof (efi_gpt_t));
3834 	struct uuid	md_efi_reserved_le;
3835 
3836 	/*
3837 	 * Sanity-check the EFI label
3838 	 */
3839 	if ((efi_header->efi_gpt_Signature != LE_64(EFI_SIGNATURE)) ||
3840 	    (efi_header->efi_gpt_NumberOfPartitionEntries != LE_32(1)))
3841 		return (EINVAL);
3842 
3843 	UUID_LE_CONVERT(md_efi_reserved_le, md_efi_reserved);
3844 
3845 	/*
3846 	 * Validate the partition
3847 	 */
3848 	if (efi_part->efi_gpe_StartingLBA != 0 ||
3849 	    efi_part->efi_gpe_EndingLBA != LE_64(un->c.un_total_blocks - 1) ||
3850 	    bcmp(&efi_part->efi_gpe_PartitionTypeGUID, &md_efi_reserved_le,
3851 	    sizeof (struct uuid))) {
3852 		return (EINVAL);
3853 	}
3854 	/*
3855 	 * If no name is specified, we have nothing to do and return success.
3856 	 * because efi_gpe_PartitionName is in unicode form, we have to
3857 	 * check the first two bytes of efi_gpe_PartitionName.
3858 	 */
3859 	if (((char *)(uintptr_t)efi_part->efi_gpe_PartitionName[0] == NULL) &&
3860 	    ((char *)(uintptr_t)efi_part->efi_gpe_PartitionName[1] == NULL)) {
3861 		return (0);
3862 	}
3863 
3864 	if (un->c.un_vtoc_id) {
3865 		recid = un->c.un_vtoc_id;
3866 		status = mddb_getrecstatus(recid);
3867 		if (status == MDDB_OK) {
3868 			/*
3869 			 * If there's enough space in the record, and the
3870 			 * existing record is an EFI record (not vtoc),
3871 			 * we just can use the existing space.
3872 			 * Otherwise, we create a new MDDB_EFILABEL record for
3873 			 * this unit.
3874 			 */
3875 			if ((mddb_getrecsize(recid) >= MD_EFI_PARTNAME_BYTES) &&
3876 			    (un->c.un_flag & MD_EFILABEL))  {
3877 				v = mddb_getrecaddr(recid);
3878 				bcopy((caddr_t)&efi_part->efi_gpe_PartitionName,
3879 				    v, MD_EFI_PARTNAME_BYTES);
3880 				mddb_commitrec_wrapper(recid);
3881 				return (0);
3882 			}
3883 
3884 			un->c.un_vtoc_id = 0;
3885 			mddb_commitrec_wrapper(un->c.un_record_id);
3886 			mddb_deleterec_wrapper(recid);
3887 		}
3888 	}
3889 
3890 	recid = mddb_createrec(MD_EFI_PARTNAME_BYTES, MDDB_EFILABEL, 0,
3891 	    MD_CRO_32BIT, MD_UN2SET(un));
3892 
3893 	if (recid < 0) {
3894 		return (ENOSPC);
3895 	}
3896 
3897 	recids[0] = recid;
3898 	recids[1] = un->c.un_record_id;
3899 	recids[2] = 0;
3900 	v = mddb_getrecaddr(recid);
3901 	bcopy((caddr_t)&efi_part->efi_gpe_PartitionName, v,
3902 	    MD_EFI_PARTNAME_BYTES);
3903 
3904 	un->c.un_vtoc_id = recid;
3905 	un->c.un_flag |= MD_EFILABEL;
3906 	mddb_commitrecs_wrapper(recids);
3907 	return (0);
3908 }
3909 
3910 int
3911 md_dkiocgetefi(minor_t mnum, void *data, int mode)
3912 {
3913 	dk_efi_t	efi;
3914 	caddr_t		*buf;
3915 	int		rval = 0;
3916 	mdi_unit_t	*ui;
3917 	md_unit_t	*mdun;
3918 
3919 	if (!(mode & FREAD))
3920 		return (EACCES);
3921 
3922 	if (ddi_copyin(data, &efi, sizeof (dk_efi_t), mode))
3923 		return (EFAULT);
3924 
3925 	efi.dki_data = (void *)(uintptr_t)efi.dki_data_64;
3926 
3927 	/*
3928 	 * If the user specified a zero length or a null pointer, we give them
3929 	 * the number of bytes to alloc in user land.
3930 	 */
3931 	if (efi.dki_length == 0 || efi.dki_data == NULL) {
3932 		efi.dki_length = MD_EFI_LABEL_SIZE;
3933 		if (ddi_copyout(&efi, data, sizeof (dk_efi_t), mode))
3934 			return (EFAULT);
3935 		return (0);
3936 	}
3937 	/* Bad size specified, better not answer to that query */
3938 	if (efi.dki_length < MD_EFI_LABEL_SIZE)
3939 		return (EINVAL);
3940 
3941 	if ((ui = MDI_UNIT(mnum)) == NULL)
3942 		return (ENXIO);
3943 
3944 	/*
3945 	 * We don't want to allocate as much bytes as we are told,
3946 	 * because we know the good size is MD_EFI_LABEL_SIZE
3947 	 */
3948 	efi.dki_length = MD_EFI_LABEL_SIZE;
3949 	buf = kmem_zalloc(MD_EFI_LABEL_SIZE, KM_SLEEP);
3950 
3951 	mdun = (md_unit_t *)md_unit_readerlock(ui);
3952 	md_get_efi(mdun, (char *)buf);
3953 	md_unit_readerexit(ui);
3954 
3955 	if (ddi_copyout(buf, efi.dki_data, efi.dki_length, mode))
3956 		rval = EFAULT;
3957 
3958 	kmem_free(buf, MD_EFI_LABEL_SIZE);
3959 	return (rval);
3960 }
3961 
3962 int
3963 md_dkiocsetefi(minor_t mnum, void *data, int mode)
3964 {
3965 	dk_efi_t	efi;
3966 	caddr_t		*buf;
3967 	int		rval = 0;
3968 	mdi_unit_t	*ui;
3969 	md_unit_t	*mdun;
3970 
3971 	if (!(mode & FREAD))
3972 		return (EACCES);
3973 
3974 	if ((ui = MDI_UNIT(mnum)) == NULL)
3975 		return (ENXIO);
3976 
3977 	if (ddi_copyin(data, &efi, sizeof (dk_efi_t), mode))
3978 		return (EFAULT);
3979 
3980 	efi.dki_data = (void *)(uintptr_t)efi.dki_data_64;
3981 
3982 	/* Sanity check of the skeleton */
3983 	if ((efi.dki_length > sizeof (efi_gpt_t) + EFI_MIN_ARRAY_SIZE) ||
3984 	    (efi.dki_length < sizeof (efi_gpt_t) + sizeof (efi_gpe_t)) ||
3985 	    (efi.dki_data == NULL))
3986 		return (EINVAL);
3987 
3988 	/*
3989 	 * It's only a real EFI label if the location is 1
3990 	 * in all other cases, we do nothing but say we did.
3991 	 */
3992 	if (efi.dki_lba != 1)
3993 		return (0);	/* success */
3994 
3995 	buf = kmem_alloc(efi.dki_length, KM_SLEEP);
3996 	/* And here we copy in the real data */
3997 	if (ddi_copyin(efi.dki_data, buf, efi.dki_length, mode)) {
3998 		rval = EFAULT;
3999 	} else {
4000 		mdun = (md_unit_t *)md_unit_readerlock(ui);
4001 		rval = md_set_efi(mdun, (char *)buf);
4002 		md_unit_readerexit(ui);
4003 	}
4004 
4005 	kmem_free(buf, efi.dki_length);
4006 	return (rval);
4007 }
4008 
4009 /*
4010  * md_dkiocpartition()
4011  * Return the appropriate partition64 structure for a given metadevice.
4012  *
4013  * Actually the only real information being returned is the number of blocks
4014  * of the specified metadevice.
4015  * The starting block is always 0, and so is the partition number, because
4016  * metadevices don't have slices.
4017  *
4018  * This function is generic for all types of metadevices.
4019  */
4020 int
4021 md_dkiocpartition(minor_t mnum, void *data, int mode)
4022 {
4023 	struct partition64	p64;
4024 	mdi_unit_t		*ui;
4025 	md_unit_t		*un;
4026 	int			rval = 0;
4027 
4028 	if (!(mode & FREAD))
4029 		return (EACCES);
4030 
4031 
4032 	if ((ui = MDI_UNIT(mnum)) == NULL)
4033 		return (ENXIO);
4034 
4035 	if (ddi_copyin(data, &p64, sizeof (struct partition64), mode))
4036 		return (EFAULT);
4037 
4038 	if (p64.p_partno != 0)
4039 		return (ESRCH);
4040 
4041 	un = (md_unit_t *)md_unit_readerlock(ui);
4042 	/* All metadevices share the same PartitionTypeGUID (see md_get_efi) */
4043 	UUID_LE_CONVERT(p64.p_type, md_efi_reserved);
4044 
4045 	p64.p_partno = 0;
4046 	p64.p_start = 0;
4047 	p64.p_size = un->c.un_total_blocks;
4048 	md_unit_readerexit(ui);
4049 
4050 	if (ddi_copyout(&p64, data, sizeof (struct partition64), mode)) {
4051 		rval = EFAULT;
4052 	}
4053 
4054 	return (rval);
4055 }
4056 
4057 
4058 /*
4059  * Remove device node
4060  */
4061 void
4062 md_remove_minor_node(minor_t mnum)
4063 {
4064 	char			name[16];
4065 	extern dev_info_t	*md_devinfo;
4066 
4067 	/*
4068 	 * Attempt release of its minor node
4069 	 */
4070 	(void) snprintf(name, sizeof (name), "%d,%d,blk", MD_MIN2SET(mnum),
4071 	    MD_MIN2UNIT(mnum));
4072 	ddi_remove_minor_node(md_devinfo, name);
4073 
4074 	(void) snprintf(name, sizeof (name), "%d,%d,raw", MD_MIN2SET(mnum),
4075 	    MD_MIN2UNIT(mnum));
4076 	ddi_remove_minor_node(md_devinfo, name);
4077 }
4078