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