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