xref: /onnv-gate/usr/src/uts/common/io/lvm/md/md_ioctl.c (revision 12678:79fad257c978)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51623Stw21770  * Common Development and Distribution License (the "License").
61623Stw21770  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
217563SPrasad.Singamsetty@Sun.COM 
220Sstevel@tonic-gate /*
23*12678SJames.Hall@Sun.COM  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * Driver for Virtual Disk.
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate #include <sys/param.h>
300Sstevel@tonic-gate #include <sys/systm.h>
310Sstevel@tonic-gate #include <sys/buf.h>
320Sstevel@tonic-gate #include <sys/conf.h>
330Sstevel@tonic-gate #include <sys/user.h>
340Sstevel@tonic-gate #include <sys/uio.h>
350Sstevel@tonic-gate #include <sys/proc.h>
360Sstevel@tonic-gate #include <sys/t_lock.h>
370Sstevel@tonic-gate #include <sys/dkio.h>
380Sstevel@tonic-gate #include <sys/kmem.h>
390Sstevel@tonic-gate #include <sys/utsname.h>
400Sstevel@tonic-gate #include <sys/debug.h>
410Sstevel@tonic-gate #include <sys/sysmacros.h>
420Sstevel@tonic-gate #include <sys/types.h>
430Sstevel@tonic-gate #include <sys/mkdev.h>
440Sstevel@tonic-gate #include <sys/vtoc.h>
450Sstevel@tonic-gate #include <sys/efi_partition.h>
460Sstevel@tonic-gate #include <sys/open.h>
470Sstevel@tonic-gate #include <sys/file.h>
480Sstevel@tonic-gate #include <sys/ddi.h>
490Sstevel@tonic-gate #include <sys/sunddi.h>
500Sstevel@tonic-gate #include <sys/lvm/mdmn_commd.h>
510Sstevel@tonic-gate 
520Sstevel@tonic-gate #include <sys/lvm/mdvar.h>
530Sstevel@tonic-gate #include <sys/lvm/md_rename.h>
540Sstevel@tonic-gate #include <sys/lvm/md_names.h>
551623Stw21770 #include <sys/lvm/md_hotspares.h>
560Sstevel@tonic-gate 
570Sstevel@tonic-gate extern md_ops_t		**md_ops;
580Sstevel@tonic-gate extern unit_t		md_nunits;
590Sstevel@tonic-gate extern set_t		md_nsets;
600Sstevel@tonic-gate extern int		md_nmedh;
610Sstevel@tonic-gate extern md_set_t		md_set[];
620Sstevel@tonic-gate extern md_set_io_t	md_set_io[];
630Sstevel@tonic-gate extern int		md_status;
640Sstevel@tonic-gate extern int		md_ioctl_cnt;
650Sstevel@tonic-gate extern int		md_in_upgrade;
660Sstevel@tonic-gate extern major_t		md_major;
670Sstevel@tonic-gate 
680Sstevel@tonic-gate /* md.c */
690Sstevel@tonic-gate extern kmutex_t		md_mx;
700Sstevel@tonic-gate extern kcondvar_t	md_cv;
710Sstevel@tonic-gate 
721623Stw21770 /* md_hotspares.c */
731623Stw21770 extern	hot_spare_pool_t *find_hot_spare_pool(set_t setno, int hsp_id);
741623Stw21770 
750Sstevel@tonic-gate /* md_med.c */
760Sstevel@tonic-gate extern int		med_addr_tab_nents;
770Sstevel@tonic-gate extern int		med_get_t_size_ioctl(mddb_med_t_parm_t *tpp, int mode);
780Sstevel@tonic-gate extern int		med_get_t_ioctl(mddb_med_t_parm_t *tpp, int mode);
790Sstevel@tonic-gate extern int		med_set_t_ioctl(mddb_med_t_parm_t *tpp, int mode);
801623Stw21770 extern unit_t		md_get_nextunit(set_t setno);
810Sstevel@tonic-gate 
820Sstevel@tonic-gate /* md_mddb.c */
830Sstevel@tonic-gate extern mddb_set_t	*mddb_setenter(set_t setno, int flag, int *errorcodep);
840Sstevel@tonic-gate extern void		mddb_setexit(mddb_set_t *s);
851623Stw21770 extern md_krwlock_t	nm_lock;
860Sstevel@tonic-gate 
878452SJohn.Wren.Kennedy@Sun.COM #define	MD_MN_COMMD_CMD "rpc.mdcommd"
888452SJohn.Wren.Kennedy@Sun.COM static pid_t		md_mn_commd_pid;
898452SJohn.Wren.Kennedy@Sun.COM 
900Sstevel@tonic-gate /*
910Sstevel@tonic-gate  * md_mn_is_commd_present:
920Sstevel@tonic-gate  * ----------------------
930Sstevel@tonic-gate  * Determine if commd is running on this node.
940Sstevel@tonic-gate  *
958452SJohn.Wren.Kennedy@Sun.COM  * If md_mn_commd_pid is 0, trust it.  Otherwise, do some in-depth checking
968452SJohn.Wren.Kennedy@Sun.COM  * to make sure it's still the one we originally set up by checking the
978452SJohn.Wren.Kennedy@Sun.COM  * provided PID's u_comm for the right program name in u_comm.
988452SJohn.Wren.Kennedy@Sun.COM  *
998452SJohn.Wren.Kennedy@Sun.COM  * This one's intended for the "something went awry" cases, and not for
1008452SJohn.Wren.Kennedy@Sun.COM  * general use, due to its higher cost for the good/normal case.
1010Sstevel@tonic-gate  */
1020Sstevel@tonic-gate int
md_mn_is_commd_present(void)1030Sstevel@tonic-gate md_mn_is_commd_present(void)
1040Sstevel@tonic-gate {
1058452SJohn.Wren.Kennedy@Sun.COM 	proc_t  *commd_procp;
1068452SJohn.Wren.Kennedy@Sun.COM 
1078452SJohn.Wren.Kennedy@Sun.COM 	if (md_mn_commd_pid == (pid_t)0) {
1088452SJohn.Wren.Kennedy@Sun.COM 		return (0);
1098452SJohn.Wren.Kennedy@Sun.COM 	}
1108452SJohn.Wren.Kennedy@Sun.COM 
1118452SJohn.Wren.Kennedy@Sun.COM 	/* some in-depth checking */
1128452SJohn.Wren.Kennedy@Sun.COM 	mutex_enter(&pidlock);
1138452SJohn.Wren.Kennedy@Sun.COM 	if ((commd_procp = prfind(md_mn_commd_pid)) != NULL &&
1148452SJohn.Wren.Kennedy@Sun.COM 	    strncmp(commd_procp->p_user.u_comm,
1158452SJohn.Wren.Kennedy@Sun.COM 	    MD_MN_COMMD_CMD, strlen(MD_MN_COMMD_CMD)) == 0) {
1168452SJohn.Wren.Kennedy@Sun.COM 		mutex_exit(&pidlock);
1178452SJohn.Wren.Kennedy@Sun.COM 		/*
1188452SJohn.Wren.Kennedy@Sun.COM 		 * returns a little more info than asked for, but it will
1198452SJohn.Wren.Kennedy@Sun.COM 		 * never be PID 0 when valid.
1208452SJohn.Wren.Kennedy@Sun.COM 		 */
1218452SJohn.Wren.Kennedy@Sun.COM 		return ((int)md_mn_commd_pid);
1228452SJohn.Wren.Kennedy@Sun.COM 	}
1238452SJohn.Wren.Kennedy@Sun.COM 	/* if it's not there, make sure we only do these contortions once */
1248452SJohn.Wren.Kennedy@Sun.COM 	md_mn_commd_pid = (pid_t)0;
1258452SJohn.Wren.Kennedy@Sun.COM 	mutex_exit(&pidlock);
1268452SJohn.Wren.Kennedy@Sun.COM 
1278452SJohn.Wren.Kennedy@Sun.COM 	cmn_err(CE_WARN, "!rpc.mdcommd exited abnormally");
1288452SJohn.Wren.Kennedy@Sun.COM 	return (0);
1298452SJohn.Wren.Kennedy@Sun.COM }
1308452SJohn.Wren.Kennedy@Sun.COM 
1318452SJohn.Wren.Kennedy@Sun.COM /*
1328452SJohn.Wren.Kennedy@Sun.COM  * This version merely checks the PID value that was set via an ioctl.
1338452SJohn.Wren.Kennedy@Sun.COM  * It's intended to be used in the main code flow, where performance is
1348452SJohn.Wren.Kennedy@Sun.COM  * critical, and accuracy can be sacrificed a little.  If something is
1358452SJohn.Wren.Kennedy@Sun.COM  * already known to be wrong, don't use this, but use
1368452SJohn.Wren.Kennedy@Sun.COM  * md_mn_is_commd_present() instead.
1378452SJohn.Wren.Kennedy@Sun.COM  */
1388452SJohn.Wren.Kennedy@Sun.COM int
md_mn_is_commd_present_lite(void)1398452SJohn.Wren.Kennedy@Sun.COM md_mn_is_commd_present_lite(void)
1408452SJohn.Wren.Kennedy@Sun.COM {
1418452SJohn.Wren.Kennedy@Sun.COM 	return ((int)md_mn_commd_pid);
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate /*
1450Sstevel@tonic-gate  * md_mn_clear_commd_present:
1460Sstevel@tonic-gate  * -------------------------
1478452SJohn.Wren.Kennedy@Sun.COM  * Clear the md_mn_commd_pid. Called only from a CPR request to suspend /
1488452SJohn.Wren.Kennedy@Sun.COM  * terminate a resync thread. We clear the md_mn_commd_pid so that
1490Sstevel@tonic-gate  * any RPC request that was in transit can complete with a failure and _not_
1500Sstevel@tonic-gate  * result in an unexpected system panic.
1510Sstevel@tonic-gate  */
1520Sstevel@tonic-gate void
md_mn_clear_commd_present()1530Sstevel@tonic-gate md_mn_clear_commd_present()
1540Sstevel@tonic-gate {
1558452SJohn.Wren.Kennedy@Sun.COM 	md_mn_commd_pid = (pid_t)0;
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate 
1585428Spetede /*
1595428Spetede  * It is possible to pass in a minor number via the ioctl interface
1605428Spetede  * and this minor number is used to reference elements in arrays.
1615428Spetede  * Therefore we need to make sure that the value passed in is
1625428Spetede  * correct within the array sizes, and array dereference. Not
1635428Spetede  * doing so allows for incorrect values which may result in panics.
1645428Spetede  */
1655428Spetede static int
verify_minor(minor_t mnum)1665428Spetede verify_minor(minor_t mnum)
1675428Spetede {
1685428Spetede 	set_t	setno = MD_MIN2SET(mnum);
1695428Spetede 
1705428Spetede 	/*
1715428Spetede 	 * Check the bounds.
1725428Spetede 	 */
1735428Spetede 	if (setno >= md_nsets || (MD_MIN2UNIT(mnum) >= md_nunits)) {
1745428Spetede 		return (EINVAL);
1755428Spetede 	}
1765428Spetede 
1775428Spetede 	/* has the set been initialised ? */
1785428Spetede 	if ((md_get_setstatus(setno) & MD_SET_SNARFED) == 0)
1795428Spetede 		return (ENODEV);
1805428Spetede 
1815428Spetede 	return (0);
1825428Spetede }
1835428Spetede 
1840Sstevel@tonic-gate static int
get_lb_inittime_ioctl(mddb_config_t * cp)1850Sstevel@tonic-gate get_lb_inittime_ioctl(
1860Sstevel@tonic-gate 	mddb_config_t	*cp
1870Sstevel@tonic-gate )
1880Sstevel@tonic-gate {
1890Sstevel@tonic-gate 	set_t		setno = cp->c_setno;
1900Sstevel@tonic-gate 	int		err;
1910Sstevel@tonic-gate 	mddb_set_t	*s;
1920Sstevel@tonic-gate 
1935428Spetede 	if (setno >= md_nsets)
1945428Spetede 		return (-1);
1955428Spetede 
1960Sstevel@tonic-gate 	if ((s = mddb_setenter(setno, MDDB_MUSTEXIST, &err)) == NULL)
1970Sstevel@tonic-gate 		return (-1);
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 	if (s->s_lbp == NULL) {
2000Sstevel@tonic-gate 		mddb_setexit(s);
2010Sstevel@tonic-gate 		return (-1);
2020Sstevel@tonic-gate 	}
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	cp->c_timestamp = s->s_lbp->lb_inittime;
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	mddb_setexit(s);
2070Sstevel@tonic-gate 	return (0);
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate static int
setnm_ioctl(mdnm_params_t * nm,int mode)2110Sstevel@tonic-gate setnm_ioctl(mdnm_params_t *nm, int mode)
2120Sstevel@tonic-gate {
2131945Sjeanm 	char 	*name, *minorname = NULL;
2140Sstevel@tonic-gate 	side_t	side;
2150Sstevel@tonic-gate 	int	err = 0;
2161945Sjeanm 	void	*devid = NULL;
2171945Sjeanm 	int	devid_sz;
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 	/*
2200Sstevel@tonic-gate 	 * Don't allow addition of new names to namespace during upgrade.
2210Sstevel@tonic-gate 	 */
2220Sstevel@tonic-gate 	if (MD_UPGRADE)  {
2230Sstevel@tonic-gate 		return (EAGAIN);
2240Sstevel@tonic-gate 	}
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	mdclrerror(&nm->mde);
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	if ((mode & FWRITE) == 0)
2290Sstevel@tonic-gate 		return (EACCES);
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
2320Sstevel@tonic-gate 		return (0);
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
2350Sstevel@tonic-gate 		return (ENODEV);
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	if (md_get_setstatus(nm->setno) & MD_SET_STALE)
2380Sstevel@tonic-gate 		return (mdmddberror(&nm->mde, MDE_DB_STALE, NODEV32,
2395428Spetede 		    nm->setno));
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	name = kmem_alloc(MAXPATHLEN, KM_SLEEP);
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	err = ddi_copyin((caddr_t)(uintptr_t)nm->devname, name,
2445428Spetede 	    (size_t)nm->devname_len, mode);
2450Sstevel@tonic-gate 	if (err) {
2460Sstevel@tonic-gate 		err = EFAULT;
2470Sstevel@tonic-gate 		goto out;
2480Sstevel@tonic-gate 	}
2490Sstevel@tonic-gate 
2501945Sjeanm 	if (nm->imp_flag) {
2511945Sjeanm 		if ((nm->devid == NULL) || (nm->minorname == NULL)) {
2521945Sjeanm 			err = EINVAL;
2531945Sjeanm 			goto out;
2541945Sjeanm 		}
2551945Sjeanm 		if (nm->devid) {
2561945Sjeanm 			devid_sz = nm->devid_size;
2571945Sjeanm 			devid = kmem_zalloc(devid_sz, KM_SLEEP);
2581945Sjeanm 			err = ddi_copyin((caddr_t)(uintptr_t)nm->devid,
2591945Sjeanm 			    devid, devid_sz, mode);
2601945Sjeanm 			if (err) {
2611945Sjeanm 				err = EFAULT;
2621945Sjeanm 				goto out;
2631945Sjeanm 			}
2641945Sjeanm 		}
2651945Sjeanm 		if (nm->minorname) {
2661945Sjeanm 			if (nm->minorname_len > MAXPATHLEN) {
2671945Sjeanm 				err = EINVAL;
2681945Sjeanm 				goto out;
2691945Sjeanm 			}
2701945Sjeanm 			minorname = kmem_zalloc(nm->minorname_len, KM_SLEEP);
2711945Sjeanm 			err = ddi_copyin((caddr_t)(uintptr_t)nm->minorname,
2721945Sjeanm 			    minorname, (size_t)nm->minorname_len, mode);
2731945Sjeanm 			if (err) {
2741945Sjeanm 				err = EFAULT;
2751945Sjeanm 				goto out;
2761945Sjeanm 			}
2771945Sjeanm 		}
2781945Sjeanm 	}
2791945Sjeanm 
2800Sstevel@tonic-gate 	if (nm->side == -1)
2810Sstevel@tonic-gate 		side = mddb_getsidenum(nm->setno);
2820Sstevel@tonic-gate 	else
2830Sstevel@tonic-gate 		side = nm->side;
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	if (strcmp(nm->drvnm, "") == 0) {
2860Sstevel@tonic-gate 		char *drvnm;
2870Sstevel@tonic-gate 		drvnm = ddi_major_to_name(nm->major);
2880Sstevel@tonic-gate 		(void) strncpy(nm->drvnm, drvnm, sizeof (nm->drvnm));
2890Sstevel@tonic-gate 	}
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	nm->key = md_setdevname(nm->setno, side, nm->key, nm->drvnm,
2921945Sjeanm 	    nm->mnum, name, nm->imp_flag, (ddi_devid_t)devid, minorname,
2931945Sjeanm 	    0, &nm->mde);
2941623Stw21770 	/*
2951623Stw21770 	 * If we got an error from md_setdevname & md_setdevname did not
2961623Stw21770 	 * set the error code, we'll default to MDE_DB_NOSPACE.
2971623Stw21770 	 */
2981623Stw21770 	if ((((int)nm->key) < 0) && mdisok(&nm->mde)) {
2990Sstevel@tonic-gate 		err = mdmddberror(&nm->mde, MDE_DB_NOSPACE, NODEV32, nm->setno);
3000Sstevel@tonic-gate 		goto out;
3010Sstevel@tonic-gate 	}
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate out:
3040Sstevel@tonic-gate 	kmem_free(name, MAXPATHLEN);
3051945Sjeanm 	if (devid) {
3061945Sjeanm 		kmem_free(devid, devid_sz);
3071945Sjeanm 	}
3081945Sjeanm 	if (minorname)
3091945Sjeanm 		kmem_free(minorname, nm->minorname_len);
3100Sstevel@tonic-gate 	return (err);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate static int
getnm_ioctl(mdnm_params_t * nm,int mode)3140Sstevel@tonic-gate getnm_ioctl(
3150Sstevel@tonic-gate 	mdnm_params_t	*nm,
3160Sstevel@tonic-gate 	int		mode
3170Sstevel@tonic-gate )
3180Sstevel@tonic-gate {
3190Sstevel@tonic-gate 	char		*name;
3200Sstevel@tonic-gate 	side_t		side;
3210Sstevel@tonic-gate 	md_dev64_t	dev = NODEV64;
3221623Stw21770 	mdc_unit_t	*un;
3231623Stw21770 	uint_t		id;
3241623Stw21770 	char		*setname;
3250Sstevel@tonic-gate 	int		err = 0;
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 	mdclrerror(&nm->mde);
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
3300Sstevel@tonic-gate 		return (0);
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
3330Sstevel@tonic-gate 		return (ENODEV);
3340Sstevel@tonic-gate 
3351945Sjeanm 
3360Sstevel@tonic-gate 	name = kmem_alloc(MAXPATHLEN, KM_SLEEP);
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	if (nm->side == -1)
3390Sstevel@tonic-gate 		side = mddb_getsidenum(nm->setno);
3400Sstevel@tonic-gate 	else
3410Sstevel@tonic-gate 		side = nm->side;
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 	if (nm->drvnm[0] == '\0') {
3440Sstevel@tonic-gate 		char *drvnm;
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 		if (MD_UPGRADE)
3470Sstevel@tonic-gate 			drvnm = md_targ_major_to_name(nm->major);
3480Sstevel@tonic-gate 		else
3490Sstevel@tonic-gate 			drvnm = ddi_major_to_name(nm->major);
3500Sstevel@tonic-gate 		if (drvnm != NULL)
3510Sstevel@tonic-gate 			(void) strncpy(nm->drvnm, drvnm, sizeof (nm->drvnm));
3520Sstevel@tonic-gate 	}
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 	if (nm->drvnm[0] != '\0') {
3550Sstevel@tonic-gate 		if (MD_UPGRADE)
3560Sstevel@tonic-gate 			dev = md_makedevice(md_targ_name_to_major(nm->drvnm),
3575428Spetede 			    nm->mnum);
3580Sstevel@tonic-gate 		else
3590Sstevel@tonic-gate 			dev = md_makedevice(ddi_name_to_major(nm->drvnm),
3605428Spetede 			    nm->mnum);
3610Sstevel@tonic-gate 	}
3621623Stw21770 
3631623Stw21770 	/*
3641623Stw21770 	 * With the introduction of friendly names, all friendly named
3651623Stw21770 	 * metadevices will have an entry in the name space. However,
3661623Stw21770 	 * systems upgraded from pre-friendly name to a friendly name
3671623Stw21770 	 * release won't have name space entries for pre-friendly name
3681623Stw21770 	 * top level metadevices.
3691623Stw21770 	 *
3701623Stw21770 	 * So we search the name space for the our entry with either the
3711623Stw21770 	 * given dev_t or key. If we can't find the entry, we'll try the
3721623Stw21770 	 * un array to get information for our target metadevice. Note
3731623Stw21770 	 * we only use the un array when searching by dev_t since a
3741623Stw21770 	 * key implies an existing device which should have been
3751623Stw21770 	 * found in the name space with the call md_getdevname.
3761623Stw21770 	 */
3771623Stw21770 	if (md_getdevname(nm->setno, side, nm->key, dev, name,
3781623Stw21770 	    MAXPATHLEN) == 0) {
3791623Stw21770 		err = md_getnment(nm->setno, side, nm->key, dev, nm->drvnm,
3801623Stw21770 		    sizeof (nm->drvnm), &nm->major, &nm->mnum, &nm->retkey);
3811623Stw21770 		if (err) {
3821623Stw21770 			if (err < 0)
3831623Stw21770 				err = EINVAL;
3841623Stw21770 			goto out;
3851623Stw21770 		}
3861623Stw21770 	} else {
3871623Stw21770 		if ((nm->key != MD_KEYWILD) ||
3885428Spetede 		    (md_set[MD_MIN2SET(nm->mnum)].s_un == NULL) ||
3891623Stw21770 		    (MD_UNIT(nm->mnum) == NULL)) {
3901623Stw21770 			err = ENOENT;
3911623Stw21770 			goto out;
3921623Stw21770 		}
3931623Stw21770 
3941623Stw21770 		/*
3951623Stw21770 		 * We're here because the mnum is of a pre-friendly
3961623Stw21770 		 * name device. Make sure the major value is for
3971623Stw21770 		 * metadevices.
3981623Stw21770 		 */
3991623Stw21770 		if (nm->major != md_major) {
4001623Stw21770 			err = ENOENT;
4011623Stw21770 			goto out;
4021623Stw21770 		}
4031623Stw21770 
4041623Stw21770 		/*
4051623Stw21770 		 * get the unit number and setname to construct the
4061623Stw21770 		 * fully qualified name for the metadevice.
4071623Stw21770 		 */
4081623Stw21770 		un = MD_UNIT(nm->mnum);
4091623Stw21770 		id =  MD_MIN2UNIT(un->un_self_id);
4101623Stw21770 		if (nm->setno != MD_LOCAL_SET) {
4111623Stw21770 			setname = mddb_getsetname(nm->setno);
4121623Stw21770 			(void) snprintf(name, MAXPATHLEN,
4131623Stw21770 			    "/dev/md/%s/dsk/d%u", setname, id);
4141623Stw21770 		} else {
4151623Stw21770 			(void) snprintf(name, MAXPATHLEN,
4161623Stw21770 			    "/dev/md/dsk/d%u", id);
4171623Stw21770 		}
4180Sstevel@tonic-gate 	}
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	err = ddi_copyout(name, (caddr_t)(uintptr_t)nm->devname,
4210Sstevel@tonic-gate 	    strlen(name) + 1, mode);
4220Sstevel@tonic-gate 	if (err) {
4230Sstevel@tonic-gate 		err = EFAULT;
4240Sstevel@tonic-gate 		goto out;
4250Sstevel@tonic-gate 	}
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate out:
4280Sstevel@tonic-gate 	kmem_free(name, MAXPATHLEN);
4290Sstevel@tonic-gate 	return (err);
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate 
4321623Stw21770 static int
gethspnm_ioctl(mdhspnm_params_t * nm,int mode)4331623Stw21770 gethspnm_ioctl(
4341623Stw21770 	mdhspnm_params_t	*nm,
4351623Stw21770 	int			mode
4361623Stw21770 )
4371623Stw21770 {
4381623Stw21770 	char			*name;
4391623Stw21770 	char			*tmpname;
4401623Stw21770 	char			*setname = NULL;
4411623Stw21770 	side_t			side;
4421623Stw21770 	hot_spare_pool_t	*hsp = NULL;
4431623Stw21770 	mdkey_t			key = MD_KEYWILD;
4441623Stw21770 	int			err = 0;
4451623Stw21770 
4461623Stw21770 	mdclrerror(&nm->mde);
4471623Stw21770 
4481623Stw21770 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
4491623Stw21770 		return (0);
4501623Stw21770 
4511623Stw21770 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
4521623Stw21770 		return (ENODEV);
4531623Stw21770 
4541623Stw21770 	name = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
4551623Stw21770 
4561623Stw21770 	if (nm->side == -1)
4571623Stw21770 		side = mddb_getsidenum(nm->setno);
4581623Stw21770 	else
4591623Stw21770 		side = nm->side;
4601623Stw21770 
4611623Stw21770 	/*
4621623Stw21770 	 * Get the key from input hspid, use different macros
4631623Stw21770 	 * since the hspid could be either a FN or pre-FN hspid.
4641623Stw21770 	 */
4651623Stw21770 	if (nm->hspid != MD_HSPID_WILD) {
4661623Stw21770 		if (HSP_ID_IS_FN(nm->hspid))
4671623Stw21770 			key = HSP_ID_TO_KEY(nm->hspid);
4681623Stw21770 		else
4691623Stw21770 			key = HSP_ID(nm->hspid);
4701623Stw21770 	}
4711623Stw21770 
4721623Stw21770 	/*
4731623Stw21770 	 * Get the input name if we're searching by hsp name. Check
4741623Stw21770 	 * that the input name length is less than MAXPATHLEN.
4751623Stw21770 	 */
4761623Stw21770 	if ((nm->hspid == MD_HSPID_WILD) &&
4771623Stw21770 	    (nm->hspname_len <= MAXPATHLEN)) {
4781623Stw21770 		err = ddi_copyin((caddr_t)(uintptr_t)nm->hspname,
4791623Stw21770 		    name, (sizeof (char)) * nm->hspname_len, mode);
4801623Stw21770 
4811623Stw21770 		/* Stop if ddi_copyin failed. */
4821623Stw21770 		if (err) {
4831623Stw21770 			err = EFAULT;
4841623Stw21770 			goto out;
4851623Stw21770 		}
4861623Stw21770 	}
4871623Stw21770 
4881623Stw21770 	/* Must have either a valid hspid or a name to continue */
4891623Stw21770 	if ((nm->hspid == MD_HSPID_WILD) && (name[0] == '\0')) {
4901623Stw21770 		err = EINVAL;
4911623Stw21770 		goto out;
4921623Stw21770 	}
4931623Stw21770 
4941623Stw21770 	/*
4951623Stw21770 	 * Try to find the hsp namespace entry corresponds to either
4961623Stw21770 	 * the given hspid or name. If we can't find it, the hsp maybe
4971623Stw21770 	 * a pre-friendly name hsp so we'll try to find it in the
4981623Stw21770 	 * s_hsp array.
4991623Stw21770 	 */
5001623Stw21770 	if ((nm->hspid == MD_HSPID_WILD) || (HSP_ID_IS_FN(nm->hspid))) {
5011623Stw21770 
5021623Stw21770 		if (md_gethspinfo(nm->setno, side, key, nm->drvnm,
5031623Stw21770 		    &nm->ret_hspid, name) != 0) {
5041623Stw21770 			/*
5051623Stw21770 			 * If we were given a key for a FN hsp and
5061623Stw21770 			 * couldn't find its entry, simply errored
5071623Stw21770 			 * out.
5081623Stw21770 			 */
5091623Stw21770 			if (HSP_ID_IS_FN(nm->hspid)) {
5101623Stw21770 				err = ENOENT;
5111623Stw21770 				goto out;
5121623Stw21770 			}
5131623Stw21770 
5141623Stw21770 			/*
5151623Stw21770 			 * Since md_gethspinfo failed and the hspid is
5161623Stw21770 			 * not a FN hspid,  we must have a name for a
5171623Stw21770 			 * pre-FN hotspare pool
5181623Stw21770 			 */
5191623Stw21770 			if (name[0] == '\0') {
5201623Stw21770 				err = EINVAL;
5211623Stw21770 				goto out;
5221623Stw21770 			}
5231623Stw21770 
5241623Stw21770 			tmpname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
5251623Stw21770 			if (nm->setno != MD_LOCAL_SET)
5261623Stw21770 				setname = mddb_getsetname(nm->setno);
5271623Stw21770 
5281623Stw21770 			hsp = (hot_spare_pool_t *)md_set[nm->setno].s_hsp;
5291623Stw21770 			while (hsp != NULL) {
5301623Stw21770 				/* Only use the pre-friendly name hsp */
5311623Stw21770 				if (!(hsp->hsp_revision & MD_FN_META_DEV)) {
5321623Stw21770 
5331623Stw21770 					if (setname != NULL) {
5341623Stw21770 						(void) snprintf(tmpname,
5351623Stw21770 						    MAXPATHLEN,
5361623Stw21770 						    "%s/hsp%03u", setname,
5371623Stw21770 						    HSP_ID(hsp->hsp_self_id));
5381623Stw21770 					} else {
5391623Stw21770 						(void) snprintf(tmpname,
5401623Stw21770 						    MAXPATHLEN, "hsp%03u",
5411623Stw21770 						    HSP_ID(hsp->hsp_self_id));
5421623Stw21770 					}
5431623Stw21770 
5441623Stw21770 					if (strcmp(name, tmpname) == 0)
5451623Stw21770 						break;
5461623Stw21770 				}
5471623Stw21770 
5481623Stw21770 				hsp = hsp->hsp_next;
5491623Stw21770 			}
5501623Stw21770 			kmem_free(tmpname, MAXPATHLEN);
5511623Stw21770 
5521623Stw21770 			if (hsp == NULL) {
5531623Stw21770 				err = ENOENT;
5541623Stw21770 				goto out;
5551623Stw21770 			}
5561623Stw21770 
5571623Stw21770 			/* Return hsp_self_id */
5581623Stw21770 			nm->ret_hspid = hsp->hsp_self_id;
5591623Stw21770 		}
5601623Stw21770 
5611623Stw21770 	} else {
5621623Stw21770 		/*
5631623Stw21770 		 * We have a hspid for a pre-FN hotspare pool. Let's
5641623Stw21770 		 * try to find the matching hsp using the given
5651623Stw21770 		 * hspid.
5661623Stw21770 		 */
5671623Stw21770 		if (nm->hspid == MD_HSPID_WILD) {
5681623Stw21770 			err = ENOENT;
5691623Stw21770 			goto out;
5701623Stw21770 		}
5711623Stw21770 
5721623Stw21770 		hsp = (hot_spare_pool_t *)md_set[nm->setno].s_hsp;
5731623Stw21770 		while (hsp != NULL) {
5741623Stw21770 			if (hsp->hsp_self_id == nm->hspid)
5751623Stw21770 				break;
5761623Stw21770 			hsp = hsp->hsp_next;
5771623Stw21770 		}
5781623Stw21770 
5791623Stw21770 		if (hsp == NULL) {
5801623Stw21770 			err = ENOENT;
5811623Stw21770 			goto out;
5821623Stw21770 		}
5831623Stw21770 
5841623Stw21770 		/* Prepare a name to return */
5851623Stw21770 		if (nm->setno != MD_LOCAL_SET)
5861623Stw21770 			setname = mddb_getsetname(nm->setno);
5871623Stw21770 
5881623Stw21770 		if (setname != NULL) {
5891623Stw21770 			(void) snprintf(name, MAXPATHLEN, "%s/hsp%03u",
5901623Stw21770 			    setname, HSP_ID(hsp->hsp_self_id));
5911623Stw21770 		} else {
5921623Stw21770 			(void) snprintf(name, MAXPATHLEN, "hsp%03u",
5931623Stw21770 			    HSP_ID(hsp->hsp_self_id));
5941623Stw21770 		}
5951623Stw21770 
5961623Stw21770 		nm->ret_hspid = hsp->hsp_self_id;
5971623Stw21770 	}
5981623Stw21770 
5991623Stw21770 	if (nm->hspid != MD_HSPID_WILD) {
6001623Stw21770 		if ((strlen(name) + 1) > nm->hspname_len) {
6011623Stw21770 			err = EINVAL;
6021623Stw21770 			goto out;
6031623Stw21770 		}
6041623Stw21770 		err = ddi_copyout(name, (caddr_t)
6051623Stw21770 		    (uintptr_t)nm->hspname, strlen(name)+1, mode);
6061623Stw21770 	}
6071623Stw21770 
6081623Stw21770 	if (err) {
6091623Stw21770 		if (err < 0)
6101623Stw21770 			err = EINVAL;
6111623Stw21770 	}
6121623Stw21770 
6131623Stw21770 out:
6141623Stw21770 	kmem_free(name, MAXPATHLEN);
6151623Stw21770 	return (err);
6161623Stw21770 }
6171623Stw21770 
6181623Stw21770 
6190Sstevel@tonic-gate /*ARGSUSED*/
6200Sstevel@tonic-gate static int
update_loc_namespace_ioctl(mdnm_params_t * nm,char * dname,char * pname,int mode)6210Sstevel@tonic-gate update_loc_namespace_ioctl(
6220Sstevel@tonic-gate 	mdnm_params_t	*nm,
6230Sstevel@tonic-gate 	char		*dname,
6240Sstevel@tonic-gate 	char		*pname,
6250Sstevel@tonic-gate 	int		mode
6260Sstevel@tonic-gate )
6270Sstevel@tonic-gate {
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate 	side_t		side;
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	mdclrerror(&nm->mde);
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
6340Sstevel@tonic-gate 		return (0);
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	if (MD_MNSET_SETNO(nm->setno))
6370Sstevel@tonic-gate 		return (0);
6380Sstevel@tonic-gate 
6390Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_STALE))
6400Sstevel@tonic-gate 		return (0);
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
6430Sstevel@tonic-gate 		return (ENODEV);
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 	if (nm->side == -1)
6460Sstevel@tonic-gate 		side = mddb_getsidenum(nm->setno);
6470Sstevel@tonic-gate 	else
6480Sstevel@tonic-gate 		side = nm->side;
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 	return (md_update_locator_namespace(nm->setno, side, dname,
6510Sstevel@tonic-gate 	    pname, nm->devt));
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate /*ARGSUSED*/
6550Sstevel@tonic-gate static int
update_namespace_did_ioctl(mdnm_params_t * nm,int mode)6560Sstevel@tonic-gate update_namespace_did_ioctl(
6570Sstevel@tonic-gate 	mdnm_params_t	*nm,
6580Sstevel@tonic-gate 	int		mode
6590Sstevel@tonic-gate )
6600Sstevel@tonic-gate {
6610Sstevel@tonic-gate 	side_t		side;
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 	mdclrerror(&nm->mde);
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
6660Sstevel@tonic-gate 		return (0);
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 	if (MD_MNSET_SETNO(nm->setno))
6690Sstevel@tonic-gate 		return (0);
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_STALE))
6720Sstevel@tonic-gate 		return (0);
6735428Spetede 
6740Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
6750Sstevel@tonic-gate 		return (ENODEV);
6765428Spetede 
6770Sstevel@tonic-gate 	if (nm->side == -1)
6780Sstevel@tonic-gate 		side = mddb_getsidenum(nm->setno);
6790Sstevel@tonic-gate 	else
6800Sstevel@tonic-gate 		side = nm->side;
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 	return (md_update_namespace_did(nm->setno, side, nm->key, &nm->mde));
6830Sstevel@tonic-gate }
6845428Spetede 
6850Sstevel@tonic-gate /*ARGSUSED*/
6860Sstevel@tonic-gate static int
update_namespace_ioctl(mdnm_params_t * nm,char * dname,char * pname,int mode)6870Sstevel@tonic-gate update_namespace_ioctl(
6880Sstevel@tonic-gate 	mdnm_params_t	*nm,
6890Sstevel@tonic-gate 	char		*dname,
6900Sstevel@tonic-gate 	char		*pname,
6910Sstevel@tonic-gate 	int		mode
6920Sstevel@tonic-gate )
6930Sstevel@tonic-gate {
6940Sstevel@tonic-gate 	side_t		side;
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	mdclrerror(&nm->mde);
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
6990Sstevel@tonic-gate 		return (0);
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	if (MD_MNSET_SETNO(nm->setno))
7020Sstevel@tonic-gate 		return (0);
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_STALE))
7050Sstevel@tonic-gate 		return (0);
7060Sstevel@tonic-gate 
7070Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
7080Sstevel@tonic-gate 		return (ENODEV);
7090Sstevel@tonic-gate 
7100Sstevel@tonic-gate 	if (nm->side == -1)
7110Sstevel@tonic-gate 		side = mddb_getsidenum(nm->setno);
7120Sstevel@tonic-gate 	else
7130Sstevel@tonic-gate 		side = nm->side;
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 	return (md_update_namespace(nm->setno, side, nm->key,
716*12678SJames.Hall@Sun.COM 	    dname, pname, nm->major, nm->mnum));
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate }
7190Sstevel@tonic-gate 
7200Sstevel@tonic-gate /*ARGSUSED*/
7210Sstevel@tonic-gate static int
getnextkey_ioctl(mdnm_params_t * nm,int mode)7220Sstevel@tonic-gate getnextkey_ioctl(
7230Sstevel@tonic-gate 	mdnm_params_t	*nm,
7240Sstevel@tonic-gate 	int		mode
7250Sstevel@tonic-gate )
7260Sstevel@tonic-gate {
7270Sstevel@tonic-gate 	side_t		side;
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate 	mdclrerror(&nm->mde);
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
7320Sstevel@tonic-gate 		return (0);
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 	if (nm->setno >= md_nsets)
7350Sstevel@tonic-gate 		return (EINVAL);
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
7380Sstevel@tonic-gate 		return (ENODEV);
7390Sstevel@tonic-gate 
7400Sstevel@tonic-gate 	if (nm->side == -1)
7410Sstevel@tonic-gate 		side = mddb_getsidenum(nm->setno);
7420Sstevel@tonic-gate 	else
7430Sstevel@tonic-gate 		side = nm->side;
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 	nm->key = md_getnextkey(nm->setno, side, nm->key, &nm->ref_count);
7460Sstevel@tonic-gate 	return (0);
7470Sstevel@tonic-gate }
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate /*ARGSUSED*/
7500Sstevel@tonic-gate static int
remnm_ioctl(mdnm_params_t * nm,int mode)7510Sstevel@tonic-gate remnm_ioctl(mdnm_params_t *nm, int mode)
7520Sstevel@tonic-gate {
7530Sstevel@tonic-gate 	side_t	side;
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate 	mdclrerror(&nm->mde);
7560Sstevel@tonic-gate 
7570Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
7580Sstevel@tonic-gate 		return (0);
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
7610Sstevel@tonic-gate 		return (ENODEV);
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate 	if (nm->side == -1)
7640Sstevel@tonic-gate 		side = mddb_getsidenum(nm->setno);
7650Sstevel@tonic-gate 	else
7660Sstevel@tonic-gate 		side = nm->side;
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 	return (md_remdevname(nm->setno, side, nm->key));
7690Sstevel@tonic-gate }
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate /*ARGSUSED*/
7730Sstevel@tonic-gate static int
getdrvnm_ioctl(md_dev64_t dev,md_i_driverinfo_t * di,int mode)7740Sstevel@tonic-gate getdrvnm_ioctl(md_dev64_t dev, md_i_driverinfo_t *di, int mode)
7750Sstevel@tonic-gate {
7760Sstevel@tonic-gate 	mdi_unit_t 	*ui;
7770Sstevel@tonic-gate 	minor_t		mnum = di->mnum;
7780Sstevel@tonic-gate 	set_t		setno = MD_MIN2SET(mnum);
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	mdclrerror(&di->mde);
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &di->mde) != 0)
7830Sstevel@tonic-gate 		return (0);
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	ui = MDI_UNIT(mnum);
7860Sstevel@tonic-gate 	if (ui == NULL) {
7870Sstevel@tonic-gate 		return (mdmderror(&di->mde, MDE_UNIT_NOT_SETUP, mnum));
7880Sstevel@tonic-gate 	}
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 	MD_SETDRIVERNAME(di, md_ops[ui->ui_opsindex]->md_driver.md_drivername,
7910Sstevel@tonic-gate 	    setno);
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 	return (0);
7940Sstevel@tonic-gate }
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate /*ARGSUSED*/
7970Sstevel@tonic-gate static int
getnext_ioctl(md_i_getnext_t * gn,int mode)7980Sstevel@tonic-gate getnext_ioctl(md_i_getnext_t *gn, int mode)
7990Sstevel@tonic-gate {
8000Sstevel@tonic-gate 	int		modindex;
8010Sstevel@tonic-gate 	md_link_t	*next;
8020Sstevel@tonic-gate 	uint_t		id;
8030Sstevel@tonic-gate 	int		found = 0;
8040Sstevel@tonic-gate 	set_t		setno = gn->md_driver.md_setno;
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate 	mdclrerror(&gn->mde);
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &gn->mde) != 0)
8090Sstevel@tonic-gate 		return (0);
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	if ((md_get_setstatus(setno) & MD_SET_SNARFED) == 0) {
8120Sstevel@tonic-gate 		if (md_get_setstatus(setno) & MD_SET_TAGDATA)
8130Sstevel@tonic-gate 			return (mdmddberror(&gn->mde, MDE_DB_TAGDATA,
8140Sstevel@tonic-gate 			    NODEV32, setno));
8150Sstevel@tonic-gate 		else
8160Sstevel@tonic-gate 			return (mderror(&gn->mde, MDE_UNIT_NOT_FOUND));
8170Sstevel@tonic-gate 	}
8180Sstevel@tonic-gate 
8190Sstevel@tonic-gate 	modindex = md_getmodindex((md_driver_t *)gn, 1, 0);
8200Sstevel@tonic-gate 	if (modindex == -1) {
8210Sstevel@tonic-gate 		return (mderror(&gn->mde, MDE_UNIT_NOT_FOUND));
8220Sstevel@tonic-gate 	}
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate 	rw_enter(&md_ops[modindex]->md_link_rw.lock, RW_READER);
8250Sstevel@tonic-gate 	id = gn->id;
8260Sstevel@tonic-gate 	next = md_ops[modindex]->md_head;
8270Sstevel@tonic-gate 	while (next) {
8280Sstevel@tonic-gate 		if ((next->ln_setno == setno) && (next->ln_id == id)) {
8290Sstevel@tonic-gate 			gn->id = id;
8300Sstevel@tonic-gate 			found = 1;
8310Sstevel@tonic-gate 			break;
8320Sstevel@tonic-gate 		}
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 		if ((next->ln_setno == setno) &&(next->ln_id > id) &&
8350Sstevel@tonic-gate 		    (! found || (next->ln_id < gn->id))) {
8360Sstevel@tonic-gate 			gn->id = next->ln_id;
8370Sstevel@tonic-gate 			found = 1;
8380Sstevel@tonic-gate 			/* continue looking for smallest */
8390Sstevel@tonic-gate 		}
8400Sstevel@tonic-gate 		next = next->ln_next;
8410Sstevel@tonic-gate 	}
8420Sstevel@tonic-gate 	rw_exit(&md_ops[modindex]->md_link_rw.lock);
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate 	if (! found)
8450Sstevel@tonic-gate 		return (mderror(&gn->mde, MDE_UNIT_NOT_FOUND));
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 	return (0);
8480Sstevel@tonic-gate }
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate /*ARGSUSED*/
8510Sstevel@tonic-gate static int
getnum_ioctl(void * d,int mode)8520Sstevel@tonic-gate getnum_ioctl(void *d, int mode)
8530Sstevel@tonic-gate {
8540Sstevel@tonic-gate 	int		modindex;
8550Sstevel@tonic-gate 	md_link_t	*next;
8560Sstevel@tonic-gate 	int		sz;
8570Sstevel@tonic-gate 	minor_t		*minors;
8580Sstevel@tonic-gate 	minor_t		*m_ptr;
8590Sstevel@tonic-gate 	set_t		setno;
8600Sstevel@tonic-gate 	int		err = 0;
8610Sstevel@tonic-gate 	md_error_t	*mdep;
8620Sstevel@tonic-gate 	int		minor_array_length;
8630Sstevel@tonic-gate 	md_driver_t	*driver;
8640Sstevel@tonic-gate 	int		count = 0;
8650Sstevel@tonic-gate 	struct md_i_getnum	*gn = d;
8660Sstevel@tonic-gate 
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 	/* number of specified devices in specified set - if 0 return count */
8690Sstevel@tonic-gate 	minor_array_length = gn->size;
8700Sstevel@tonic-gate 	if (minor_array_length > md_nunits)
8710Sstevel@tonic-gate 		return (EINVAL);
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 	mdep = &gn->mde;
8740Sstevel@tonic-gate 	driver = &gn->md_driver;
8750Sstevel@tonic-gate 	setno = driver->md_setno;
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate 	mdclrerror(mdep);
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, mdep) != 0)
8800Sstevel@tonic-gate 		return (0);
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate 	if ((md_get_setstatus(setno) & MD_SET_SNARFED) == 0) {
8830Sstevel@tonic-gate 		if (md_get_setstatus(setno) & MD_SET_TAGDATA) {
8840Sstevel@tonic-gate 			return (mdmddberror(mdep, MDE_DB_TAGDATA,
8850Sstevel@tonic-gate 			    NODEV32, setno));
8860Sstevel@tonic-gate 		} else {
8870Sstevel@tonic-gate 			return (mderror(mdep, MDE_UNIT_NOT_FOUND));
8880Sstevel@tonic-gate 		}
8890Sstevel@tonic-gate 	}
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 	modindex = md_getmodindex(driver, 0, 0);
8920Sstevel@tonic-gate 	if (modindex == -1) {
8930Sstevel@tonic-gate 
8940Sstevel@tonic-gate 		return (mderror(mdep, MDE_UNIT_NOT_FOUND));
8950Sstevel@tonic-gate 	}
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 	/* if array length is not 0 then allocate the output buffers */
8980Sstevel@tonic-gate 	if (minor_array_length != 0) {
8990Sstevel@tonic-gate 		sz = minor_array_length * ((int)sizeof (minor_t));
9000Sstevel@tonic-gate 		minors = kmem_zalloc(sz, KM_SLEEP);
9010Sstevel@tonic-gate 		m_ptr = minors;
9020Sstevel@tonic-gate 	}
9030Sstevel@tonic-gate 
9048452SJohn.Wren.Kennedy@Sun.COM 	rw_enter(&md_ops[modindex]->md_link_rw.lock, RW_READER);
9050Sstevel@tonic-gate 	next = md_ops[modindex]->md_head;
9060Sstevel@tonic-gate 	count = 0;
9070Sstevel@tonic-gate 	while (next) {
9085428Spetede 		if (next->ln_setno == setno) {
9095428Spetede 			if ((minor_array_length > 0) &&
9105428Spetede 			    (count < minor_array_length)) {
9115428Spetede 				*m_ptr = next->ln_id;
9125428Spetede 				m_ptr++;
9135428Spetede 			}
9145428Spetede 			count++;
9155428Spetede 		}
9165428Spetede 		next = next->ln_next;
9170Sstevel@tonic-gate 	}
9180Sstevel@tonic-gate 	rw_exit(&md_ops[modindex]->md_link_rw.lock);
9190Sstevel@tonic-gate 
9200Sstevel@tonic-gate 	gn->size = count;
9210Sstevel@tonic-gate 	/* now copy the array back */
9220Sstevel@tonic-gate 	if (minor_array_length > 0) {
9235428Spetede 		err = ddi_copyout(minors,
9245428Spetede 		    (caddr_t)(uintptr_t)gn->minors, sz, mode);
9255428Spetede 		kmem_free(minors, sz);
9260Sstevel@tonic-gate 	}
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 	return (err);
9290Sstevel@tonic-gate }
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate /*ARGSUSED*/
9320Sstevel@tonic-gate static int
didstat_ioctl(md_i_didstat_t * ds)9330Sstevel@tonic-gate didstat_ioctl(
9340Sstevel@tonic-gate 	md_i_didstat_t	*ds
9350Sstevel@tonic-gate )
9360Sstevel@tonic-gate {
9370Sstevel@tonic-gate 	int		cnt = 0;
9380Sstevel@tonic-gate 	int		err = 0;
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate 	mdclrerror(&ds->mde);
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &ds->mde) != 0)
9430Sstevel@tonic-gate 		return (0);
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate 	if (ds->setno >= md_nsets) {
9460Sstevel@tonic-gate 		return (EINVAL);
9470Sstevel@tonic-gate 	}
9480Sstevel@tonic-gate 
9490Sstevel@tonic-gate 	if ((md_get_setstatus(ds->setno) & MD_SET_SNARFED) == 0)
9500Sstevel@tonic-gate 		return (ENODEV);
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate 	if (ds->mode == MD_FIND_INVDID) {
9530Sstevel@tonic-gate 		cnt = md_validate_devid(ds->setno, ds->side, &ds->maxsz);
9540Sstevel@tonic-gate 		if (cnt == -1)
9550Sstevel@tonic-gate 			err = -1;
9560Sstevel@tonic-gate 		ds->cnt = cnt;
9570Sstevel@tonic-gate 	} else if (ds->mode == MD_GET_INVDID) {
9580Sstevel@tonic-gate 		if (md_get_invdid(ds->setno, ds->side, ds->cnt, ds->maxsz,
9590Sstevel@tonic-gate 		    (caddr_t)(uintptr_t)ds->ctdp) == -1) {
9600Sstevel@tonic-gate 			err = -1;
9610Sstevel@tonic-gate 		}
9620Sstevel@tonic-gate 	} else {
9630Sstevel@tonic-gate 		/* invalid mode */
9640Sstevel@tonic-gate 		err = EINVAL;
9650Sstevel@tonic-gate 	}
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 	return (err);
9680Sstevel@tonic-gate }
9690Sstevel@tonic-gate 
9700Sstevel@tonic-gate /*ARGSUSED*/
9710Sstevel@tonic-gate static int
getdid_ioctl(mdnm_params_t * nm,int mode)9720Sstevel@tonic-gate getdid_ioctl(
9730Sstevel@tonic-gate 	mdnm_params_t	*nm,
9740Sstevel@tonic-gate 	int		mode
9750Sstevel@tonic-gate )
9760Sstevel@tonic-gate {
9770Sstevel@tonic-gate 	int		err = 0;
9780Sstevel@tonic-gate 	ddi_devid_t	did = NULL;
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate 	mdclrerror(&nm->mde);
9810Sstevel@tonic-gate 
9820Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
9830Sstevel@tonic-gate 		return (0);
9840Sstevel@tonic-gate 
9850Sstevel@tonic-gate 	if (nm->setno >= md_nsets) {
9860Sstevel@tonic-gate 		return (EINVAL);
9870Sstevel@tonic-gate 	}
9880Sstevel@tonic-gate 
9890Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
9900Sstevel@tonic-gate 		return (ENODEV);
9910Sstevel@tonic-gate 
9920Sstevel@tonic-gate 	/*
9930Sstevel@tonic-gate 	 * Tell user that replica is not in devid mode
9940Sstevel@tonic-gate 	 */
9950Sstevel@tonic-gate 	if (!(((mddb_set_t *)md_set[nm->setno].s_db)->s_lbp->lb_flags
9960Sstevel@tonic-gate 	    & MDDB_DEVID_STYLE) && md_keep_repl_state) {
9970Sstevel@tonic-gate 		return (mdsyserror(&nm->mde, MDDB_F_NODEVID));
9980Sstevel@tonic-gate 	}
9990Sstevel@tonic-gate 
10000Sstevel@tonic-gate 	/*
10010Sstevel@tonic-gate 	 * If user is prepared to receive the devid allocate a kernel buffer.
10020Sstevel@tonic-gate 	 */
10030Sstevel@tonic-gate 	if (nm->devid_size != 0) {
10040Sstevel@tonic-gate 		/* check for bogus value of devid_size */
10050Sstevel@tonic-gate 		if (nm->devid_size > MAXPATHLEN) {
10060Sstevel@tonic-gate 			return (EINVAL);
10070Sstevel@tonic-gate 		}
10080Sstevel@tonic-gate 		did = kmem_alloc(nm->devid_size, KM_SLEEP);
10090Sstevel@tonic-gate 	}
10100Sstevel@tonic-gate 
10110Sstevel@tonic-gate 	err = md_getdevid(nm->setno, nm->side, nm->key, did, &nm->devid_size);
10120Sstevel@tonic-gate 
10130Sstevel@tonic-gate 	if (err) {
10140Sstevel@tonic-gate 		if (err < 0)
10150Sstevel@tonic-gate 			err = EINVAL;
10160Sstevel@tonic-gate 		goto out;
10170Sstevel@tonic-gate 	}
10180Sstevel@tonic-gate 
10190Sstevel@tonic-gate 	/*
10200Sstevel@tonic-gate 	 * If devid size was already known to user then give them the devid.
10210Sstevel@tonic-gate 	 */
10220Sstevel@tonic-gate 	if (did != NULL)
10230Sstevel@tonic-gate 		err = ddi_copyout(did,
10240Sstevel@tonic-gate 		    (caddr_t)(uintptr_t)nm->devid, nm->devid_size, mode);
10250Sstevel@tonic-gate 
10260Sstevel@tonic-gate out:
10270Sstevel@tonic-gate 	if (did != NULL)
10280Sstevel@tonic-gate 		kmem_free(did, nm->devid_size);
10290Sstevel@tonic-gate 	return (err);
10300Sstevel@tonic-gate }
10310Sstevel@tonic-gate 
10320Sstevel@tonic-gate int
mddb_setmaster_ioctl(mddb_setmaster_config_t * info)10330Sstevel@tonic-gate mddb_setmaster_ioctl(mddb_setmaster_config_t *info)
10340Sstevel@tonic-gate {
10350Sstevel@tonic-gate 	/* Verify that setno is in valid range */
10360Sstevel@tonic-gate 	if (info->c_setno >= md_nsets)
10370Sstevel@tonic-gate 		return (EINVAL);
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate 	/*
10400Sstevel@tonic-gate 	 * When adding the first disk to a MN diskset, the master
10410Sstevel@tonic-gate 	 * needs to be set (in order to write out the mddb)
10420Sstevel@tonic-gate 	 * before the set is snarfed or even before the set
10430Sstevel@tonic-gate 	 * is marked as a MNset in the md_set structure.
10440Sstevel@tonic-gate 	 * So, don't check for MNset or SNARFED and don't call
10450Sstevel@tonic-gate 	 * mddb_setenter. In order to discourage bad ioctl calls,
10460Sstevel@tonic-gate 	 * verify that magic field in structure is set correctly.
10470Sstevel@tonic-gate 	 */
10480Sstevel@tonic-gate 	if (info->c_magic != MDDB_SETMASTER_MAGIC)
10490Sstevel@tonic-gate 		return (EINVAL);
10500Sstevel@tonic-gate 
10510Sstevel@tonic-gate 	if (info->c_current_host_master)
10520Sstevel@tonic-gate 		md_set[info->c_setno].s_am_i_master = 1;
10530Sstevel@tonic-gate 	else
10540Sstevel@tonic-gate 		md_set[info->c_setno].s_am_i_master = 0;
10550Sstevel@tonic-gate 
10560Sstevel@tonic-gate 	return (0);
10570Sstevel@tonic-gate }
10580Sstevel@tonic-gate 
10590Sstevel@tonic-gate /*
10600Sstevel@tonic-gate  * Set the devid for the namespace record identified by the tuple
10610Sstevel@tonic-gate  * [setno, sideno, key]. The key is the namespace key. The md_getdevnum()
10620Sstevel@tonic-gate  * function is used to actually regenerate the devid.
10630Sstevel@tonic-gate  */
10640Sstevel@tonic-gate /*ARGSUSED*/
10650Sstevel@tonic-gate static int
setdid_ioctl(mdnm_params_t * nm,int mode)10660Sstevel@tonic-gate setdid_ioctl(
10670Sstevel@tonic-gate 	mdnm_params_t	*nm,
10680Sstevel@tonic-gate 	int		mode
10690Sstevel@tonic-gate )
10700Sstevel@tonic-gate {
10710Sstevel@tonic-gate 	dev_t		devt;
10720Sstevel@tonic-gate 
10730Sstevel@tonic-gate 	/*
10740Sstevel@tonic-gate 	 * If upgrading do not allow modification of the namespace.
10750Sstevel@tonic-gate 	 */
10760Sstevel@tonic-gate 	if (MD_UPGRADE)
10770Sstevel@tonic-gate 		return (EAGAIN);
10780Sstevel@tonic-gate 
10790Sstevel@tonic-gate 	mdclrerror(&nm->mde);
10800Sstevel@tonic-gate 
10810Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
10820Sstevel@tonic-gate 		return (0);
10830Sstevel@tonic-gate 
10845428Spetede 	if (nm->setno >= md_nsets)
10855428Spetede 		return (EINVAL);
10865428Spetede 
10870Sstevel@tonic-gate 	if (MD_MNSET_SETNO(nm->setno))
10880Sstevel@tonic-gate 		return (0);
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
10910Sstevel@tonic-gate 		return (ENODEV);
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 	devt = md_dev64_to_dev(
10940Sstevel@tonic-gate 	    md_getdevnum(nm->setno, nm->side, nm->key, MD_TRUST_DEVT));
10950Sstevel@tonic-gate 
10960Sstevel@tonic-gate 	if (devt == NODEV)
10970Sstevel@tonic-gate 		return (ENODEV);
10980Sstevel@tonic-gate 
10990Sstevel@tonic-gate 	return (0);
11000Sstevel@tonic-gate }
11010Sstevel@tonic-gate 
11020Sstevel@tonic-gate /*ARGSUSED*/
11030Sstevel@tonic-gate static int
getdidmin_ioctl(mdnm_params_t * nm,int mode)11040Sstevel@tonic-gate getdidmin_ioctl(
11050Sstevel@tonic-gate 	mdnm_params_t   *nm,
11060Sstevel@tonic-gate 	int		mode
11070Sstevel@tonic-gate )
11080Sstevel@tonic-gate {
11090Sstevel@tonic-gate 	int	err = 0;
11100Sstevel@tonic-gate 	char	*minorname = NULL;
11110Sstevel@tonic-gate 
11120Sstevel@tonic-gate 	mdclrerror(&nm->mde);
11130Sstevel@tonic-gate 
11140Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
11150Sstevel@tonic-gate 		return (0);
11160Sstevel@tonic-gate 
11175428Spetede 	if (nm->setno >= md_nsets)
11185428Spetede 		return (EINVAL);
11195428Spetede 
11200Sstevel@tonic-gate 	if (MD_MNSET_SETNO(nm->setno))
11210Sstevel@tonic-gate 		return (0);
11220Sstevel@tonic-gate 
11230Sstevel@tonic-gate 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
11240Sstevel@tonic-gate 		return (ENODEV);
11250Sstevel@tonic-gate 
11260Sstevel@tonic-gate 	minorname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate 	if (nm->side == -1) {
11290Sstevel@tonic-gate 		err = EINVAL;
11300Sstevel@tonic-gate 		goto out;
11310Sstevel@tonic-gate 	}
11320Sstevel@tonic-gate 
11330Sstevel@tonic-gate 	err = md_getdevidminor(nm->setno, nm->side, nm->key, minorname,
11340Sstevel@tonic-gate 	    MAXPATHLEN);
11350Sstevel@tonic-gate 
11360Sstevel@tonic-gate 	if (err) {
11370Sstevel@tonic-gate 		if (err < 0)
11380Sstevel@tonic-gate 			err = EINVAL;
11390Sstevel@tonic-gate 		goto out;
11400Sstevel@tonic-gate 	}
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate 	err = ddi_copyout(minorname, (caddr_t)(uintptr_t)nm->minorname,
11430Sstevel@tonic-gate 	    strlen(minorname) + 1, mode);
11440Sstevel@tonic-gate 
11450Sstevel@tonic-gate out:
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate 	kmem_free(minorname, MAXPATHLEN);
11480Sstevel@tonic-gate 	return (err);
11490Sstevel@tonic-gate }
11500Sstevel@tonic-gate 
11510Sstevel@tonic-gate static int
mddb_userreq_ioctl(mddb_userreq_t * ur,int mode)11520Sstevel@tonic-gate mddb_userreq_ioctl(mddb_userreq_t *ur, int mode)
11530Sstevel@tonic-gate {
11540Sstevel@tonic-gate 	void			*data;
11550Sstevel@tonic-gate 	int			status;
11560Sstevel@tonic-gate 	mddb_recid_t		*recids;
11570Sstevel@tonic-gate 	int			flags;
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate 	if (ur->ur_setno >= md_nsets)
11600Sstevel@tonic-gate 		return (EINVAL);
11610Sstevel@tonic-gate 
11620Sstevel@tonic-gate 	mdclrerror(&ur->ur_mde);
11630Sstevel@tonic-gate 
11640Sstevel@tonic-gate 	if (md_snarf_db_set(MD_LOCAL_SET, &ur->ur_mde) != 0)
11650Sstevel@tonic-gate 		return (0);
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate 	if ((md_get_setstatus(ur->ur_setno) & MD_SET_SNARFED) == 0)
11680Sstevel@tonic-gate 		return (ENODEV);
11690Sstevel@tonic-gate 
11700Sstevel@tonic-gate 	switch (ur->ur_cmd) {
11710Sstevel@tonic-gate 	case MD_DB_GETNEXTREC:
11720Sstevel@tonic-gate 		if (ur->ur_recid == 0)
11730Sstevel@tonic-gate 			ur->ur_recid = mddb_makerecid(ur->ur_setno, 0);
11740Sstevel@tonic-gate 		/*
11750Sstevel@tonic-gate 		 * Is ur_recid a valid one ?
11760Sstevel@tonic-gate 		 */
11770Sstevel@tonic-gate 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
11780Sstevel@tonic-gate 			return (EINVAL);
11790Sstevel@tonic-gate 
11800Sstevel@tonic-gate 		ur->ur_recid = mddb_getnextrec(ur->ur_recid, ur->ur_type,
11810Sstevel@tonic-gate 		    ur->ur_type2);
11820Sstevel@tonic-gate 		if (ur->ur_recid > 0) {
11830Sstevel@tonic-gate 			ur->ur_type = mddb_getrectype1(ur->ur_recid);
11840Sstevel@tonic-gate 			ur->ur_type2 = mddb_getrectype2(ur->ur_recid);
11850Sstevel@tonic-gate 			ur->ur_recstat = mddb_getrecstatus(ur->ur_recid);
11860Sstevel@tonic-gate 		}
11870Sstevel@tonic-gate 		break;
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 	case MD_DB_COMMIT_ONE:
11900Sstevel@tonic-gate 		/*
11910Sstevel@tonic-gate 		 * Is ur_recid a valid one?
11920Sstevel@tonic-gate 		 */
11930Sstevel@tonic-gate 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
11940Sstevel@tonic-gate 			return (EINVAL);
11950Sstevel@tonic-gate 
11960Sstevel@tonic-gate 		ur->ur_recstat = mddb_getrecstatus(ur->ur_recid);
11970Sstevel@tonic-gate 		if (ur->ur_recstat == MDDB_NORECORD)
11980Sstevel@tonic-gate 			return (ENXIO);
11990Sstevel@tonic-gate 		status = mddb_commitrec(ur->ur_recid);
12000Sstevel@tonic-gate 		/*
12010Sstevel@tonic-gate 		 * For MN sets we panic if there are too few database replicas
12020Sstevel@tonic-gate 		 * and we're attempting to add entries to the log.
12030Sstevel@tonic-gate 		 */
12040Sstevel@tonic-gate 		if (status != 0) {
12050Sstevel@tonic-gate 			if ((MD_MNSET_SETNO(ur->ur_setno) &&
12060Sstevel@tonic-gate 			    (ur->ur_type2 == MDDB_UR_LR)) &&
12070Sstevel@tonic-gate 			    (md_get_setstatus(ur->ur_setno) & MD_SET_TOOFEW)) {
12080Sstevel@tonic-gate 				cmn_err(CE_PANIC,
12090Sstevel@tonic-gate 				    "md: Panic due to lack of DiskSuite state\n"
12100Sstevel@tonic-gate 				    " database replicas. Fewer than 50%% of "
12110Sstevel@tonic-gate 				    "the total were available,\n so panic to "
12120Sstevel@tonic-gate 				    "ensure data integrity.");
12130Sstevel@tonic-gate 			}
12140Sstevel@tonic-gate 			return (mddbstatus2error(&ur->ur_mde, status, NODEV32,
12150Sstevel@tonic-gate 			    ur->ur_setno));
12160Sstevel@tonic-gate 		}
12170Sstevel@tonic-gate 		break;
12180Sstevel@tonic-gate 
12190Sstevel@tonic-gate 	case MD_DB_COMMIT_MANY:
12200Sstevel@tonic-gate 		if (ur->ur_size <= 0)
12210Sstevel@tonic-gate 			return (EINVAL);
12220Sstevel@tonic-gate 
12230Sstevel@tonic-gate 		data = kmem_alloc(ur->ur_size, KM_SLEEP);
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 		if (ddi_copyin((caddr_t)(uintptr_t)ur->ur_data, data,
12260Sstevel@tonic-gate 		    (size_t)ur->ur_size, mode)) {
12270Sstevel@tonic-gate 			kmem_free(data, ur->ur_size);
12280Sstevel@tonic-gate 			return (EFAULT);
12290Sstevel@tonic-gate 		}
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate 		recids = (mddb_recid_t *)data;
12320Sstevel@tonic-gate 		while (*recids != 0) {
12330Sstevel@tonic-gate 			/*
12340Sstevel@tonic-gate 			 * Is recid a valid ?
12350Sstevel@tonic-gate 			 */
12360Sstevel@tonic-gate 			if (DBSET(*recids) < 0 || DBSET(*recids) >= md_nsets) {
12370Sstevel@tonic-gate 				kmem_free(data, ur->ur_size);
12380Sstevel@tonic-gate 				return (EINVAL);
12390Sstevel@tonic-gate 			}
12400Sstevel@tonic-gate 			ur->ur_recstat = mddb_getrecstatus(*recids++);
12410Sstevel@tonic-gate 			if (ur->ur_recstat == MDDB_NORECORD) {
12420Sstevel@tonic-gate 				kmem_free(data, ur->ur_size);
12430Sstevel@tonic-gate 				return (ENXIO);
12440Sstevel@tonic-gate 			}
12450Sstevel@tonic-gate 		}
12460Sstevel@tonic-gate 		status = mddb_commitrecs(data);
12470Sstevel@tonic-gate 		kmem_free(data, ur->ur_size);
12480Sstevel@tonic-gate 		/*
12490Sstevel@tonic-gate 		 * For MN sets we panic if there are too few database replicas
12500Sstevel@tonic-gate 		 * and we're attempting to add entries to the log.
12510Sstevel@tonic-gate 		 */
12520Sstevel@tonic-gate 		if (status != 0) {
12530Sstevel@tonic-gate 			if ((MD_MNSET_SETNO(ur->ur_setno) &&
12540Sstevel@tonic-gate 			    (ur->ur_type2 == MDDB_UR_LR)) &&
12550Sstevel@tonic-gate 			    (md_get_setstatus(ur->ur_setno) & MD_SET_TOOFEW)) {
12560Sstevel@tonic-gate 				cmn_err(CE_PANIC,
12570Sstevel@tonic-gate 				    "md: Panic due to lack of DiskSuite state\n"
12580Sstevel@tonic-gate 				    " database replicas. Fewer than 50%% of "
12590Sstevel@tonic-gate 				    "the total were available,\n so panic to "
12600Sstevel@tonic-gate 				    "ensure data integrity.");
12610Sstevel@tonic-gate 			}
12620Sstevel@tonic-gate 			return (mddbstatus2error(&ur->ur_mde, status, NODEV32,
12630Sstevel@tonic-gate 			    ur->ur_setno));
12640Sstevel@tonic-gate 		}
12650Sstevel@tonic-gate 		break;
12660Sstevel@tonic-gate 
12670Sstevel@tonic-gate 	case MD_DB_GETDATA:
12680Sstevel@tonic-gate 		/*
12690Sstevel@tonic-gate 		 * Check ur_recid
12700Sstevel@tonic-gate 		 */
12710Sstevel@tonic-gate 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
12720Sstevel@tonic-gate 			return (EINVAL);
12730Sstevel@tonic-gate 
12740Sstevel@tonic-gate 		ur->ur_recstat = mddb_getrecstatus(ur->ur_recid);
12750Sstevel@tonic-gate 		if (ur->ur_recstat == MDDB_NORECORD ||
12760Sstevel@tonic-gate 		    ur->ur_recstat == MDDB_NODATA)
12770Sstevel@tonic-gate 			return (ENXIO);
12780Sstevel@tonic-gate 
12790Sstevel@tonic-gate 		if (ur->ur_size > mddb_getrecsize(ur->ur_recid))
12800Sstevel@tonic-gate 			return (EINVAL);
12810Sstevel@tonic-gate 
12820Sstevel@tonic-gate 		data = mddb_getrecaddr(ur->ur_recid);
12830Sstevel@tonic-gate 		if (ddi_copyout(data, (caddr_t)(uintptr_t)ur->ur_data,
12840Sstevel@tonic-gate 		    (size_t)ur->ur_size, mode)) {
12850Sstevel@tonic-gate 			return (EFAULT);
12860Sstevel@tonic-gate 		}
12870Sstevel@tonic-gate 		break;
12880Sstevel@tonic-gate 
12890Sstevel@tonic-gate 	case MD_DB_SETDATA:
12900Sstevel@tonic-gate 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
12910Sstevel@tonic-gate 			return (EINVAL);
12920Sstevel@tonic-gate 
12930Sstevel@tonic-gate 		ur->ur_recstat = mddb_getrecstatus(ur->ur_recid);
12940Sstevel@tonic-gate 		if (ur->ur_recstat == MDDB_NORECORD)
12950Sstevel@tonic-gate 			return (ENXIO);
12960Sstevel@tonic-gate 
12970Sstevel@tonic-gate 		if (ur->ur_size > mddb_getrecsize(ur->ur_recid))
12980Sstevel@tonic-gate 			return (EINVAL);
12990Sstevel@tonic-gate 
13000Sstevel@tonic-gate 		data = mddb_getrecaddr(ur->ur_recid);
13010Sstevel@tonic-gate 		if (ddi_copyin((caddr_t)(uintptr_t)ur->ur_data, data,
13020Sstevel@tonic-gate 		    (size_t)ur->ur_size, mode)) {
13030Sstevel@tonic-gate 			return (EFAULT);
13040Sstevel@tonic-gate 		}
13050Sstevel@tonic-gate 		break;
13060Sstevel@tonic-gate 
13070Sstevel@tonic-gate 	case MD_DB_DELETE:
13080Sstevel@tonic-gate 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
13090Sstevel@tonic-gate 			return (EINVAL);
13100Sstevel@tonic-gate 
13110Sstevel@tonic-gate 		ur->ur_recstat = mddb_getrecstatus(ur->ur_recid);
13120Sstevel@tonic-gate 		if (ur->ur_recstat == MDDB_NORECORD)
13130Sstevel@tonic-gate 			return (ENXIO);
13140Sstevel@tonic-gate 		status = mddb_deleterec(ur->ur_recid);
13150Sstevel@tonic-gate 		if (status < 0)
13160Sstevel@tonic-gate 			return (mddbstatus2error(&ur->ur_mde, status, NODEV32,
13170Sstevel@tonic-gate 			    ur->ur_setno));
13180Sstevel@tonic-gate 		break;
13190Sstevel@tonic-gate 
13200Sstevel@tonic-gate 	case MD_DB_CREATE:
13210Sstevel@tonic-gate 	{
13220Sstevel@tonic-gate 		int	mn_set = 0;
13230Sstevel@tonic-gate 
13240Sstevel@tonic-gate 		if (md_get_setstatus(ur->ur_setno) & MD_SET_MNSET)
13250Sstevel@tonic-gate 			mn_set = 1;
13260Sstevel@tonic-gate 
13270Sstevel@tonic-gate 		if (ur->ur_setno >= md_nsets)
13280Sstevel@tonic-gate 			return (EINVAL);
13290Sstevel@tonic-gate 		if ((mn_set) && (ur->ur_type2 == MDDB_UR_LR))
13300Sstevel@tonic-gate 			flags = MD_CRO_32BIT | MD_CRO_CHANGELOG;
13310Sstevel@tonic-gate 		else
13320Sstevel@tonic-gate 			flags = MD_CRO_32BIT;
13330Sstevel@tonic-gate 		ur->ur_recid = mddb_createrec(ur->ur_size, ur->ur_type,
13340Sstevel@tonic-gate 		    ur->ur_type2, flags, ur->ur_setno);
13350Sstevel@tonic-gate 		if (ur->ur_recid < 0)
13360Sstevel@tonic-gate 			return (mddbstatus2error(&ur->ur_mde, ur->ur_recid,
13370Sstevel@tonic-gate 			    NODEV32, ur->ur_setno));
13380Sstevel@tonic-gate 		break;
13390Sstevel@tonic-gate 	}
13400Sstevel@tonic-gate 
13410Sstevel@tonic-gate 	case MD_DB_GETSTATUS:
13420Sstevel@tonic-gate 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
13430Sstevel@tonic-gate 			return (EINVAL);
13440Sstevel@tonic-gate 		ur->ur_recstat = mddb_getrecstatus(ur->ur_recid);
13450Sstevel@tonic-gate 		break;
13460Sstevel@tonic-gate 
13470Sstevel@tonic-gate 	case MD_DB_GETSIZE:
13480Sstevel@tonic-gate 		if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets)
13490Sstevel@tonic-gate 			return (EINVAL);
13500Sstevel@tonic-gate 		ur->ur_size = mddb_getrecsize(ur->ur_recid);
13510Sstevel@tonic-gate 		break;
13520Sstevel@tonic-gate 
13530Sstevel@tonic-gate 	case MD_DB_MAKEID:
13540Sstevel@tonic-gate 		if (ur->ur_setno >= md_nsets)
13550Sstevel@tonic-gate 			return (EINVAL);
13560Sstevel@tonic-gate 		ur->ur_recid = mddb_makerecid(ur->ur_setno, ur->ur_recid);
13570Sstevel@tonic-gate 		break;
13580Sstevel@tonic-gate 
13590Sstevel@tonic-gate 	default:
13600Sstevel@tonic-gate 		return (EINVAL);
13610Sstevel@tonic-gate 	}
13620Sstevel@tonic-gate 	return (0);
13630Sstevel@tonic-gate }
13640Sstevel@tonic-gate 
13650Sstevel@tonic-gate static int
setuserflags(md_set_userflags_t * msu,IOLOCK * lock)13660Sstevel@tonic-gate setuserflags(
13670Sstevel@tonic-gate 	md_set_userflags_t	*msu,
13680Sstevel@tonic-gate 	IOLOCK			*lock
13690Sstevel@tonic-gate )
13700Sstevel@tonic-gate {
13710Sstevel@tonic-gate 	minor_t			mnum = msu->mnum;
13720Sstevel@tonic-gate 	set_t			setno = MD_MIN2SET(mnum);
13730Sstevel@tonic-gate 	md_unit_t		*un;
13740Sstevel@tonic-gate 	mdi_unit_t		*ui;
13750Sstevel@tonic-gate 
13760Sstevel@tonic-gate 	mdclrerror(&msu->mde);
13770Sstevel@tonic-gate 
13780Sstevel@tonic-gate 	if (md_get_setstatus(setno) & MD_SET_STALE)
13790Sstevel@tonic-gate 		return (mdmddberror(&msu->mde, MDE_DB_STALE, mnum, setno));
13800Sstevel@tonic-gate 
13810Sstevel@tonic-gate 	if ((ui = MDI_UNIT(mnum)) == NULL) {
13820Sstevel@tonic-gate 		return (mdmderror(&msu->mde, MDE_UNIT_NOT_SETUP, mnum));
13830Sstevel@tonic-gate 	}
13840Sstevel@tonic-gate 
13850Sstevel@tonic-gate 	un = (md_unit_t *)md_ioctl_writerlock(lock, ui);
13860Sstevel@tonic-gate 
13870Sstevel@tonic-gate 	un->c.un_user_flags = msu->userflags;
13880Sstevel@tonic-gate 	mddb_commitrec_wrapper(un->c.un_record_id);
13890Sstevel@tonic-gate 
13900Sstevel@tonic-gate 	return (0);
13910Sstevel@tonic-gate }
13920Sstevel@tonic-gate 
13930Sstevel@tonic-gate /*
13940Sstevel@tonic-gate  * mddb_didstat_from_user -- called for DIDSTAT ioctl. 2 different calling
13950Sstevel@tonic-gate  * 	scenarios.
13960Sstevel@tonic-gate  * 	1) data->mode == MD_FIND_INVDID
13970Sstevel@tonic-gate  *	   when user is inquiring about the existence of invalid device id's.
13980Sstevel@tonic-gate  *	   Upon return to the user d->cnt may have a value in it.
13990Sstevel@tonic-gate  *	2) data->mode == MD_GET_INVDID
14000Sstevel@tonic-gate  *	   when the user wants a list of the invalid device id's.
14010Sstevel@tonic-gate  *	   In this case d->ctdp is non Null and cnt has	a value in it.
14020Sstevel@tonic-gate  *
14030Sstevel@tonic-gate  * Basically this routine along with mddb_didstat_to_user can be eliminated
14040Sstevel@tonic-gate  * by pushing ddi_copyout down to lower level interfaces.  To minimize impact
14050Sstevel@tonic-gate  * just keep the current implementation intact.
14060Sstevel@tonic-gate  */
14070Sstevel@tonic-gate static int
mddb_didstat_from_user(void ** d,caddr_t data,int mode,caddr_t * ds_ctd_addr)14080Sstevel@tonic-gate mddb_didstat_from_user(
14090Sstevel@tonic-gate 	void		**d,
14100Sstevel@tonic-gate 	caddr_t		data,
14110Sstevel@tonic-gate 	int		mode,
14120Sstevel@tonic-gate 	caddr_t		*ds_ctd_addr
14130Sstevel@tonic-gate )
14140Sstevel@tonic-gate {
14150Sstevel@tonic-gate 	size_t		sz1 = 0, sz2 = 0;
14160Sstevel@tonic-gate 	md_i_didstat_t	*d1;
14170Sstevel@tonic-gate 	void		*d2;
14180Sstevel@tonic-gate 	*ds_ctd_addr	= 0;
14190Sstevel@tonic-gate 
14200Sstevel@tonic-gate 	sz1 = sizeof (md_i_didstat_t);
14210Sstevel@tonic-gate 	d1 = (md_i_didstat_t *)kmem_zalloc(sz1, KM_SLEEP);
14220Sstevel@tonic-gate 
14230Sstevel@tonic-gate 	if (ddi_copyin(data, (void *)d1, sz1, mode) != 0) {
14240Sstevel@tonic-gate 		kmem_free((void *)d1, sz1);
14250Sstevel@tonic-gate 		return (EFAULT);
14260Sstevel@tonic-gate 	}
14270Sstevel@tonic-gate 
14280Sstevel@tonic-gate 	/*
14290Sstevel@tonic-gate 	 * ds_ctd_addr has actual user ctdp
14300Sstevel@tonic-gate 	 */
14310Sstevel@tonic-gate 	*ds_ctd_addr = (caddr_t)(uintptr_t)d1->ctdp;
14320Sstevel@tonic-gate 	if (d1->mode == MD_GET_INVDID) {
14330Sstevel@tonic-gate 		sz2 = (d1->cnt * d1->maxsz) + 1;
14340Sstevel@tonic-gate 		if (sz2 <= 0) {
14350Sstevel@tonic-gate 			kmem_free(d1, sz1);
14360Sstevel@tonic-gate 			return (EINVAL);
14370Sstevel@tonic-gate 		}
14380Sstevel@tonic-gate 		d2 = kmem_zalloc(sz2, KM_SLEEP);
14390Sstevel@tonic-gate 		d1->ctdp = (uint64_t)(uintptr_t)d2;
14400Sstevel@tonic-gate 	} else if (d1->mode != MD_FIND_INVDID) {
14410Sstevel@tonic-gate 		kmem_free(d1, sz1);
14420Sstevel@tonic-gate 		return (EINVAL);
14430Sstevel@tonic-gate 	}
14440Sstevel@tonic-gate 	*d = (void *)d1;
14450Sstevel@tonic-gate 	return (0);
14460Sstevel@tonic-gate }
14470Sstevel@tonic-gate 
14480Sstevel@tonic-gate /*
14490Sstevel@tonic-gate  * mddb_didstat_to_user -- see comment for mddb_didstat_from_user. In this
14500Sstevel@tonic-gate  * 		case d->cnt could have a value in it for either usage of
14510Sstevel@tonic-gate  *		the ioctl.
14520Sstevel@tonic-gate  */
14530Sstevel@tonic-gate /*ARGSUSED*/
14540Sstevel@tonic-gate static int
mddb_didstat_to_user(void * d,caddr_t data,int mode,caddr_t ds_ctd_addr)14550Sstevel@tonic-gate mddb_didstat_to_user(
14560Sstevel@tonic-gate 	void 		*d,
14570Sstevel@tonic-gate 	caddr_t		data,
14580Sstevel@tonic-gate 	int		mode,
14590Sstevel@tonic-gate 	caddr_t		ds_ctd_addr
14600Sstevel@tonic-gate )
14610Sstevel@tonic-gate {
14620Sstevel@tonic-gate 	size_t		sz1 = 0, sz2 = 0;
14630Sstevel@tonic-gate 	md_i_didstat_t		*d1;
14640Sstevel@tonic-gate 	void			*d2;
14650Sstevel@tonic-gate 
14660Sstevel@tonic-gate 
14670Sstevel@tonic-gate 	d1 = (md_i_didstat_t *)d;
14680Sstevel@tonic-gate 	sz1 = sizeof (md_i_didstat_t);
14690Sstevel@tonic-gate 
14700Sstevel@tonic-gate 	sz2 = (d1->cnt * d1->maxsz) + 1;
14710Sstevel@tonic-gate 	d2 = (caddr_t)(uintptr_t)d1->ctdp;
14720Sstevel@tonic-gate 	if (d2 && sz2) {
14730Sstevel@tonic-gate 		/*
14740Sstevel@tonic-gate 		 * Copy out from kernel ctdp to user ctdp area
14750Sstevel@tonic-gate 		 */
14760Sstevel@tonic-gate 		if (ddi_copyout(d2, (caddr_t)ds_ctd_addr, sz2, mode) != 0) {
14770Sstevel@tonic-gate 			kmem_free(d1, sz1);
14780Sstevel@tonic-gate 			kmem_free(d2, sz2);
14790Sstevel@tonic-gate 			return (EFAULT);
14800Sstevel@tonic-gate 		}
14810Sstevel@tonic-gate 		d1->ctdp = (uint64_t)(uintptr_t)ds_ctd_addr;
14820Sstevel@tonic-gate 	}
14830Sstevel@tonic-gate 	if (ddi_copyout(d1, data, sz1, mode) != 0) {
14840Sstevel@tonic-gate 		kmem_free(d1, sz1);
14850Sstevel@tonic-gate 		if (sz2 && d2)
14860Sstevel@tonic-gate 			kmem_free(d2, sz2);
14870Sstevel@tonic-gate 		return (EFAULT);
14880Sstevel@tonic-gate 	}
14890Sstevel@tonic-gate 	kmem_free(d1, sz1);
14900Sstevel@tonic-gate 	if (sz2 && d2)
14910Sstevel@tonic-gate 		kmem_free(d2, sz2);
14920Sstevel@tonic-gate 	return (0);
14930Sstevel@tonic-gate }
14940Sstevel@tonic-gate 
14950Sstevel@tonic-gate 
14960Sstevel@tonic-gate static int
mddb_config_from_user(void ** d,caddr_t data,int mode,caddr_t * c_devid_addr,caddr_t * c_old_devid_addr)14970Sstevel@tonic-gate mddb_config_from_user(
14980Sstevel@tonic-gate 	void 		**d,
14990Sstevel@tonic-gate 	caddr_t 	data,
15000Sstevel@tonic-gate 	int 		mode,
15010Sstevel@tonic-gate 	caddr_t 	*c_devid_addr,
15020Sstevel@tonic-gate 	caddr_t		*c_old_devid_addr
15030Sstevel@tonic-gate )
15040Sstevel@tonic-gate {
15050Sstevel@tonic-gate 	size_t		sz1 = 0, sz2 = 0, sz3 = 0;
15060Sstevel@tonic-gate 	mddb_config_t	*d1;
15070Sstevel@tonic-gate 	void		*d2;
15080Sstevel@tonic-gate 	void 		*d3;
15090Sstevel@tonic-gate 
15100Sstevel@tonic-gate 	*c_devid_addr = 0;
15110Sstevel@tonic-gate 
15120Sstevel@tonic-gate 	sz1 = sizeof (mddb_config_t);
15130Sstevel@tonic-gate 	d1 = (mddb_config_t *)kmem_zalloc(sz1, KM_SLEEP);
15140Sstevel@tonic-gate 
15150Sstevel@tonic-gate 	if (ddi_copyin(data, (void *)d1, sz1, mode) != 0) {
15160Sstevel@tonic-gate 		kmem_free((void *)d1, sz1);
15170Sstevel@tonic-gate 		return (EFAULT);
15180Sstevel@tonic-gate 	}
15190Sstevel@tonic-gate 	*c_devid_addr = (caddr_t)(uintptr_t)d1->c_locator.l_devid;
15200Sstevel@tonic-gate 
15210Sstevel@tonic-gate 	if (d1->c_locator.l_devid_flags & MDDB_DEVID_SPACE) {
15220Sstevel@tonic-gate 		sz2 = d1->c_locator.l_devid_sz;
15230Sstevel@tonic-gate 		if (d1->c_locator.l_devid_sz <= 0 ||
15245428Spetede 		    d1->c_locator.l_devid_sz > MAXPATHLEN) {
15255428Spetede 			kmem_free((void *)d1, sz1);
15265428Spetede 			return (EINVAL);
15270Sstevel@tonic-gate 		}
15280Sstevel@tonic-gate 		d2 = kmem_zalloc(sz2, KM_SLEEP);
15290Sstevel@tonic-gate 		if (ddi_copyin((caddr_t)(uintptr_t)d1->c_locator.l_devid,
15300Sstevel@tonic-gate 		    d2, sz2, mode) != 0) {
15310Sstevel@tonic-gate 			kmem_free(d1, sz1);
15320Sstevel@tonic-gate 			kmem_free(d2, sz2);
15330Sstevel@tonic-gate 			return (EFAULT);
15340Sstevel@tonic-gate 		}
15350Sstevel@tonic-gate 		d1->c_locator.l_devid = (uint64_t)(uintptr_t)d2;
15360Sstevel@tonic-gate 
153762Sjeanm 		if ((caddr_t)(uintptr_t)d1->c_locator.l_old_devid) {
153862Sjeanm 			*c_old_devid_addr = (caddr_t)(uintptr_t)
153962Sjeanm 			    d1->c_locator.l_old_devid;
15400Sstevel@tonic-gate 
15410Sstevel@tonic-gate 			sz3 = d1->c_locator.l_old_devid_sz;
15420Sstevel@tonic-gate 			if (d1->c_locator.l_old_devid_sz <= 0 ||
15430Sstevel@tonic-gate 			    d1->c_locator.l_old_devid_sz > MAXPATHLEN) {
15440Sstevel@tonic-gate 				kmem_free((void *)d1, sz1);
15450Sstevel@tonic-gate 				kmem_free(d2, sz2);
15460Sstevel@tonic-gate 				return (EINVAL);
15470Sstevel@tonic-gate 			}
15480Sstevel@tonic-gate 			d3 = kmem_zalloc(sz3, KM_SLEEP);
154962Sjeanm 			if (ddi_copyin(
155062Sjeanm 			    (caddr_t)(uintptr_t)d1->c_locator.l_old_devid,
15510Sstevel@tonic-gate 			    d3, sz3, mode) != 0) {
15520Sstevel@tonic-gate 				kmem_free((void *)d1, sz1);
15530Sstevel@tonic-gate 				kmem_free(d2, sz2);
15540Sstevel@tonic-gate 				kmem_free(d3, sz3);
15550Sstevel@tonic-gate 				return (EFAULT);
15560Sstevel@tonic-gate 			}
155762Sjeanm 			d1->c_locator.l_old_devid = (uintptr_t)d3;
15580Sstevel@tonic-gate 		}
15590Sstevel@tonic-gate 	} else {
15600Sstevel@tonic-gate 		d1->c_locator.l_devid = (uint64_t)0;
15610Sstevel@tonic-gate 		d1->c_locator.l_old_devid = (uint64_t)0;
15620Sstevel@tonic-gate 	}
15630Sstevel@tonic-gate 
15640Sstevel@tonic-gate 	*d = (void *)d1;
15650Sstevel@tonic-gate 	return (0);
15660Sstevel@tonic-gate }
15670Sstevel@tonic-gate 
15680Sstevel@tonic-gate /*ARGSUSED*/
15690Sstevel@tonic-gate static int
mddb_config_to_user(void * d,caddr_t data,int mode,caddr_t c_devid_addr,caddr_t c_old_devid_addr)15700Sstevel@tonic-gate mddb_config_to_user(
15710Sstevel@tonic-gate 	void 		*d,
15720Sstevel@tonic-gate 	caddr_t 	data,
15730Sstevel@tonic-gate 	int 		mode,
15740Sstevel@tonic-gate 	caddr_t 	c_devid_addr,
15750Sstevel@tonic-gate 	caddr_t		c_old_devid_addr
15760Sstevel@tonic-gate )
15770Sstevel@tonic-gate {
15780Sstevel@tonic-gate 	size_t		sz1 = 0, sz2 = 0, sz3 = 0;
15790Sstevel@tonic-gate 	mddb_config_t		*d1;
15800Sstevel@tonic-gate 	void			*d2;
15810Sstevel@tonic-gate 	void			*d3;
15820Sstevel@tonic-gate 
15830Sstevel@tonic-gate 	d1 = (mddb_config_t *)d;
15840Sstevel@tonic-gate 	sz1 = sizeof (mddb_config_t);
15850Sstevel@tonic-gate 
15860Sstevel@tonic-gate 	if (d1->c_locator.l_devid_flags & MDDB_DEVID_SPACE) {
15870Sstevel@tonic-gate 		sz2 = d1->c_locator.l_devid_sz;
15880Sstevel@tonic-gate 		d2 = (caddr_t)(uintptr_t)d1->c_locator.l_devid;
15890Sstevel@tonic-gate 		/* Only copyout devid if valid */
15900Sstevel@tonic-gate 		if (d1->c_locator.l_devid_flags & MDDB_DEVID_VALID) {
15910Sstevel@tonic-gate 			if (ddi_copyout(d2, (caddr_t)c_devid_addr,
15920Sstevel@tonic-gate 			    sz2, mode) != 0) {
15930Sstevel@tonic-gate 				kmem_free(d1, sz1);
15940Sstevel@tonic-gate 				kmem_free(d2, sz2);
15950Sstevel@tonic-gate 				return (EFAULT);
15960Sstevel@tonic-gate 			}
15970Sstevel@tonic-gate 		}
15980Sstevel@tonic-gate 	}
15990Sstevel@tonic-gate 
16000Sstevel@tonic-gate 	d1->c_locator.l_devid = (uint64_t)(uintptr_t)c_devid_addr;
16010Sstevel@tonic-gate 
16020Sstevel@tonic-gate 	if (d1->c_locator.l_old_devid) {
16030Sstevel@tonic-gate 		sz3 = d1->c_locator.l_old_devid_sz;
160462Sjeanm 		d3 = (caddr_t)(uintptr_t)d1->c_locator.l_old_devid;
16050Sstevel@tonic-gate 		if (ddi_copyout(d3, (caddr_t)c_old_devid_addr,
16060Sstevel@tonic-gate 		    sz3, mode) != 0) {
16070Sstevel@tonic-gate 			kmem_free(d1, sz1);
16080Sstevel@tonic-gate 			kmem_free(d2, sz2);
16090Sstevel@tonic-gate 			kmem_free(d3, sz3);
16100Sstevel@tonic-gate 		}
16110Sstevel@tonic-gate 	}
161262Sjeanm 	d1->c_locator.l_old_devid = (uintptr_t)c_old_devid_addr;
16130Sstevel@tonic-gate 
16140Sstevel@tonic-gate 	if (ddi_copyout(d1, data, sz1, mode) != 0) {
16150Sstevel@tonic-gate 		kmem_free(d1, sz1);
16160Sstevel@tonic-gate 		if (sz2)
16170Sstevel@tonic-gate 			kmem_free(d2, sz2);
16180Sstevel@tonic-gate 		if (sz3)
16190Sstevel@tonic-gate 			kmem_free(d3, sz3);
16200Sstevel@tonic-gate 		return (EFAULT);
16210Sstevel@tonic-gate 	}
16220Sstevel@tonic-gate 
16230Sstevel@tonic-gate 	if (d1)
16240Sstevel@tonic-gate 		kmem_free(d1, sz1);
16250Sstevel@tonic-gate 	if (sz2)
16260Sstevel@tonic-gate 		kmem_free(d2, sz2);
16270Sstevel@tonic-gate 	if (sz3)
16280Sstevel@tonic-gate 		kmem_free(d3, sz3);
16290Sstevel@tonic-gate 
16300Sstevel@tonic-gate 	return (0);
16310Sstevel@tonic-gate }
16320Sstevel@tonic-gate 
16330Sstevel@tonic-gate /*
16340Sstevel@tonic-gate  * NAME:	get_tstate
16350Sstevel@tonic-gate  * PURPOSE:	Return unit's transient error state to user.
16360Sstevel@tonic-gate  * INPUT:	device node (set + metadevice number)
16370Sstevel@tonic-gate  * OUTPUT:	gu->tstate
16380Sstevel@tonic-gate  * RETURNS:	0 on success
16390Sstevel@tonic-gate  *		EINVAL on failure
16400Sstevel@tonic-gate  */
16410Sstevel@tonic-gate static int
get_tstate(md_i_get_tstate_t * gu,IOLOCK * lock)16420Sstevel@tonic-gate get_tstate(md_i_get_tstate_t *gu, IOLOCK *lock)
16430Sstevel@tonic-gate {
16440Sstevel@tonic-gate 	mdi_unit_t	*ui;
16450Sstevel@tonic-gate 
16465428Spetede 	ui = MDI_UNIT(gu->id);
16475428Spetede 	if (ui == (mdi_unit_t *)NULL) {
16485428Spetede 		(void) mdmderror(&gu->mde, MDE_UNIT_NOT_SETUP, gu->id);
16490Sstevel@tonic-gate 		return (EINVAL);
16500Sstevel@tonic-gate 	}
16510Sstevel@tonic-gate 
16520Sstevel@tonic-gate 	(void) md_ioctl_readerlock(lock, ui);
16530Sstevel@tonic-gate 	gu->tstate = ui->ui_tstate;
16540Sstevel@tonic-gate 	md_ioctl_readerexit(lock);
16550Sstevel@tonic-gate 
16560Sstevel@tonic-gate 	return (0);
16570Sstevel@tonic-gate }
16580Sstevel@tonic-gate 
16590Sstevel@tonic-gate /*
16600Sstevel@tonic-gate  * NAME:	md_clu_ioctl
16610Sstevel@tonic-gate  * PURPOSE:	depending on clu_cmd:
16620Sstevel@tonic-gate  *		- Check open state,
16630Sstevel@tonic-gate  *		- lock opens and check open state
16640Sstevel@tonic-gate  *		- unlock opens again
16650Sstevel@tonic-gate  * INPUT:	metadevice and clu_cmd
16660Sstevel@tonic-gate  * OUTPUT:	open state (for MD_MN_LCU_UNLOCK always 0)
16670Sstevel@tonic-gate  * RETURNS:	0 on success
16680Sstevel@tonic-gate  *		EINVAL on failure
16690Sstevel@tonic-gate  */
16700Sstevel@tonic-gate int
md_clu_ioctl(md_clu_open_t * clu)16710Sstevel@tonic-gate md_clu_ioctl(md_clu_open_t *clu)
16720Sstevel@tonic-gate {
16730Sstevel@tonic-gate 	mdi_unit_t	*ui;
16740Sstevel@tonic-gate 	minor_t		mnum;
16750Sstevel@tonic-gate 
16760Sstevel@tonic-gate 	if ((clu->clu_dev <= 0) ||
16770Sstevel@tonic-gate 	    (md_getmajor(clu->clu_dev)) != md_major) {
16780Sstevel@tonic-gate 		return (EINVAL);
16790Sstevel@tonic-gate 	}
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate 	mnum = md_getminor(clu->clu_dev);
16820Sstevel@tonic-gate 	if ((ui = MDI_UNIT(mnum)) == NULL) {
16830Sstevel@tonic-gate 		return (mdmderror(&clu->clu_mde, MDE_UNIT_NOT_SETUP, mnum));
16840Sstevel@tonic-gate 	}
16855428Spetede 
16860Sstevel@tonic-gate 	switch (clu->clu_cmd) {
16870Sstevel@tonic-gate 	case MD_MN_LCU_CHECK:
16880Sstevel@tonic-gate 		/* No lock here, just checking */
16890Sstevel@tonic-gate 		clu->clu_isopen = md_unit_isopen(ui);
16900Sstevel@tonic-gate 		break;
16910Sstevel@tonic-gate 	case MD_MN_LCU_LOCK:
16920Sstevel@tonic-gate 		/* This inhibits later opens to succeed */
16930Sstevel@tonic-gate 		ui->ui_tstate |= MD_OPENLOCKED;
16940Sstevel@tonic-gate 		clu->clu_isopen = md_unit_isopen(ui);
16950Sstevel@tonic-gate 		/* In case the md is opened, reset the lock immediately */
16960Sstevel@tonic-gate 		if (clu->clu_isopen != 0) {
16970Sstevel@tonic-gate 			ui->ui_tstate &= ~MD_OPENLOCKED;
16980Sstevel@tonic-gate 		}
16990Sstevel@tonic-gate 		break;
17000Sstevel@tonic-gate 	case MD_MN_LCU_UNLOCK:
17010Sstevel@tonic-gate 		ui->ui_tstate &= ~MD_OPENLOCKED;
17020Sstevel@tonic-gate 		clu->clu_isopen = 0;	/* always sucess */
17030Sstevel@tonic-gate 		break;
17040Sstevel@tonic-gate 	}
17050Sstevel@tonic-gate 	return (0);
17060Sstevel@tonic-gate }
17070Sstevel@tonic-gate 
17080Sstevel@tonic-gate /*
17090Sstevel@tonic-gate  * NAME:	mkdev_ioctl
17100Sstevel@tonic-gate  * PURPOSE:	Create device node for specified set / metadevice tuple
17110Sstevel@tonic-gate  * INPUT:	device tuple (set number + metadevice number)
17120Sstevel@tonic-gate  * OUTPUT:	None
17130Sstevel@tonic-gate  * RETURNS:	0 on success
17140Sstevel@tonic-gate  *		EINVAL on failure
17150Sstevel@tonic-gate  */
17160Sstevel@tonic-gate static int
mkdev_ioctl(md_mkdev_params_t * p)17170Sstevel@tonic-gate mkdev_ioctl(md_mkdev_params_t *p)
17180Sstevel@tonic-gate {
17190Sstevel@tonic-gate 	set_t	setno = p->md_driver.md_setno;
17201623Stw21770 	unit_t	un;
17210Sstevel@tonic-gate 
17220Sstevel@tonic-gate 	mdclrerror(&p->mde);
17230Sstevel@tonic-gate 
17245428Spetede 	/* Validate arguments passed in to ioctl */
17255428Spetede 	if (setno >= MD_MAXSETS) {
17265428Spetede 		(void) mderror(&p->mde, MDE_NO_SET);
17275428Spetede 		return (EINVAL);
17285428Spetede 	}
17295428Spetede 
17301623Stw21770 	/*
17311623Stw21770 	 * Get the next available unit number in this set
17321623Stw21770 	 */
17331623Stw21770 	un = md_get_nextunit(setno);
17341623Stw21770 	if (un == MD_UNITBAD) {
17351623Stw21770 		(void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, un);
17361623Stw21770 		return (ENODEV);
17371623Stw21770 	}
17381623Stw21770 
17390Sstevel@tonic-gate 	/* Create the device node */
17401623Stw21770 	if (md_create_minor_node(setno, un)) {
17411623Stw21770 		(void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, un);
17420Sstevel@tonic-gate 		return (ENODEV);
17430Sstevel@tonic-gate 	}
17440Sstevel@tonic-gate 
17451623Stw21770 	/* Return the minor number */
17461623Stw21770 	p->un = un;
17471623Stw21770 
17480Sstevel@tonic-gate 	return (0);
17490Sstevel@tonic-gate }
17500Sstevel@tonic-gate 
17510Sstevel@tonic-gate /*
17520Sstevel@tonic-gate  * admin device ioctls
17530Sstevel@tonic-gate  */
17540Sstevel@tonic-gate static int
md_base_ioctl(md_dev64_t dev,int cmd,caddr_t data,int mode,IOLOCK * lockp)17550Sstevel@tonic-gate md_base_ioctl(md_dev64_t dev, int cmd, caddr_t data, int mode, IOLOCK *lockp)
17560Sstevel@tonic-gate {
17570Sstevel@tonic-gate 	size_t		sz = 0;
17580Sstevel@tonic-gate 	void		*d = NULL;
17590Sstevel@tonic-gate 	mddb_config_t	*cp;
17600Sstevel@tonic-gate 	set_t		setno;
17610Sstevel@tonic-gate 	int		err = 0;
17620Sstevel@tonic-gate 	int		err_to_user = 0;
17630Sstevel@tonic-gate 	int		mddb_config_case = 0;
17640Sstevel@tonic-gate 	int		mddb_didstat_case = 0;
17650Sstevel@tonic-gate 	caddr_t		c_devid_addr = 0;
17660Sstevel@tonic-gate 	caddr_t		c_old_devid_addr = 0;
17670Sstevel@tonic-gate 	caddr_t		ds_ctd_addr = 0;
17680Sstevel@tonic-gate 	mddb_set_node_params_t	*snp;
17690Sstevel@tonic-gate 
17700Sstevel@tonic-gate 	/* For now we can only handle 32-bit clients for internal commands */
17710Sstevel@tonic-gate 	if ((cmd != DKIOCINFO) &&
17720Sstevel@tonic-gate 	    ((mode & DATAMODEL_MASK) != DATAMODEL_ILP32)) {
17730Sstevel@tonic-gate 		return (EINVAL);
17740Sstevel@tonic-gate 	}
17750Sstevel@tonic-gate 
17760Sstevel@tonic-gate 	switch (cmd) {
17770Sstevel@tonic-gate 
17780Sstevel@tonic-gate 	case DKIOCINFO:
17790Sstevel@tonic-gate 	{
17800Sstevel@tonic-gate 		if (! (mode & FREAD))
17810Sstevel@tonic-gate 			return (EACCES);
17820Sstevel@tonic-gate 
17830Sstevel@tonic-gate 		sz = sizeof (struct dk_cinfo);
17840Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
17850Sstevel@tonic-gate 
17860Sstevel@tonic-gate 		get_info((struct dk_cinfo *)d, md_getminor(dev));
17870Sstevel@tonic-gate 		break;
17880Sstevel@tonic-gate 	}
17890Sstevel@tonic-gate 
17900Sstevel@tonic-gate 	case MD_DB_USEDEV:
17910Sstevel@tonic-gate 	{
17920Sstevel@tonic-gate 		if (! (mode & FWRITE))
17930Sstevel@tonic-gate 			return (EACCES);
17940Sstevel@tonic-gate 
17950Sstevel@tonic-gate 		mddb_config_case = 1;
17960Sstevel@tonic-gate 
17970Sstevel@tonic-gate 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
17980Sstevel@tonic-gate 		    &c_old_devid_addr);
17990Sstevel@tonic-gate 
18000Sstevel@tonic-gate 		if (err)
18010Sstevel@tonic-gate 			return (err);
18020Sstevel@tonic-gate 
18030Sstevel@tonic-gate 		err = mddb_configure(MDDB_USEDEV, (mddb_config_t *)d);
18040Sstevel@tonic-gate 		break;
18050Sstevel@tonic-gate 	}
18060Sstevel@tonic-gate 
18070Sstevel@tonic-gate 	case MD_DB_GETDEV:
18080Sstevel@tonic-gate 	{
18090Sstevel@tonic-gate 		if (! (mode & FREAD))
18100Sstevel@tonic-gate 			return (EACCES);
18110Sstevel@tonic-gate 
18120Sstevel@tonic-gate 		mddb_config_case = 1;
18130Sstevel@tonic-gate 
18140Sstevel@tonic-gate 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
18150Sstevel@tonic-gate 		    &c_old_devid_addr);
18160Sstevel@tonic-gate 
18170Sstevel@tonic-gate 		if (err)
18180Sstevel@tonic-gate 			return (err);
18190Sstevel@tonic-gate 
18200Sstevel@tonic-gate 		err = mddb_configure(MDDB_GETDEV, (mddb_config_t *)d);
18210Sstevel@tonic-gate 		break;
18220Sstevel@tonic-gate 	}
18230Sstevel@tonic-gate 
18240Sstevel@tonic-gate 	case MD_DB_GETDRVNM:
18250Sstevel@tonic-gate 	{
18260Sstevel@tonic-gate 		if (! (mode & FREAD))
18270Sstevel@tonic-gate 			return (EACCES);
18280Sstevel@tonic-gate 
18290Sstevel@tonic-gate 		mddb_config_case = 1;
18300Sstevel@tonic-gate 
18310Sstevel@tonic-gate 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
18320Sstevel@tonic-gate 		    &c_old_devid_addr);
18330Sstevel@tonic-gate 
18340Sstevel@tonic-gate 		if (err)
18350Sstevel@tonic-gate 			return (err);
18360Sstevel@tonic-gate 
18370Sstevel@tonic-gate 		err = mddb_configure(MDDB_GETDRVRNAME, (mddb_config_t *)d);
18380Sstevel@tonic-gate 		break;
18390Sstevel@tonic-gate 	}
18400Sstevel@tonic-gate 
18410Sstevel@tonic-gate 	case MD_DB_ENDDEV:
18420Sstevel@tonic-gate 	{
18430Sstevel@tonic-gate 		if (! (mode & FREAD))
18440Sstevel@tonic-gate 			return (EACCES);
18450Sstevel@tonic-gate 
18460Sstevel@tonic-gate 		mddb_config_case = 1;
18470Sstevel@tonic-gate 
18480Sstevel@tonic-gate 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
18490Sstevel@tonic-gate 		    &c_old_devid_addr);
18500Sstevel@tonic-gate 
18510Sstevel@tonic-gate 		if (err)
18520Sstevel@tonic-gate 			return (err);
18530Sstevel@tonic-gate 
18540Sstevel@tonic-gate 		err = mddb_configure(MDDB_ENDDEV, (mddb_config_t *)d);
18550Sstevel@tonic-gate 		break;
18560Sstevel@tonic-gate 	}
18570Sstevel@tonic-gate 
18580Sstevel@tonic-gate 	case MD_DB_DELDEV:
18590Sstevel@tonic-gate 	{
18600Sstevel@tonic-gate 		if (! (mode & FWRITE))
18610Sstevel@tonic-gate 			return (EACCES);
18620Sstevel@tonic-gate 
18630Sstevel@tonic-gate 		mddb_config_case = 1;
18640Sstevel@tonic-gate 
18650Sstevel@tonic-gate 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
18660Sstevel@tonic-gate 		    &c_old_devid_addr);
18670Sstevel@tonic-gate 
18680Sstevel@tonic-gate 		if (err)
18690Sstevel@tonic-gate 			return (err);
18700Sstevel@tonic-gate 
18710Sstevel@tonic-gate 		cp = (mddb_config_t *)d;
18720Sstevel@tonic-gate 		setno = cp->c_setno;
18730Sstevel@tonic-gate 		err = mddb_configure(MDDB_DELDEV, cp);
18740Sstevel@tonic-gate 		if (! mdisok(&cp->c_mde))
18750Sstevel@tonic-gate 			break;
18760Sstevel@tonic-gate 
18770Sstevel@tonic-gate 		if (setno == MD_LOCAL_SET)
18780Sstevel@tonic-gate 			break;
18790Sstevel@tonic-gate 
18800Sstevel@tonic-gate 		if (cp->c_dbcnt != 0)
18810Sstevel@tonic-gate 			break;
18820Sstevel@tonic-gate 
18830Sstevel@tonic-gate 		/*
18840Sstevel@tonic-gate 		 * if the last db replica of a diskset is deleted
18850Sstevel@tonic-gate 		 * unload everything.
18860Sstevel@tonic-gate 		 */
18870Sstevel@tonic-gate 
18880Sstevel@tonic-gate 		/* Requesting a release, clean up everything */
18890Sstevel@tonic-gate 		md_clr_setstatus(setno, MD_SET_KEEPTAG);
18900Sstevel@tonic-gate 
18910Sstevel@tonic-gate 		err = release_set(cp, mode);
18920Sstevel@tonic-gate 
18930Sstevel@tonic-gate 		break;
18940Sstevel@tonic-gate 	}
18950Sstevel@tonic-gate 
18960Sstevel@tonic-gate 	case MD_DB_NEWDEV:
18970Sstevel@tonic-gate 	{
18980Sstevel@tonic-gate 		if (! (mode & FWRITE))
18990Sstevel@tonic-gate 			return (EACCES);
19000Sstevel@tonic-gate 
19010Sstevel@tonic-gate 		mddb_config_case = 1;
19020Sstevel@tonic-gate 
19030Sstevel@tonic-gate 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
19040Sstevel@tonic-gate 		    &c_old_devid_addr);
19050Sstevel@tonic-gate 
19060Sstevel@tonic-gate 		if (err)
19070Sstevel@tonic-gate 			return (err);
19080Sstevel@tonic-gate 
19090Sstevel@tonic-gate 		cp = (mddb_config_t *)d;
19100Sstevel@tonic-gate 		setno = cp->c_setno;
19110Sstevel@tonic-gate 		err = mddb_configure(MDDB_NEWDEV, cp);
19120Sstevel@tonic-gate 		if (! err && mdisok(&cp->c_mde))
19130Sstevel@tonic-gate 			(void) md_snarf_db_set(setno, &cp->c_mde);
19140Sstevel@tonic-gate 		break;
19150Sstevel@tonic-gate 	}
19160Sstevel@tonic-gate 
19170Sstevel@tonic-gate 	case MD_DB_NEWSIDE:
19180Sstevel@tonic-gate 	{
19190Sstevel@tonic-gate 		if (! (mode & FWRITE))
19200Sstevel@tonic-gate 			return (EACCES);
19210Sstevel@tonic-gate 
19220Sstevel@tonic-gate 		mddb_config_case = 1;
19230Sstevel@tonic-gate 
19240Sstevel@tonic-gate 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
19250Sstevel@tonic-gate 		    &c_old_devid_addr);
19260Sstevel@tonic-gate 
19270Sstevel@tonic-gate 		if (err)
19280Sstevel@tonic-gate 			return (err);
19290Sstevel@tonic-gate 
19300Sstevel@tonic-gate 		err = mddb_configure(MDDB_NEWSIDE, (mddb_config_t *)d);
19310Sstevel@tonic-gate 		break;
19320Sstevel@tonic-gate 	}
19330Sstevel@tonic-gate 
19340Sstevel@tonic-gate 	case MD_DB_DELSIDE:
19350Sstevel@tonic-gate 	{
19360Sstevel@tonic-gate 		if (! (mode & FWRITE))
19370Sstevel@tonic-gate 			return (EACCES);
19380Sstevel@tonic-gate 
19390Sstevel@tonic-gate 		mddb_config_case = 1;
19400Sstevel@tonic-gate 
19410Sstevel@tonic-gate 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
19420Sstevel@tonic-gate 		    &c_old_devid_addr);
19430Sstevel@tonic-gate 
19440Sstevel@tonic-gate 		if (err)
19450Sstevel@tonic-gate 			return (err);
19460Sstevel@tonic-gate 
19470Sstevel@tonic-gate 		err = mddb_configure(MDDB_DELSIDE, (mddb_config_t *)d);
19480Sstevel@tonic-gate 		break;
19490Sstevel@tonic-gate 	}
19500Sstevel@tonic-gate 
19510Sstevel@tonic-gate 	case MD_DB_SETDID:
19520Sstevel@tonic-gate 	{
19530Sstevel@tonic-gate 		if (!(mode & FWRITE)) {
19540Sstevel@tonic-gate 			return (EACCES);
19550Sstevel@tonic-gate 		}
19560Sstevel@tonic-gate 
19570Sstevel@tonic-gate 		mddb_config_case = 1;
19580Sstevel@tonic-gate 
19590Sstevel@tonic-gate 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
19600Sstevel@tonic-gate 		    &c_old_devid_addr);
19610Sstevel@tonic-gate 
19620Sstevel@tonic-gate 		if (err) {
19630Sstevel@tonic-gate 			return (err);
19640Sstevel@tonic-gate 		}
19650Sstevel@tonic-gate 
19660Sstevel@tonic-gate 		err = mddb_configure(MDDB_SETDID, (mddb_config_t *)d);
19670Sstevel@tonic-gate 
19680Sstevel@tonic-gate 		break;
19690Sstevel@tonic-gate 	}
19700Sstevel@tonic-gate 
19710Sstevel@tonic-gate 	case MD_GRAB_SET:
19720Sstevel@tonic-gate 	{
19730Sstevel@tonic-gate 		if (! (mode & FWRITE))
19740Sstevel@tonic-gate 			return (EACCES);
19750Sstevel@tonic-gate 
19760Sstevel@tonic-gate 		mddb_config_case = 1;
19770Sstevel@tonic-gate 
19780Sstevel@tonic-gate 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
19790Sstevel@tonic-gate 		    &c_old_devid_addr);
19800Sstevel@tonic-gate 
19810Sstevel@tonic-gate 		if (err)
19820Sstevel@tonic-gate 			return (err);
19830Sstevel@tonic-gate 
19840Sstevel@tonic-gate 		cp = (mddb_config_t *)d;
19850Sstevel@tonic-gate 		setno = cp->c_setno;
19860Sstevel@tonic-gate 
19870Sstevel@tonic-gate 		err = take_set(cp, mode);
19880Sstevel@tonic-gate 
19890Sstevel@tonic-gate 		if (err || ! mdisok(&cp->c_mde))
19900Sstevel@tonic-gate 			break;
19910Sstevel@tonic-gate 
19920Sstevel@tonic-gate 		if (md_get_setstatus(setno) & MD_SET_ACCOK)
19930Sstevel@tonic-gate 			err = mdmddberror(&cp->c_mde, MDE_DB_ACCOK, NODEV32,
19940Sstevel@tonic-gate 			    setno);
19950Sstevel@tonic-gate 
19960Sstevel@tonic-gate 		md_unblock_setio(setno);
19970Sstevel@tonic-gate 		break;
19980Sstevel@tonic-gate 	}
19990Sstevel@tonic-gate 
20000Sstevel@tonic-gate 	case MD_RELEASE_SET:
20010Sstevel@tonic-gate 	{
20020Sstevel@tonic-gate 		if (! (mode & FWRITE))
20030Sstevel@tonic-gate 			return (EACCES);
20040Sstevel@tonic-gate 
20050Sstevel@tonic-gate 		mddb_config_case = 1;
20060Sstevel@tonic-gate 
20070Sstevel@tonic-gate 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
20080Sstevel@tonic-gate 		    &c_old_devid_addr);
20090Sstevel@tonic-gate 
20100Sstevel@tonic-gate 		if (err)
20110Sstevel@tonic-gate 			return (err);
20120Sstevel@tonic-gate 
20130Sstevel@tonic-gate 		/* shorthand */
20140Sstevel@tonic-gate 		cp = (mddb_config_t *)d;
20150Sstevel@tonic-gate 		setno = cp->c_setno;
20160Sstevel@tonic-gate 
20170Sstevel@tonic-gate 		/* If the user requests a release, clean up everything */
20180Sstevel@tonic-gate 		md_clr_setstatus(setno, MD_SET_KEEPTAG);
20190Sstevel@tonic-gate 
20202291Stn143363 		/* Block incoming I/Os during release_set operation */
20210Sstevel@tonic-gate 		if (MD_MNSET_SETNO(setno)) {
20220Sstevel@tonic-gate 			/*
20230Sstevel@tonic-gate 			 * md_tas_block_setio will block the set if
20240Sstevel@tonic-gate 			 * there are no outstanding I/O requests,
20250Sstevel@tonic-gate 			 * otherwise it returns -1.
20260Sstevel@tonic-gate 			 */
20270Sstevel@tonic-gate 			if (md_tas_block_setio(setno) != 1) {
20280Sstevel@tonic-gate 				err = EBUSY;
20290Sstevel@tonic-gate 				break;
20300Sstevel@tonic-gate 			}
20310Sstevel@tonic-gate 		} else {
20320Sstevel@tonic-gate 			/*
20330Sstevel@tonic-gate 			 * Should not return something other than 1
20340Sstevel@tonic-gate 			 */
20350Sstevel@tonic-gate 			if (md_block_setio(setno) != 1) {
20360Sstevel@tonic-gate 				md_clearblock_setio(setno);
20370Sstevel@tonic-gate 				err = EACCES;
20380Sstevel@tonic-gate 				break;
20390Sstevel@tonic-gate 			}
20400Sstevel@tonic-gate 		}
20410Sstevel@tonic-gate 
20420Sstevel@tonic-gate 		err = release_set(cp, mode);
20430Sstevel@tonic-gate 
20445684Sjr26306 		/* Always unblock I/O even if release_set fails */
20455684Sjr26306 		md_clearblock_setio(setno);
20462291Stn143363 
20470Sstevel@tonic-gate 		break;
20480Sstevel@tonic-gate 	}
20490Sstevel@tonic-gate 
20500Sstevel@tonic-gate 	case MD_DB_GETOPTLOC:
20510Sstevel@tonic-gate 	{
20520Sstevel@tonic-gate 		if (! (mode & FREAD))
20530Sstevel@tonic-gate 			return (EACCES);
20540Sstevel@tonic-gate 
20550Sstevel@tonic-gate 		sz = sizeof (mddb_optloc_t);
20560Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
20570Sstevel@tonic-gate 
20580Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
20590Sstevel@tonic-gate 			err = EFAULT;
20600Sstevel@tonic-gate 			break;
20610Sstevel@tonic-gate 		}
20620Sstevel@tonic-gate 
20630Sstevel@tonic-gate 		err = mddb_getoptloc((mddb_optloc_t *)d);
20640Sstevel@tonic-gate 		break;
20650Sstevel@tonic-gate 	}
20660Sstevel@tonic-gate 
20670Sstevel@tonic-gate 	case MD_HALT:
20680Sstevel@tonic-gate 	{
20690Sstevel@tonic-gate 		if (! (mode & FWRITE))
20700Sstevel@tonic-gate 			return (EACCES);
20710Sstevel@tonic-gate 
20720Sstevel@tonic-gate 		/* already have the ioctl lock */
20730Sstevel@tonic-gate 		return (md_halt(MD_GBL_IOCTL_LOCK));
20740Sstevel@tonic-gate 	}
20750Sstevel@tonic-gate 
20760Sstevel@tonic-gate 	case MD_IOCSET_NM:
20770Sstevel@tonic-gate 	{
20780Sstevel@tonic-gate 		if (! (mode & FREAD))
20790Sstevel@tonic-gate 			return (EACCES);
20800Sstevel@tonic-gate 
20810Sstevel@tonic-gate 		sz = sizeof (mdnm_params_t);
20820Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
20830Sstevel@tonic-gate 
20840Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
20850Sstevel@tonic-gate 			err = EFAULT;
20860Sstevel@tonic-gate 			break;
20870Sstevel@tonic-gate 		}
20880Sstevel@tonic-gate 
20890Sstevel@tonic-gate 		/* check data integrity */
20900Sstevel@tonic-gate 		if (((mdnm_params_t *)d)->setno >= md_nsets) {
20910Sstevel@tonic-gate 			err = EINVAL;
20920Sstevel@tonic-gate 			break;
20930Sstevel@tonic-gate 		}
20940Sstevel@tonic-gate 
20950Sstevel@tonic-gate 		if ((((mdnm_params_t *)d)->devname_len == 0) ||
20960Sstevel@tonic-gate 		    (((mdnm_params_t *)d)->devname_len > MAXPATHLEN)) {
20970Sstevel@tonic-gate 			err = EINVAL;
20980Sstevel@tonic-gate 			break;
20990Sstevel@tonic-gate 		}
21000Sstevel@tonic-gate 
21010Sstevel@tonic-gate 		if (((mdnm_params_t *)d)->devname == NULL) {
21020Sstevel@tonic-gate 			err = EINVAL;
21030Sstevel@tonic-gate 			break;
21040Sstevel@tonic-gate 		}
21050Sstevel@tonic-gate 
21060Sstevel@tonic-gate 		err = setnm_ioctl((mdnm_params_t *)d, mode);
21070Sstevel@tonic-gate 		break;
21080Sstevel@tonic-gate 	}
21090Sstevel@tonic-gate 
21100Sstevel@tonic-gate 	case MD_IOCGET_NM:
21110Sstevel@tonic-gate 	{
21120Sstevel@tonic-gate 		if (! (mode & FREAD))
21130Sstevel@tonic-gate 			return (EACCES);
21140Sstevel@tonic-gate 
21150Sstevel@tonic-gate 		sz = sizeof (mdnm_params_t);
21160Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
21170Sstevel@tonic-gate 
21180Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
21190Sstevel@tonic-gate 			err = EFAULT;
21200Sstevel@tonic-gate 			break;
21210Sstevel@tonic-gate 		}
21220Sstevel@tonic-gate 
21230Sstevel@tonic-gate 		/* check data integrity */
21240Sstevel@tonic-gate 		if (((mdnm_params_t *)d)->setno >= md_nsets) {
21250Sstevel@tonic-gate 			err = EINVAL;
21260Sstevel@tonic-gate 			break;
21270Sstevel@tonic-gate 		}
21280Sstevel@tonic-gate 		if (((mdnm_params_t *)d)->devname == NULL) {
21290Sstevel@tonic-gate 			err = EINVAL;
21300Sstevel@tonic-gate 			break;
21310Sstevel@tonic-gate 		}
21320Sstevel@tonic-gate 
21330Sstevel@tonic-gate 		err = getnm_ioctl((mdnm_params_t *)d, mode);
21340Sstevel@tonic-gate 		break;
21350Sstevel@tonic-gate 	}
21360Sstevel@tonic-gate 
21371623Stw21770 	case MD_IOCGET_HSP_NM:
21381623Stw21770 	{
21391623Stw21770 		if (! (mode & FREAD))
21401623Stw21770 			return (EACCES);
21411623Stw21770 
21421623Stw21770 		sz = sizeof (mdhspnm_params_t);
21431623Stw21770 		d = kmem_alloc(sz, KM_SLEEP);
21441623Stw21770 
21451623Stw21770 		if (ddi_copyin(data, d, sz, mode) != 0) {
21461623Stw21770 			err = EFAULT;
21471623Stw21770 			break;
21481623Stw21770 		}
21491623Stw21770 
21501623Stw21770 		/* check data integrity */
21511623Stw21770 		if (((mdhspnm_params_t *)d)->setno >= md_nsets) {
21521623Stw21770 			err = EINVAL;
21531623Stw21770 			break;
21541623Stw21770 		}
21551623Stw21770 		if (((mdhspnm_params_t *)d)->hspname == NULL) {
21561623Stw21770 			err = EINVAL;
21571623Stw21770 			break;
21581623Stw21770 		}
21591623Stw21770 
21601623Stw21770 		err = gethspnm_ioctl((mdhspnm_params_t *)d, mode);
21611623Stw21770 		break;
21621623Stw21770 	}
21631623Stw21770 
21640Sstevel@tonic-gate 	case MD_IOCNXTKEY_NM:
21650Sstevel@tonic-gate 	{
21660Sstevel@tonic-gate 		if (! (mode & FREAD))
21670Sstevel@tonic-gate 			return (EACCES);
21680Sstevel@tonic-gate 
21690Sstevel@tonic-gate 		sz = sizeof (mdnm_params_t);
21700Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
21710Sstevel@tonic-gate 
21720Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
21730Sstevel@tonic-gate 			err = EFAULT;
21740Sstevel@tonic-gate 			break;
21750Sstevel@tonic-gate 		}
21760Sstevel@tonic-gate 
21770Sstevel@tonic-gate 		err = getnextkey_ioctl((mdnm_params_t *)d, mode);
21780Sstevel@tonic-gate 		break;
21790Sstevel@tonic-gate 	}
21800Sstevel@tonic-gate 
21810Sstevel@tonic-gate 	case MD_IOCREM_NM:
21820Sstevel@tonic-gate 	{
21830Sstevel@tonic-gate 		if (! (mode & FREAD))
21840Sstevel@tonic-gate 			return (EACCES);
21850Sstevel@tonic-gate 
21860Sstevel@tonic-gate 		sz = sizeof (mdnm_params_t);
21870Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
21880Sstevel@tonic-gate 
21890Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
21900Sstevel@tonic-gate 			err = EFAULT;
21910Sstevel@tonic-gate 			break;
21920Sstevel@tonic-gate 		}
21930Sstevel@tonic-gate 
21940Sstevel@tonic-gate 		/* check data integrity */
21950Sstevel@tonic-gate 		if (((mdnm_params_t *)d)->setno >= md_nsets) {
21960Sstevel@tonic-gate 			err = EINVAL;
21970Sstevel@tonic-gate 			break;
21980Sstevel@tonic-gate 		}
21990Sstevel@tonic-gate 
22000Sstevel@tonic-gate 		err = remnm_ioctl((mdnm_params_t *)d, mode);
22010Sstevel@tonic-gate 		break;
22020Sstevel@tonic-gate 	}
22030Sstevel@tonic-gate 
22040Sstevel@tonic-gate 	case MD_IOCGET_TSTATE:
22050Sstevel@tonic-gate 	{
22065428Spetede 		md_i_get_tstate_t	*p;
22075428Spetede 
22080Sstevel@tonic-gate 		if (! (mode & FREAD))
22090Sstevel@tonic-gate 			return (EACCES);
22100Sstevel@tonic-gate 
22110Sstevel@tonic-gate 		sz = sizeof (md_i_get_tstate_t);
22120Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
22130Sstevel@tonic-gate 
22140Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
22150Sstevel@tonic-gate 			err = EFAULT;
22160Sstevel@tonic-gate 			break;
22170Sstevel@tonic-gate 		}
22180Sstevel@tonic-gate 
22195428Spetede 		p = (md_i_get_tstate_t *)d;
22205428Spetede 
22215428Spetede 		if ((err = verify_minor(p->id)) != 0) {
22225428Spetede 			if (err == EINVAL)
22235428Spetede 				(void) mdmderror(&p->mde, MDE_INVAL_UNIT,
22245428Spetede 				    p->id);
22255428Spetede 			break;
22265428Spetede 		}
22275428Spetede 
22285428Spetede 		err = get_tstate(p, lockp);
22290Sstevel@tonic-gate 		break;
22300Sstevel@tonic-gate 	}
22310Sstevel@tonic-gate 
22320Sstevel@tonic-gate 	case MD_IOCGET_DRVNM:
22330Sstevel@tonic-gate 	{
22345428Spetede 		md_i_driverinfo_t	*p;
22355428Spetede 
22360Sstevel@tonic-gate 		if (! (mode & FREAD))
22370Sstevel@tonic-gate 			return (EACCES);
22380Sstevel@tonic-gate 
22390Sstevel@tonic-gate 		sz = sizeof (md_i_driverinfo_t);
22400Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
22410Sstevel@tonic-gate 
22420Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
22430Sstevel@tonic-gate 			err = EFAULT;
22440Sstevel@tonic-gate 			break;
22450Sstevel@tonic-gate 		}
22460Sstevel@tonic-gate 
22475428Spetede 		p = (md_i_driverinfo_t *)d;
22485428Spetede 
22490Sstevel@tonic-gate 		/* check data integrity */
22505428Spetede 		if (p->md_driver.md_drivername == NULL) {
22510Sstevel@tonic-gate 			err = EINVAL;
22520Sstevel@tonic-gate 			break;
22530Sstevel@tonic-gate 		}
22540Sstevel@tonic-gate 
22555428Spetede 		if ((err = verify_minor(p->mnum)) != 0) {
22565428Spetede 			if (err == EINVAL)
22575428Spetede 				(void) mdmderror(&p->mde, MDE_INVAL_UNIT,
22585428Spetede 				    p->mnum);
22590Sstevel@tonic-gate 			break;
22600Sstevel@tonic-gate 		}
22610Sstevel@tonic-gate 
22625428Spetede 		err = getdrvnm_ioctl(dev, p, mode);
22630Sstevel@tonic-gate 		break;
22640Sstevel@tonic-gate 	}
22650Sstevel@tonic-gate 
22660Sstevel@tonic-gate 	case MD_IOCGET_NEXT:
22670Sstevel@tonic-gate 	{
22680Sstevel@tonic-gate 		if (! (mode & FREAD))
22690Sstevel@tonic-gate 			return (EACCES);
22700Sstevel@tonic-gate 
22710Sstevel@tonic-gate 		sz = sizeof (md_i_getnext_t);
22720Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
22730Sstevel@tonic-gate 
22740Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
22750Sstevel@tonic-gate 			err = EFAULT;
22760Sstevel@tonic-gate 			break;
22770Sstevel@tonic-gate 		}
22780Sstevel@tonic-gate 
22790Sstevel@tonic-gate 		/* check data integrity */
22800Sstevel@tonic-gate 		if (((md_i_getnext_t *)d)->md_driver.md_setno >= md_nsets) {
22810Sstevel@tonic-gate 			err = EINVAL;
22820Sstevel@tonic-gate 			break;
22830Sstevel@tonic-gate 		}
22840Sstevel@tonic-gate 
22850Sstevel@tonic-gate 		err = getnext_ioctl((md_i_getnext_t *)d, mode);
22860Sstevel@tonic-gate 		break;
22870Sstevel@tonic-gate 	}
22880Sstevel@tonic-gate 
22890Sstevel@tonic-gate 	case MD_DB_USERREQ:
22900Sstevel@tonic-gate 	case MD_MN_DB_USERREQ:
22910Sstevel@tonic-gate 	{
22920Sstevel@tonic-gate 		if (! (mode & FREAD))
22930Sstevel@tonic-gate 			return (EACCES);
22940Sstevel@tonic-gate 
22950Sstevel@tonic-gate 		sz = sizeof (mddb_userreq_t);
22960Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
22970Sstevel@tonic-gate 
22980Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
22990Sstevel@tonic-gate 			err = EFAULT;
23000Sstevel@tonic-gate 			break;
23010Sstevel@tonic-gate 		}
23020Sstevel@tonic-gate 		err = mddb_userreq_ioctl((mddb_userreq_t *)d, mode);
23030Sstevel@tonic-gate 		break;
23040Sstevel@tonic-gate 	}
23050Sstevel@tonic-gate 
23060Sstevel@tonic-gate 	case MD_IOCGET_NUM:
23070Sstevel@tonic-gate 	{
23080Sstevel@tonic-gate 		if (! (mode & FREAD))
23090Sstevel@tonic-gate 			return (EACCES);
23100Sstevel@tonic-gate 
23110Sstevel@tonic-gate 		sz = sizeof (md_i_getnum_t);
23120Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
23130Sstevel@tonic-gate 
23140Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
23150Sstevel@tonic-gate 			err = EFAULT;
23160Sstevel@tonic-gate 			break;
23170Sstevel@tonic-gate 		}
23180Sstevel@tonic-gate 
23190Sstevel@tonic-gate 		err = getnum_ioctl(d, mode);
23200Sstevel@tonic-gate 		break;
23210Sstevel@tonic-gate 	}
23220Sstevel@tonic-gate 
23230Sstevel@tonic-gate 	case MD_DB_OWNSET:
23240Sstevel@tonic-gate 	{
23250Sstevel@tonic-gate 		if (! (mode & FREAD))
23260Sstevel@tonic-gate 			return (EACCES);
23270Sstevel@tonic-gate 
23280Sstevel@tonic-gate 		sz = sizeof (mddb_ownset_t);
23290Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
23300Sstevel@tonic-gate 
23310Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
23320Sstevel@tonic-gate 			err = EFAULT;
23330Sstevel@tonic-gate 			break;
23340Sstevel@tonic-gate 		}
23350Sstevel@tonic-gate 
23360Sstevel@tonic-gate 		if (((mddb_ownset_t *)d)->setno >= md_nsets) {
23370Sstevel@tonic-gate 			err = EINVAL;
23380Sstevel@tonic-gate 			break;
23390Sstevel@tonic-gate 		}
23400Sstevel@tonic-gate 
23410Sstevel@tonic-gate 		((mddb_ownset_t *)d)->owns_set =
23420Sstevel@tonic-gate 		    mddb_ownset(((mddb_ownset_t *)d)->setno);
23430Sstevel@tonic-gate 
23440Sstevel@tonic-gate 		break;
23450Sstevel@tonic-gate 	}
23460Sstevel@tonic-gate 
23470Sstevel@tonic-gate 	case MD_IOCGETNSET:
23480Sstevel@tonic-gate 	{
23490Sstevel@tonic-gate 		if (! (mode & FREAD))
23500Sstevel@tonic-gate 			return (EACCES);
23510Sstevel@tonic-gate 
23520Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&md_nsets, data,
23530Sstevel@tonic-gate 		    sizeof (set_t), mode) != 0) {
23540Sstevel@tonic-gate 			err = EFAULT;
23550Sstevel@tonic-gate 			break;
23560Sstevel@tonic-gate 		}
23570Sstevel@tonic-gate 		break;
23580Sstevel@tonic-gate 	}
23590Sstevel@tonic-gate 
23600Sstevel@tonic-gate 	case MD_IOCGETNUNITS:
23610Sstevel@tonic-gate 	{
23620Sstevel@tonic-gate 		if (! (mode & FREAD))
23630Sstevel@tonic-gate 			return (EACCES);
23640Sstevel@tonic-gate 
23650Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&md_nunits, data,
23660Sstevel@tonic-gate 		    sizeof (set_t), mode) != 0) {
23670Sstevel@tonic-gate 			err = EFAULT;
23680Sstevel@tonic-gate 			break;
23690Sstevel@tonic-gate 		}
23700Sstevel@tonic-gate 		break;
23710Sstevel@tonic-gate 	}
23720Sstevel@tonic-gate 
23730Sstevel@tonic-gate 	case MD_IOCGVERSION:
23740Sstevel@tonic-gate 	{
23750Sstevel@tonic-gate 		uint_t	dversion = MD_DVERSION;
23760Sstevel@tonic-gate 
23770Sstevel@tonic-gate 		if (! (mode & FREAD))
23780Sstevel@tonic-gate 			return (EACCES);
23790Sstevel@tonic-gate 
23800Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&dversion, data,
23810Sstevel@tonic-gate 		    sizeof (dversion), mode) != 0) {
23820Sstevel@tonic-gate 			err = EFAULT;
23830Sstevel@tonic-gate 			break;
23840Sstevel@tonic-gate 		}
23850Sstevel@tonic-gate 		break;
23860Sstevel@tonic-gate 	}
23870Sstevel@tonic-gate 
23880Sstevel@tonic-gate 	case MD_IOCSET_FLAGS:
23890Sstevel@tonic-gate 	{
23905428Spetede 		md_set_userflags_t	*p;
23915428Spetede 
23920Sstevel@tonic-gate 		if (! (mode & FWRITE))
23930Sstevel@tonic-gate 			return (EACCES);
23940Sstevel@tonic-gate 
23950Sstevel@tonic-gate 		sz = sizeof (md_set_userflags_t);
23960Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
23970Sstevel@tonic-gate 
23980Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode)) {
23990Sstevel@tonic-gate 			err = EFAULT;
24000Sstevel@tonic-gate 			break;
24010Sstevel@tonic-gate 		}
24020Sstevel@tonic-gate 
24035428Spetede 		p = (md_set_userflags_t *)d;
24045428Spetede 
24055428Spetede 		if ((err = verify_minor(p->mnum)) != 0) {
24065428Spetede 			if (err == EINVAL)
24075428Spetede 				(void) mdmderror(&p->mde, MDE_INVAL_UNIT,
24085428Spetede 				    p->mnum);
24090Sstevel@tonic-gate 			break;
24100Sstevel@tonic-gate 		}
24110Sstevel@tonic-gate 
24125428Spetede 		err = setuserflags(p, lockp);
24130Sstevel@tonic-gate 		break;
24140Sstevel@tonic-gate 	}
24150Sstevel@tonic-gate 
24160Sstevel@tonic-gate 	case MD_IOCRENAME:
24170Sstevel@tonic-gate 	{
24185428Spetede 		md_rename_t	*p;
24195428Spetede 
24200Sstevel@tonic-gate 		if (! (mode & FWRITE)) {
24210Sstevel@tonic-gate 			return (EACCES);
24220Sstevel@tonic-gate 		}
24230Sstevel@tonic-gate 
24240Sstevel@tonic-gate 		sz = sizeof (md_rename_t);
24250Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
24260Sstevel@tonic-gate 
24270Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode)) {
24280Sstevel@tonic-gate 			err = EFAULT;
24290Sstevel@tonic-gate 			break;
24300Sstevel@tonic-gate 		}
24310Sstevel@tonic-gate 
24325428Spetede 		p = (md_rename_t *)d;
24335428Spetede 
24345428Spetede 		if ((err = verify_minor(p->to.mnum)) != 0) {
24355428Spetede 			if (err == EINVAL)
24365428Spetede 				(void) mdmderror(&p->mde, MDE_INVAL_UNIT,
24375428Spetede 				    p->to.mnum);
24385428Spetede 			break;
24395428Spetede 		}
24405428Spetede 
24415428Spetede 		if ((err = verify_minor(p->from.mnum)) != 0) {
24425428Spetede 			if (err == EINVAL)
24435428Spetede 				(void) mdmderror(&p->mde, MDE_INVAL_UNIT,
24445428Spetede 				    p->from.mnum);
24455428Spetede 			break;
24465428Spetede 		}
24475428Spetede 
24485428Spetede 		err = md_rename(p, lockp);
24490Sstevel@tonic-gate 		break;
24500Sstevel@tonic-gate 	}
24510Sstevel@tonic-gate 
24520Sstevel@tonic-gate 	case MD_IOCISOPEN:
24530Sstevel@tonic-gate 	{
24540Sstevel@tonic-gate 		md_isopen_t	*p;
24550Sstevel@tonic-gate 		mdi_unit_t	*ui;
24560Sstevel@tonic-gate 		minor_t		mnum;
24570Sstevel@tonic-gate 
24580Sstevel@tonic-gate 		if (! (mode & FREAD))
24590Sstevel@tonic-gate 			return (EACCES);
24600Sstevel@tonic-gate 
24610Sstevel@tonic-gate 		sz = sizeof (md_isopen_t);
24620Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
24630Sstevel@tonic-gate 
24640Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode)) {
24650Sstevel@tonic-gate 			err = EFAULT;
24660Sstevel@tonic-gate 			break;
24670Sstevel@tonic-gate 		}
24680Sstevel@tonic-gate 
24690Sstevel@tonic-gate 		p = (md_isopen_t *)d;
24700Sstevel@tonic-gate 		if ((p->dev <= 0) || (md_getmajor(p->dev)) != md_major) {
24710Sstevel@tonic-gate 			err = EINVAL;
24720Sstevel@tonic-gate 			break;
24730Sstevel@tonic-gate 		}
24740Sstevel@tonic-gate 
24750Sstevel@tonic-gate 		mnum = md_getminor(p->dev);
24765428Spetede 
24775428Spetede 		if ((err = verify_minor(mnum)) != 0) {
24785428Spetede 			if (err == EINVAL)
24795428Spetede 				(void) mdmderror(&p->mde, MDE_INVAL_UNIT, mnum);
24805428Spetede 			break;
24815428Spetede 		}
24825428Spetede 
24830Sstevel@tonic-gate 		if ((ui = MDI_UNIT(mnum)) == NULL) {
24847034Ssk102515 			/*
24857034Ssk102515 			 * If the incore unit does not exist then rather
24867034Ssk102515 			 * than set err we need to set it to 0 because the
24877034Ssk102515 			 * multi-node code is expecting a return of
24887034Ssk102515 			 * 0 (from mdmderror() but with the mde structure
24897034Ssk102515 			 * filled with particular information
24907034Ssk102515 			 * (MDE_UNIT_NOT_SETUP).
24917034Ssk102515 			 */
24927034Ssk102515 			err = mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, mnum);
24930Sstevel@tonic-gate 			break;
24940Sstevel@tonic-gate 		}
24950Sstevel@tonic-gate 
24960Sstevel@tonic-gate 		p->isopen = md_unit_isopen(ui);
24970Sstevel@tonic-gate 		break;
24980Sstevel@tonic-gate 	}
24990Sstevel@tonic-gate 
25000Sstevel@tonic-gate 	case MD_MED_GET_LST:
25010Sstevel@tonic-gate 	{
25020Sstevel@tonic-gate 		mddb_med_parm_t		*medpp;
25030Sstevel@tonic-gate 
25040Sstevel@tonic-gate 		if (! (mode & FREAD))
25050Sstevel@tonic-gate 			return (EACCES);
25060Sstevel@tonic-gate 
25070Sstevel@tonic-gate 		sz = sizeof (mddb_med_parm_t);
25080Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
25090Sstevel@tonic-gate 
25100Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
25110Sstevel@tonic-gate 			err = EFAULT;
25120Sstevel@tonic-gate 			break;
25130Sstevel@tonic-gate 		}
25140Sstevel@tonic-gate 
25150Sstevel@tonic-gate 		medpp = (mddb_med_parm_t *)d;
25160Sstevel@tonic-gate 
25170Sstevel@tonic-gate 		err = getmed_ioctl(medpp, mode);
25180Sstevel@tonic-gate 		break;
25190Sstevel@tonic-gate 	}
25200Sstevel@tonic-gate 
25210Sstevel@tonic-gate 	case MD_MED_SET_LST:
25220Sstevel@tonic-gate 	{
25230Sstevel@tonic-gate 		mddb_med_parm_t		*medpp;
25240Sstevel@tonic-gate 
25250Sstevel@tonic-gate 		if (! (mode & FWRITE))
25260Sstevel@tonic-gate 			return (EACCES);
25270Sstevel@tonic-gate 
25280Sstevel@tonic-gate 		sz = sizeof (mddb_med_parm_t);
25290Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
25300Sstevel@tonic-gate 
25310Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
25320Sstevel@tonic-gate 			err = EFAULT;
25330Sstevel@tonic-gate 			break;
25340Sstevel@tonic-gate 		}
25350Sstevel@tonic-gate 
25360Sstevel@tonic-gate 		medpp = (mddb_med_parm_t *)d;
25370Sstevel@tonic-gate 
25380Sstevel@tonic-gate 		err = setmed_ioctl(medpp, mode);
25390Sstevel@tonic-gate 
25400Sstevel@tonic-gate 		break;
25410Sstevel@tonic-gate 	}
25420Sstevel@tonic-gate 
25430Sstevel@tonic-gate 	case MD_MED_UPD_MED:
25440Sstevel@tonic-gate 	{
25450Sstevel@tonic-gate 		if (! (mode & FWRITE))
25460Sstevel@tonic-gate 			return (EACCES);
25470Sstevel@tonic-gate 
25480Sstevel@tonic-gate 		sz = sizeof (mddb_med_upd_parm_t);
25490Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
25500Sstevel@tonic-gate 
25510Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
25520Sstevel@tonic-gate 			err = EFAULT;
25530Sstevel@tonic-gate 			break;
25540Sstevel@tonic-gate 		}
25550Sstevel@tonic-gate 
25560Sstevel@tonic-gate 		err = updmed_ioctl((mddb_med_upd_parm_t *)d, mode);
25570Sstevel@tonic-gate 
25580Sstevel@tonic-gate 		break;
25590Sstevel@tonic-gate 	}
25600Sstevel@tonic-gate 
25610Sstevel@tonic-gate 	case MD_MED_GET_NMED:
25620Sstevel@tonic-gate 	{
25630Sstevel@tonic-gate 		if (! (mode & FREAD))
25640Sstevel@tonic-gate 			return (EACCES);
25650Sstevel@tonic-gate 
25660Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&md_nmedh, data,
25670Sstevel@tonic-gate 		    sizeof (int), mode) != 0) {
25680Sstevel@tonic-gate 			err = EFAULT;
25690Sstevel@tonic-gate 			break;
25700Sstevel@tonic-gate 		}
25710Sstevel@tonic-gate 		break;
25720Sstevel@tonic-gate 	}
25730Sstevel@tonic-gate 
25740Sstevel@tonic-gate 	case MD_MED_GET_TAG:
25750Sstevel@tonic-gate 	{
25760Sstevel@tonic-gate 		if (! (mode & FREAD))
25770Sstevel@tonic-gate 			return (EACCES);
25780Sstevel@tonic-gate 
25790Sstevel@tonic-gate 		sz = sizeof (mddb_dtag_get_parm_t);
25800Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
25810Sstevel@tonic-gate 
25820Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
25830Sstevel@tonic-gate 			err = EFAULT;
25840Sstevel@tonic-gate 			break;
25850Sstevel@tonic-gate 		}
25860Sstevel@tonic-gate 
25870Sstevel@tonic-gate 		err = gettag_ioctl((mddb_dtag_get_parm_t *)d, mode);
25880Sstevel@tonic-gate 
25890Sstevel@tonic-gate 		break;
25900Sstevel@tonic-gate 	}
25910Sstevel@tonic-gate 
25920Sstevel@tonic-gate 	case MD_MED_USE_TAG:
25930Sstevel@tonic-gate 	{
25940Sstevel@tonic-gate 		if (! (mode & FWRITE))
25950Sstevel@tonic-gate 			return (EACCES);
25960Sstevel@tonic-gate 
25970Sstevel@tonic-gate 		sz = sizeof (mddb_dtag_use_parm_t);
25980Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
25990Sstevel@tonic-gate 
26000Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
26010Sstevel@tonic-gate 			err = EFAULT;
26020Sstevel@tonic-gate 			break;
26030Sstevel@tonic-gate 		}
26040Sstevel@tonic-gate 
26050Sstevel@tonic-gate 		err = usetag_ioctl((mddb_dtag_use_parm_t *)d, mode);
26060Sstevel@tonic-gate 
26070Sstevel@tonic-gate 		break;
26080Sstevel@tonic-gate 	}
26090Sstevel@tonic-gate 
26100Sstevel@tonic-gate 	case MD_MED_ACCEPT:
26110Sstevel@tonic-gate 	{
26120Sstevel@tonic-gate 		if (! (mode & FWRITE))
26130Sstevel@tonic-gate 			return (EACCES);
26140Sstevel@tonic-gate 
26150Sstevel@tonic-gate 		sz = sizeof (mddb_accept_parm_t);
26160Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
26170Sstevel@tonic-gate 
26180Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
26190Sstevel@tonic-gate 			err = EFAULT;
26200Sstevel@tonic-gate 			break;
26210Sstevel@tonic-gate 		}
26220Sstevel@tonic-gate 
26230Sstevel@tonic-gate 		err = accept_ioctl((mddb_accept_parm_t *)d, mode);
26240Sstevel@tonic-gate 
26250Sstevel@tonic-gate 		break;
26260Sstevel@tonic-gate 	}
26270Sstevel@tonic-gate 
26280Sstevel@tonic-gate 	case MD_MED_GET_TLEN:
26290Sstevel@tonic-gate 	{
26300Sstevel@tonic-gate 		if (! (mode & FREAD))
26310Sstevel@tonic-gate 			return (EACCES);
26320Sstevel@tonic-gate 
26330Sstevel@tonic-gate 		sz = sizeof (mddb_med_t_parm_t);
26340Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
26350Sstevel@tonic-gate 
26360Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
26370Sstevel@tonic-gate 			err = EFAULT;
26380Sstevel@tonic-gate 			break;
26390Sstevel@tonic-gate 		}
26400Sstevel@tonic-gate 
26410Sstevel@tonic-gate 		err = med_get_t_size_ioctl((mddb_med_t_parm_t *)d, mode);
26420Sstevel@tonic-gate 
26430Sstevel@tonic-gate 		break;
26440Sstevel@tonic-gate 	}
26450Sstevel@tonic-gate 
26460Sstevel@tonic-gate 	case MD_MED_GET_T:
26470Sstevel@tonic-gate 	{
26480Sstevel@tonic-gate 		if (! (mode & FREAD))
26490Sstevel@tonic-gate 			return (EACCES);
26500Sstevel@tonic-gate 
26510Sstevel@tonic-gate 		sz = (sizeof (mddb_med_t_parm_t) - sizeof (mddb_med_t_ent_t)) +
26520Sstevel@tonic-gate 		    (sizeof (mddb_med_t_ent_t) * med_addr_tab_nents);
26530Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
26540Sstevel@tonic-gate 
26550Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
26560Sstevel@tonic-gate 			err = EFAULT;
26570Sstevel@tonic-gate 			break;
26580Sstevel@tonic-gate 		}
26590Sstevel@tonic-gate 
26600Sstevel@tonic-gate 		err = med_get_t_ioctl((mddb_med_t_parm_t *)d, mode);
26610Sstevel@tonic-gate 
26620Sstevel@tonic-gate 		break;
26630Sstevel@tonic-gate 	}
26640Sstevel@tonic-gate 
26650Sstevel@tonic-gate 	case MD_MED_SET_T:
26660Sstevel@tonic-gate 	{
26670Sstevel@tonic-gate 		if (! (mode & FWRITE))
26680Sstevel@tonic-gate 			return (EACCES);
26690Sstevel@tonic-gate 
26700Sstevel@tonic-gate 		sz = (sizeof (mddb_med_t_parm_t) - sizeof (mddb_med_t_ent_t)) +
26710Sstevel@tonic-gate 		    (sizeof (mddb_med_t_ent_t) * med_addr_tab_nents);
26720Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
26730Sstevel@tonic-gate 
26740Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
26750Sstevel@tonic-gate 			err = EFAULT;
26760Sstevel@tonic-gate 			break;
26770Sstevel@tonic-gate 		}
26780Sstevel@tonic-gate 
26790Sstevel@tonic-gate 		err = med_set_t_ioctl((mddb_med_t_parm_t *)d, mode);
26800Sstevel@tonic-gate 
26810Sstevel@tonic-gate 		break;
26820Sstevel@tonic-gate 	}
26830Sstevel@tonic-gate 
26840Sstevel@tonic-gate 	case  MD_GET_SETSTAT:
26850Sstevel@tonic-gate 	{
26860Sstevel@tonic-gate 		md_gs_stat_parm_t	*gsp;
26870Sstevel@tonic-gate 
26880Sstevel@tonic-gate 		if (! (mode & FREAD))
26890Sstevel@tonic-gate 			return (EACCES);
26900Sstevel@tonic-gate 
26910Sstevel@tonic-gate 		sz = sizeof (md_gs_stat_parm_t);
26920Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
26930Sstevel@tonic-gate 
26940Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
26950Sstevel@tonic-gate 			err = EFAULT;
26960Sstevel@tonic-gate 			break;
26970Sstevel@tonic-gate 		}
26980Sstevel@tonic-gate 
26990Sstevel@tonic-gate 		gsp = (md_gs_stat_parm_t *)d;
27000Sstevel@tonic-gate 
27010Sstevel@tonic-gate 		if (gsp->gs_setno > (md_nsets - 1)) {
27020Sstevel@tonic-gate 			err = EINVAL;
27030Sstevel@tonic-gate 			break;
27040Sstevel@tonic-gate 		}
27050Sstevel@tonic-gate 
27060Sstevel@tonic-gate 		gsp->gs_status = md_set[gsp->gs_setno].s_status;
27070Sstevel@tonic-gate 
27080Sstevel@tonic-gate 		break;
27090Sstevel@tonic-gate 	}
27100Sstevel@tonic-gate 
27110Sstevel@tonic-gate 	case  MD_SETNMDID:
27120Sstevel@tonic-gate 	{
27130Sstevel@tonic-gate 		if (!(mode & FREAD))
27140Sstevel@tonic-gate 			return (EACCES);
27150Sstevel@tonic-gate 
27160Sstevel@tonic-gate 		sz = sizeof (mdnm_params_t);
27170Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
27180Sstevel@tonic-gate 
27190Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
27200Sstevel@tonic-gate 			err = EFAULT;
27210Sstevel@tonic-gate 			break;
27220Sstevel@tonic-gate 		}
27230Sstevel@tonic-gate 
27240Sstevel@tonic-gate 		err = update_namespace_did_ioctl((mdnm_params_t *)d, mode);
27250Sstevel@tonic-gate 		break;
27260Sstevel@tonic-gate 
27270Sstevel@tonic-gate 	}
27280Sstevel@tonic-gate 	case  MD_IOCUPD_NM:
27290Sstevel@tonic-gate 	{
27300Sstevel@tonic-gate 		char *dname;
27310Sstevel@tonic-gate 		char *pname;
27320Sstevel@tonic-gate 		uint_t	devnamelen, pathnamelen;
27330Sstevel@tonic-gate 
27340Sstevel@tonic-gate 		if (!(mode & FREAD))
27350Sstevel@tonic-gate 			return (EACCES);
27360Sstevel@tonic-gate 
27370Sstevel@tonic-gate 		sz = sizeof (mdnm_params_t);
27380Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
27390Sstevel@tonic-gate 
27400Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
27410Sstevel@tonic-gate 			err = EFAULT;
27420Sstevel@tonic-gate 			break;
27430Sstevel@tonic-gate 		}
27440Sstevel@tonic-gate 
27450Sstevel@tonic-gate 		devnamelen = ((mdnm_params_t *)d)->devname_len;
27460Sstevel@tonic-gate 		pathnamelen = ((mdnm_params_t *)d)->pathname_len;
27470Sstevel@tonic-gate 
27480Sstevel@tonic-gate 		if ((devnamelen > MAXPATHLEN) || (pathnamelen > MAXPATHLEN) ||
27490Sstevel@tonic-gate 		    (devnamelen == 0) || (pathnamelen == 0)) {
27500Sstevel@tonic-gate 			kmem_free(d, sz);
27510Sstevel@tonic-gate 			return (EINVAL);
27520Sstevel@tonic-gate 		}
27530Sstevel@tonic-gate 
27540Sstevel@tonic-gate 		/* alloc memory for devname */
27550Sstevel@tonic-gate 		dname = kmem_alloc(devnamelen + 1, KM_SLEEP);
27560Sstevel@tonic-gate 
27570Sstevel@tonic-gate 		if (ddi_copyin(
27580Sstevel@tonic-gate 		    (void *)(uintptr_t)((mdnm_params_t *)d)->devname,
27590Sstevel@tonic-gate 		    (void *)dname, devnamelen + 1, mode) != 0) {
27600Sstevel@tonic-gate 			err = EFAULT;
27610Sstevel@tonic-gate 			kmem_free(dname, devnamelen + 1);
27620Sstevel@tonic-gate 			break;
27630Sstevel@tonic-gate 		}
27640Sstevel@tonic-gate 
27650Sstevel@tonic-gate 		pname = kmem_alloc(pathnamelen + 1, KM_SLEEP);
27660Sstevel@tonic-gate 
27670Sstevel@tonic-gate 		if (ddi_copyin(
27680Sstevel@tonic-gate 		    (void *)(uintptr_t)((mdnm_params_t *)d)->pathname,
27690Sstevel@tonic-gate 		    (void *)pname, pathnamelen + 1, mode) != 0) {
27700Sstevel@tonic-gate 			err = EFAULT;
27710Sstevel@tonic-gate 			kmem_free(dname, devnamelen + 1);
27720Sstevel@tonic-gate 			kmem_free(pname, pathnamelen + 1);
27730Sstevel@tonic-gate 			break;
27740Sstevel@tonic-gate 		}
27750Sstevel@tonic-gate 
27760Sstevel@tonic-gate 		err = update_namespace_ioctl((mdnm_params_t *)d, dname, pname,
27770Sstevel@tonic-gate 		    mode);
27780Sstevel@tonic-gate 
27790Sstevel@tonic-gate 		kmem_free(dname, devnamelen + 1);
27800Sstevel@tonic-gate 		kmem_free(pname, pathnamelen + 1);
27810Sstevel@tonic-gate 		break;
27820Sstevel@tonic-gate 	}
27830Sstevel@tonic-gate 
27840Sstevel@tonic-gate 	case	MD_IOCUPD_LOCNM:
27850Sstevel@tonic-gate 	{
27860Sstevel@tonic-gate 		char *dname;
27870Sstevel@tonic-gate 		char *pname;
27880Sstevel@tonic-gate 		uint_t	devnamelen, pathnamelen;
27890Sstevel@tonic-gate 
27900Sstevel@tonic-gate 		if (!(mode & FREAD))
27910Sstevel@tonic-gate 			return (EACCES);
27920Sstevel@tonic-gate 
27930Sstevel@tonic-gate 		sz = sizeof (mdnm_params_t);
27940Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
27950Sstevel@tonic-gate 
27960Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
27970Sstevel@tonic-gate 			err = EFAULT;
27980Sstevel@tonic-gate 			break;
27990Sstevel@tonic-gate 		}
28000Sstevel@tonic-gate 
28010Sstevel@tonic-gate 		devnamelen = ((mdnm_params_t *)d)->devname_len;
28020Sstevel@tonic-gate 		pathnamelen = ((mdnm_params_t *)d)->pathname_len;
28030Sstevel@tonic-gate 
28040Sstevel@tonic-gate 		if ((devnamelen > MAXPATHLEN) || (pathnamelen > MAXPATHLEN) ||
28050Sstevel@tonic-gate 		    (devnamelen == 0) || (pathnamelen == 0)) {
28060Sstevel@tonic-gate 			kmem_free(d, sz);
28070Sstevel@tonic-gate 			return (EINVAL);
28080Sstevel@tonic-gate 		}
28090Sstevel@tonic-gate 
28100Sstevel@tonic-gate 		/* alloc memory for devname */
28110Sstevel@tonic-gate 		dname = kmem_alloc(devnamelen + 1, KM_SLEEP);
28120Sstevel@tonic-gate 
28130Sstevel@tonic-gate 		if (ddi_copyin(
28140Sstevel@tonic-gate 		    (void *)(uintptr_t)((mdnm_params_t *)d)->devname,
28150Sstevel@tonic-gate 		    (void *)dname, devnamelen + 1, mode) != 0) {
28160Sstevel@tonic-gate 			err = EFAULT;
28170Sstevel@tonic-gate 			kmem_free(dname, devnamelen + 1);
28180Sstevel@tonic-gate 			break;
28190Sstevel@tonic-gate 		}
28200Sstevel@tonic-gate 
28210Sstevel@tonic-gate 		pname = kmem_alloc(pathnamelen + 1, KM_SLEEP);
28220Sstevel@tonic-gate 
28230Sstevel@tonic-gate 		if (ddi_copyin(
28240Sstevel@tonic-gate 		    (void *)(uintptr_t)((mdnm_params_t *)d)->pathname,
28250Sstevel@tonic-gate 		    (void *)pname, pathnamelen + 1, mode) != 0) {
28260Sstevel@tonic-gate 			err = EFAULT;
28270Sstevel@tonic-gate 			kmem_free(dname, devnamelen + 1);
28280Sstevel@tonic-gate 			kmem_free(pname, pathnamelen + 1);
28290Sstevel@tonic-gate 			break;
28300Sstevel@tonic-gate 		}
28310Sstevel@tonic-gate 
28320Sstevel@tonic-gate 		err = update_loc_namespace_ioctl((mdnm_params_t *)d, dname,
28330Sstevel@tonic-gate 		    pname, mode);
28340Sstevel@tonic-gate 
28350Sstevel@tonic-gate 		kmem_free(dname, devnamelen + 1);
28360Sstevel@tonic-gate 		kmem_free(pname, pathnamelen + 1);
28370Sstevel@tonic-gate 		break;
28380Sstevel@tonic-gate 	}
28390Sstevel@tonic-gate 
28400Sstevel@tonic-gate 	case  MD_SET_SETSTAT:
28410Sstevel@tonic-gate 	{
28420Sstevel@tonic-gate #ifdef DEBUG
28430Sstevel@tonic-gate 		/* Can be used to set the s_status flags from user code */
28440Sstevel@tonic-gate 		md_gs_stat_parm_t	*gsp;
28450Sstevel@tonic-gate 
28460Sstevel@tonic-gate 		if (! (mode & FWRITE))
28470Sstevel@tonic-gate 			return (EACCES);
28480Sstevel@tonic-gate 
28490Sstevel@tonic-gate 		sz = sizeof (md_gs_stat_parm_t);
28500Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
28510Sstevel@tonic-gate 
28520Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
28530Sstevel@tonic-gate 			err = EFAULT;
28540Sstevel@tonic-gate 			break;
28550Sstevel@tonic-gate 		}
28560Sstevel@tonic-gate 
28570Sstevel@tonic-gate 		gsp = (md_gs_stat_parm_t *)d;
28580Sstevel@tonic-gate 
28590Sstevel@tonic-gate 		if (gsp->gs_setno > (md_nsets - 1)) {
28600Sstevel@tonic-gate 			err = EINVAL;
28610Sstevel@tonic-gate 			break;
28620Sstevel@tonic-gate 		}
28630Sstevel@tonic-gate 
28640Sstevel@tonic-gate 		md_set[gsp->gs_setno].s_status = gsp->gs_status;
28650Sstevel@tonic-gate 
28660Sstevel@tonic-gate #endif	/* DEBUG */
28670Sstevel@tonic-gate 		break;
28680Sstevel@tonic-gate 	}
28690Sstevel@tonic-gate 
28700Sstevel@tonic-gate 	case MD_IOCGET_DID:
28710Sstevel@tonic-gate 	{
28720Sstevel@tonic-gate 		if (! (mode & FREAD))
28730Sstevel@tonic-gate 			return (EACCES);
28740Sstevel@tonic-gate 
28750Sstevel@tonic-gate 		sz = sizeof (mdnm_params_t);
28760Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
28770Sstevel@tonic-gate 
28780Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
28790Sstevel@tonic-gate 			err = EFAULT;
28800Sstevel@tonic-gate 			break;
28810Sstevel@tonic-gate 		}
28820Sstevel@tonic-gate 
28830Sstevel@tonic-gate 		err = getdid_ioctl((mdnm_params_t *)d, mode);
28840Sstevel@tonic-gate 		break;
28850Sstevel@tonic-gate 	}
28860Sstevel@tonic-gate 
28870Sstevel@tonic-gate 	case MD_IOCSET_DID:
28880Sstevel@tonic-gate 	{
28890Sstevel@tonic-gate 		if (! (mode & FWRITE))
28900Sstevel@tonic-gate 			return (EACCES);
28910Sstevel@tonic-gate 
28920Sstevel@tonic-gate 		sz = sizeof (mdnm_params_t);
28930Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
28940Sstevel@tonic-gate 
28950Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
28960Sstevel@tonic-gate 			err = EFAULT;
28970Sstevel@tonic-gate 			break;
28980Sstevel@tonic-gate 		}
28990Sstevel@tonic-gate 
29000Sstevel@tonic-gate 		err = setdid_ioctl((mdnm_params_t *)d, mode);
29010Sstevel@tonic-gate 		break;
29020Sstevel@tonic-gate 	}
29030Sstevel@tonic-gate 
29040Sstevel@tonic-gate 	case MD_IOCGET_DIDMIN:
29050Sstevel@tonic-gate 	{
29060Sstevel@tonic-gate 		if (! (mode & FREAD))
29070Sstevel@tonic-gate 			return (EACCES);
29080Sstevel@tonic-gate 
29090Sstevel@tonic-gate 		sz = sizeof (mdnm_params_t);
29100Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
29110Sstevel@tonic-gate 
29120Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
29130Sstevel@tonic-gate 			err = EFAULT;
29140Sstevel@tonic-gate 			break;
29150Sstevel@tonic-gate 		}
29160Sstevel@tonic-gate 
29170Sstevel@tonic-gate 		if (((mdnm_params_t *)d)->setno >= md_nsets) {
29180Sstevel@tonic-gate 			err = EINVAL;
29190Sstevel@tonic-gate 			break;
29200Sstevel@tonic-gate 		}
29210Sstevel@tonic-gate 
29220Sstevel@tonic-gate 		err = getdidmin_ioctl((mdnm_params_t *)d, mode);
29230Sstevel@tonic-gate 		break;
29240Sstevel@tonic-gate 	}
29250Sstevel@tonic-gate 
29260Sstevel@tonic-gate 	case MD_IOCDID_STAT:
29270Sstevel@tonic-gate 	{
29280Sstevel@tonic-gate 		if (!(mode & FREAD))
29290Sstevel@tonic-gate 			return (EACCES);
29300Sstevel@tonic-gate 
29310Sstevel@tonic-gate 		mddb_didstat_case = 1;
29320Sstevel@tonic-gate 
29330Sstevel@tonic-gate 		err = mddb_didstat_from_user(&d, data, mode, &ds_ctd_addr);
29340Sstevel@tonic-gate 
29350Sstevel@tonic-gate 		if (err) {
29360Sstevel@tonic-gate 			return (err);
29370Sstevel@tonic-gate 		}
29380Sstevel@tonic-gate 
29390Sstevel@tonic-gate 		err = didstat_ioctl((md_i_didstat_t *)d);
29400Sstevel@tonic-gate 		break;
29410Sstevel@tonic-gate 	}
29420Sstevel@tonic-gate 
29430Sstevel@tonic-gate 	case MD_UPGRADE_STAT:
29440Sstevel@tonic-gate 	{
29450Sstevel@tonic-gate 		if (! (mode & FREAD))
29460Sstevel@tonic-gate 			return (EACCES);
29470Sstevel@tonic-gate 
29480Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&md_in_upgrade, data,
29490Sstevel@tonic-gate 		    sizeof (int), mode) != 0) {
29500Sstevel@tonic-gate 			err = EFAULT;
29510Sstevel@tonic-gate 			break;
29520Sstevel@tonic-gate 		}
29530Sstevel@tonic-gate 		break;
29540Sstevel@tonic-gate 	}
29550Sstevel@tonic-gate 
29560Sstevel@tonic-gate 	case MD_SETMASTER:
29570Sstevel@tonic-gate 	{
29580Sstevel@tonic-gate 		if (! (mode & FREAD))
29590Sstevel@tonic-gate 			return (EACCES);
29600Sstevel@tonic-gate 
29610Sstevel@tonic-gate 		sz = sizeof (mddb_setmaster_config_t);
29620Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
29630Sstevel@tonic-gate 
29640Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
29650Sstevel@tonic-gate 			err = EFAULT;
29660Sstevel@tonic-gate 			break;
29670Sstevel@tonic-gate 		}
29680Sstevel@tonic-gate 
29690Sstevel@tonic-gate 		err = mddb_setmaster_ioctl((mddb_setmaster_config_t *)d);
29700Sstevel@tonic-gate 		break;
29710Sstevel@tonic-gate 	}
29720Sstevel@tonic-gate 
29730Sstevel@tonic-gate 	case MD_MN_SET_DOORH:
29740Sstevel@tonic-gate 	{
29750Sstevel@tonic-gate 	/* This ioctl sets the global kernel variable mdmn_door_handle */
29760Sstevel@tonic-gate 		if (ddi_copyin(data, &mdmn_door_did, sizeof (int), mode) != 0) {
29770Sstevel@tonic-gate 			err = EFAULT;
29780Sstevel@tonic-gate 		} else {
29790Sstevel@tonic-gate 			err = 0;
29800Sstevel@tonic-gate 		}
29810Sstevel@tonic-gate 		mdmn_door_handle = door_ki_lookup(mdmn_door_did);
29820Sstevel@tonic-gate 
29830Sstevel@tonic-gate 		break;
29840Sstevel@tonic-gate 	}
29850Sstevel@tonic-gate 
29860Sstevel@tonic-gate #ifdef DEBUG
29870Sstevel@tonic-gate 	case MD_MN_CHECK_DOOR1:
29880Sstevel@tonic-gate 	{
29890Sstevel@tonic-gate 	/* This ioctl sends a message through a previously opened door */
29900Sstevel@tonic-gate 		int		ret;
29910Sstevel@tonic-gate 		int		msg_test = 11111111;
29920Sstevel@tonic-gate 		int		nloops = 0;
29930Sstevel@tonic-gate 		set_t		setno;
29940Sstevel@tonic-gate 		md_mn_kresult_t	*result;
29950Sstevel@tonic-gate 		uint_t		flags = MD_MSGF_NO_LOG | MD_MSGF_NO_BCAST;
29960Sstevel@tonic-gate 
29970Sstevel@tonic-gate 		result = kmem_zalloc(sizeof (md_mn_kresult_t), KM_SLEEP);
29980Sstevel@tonic-gate 		if (ddi_copyin(data, &nloops, sizeof (int), mode) != 0) {
29990Sstevel@tonic-gate 			err = EFAULT;
30000Sstevel@tonic-gate 		} else {
30010Sstevel@tonic-gate 			err = 0;
30020Sstevel@tonic-gate 		}
30030Sstevel@tonic-gate 
30040Sstevel@tonic-gate 		/*
30050Sstevel@tonic-gate 		 * This is a way to tell ksend_message() to use different sets.
30060Sstevel@tonic-gate 		 * Odd numbers go to set 1 even numbers go to set 2
30070Sstevel@tonic-gate 		 */
30080Sstevel@tonic-gate 		if (nloops & 0x1) {
30090Sstevel@tonic-gate 			setno = 1;
30100Sstevel@tonic-gate 		} else {
30110Sstevel@tonic-gate 			setno = 2;
30120Sstevel@tonic-gate 		}
30130Sstevel@tonic-gate 		while (nloops--)  {
30140Sstevel@tonic-gate 			ret = mdmn_ksend_message(
30150Sstevel@tonic-gate 			    setno,
30160Sstevel@tonic-gate 			    MD_MN_MSG_TEST1,
30170Sstevel@tonic-gate 			    flags,
30188452SJohn.Wren.Kennedy@Sun.COM 			    0,
30190Sstevel@tonic-gate 			    (char *)&msg_test,
30200Sstevel@tonic-gate 			    sizeof (msg_test),
30210Sstevel@tonic-gate 			    result);
30220Sstevel@tonic-gate 
30230Sstevel@tonic-gate 			if (ret != 0) {
30240Sstevel@tonic-gate 				printf("mdmn_ksend_message failed (%d)\n", ret);
30250Sstevel@tonic-gate 			}
30260Sstevel@tonic-gate 		}
30270Sstevel@tonic-gate 		kmem_free(result, sizeof (md_mn_kresult_t));
30280Sstevel@tonic-gate 
30290Sstevel@tonic-gate 		break;
30300Sstevel@tonic-gate 	}
30310Sstevel@tonic-gate 
30320Sstevel@tonic-gate 	case MD_MN_CHECK_DOOR2:
30330Sstevel@tonic-gate 	{
30340Sstevel@tonic-gate 	/* This ioctl sends a message through a previously opened door */
30350Sstevel@tonic-gate 		int		ret;
30360Sstevel@tonic-gate 		int		msg_test = 22222222;
30370Sstevel@tonic-gate 		int		nloops = 0;
30380Sstevel@tonic-gate 		md_mn_kresult_t	*result;
30390Sstevel@tonic-gate 		set_t		setno;
30400Sstevel@tonic-gate 		uint_t		flags = MD_MSGF_NO_LOG;
30410Sstevel@tonic-gate 
30420Sstevel@tonic-gate 		result = kmem_zalloc(sizeof (md_mn_kresult_t), KM_SLEEP);
30430Sstevel@tonic-gate 		if (ddi_copyin(data, &nloops, sizeof (int), mode) != 0) {
30440Sstevel@tonic-gate 			err = EFAULT;
30450Sstevel@tonic-gate 		} else {
30460Sstevel@tonic-gate 			err = 0;
30470Sstevel@tonic-gate 		}
30480Sstevel@tonic-gate 		/*
30490Sstevel@tonic-gate 		 * This is a way to tell ksend_message() to use different sets.
30500Sstevel@tonic-gate 		 * Odd numbers go to set 1 even numbers go to set 2
30510Sstevel@tonic-gate 		 */
30520Sstevel@tonic-gate 		if (nloops & 0x1) {
30530Sstevel@tonic-gate 			setno = 1;
30540Sstevel@tonic-gate 		} else {
30550Sstevel@tonic-gate 			setno = 2;
30560Sstevel@tonic-gate 		}
30570Sstevel@tonic-gate 		while (nloops--)  {
30580Sstevel@tonic-gate 			ret = mdmn_ksend_message(
30590Sstevel@tonic-gate 			    setno,
30600Sstevel@tonic-gate 			    MD_MN_MSG_TEST2,
30610Sstevel@tonic-gate 			    flags,
30628452SJohn.Wren.Kennedy@Sun.COM 			    0,
30630Sstevel@tonic-gate 			    (char *)&msg_test,
30640Sstevel@tonic-gate 			    sizeof (msg_test),
30650Sstevel@tonic-gate 			    result);
30660Sstevel@tonic-gate 
30670Sstevel@tonic-gate 			if (ret != 0) {
30680Sstevel@tonic-gate 				printf("mdmn_ksend_message failed (%d)\n", ret);
30690Sstevel@tonic-gate 			}
30700Sstevel@tonic-gate 		}
30710Sstevel@tonic-gate 		kmem_free(result, sizeof (md_mn_kresult_t));
30720Sstevel@tonic-gate 
30730Sstevel@tonic-gate 		break;
30740Sstevel@tonic-gate 	}
30750Sstevel@tonic-gate #endif
30760Sstevel@tonic-gate 
30770Sstevel@tonic-gate 	case MD_MN_OPEN_TEST:
30780Sstevel@tonic-gate 	{
30795428Spetede 		md_clu_open_t	*p;
30805428Spetede 		minor_t		mnum;
30815428Spetede 
30820Sstevel@tonic-gate 		sz = sizeof (md_clu_open_t);
30830Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
30840Sstevel@tonic-gate 
30850Sstevel@tonic-gate 		if (ddi_copyin(data, d, sizeof (md_clu_open_t), mode) != 0) {
30860Sstevel@tonic-gate 			err = EFAULT;
30870Sstevel@tonic-gate 			break;
30880Sstevel@tonic-gate 		}
30895428Spetede 
30905428Spetede 		p = (md_clu_open_t *)d;
30915428Spetede 		mnum = md_getminor(p->clu_dev);
30925428Spetede 
30935428Spetede 		if ((err = verify_minor(mnum)) != 0) {
30945428Spetede 			if (err == EINVAL)
30955428Spetede 				(void) mdmderror(&p->clu_mde, MDE_INVAL_UNIT,
30965428Spetede 				    mnum);
30975428Spetede 			break;
30985428Spetede 		}
30995428Spetede 		err = md_clu_ioctl(p);
31000Sstevel@tonic-gate 		break;
31010Sstevel@tonic-gate 	}
31020Sstevel@tonic-gate 
31030Sstevel@tonic-gate 	case MD_MN_SET_NODEID:
31040Sstevel@tonic-gate 	{
31050Sstevel@tonic-gate 		if (! (mode & FWRITE))
31060Sstevel@tonic-gate 			return (EACCES);
31070Sstevel@tonic-gate 
31080Sstevel@tonic-gate 		sz = sizeof (mddb_set_node_params_t);
31090Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
31100Sstevel@tonic-gate 
31110Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
31120Sstevel@tonic-gate 			err = EFAULT;
31130Sstevel@tonic-gate 			break;
31140Sstevel@tonic-gate 		}
31150Sstevel@tonic-gate 		snp = (mddb_set_node_params_t *)d;
31160Sstevel@tonic-gate 
31170Sstevel@tonic-gate 		if (snp->sn_setno >= md_nsets) {
31180Sstevel@tonic-gate 			err = EINVAL;
31190Sstevel@tonic-gate 			break;
31200Sstevel@tonic-gate 		}
31210Sstevel@tonic-gate 
31220Sstevel@tonic-gate 		md_set[snp->sn_setno].s_nodeid = snp->sn_nodeid;
31230Sstevel@tonic-gate 
31240Sstevel@tonic-gate 		if (md_mn_mynode_id == MD_MN_INVALID_NID)
31250Sstevel@tonic-gate 			md_mn_mynode_id = snp->sn_nodeid;
31260Sstevel@tonic-gate #ifdef DEBUG
31270Sstevel@tonic-gate 		else if (md_mn_mynode_id != snp->sn_nodeid)
31280Sstevel@tonic-gate 			cmn_err(CE_WARN, "Previously set nodeid 0x%x for this"
31290Sstevel@tonic-gate 			    "node doesn't match nodeid being set 0x%x\n",
31300Sstevel@tonic-gate 			    md_mn_mynode_id, snp->sn_nodeid);
31310Sstevel@tonic-gate #endif /* DEBUG */
31320Sstevel@tonic-gate 		err = 0;
31330Sstevel@tonic-gate 		break;
31340Sstevel@tonic-gate 	}
31350Sstevel@tonic-gate 	case MD_IOCGUNIQMSGID:
31360Sstevel@tonic-gate 	{
31370Sstevel@tonic-gate 		md_mn_msgid_t msgid;
31380Sstevel@tonic-gate 		struct timeval32 tv;
31390Sstevel@tonic-gate 
31400Sstevel@tonic-gate 		if (! (mode & FREAD))
31410Sstevel@tonic-gate 			return (EACCES);
31420Sstevel@tonic-gate 
31430Sstevel@tonic-gate 		uniqtime32(&tv);
31440Sstevel@tonic-gate 
31450Sstevel@tonic-gate 		/* high 32 bits are the seconds */
31460Sstevel@tonic-gate 		msgid.mid_time = (u_longlong_t)tv.tv_sec << 32;
31470Sstevel@tonic-gate 		/* low 32 bits are the micro secs */
31480Sstevel@tonic-gate 		msgid.mid_time |= tv.tv_usec;
31490Sstevel@tonic-gate 
31500Sstevel@tonic-gate 		msgid.mid_nid = md_mn_mynode_id;
31510Sstevel@tonic-gate 		/*
31520Sstevel@tonic-gate 		 * This is never called for submessages, so we better
31530Sstevel@tonic-gate 		 * null out the submessage ID
31540Sstevel@tonic-gate 		 */
31550Sstevel@tonic-gate 		msgid.mid_smid = 0;
31560Sstevel@tonic-gate 
31570Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&msgid, data, sizeof (msgid), mode)
31580Sstevel@tonic-gate 		    != 0) {
31590Sstevel@tonic-gate 			err = EFAULT;
31600Sstevel@tonic-gate 			break;
31610Sstevel@tonic-gate 		}
31620Sstevel@tonic-gate 		break;
31630Sstevel@tonic-gate 	}
31640Sstevel@tonic-gate 
31650Sstevel@tonic-gate 	/*
31660Sstevel@tonic-gate 	 * suspend the IO's for a given set number.
31670Sstevel@tonic-gate 	 *
31680Sstevel@tonic-gate 	 * If setno = 0 is specified, try operation on all snarfed MN disksets.
31690Sstevel@tonic-gate 	 * If there are no snarfed MN disksets, then return success.
31700Sstevel@tonic-gate 	 *
31710Sstevel@tonic-gate 	 * If a specific set number is given, then return EINVAL if unable
31720Sstevel@tonic-gate 	 * to perform operation.
31730Sstevel@tonic-gate 	 */
31740Sstevel@tonic-gate 	case MD_MN_SUSPEND_SET:
31750Sstevel@tonic-gate 	{
31760Sstevel@tonic-gate 		set_t	setno;
31770Sstevel@tonic-gate 		int	rval = 0;
31780Sstevel@tonic-gate 		int	i;
31790Sstevel@tonic-gate 
31800Sstevel@tonic-gate 		if (! (mode & FWRITE))
31810Sstevel@tonic-gate 			return (EACCES);
31820Sstevel@tonic-gate 
31830Sstevel@tonic-gate 		if (ddi_copyin(data, &setno, sizeof (set_t), mode) != 0) {
31840Sstevel@tonic-gate 			return (EFAULT);
31850Sstevel@tonic-gate 		}
31860Sstevel@tonic-gate 		if (setno >= MD_MAXSETS) {
31870Sstevel@tonic-gate 			return (EINVAL);
31880Sstevel@tonic-gate 		}
31890Sstevel@tonic-gate 
31900Sstevel@tonic-gate 		mutex_enter(&md_mx);
31910Sstevel@tonic-gate 		if (setno == 0) {
31920Sstevel@tonic-gate 			/* if set number is 0, we walk all sets */
31930Sstevel@tonic-gate 			for (i = 1; i <= (MD_MAXSETS - 1); i++) {
31940Sstevel@tonic-gate 				if ((md_set[i].s_status &
31950Sstevel@tonic-gate 				    (MD_SET_SNARFED|MD_SET_MNSET)) ==
31960Sstevel@tonic-gate 				    (MD_SET_SNARFED|MD_SET_MNSET)) {
31970Sstevel@tonic-gate 					md_set[i].s_status |= MD_SET_HALTED;
31980Sstevel@tonic-gate 				}
31990Sstevel@tonic-gate 			}
32000Sstevel@tonic-gate 		} else {
32010Sstevel@tonic-gate 			/* If unable to halt specified set, set EINVAL */
32020Sstevel@tonic-gate 			if ((md_set[setno].s_status &
32030Sstevel@tonic-gate 			    (MD_SET_SNARFED|MD_SET_MNSET)) ==
32040Sstevel@tonic-gate 			    (MD_SET_SNARFED|MD_SET_MNSET)) {
32050Sstevel@tonic-gate 				md_set[setno].s_status |= MD_SET_HALTED;
32060Sstevel@tonic-gate 			} else {
32070Sstevel@tonic-gate 				rval = EINVAL;
32080Sstevel@tonic-gate 			}
32090Sstevel@tonic-gate 		}
32100Sstevel@tonic-gate 		mutex_exit(&md_mx);
32110Sstevel@tonic-gate 		return (rval);
32120Sstevel@tonic-gate 	}
32130Sstevel@tonic-gate 
32140Sstevel@tonic-gate 	/*
32150Sstevel@tonic-gate 	 * resume the IO's for a given set number.
32160Sstevel@tonic-gate 	 *
32170Sstevel@tonic-gate 	 * If setno = 0 is specified, try operation on all snarfed MN disksets.
32180Sstevel@tonic-gate 	 * If there are no snarfed MN disksets, then return success.
32190Sstevel@tonic-gate 	 *
32200Sstevel@tonic-gate 	 * If a specific set number is given, then return EINVAL if unable
32210Sstevel@tonic-gate 	 * to perform operation.
32220Sstevel@tonic-gate 	 */
32230Sstevel@tonic-gate 	case MD_MN_RESUME_SET:
32240Sstevel@tonic-gate 	{
32250Sstevel@tonic-gate 		set_t	setno;
32260Sstevel@tonic-gate 		int	resumed_set = 0;
32270Sstevel@tonic-gate 		int	rval = 0;
32280Sstevel@tonic-gate 		int	i;
32290Sstevel@tonic-gate 
32300Sstevel@tonic-gate 		if (! (mode & FWRITE))
32310Sstevel@tonic-gate 			return (EACCES);
32320Sstevel@tonic-gate 
32330Sstevel@tonic-gate 		if (ddi_copyin(data, &setno, sizeof (set_t), mode) != 0) {
32340Sstevel@tonic-gate 			return (EFAULT);
32350Sstevel@tonic-gate 		}
32360Sstevel@tonic-gate 		if (setno >= MD_MAXSETS) {
32370Sstevel@tonic-gate 			return (EINVAL);
32380Sstevel@tonic-gate 		}
32390Sstevel@tonic-gate 
32400Sstevel@tonic-gate 		/* if 0 is specified as the set number, we walk all sets */
32410Sstevel@tonic-gate 		mutex_enter(&md_mx);
32420Sstevel@tonic-gate 		if (setno == 0) {
32430Sstevel@tonic-gate 			/* if set number is 0, we walk all sets */
32440Sstevel@tonic-gate 			for (i = 1; i <= (MD_MAXSETS - 1); i++) {
32450Sstevel@tonic-gate 				if ((md_set[i].s_status &
32460Sstevel@tonic-gate 				    (MD_SET_SNARFED|MD_SET_MNSET)) ==
32470Sstevel@tonic-gate 				    (MD_SET_SNARFED|MD_SET_MNSET)) {
32480Sstevel@tonic-gate 					md_set[i].s_status &= ~MD_SET_HALTED;
32490Sstevel@tonic-gate 					resumed_set = 1;
32500Sstevel@tonic-gate 				}
32510Sstevel@tonic-gate 			}
32520Sstevel@tonic-gate 		} else {
32530Sstevel@tonic-gate 			/* If unable to resume specified set, set EINVAL */
32540Sstevel@tonic-gate 			if ((md_set[setno].s_status &
32550Sstevel@tonic-gate 			    (MD_SET_SNARFED|MD_SET_MNSET)) ==
32560Sstevel@tonic-gate 			    (MD_SET_SNARFED|MD_SET_MNSET)) {
32570Sstevel@tonic-gate 				md_set[setno].s_status &= ~MD_SET_HALTED;
32580Sstevel@tonic-gate 				resumed_set = 1;
32590Sstevel@tonic-gate 			} else {
32600Sstevel@tonic-gate 				rval = EINVAL;
32610Sstevel@tonic-gate 			}
32620Sstevel@tonic-gate 		}
32630Sstevel@tonic-gate 
32640Sstevel@tonic-gate 		/*
32650Sstevel@tonic-gate 		 * In case we actually resumed at least one set,
32660Sstevel@tonic-gate 		 * Inform all threads waiting for this change
32670Sstevel@tonic-gate 		 */
32680Sstevel@tonic-gate 		if (resumed_set == 1) {
32690Sstevel@tonic-gate 			cv_broadcast(&md_cv);
32700Sstevel@tonic-gate 		}
32710Sstevel@tonic-gate 
32720Sstevel@tonic-gate 		mutex_exit(&md_mx);
32730Sstevel@tonic-gate 		return (rval);
32740Sstevel@tonic-gate 	}
32750Sstevel@tonic-gate 
32760Sstevel@tonic-gate 	case MD_MN_MDDB_PARSE:
32770Sstevel@tonic-gate 	{
32780Sstevel@tonic-gate 		if (! (mode & FWRITE))
32790Sstevel@tonic-gate 			return (EACCES);
32800Sstevel@tonic-gate 
32810Sstevel@tonic-gate 		sz = sizeof (mddb_parse_parm_t);
32820Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
32830Sstevel@tonic-gate 
32840Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
32850Sstevel@tonic-gate 			err = EFAULT;
32860Sstevel@tonic-gate 			break;
32870Sstevel@tonic-gate 		}
32880Sstevel@tonic-gate 		err = mddb_parse((mddb_parse_parm_t *)d);
32890Sstevel@tonic-gate 		break;
32900Sstevel@tonic-gate 
32910Sstevel@tonic-gate 	}
32920Sstevel@tonic-gate 
32930Sstevel@tonic-gate 	case MD_MN_MDDB_BLOCK:
32940Sstevel@tonic-gate 	{
32950Sstevel@tonic-gate 		if (! (mode & FWRITE))
32960Sstevel@tonic-gate 			return (EACCES);
32970Sstevel@tonic-gate 
32980Sstevel@tonic-gate 		sz = sizeof (mddb_block_parm_t);
32990Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
33000Sstevel@tonic-gate 
33010Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
33020Sstevel@tonic-gate 			err = EFAULT;
33030Sstevel@tonic-gate 			break;
33040Sstevel@tonic-gate 		}
33050Sstevel@tonic-gate 		err = mddb_block((mddb_block_parm_t *)d);
33060Sstevel@tonic-gate 		break;
33070Sstevel@tonic-gate 
33080Sstevel@tonic-gate 	}
33090Sstevel@tonic-gate 
33100Sstevel@tonic-gate 	case MD_MN_MDDB_OPTRECFIX:
33110Sstevel@tonic-gate 	{
33120Sstevel@tonic-gate 		if (! (mode & FWRITE))
33130Sstevel@tonic-gate 			return (EACCES);
33140Sstevel@tonic-gate 
33150Sstevel@tonic-gate 		sz = sizeof (mddb_optrec_parm_t);
33160Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
33170Sstevel@tonic-gate 
33180Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
33190Sstevel@tonic-gate 			err = EFAULT;
33200Sstevel@tonic-gate 			break;
33210Sstevel@tonic-gate 		}
33220Sstevel@tonic-gate 		err = mddb_optrecfix((mddb_optrec_parm_t *)d);
33230Sstevel@tonic-gate 		break;
33240Sstevel@tonic-gate 
33250Sstevel@tonic-gate 	}
33260Sstevel@tonic-gate 
33270Sstevel@tonic-gate 	case MD_MN_CHK_WRT_MDDB:
33280Sstevel@tonic-gate 	{
33290Sstevel@tonic-gate 		if (! (mode & FWRITE))
33300Sstevel@tonic-gate 			return (EACCES);
33310Sstevel@tonic-gate 
33320Sstevel@tonic-gate 		sz = sizeof (mddb_config_t);
33330Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
33340Sstevel@tonic-gate 
33350Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
33360Sstevel@tonic-gate 			err = EFAULT;
33370Sstevel@tonic-gate 			break;
33380Sstevel@tonic-gate 		}
33390Sstevel@tonic-gate 
33400Sstevel@tonic-gate 		err = mddb_check_write_ioctl((mddb_config_t *)d);
33410Sstevel@tonic-gate 		break;
33420Sstevel@tonic-gate 	}
33430Sstevel@tonic-gate 
33440Sstevel@tonic-gate 	case MD_MN_SET_SETFLAGS:
33450Sstevel@tonic-gate 	case MD_MN_GET_SETFLAGS:
33460Sstevel@tonic-gate 	{
33470Sstevel@tonic-gate 		if (! (mode & FREAD))
33480Sstevel@tonic-gate 			return (EACCES);
33490Sstevel@tonic-gate 
33500Sstevel@tonic-gate 		sz = sizeof (mddb_setflags_config_t);
33510Sstevel@tonic-gate 		d = kmem_alloc(sz, KM_SLEEP);
33520Sstevel@tonic-gate 
33530Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
33540Sstevel@tonic-gate 			err = EFAULT;
33550Sstevel@tonic-gate 			break;
33560Sstevel@tonic-gate 		}
33570Sstevel@tonic-gate 
33580Sstevel@tonic-gate 		err = mddb_setflags_ioctl((mddb_setflags_config_t *)d);
33590Sstevel@tonic-gate 		break;
33600Sstevel@tonic-gate 	}
33610Sstevel@tonic-gate 
33620Sstevel@tonic-gate 	case MD_MN_COMMD_ERR:
33630Sstevel@tonic-gate 	{
33640Sstevel@tonic-gate 		md_mn_commd_err_t *cmp;
33650Sstevel@tonic-gate 		char *msg;
33660Sstevel@tonic-gate 
33670Sstevel@tonic-gate 		sz = sizeof (md_mn_commd_err_t);
33680Sstevel@tonic-gate 		d = kmem_zalloc(sz, KM_SLEEP);
33690Sstevel@tonic-gate 
33700Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
33710Sstevel@tonic-gate 			err = EFAULT;
33720Sstevel@tonic-gate 			break;
33730Sstevel@tonic-gate 		}
33740Sstevel@tonic-gate 
33750Sstevel@tonic-gate 		cmp = (md_mn_commd_err_t *)d;
33760Sstevel@tonic-gate 		if (cmp->size > MAXPATHLEN) {
33770Sstevel@tonic-gate 			err = EINVAL;
33780Sstevel@tonic-gate 			break;
33790Sstevel@tonic-gate 		}
33800Sstevel@tonic-gate 
33810Sstevel@tonic-gate 		msg = (char *)kmem_zalloc(cmp->size + 1, KM_SLEEP);
338262Sjeanm 		if (ddi_copyin((caddr_t)(uintptr_t)cmp->md_message, msg,
33835428Spetede 		    cmp->size, mode) != 0) {
33840Sstevel@tonic-gate 			kmem_free(msg, cmp->size + 1);
33850Sstevel@tonic-gate 			err = EFAULT;
33860Sstevel@tonic-gate 			break;
33870Sstevel@tonic-gate 		}
33880Sstevel@tonic-gate 		cmn_err(CE_WARN, "%s\n", msg);
33890Sstevel@tonic-gate 		kmem_free(msg, cmp->size + 1);
33900Sstevel@tonic-gate 		break;
33910Sstevel@tonic-gate 	}
33920Sstevel@tonic-gate 
33930Sstevel@tonic-gate 	case MD_IOCMAKE_DEV:
33940Sstevel@tonic-gate 	{
33950Sstevel@tonic-gate 		if (! (mode & FWRITE))
33960Sstevel@tonic-gate 			return (EACCES);
33970Sstevel@tonic-gate 
33980Sstevel@tonic-gate 		sz = sizeof (md_mkdev_params_t);
33990Sstevel@tonic-gate 
34000Sstevel@tonic-gate 		if ((d = kmem_alloc(sz, KM_NOSLEEP)) == NULL)
34010Sstevel@tonic-gate 			return (ENOMEM);
34020Sstevel@tonic-gate 
34030Sstevel@tonic-gate 		if (ddi_copyin(data, d, sz, mode) != 0) {
34040Sstevel@tonic-gate 			err = EFAULT;
34050Sstevel@tonic-gate 			break;
34060Sstevel@tonic-gate 		}
34070Sstevel@tonic-gate 
34080Sstevel@tonic-gate 		err = mkdev_ioctl((md_mkdev_params_t *)d);
34090Sstevel@tonic-gate 		break;
34100Sstevel@tonic-gate 	}
34110Sstevel@tonic-gate 
34121623Stw21770 	case MD_IOCREM_DEV:
34131623Stw21770 	{
34141623Stw21770 		set_t	setno;
34151623Stw21770 
34161623Stw21770 		if (! (mode & FWRITE))
34171623Stw21770 			return (EACCES);
34181623Stw21770 
34191623Stw21770 		sz = sizeof (minor_t);
34201623Stw21770 
34211623Stw21770 		d = kmem_zalloc(sz, KM_SLEEP);
34221623Stw21770 
34231623Stw21770 		if (ddi_copyin(data, d, sz, mode) != 0) {
34241623Stw21770 			err = EFAULT;
34251623Stw21770 			break;
34261623Stw21770 		}
34271623Stw21770 
34281623Stw21770 		/*
34291623Stw21770 		 * This ioctl is called to cleanup the device name
34301623Stw21770 		 * space when metainit fails or -n is invoked
34311623Stw21770 		 * In this case, reclaim the dispatched un slot
34321623Stw21770 		 */
34331623Stw21770 		setno = MD_MIN2SET(*(minor_t *)d);
34345428Spetede 		if (setno >= md_nsets) {
34355428Spetede 			err = EINVAL;
34365428Spetede 			break;
34375428Spetede 		} else if (md_set[setno].s_un_next <= 0) {
34381623Stw21770 			err = EFAULT;
34391623Stw21770 			break;
34401623Stw21770 		} else {
34411623Stw21770 			md_set[setno].s_un_next--;
34421623Stw21770 		}
34431623Stw21770 
34441623Stw21770 		/*
34451623Stw21770 		 * Attempt to remove the assocated device node
34461623Stw21770 		 */
34472077Stw21770 		md_remove_minor_node(*(minor_t *)d);
34481623Stw21770 		break;
34491623Stw21770 	}
34501623Stw21770 
34510Sstevel@tonic-gate 	/*
34528452SJohn.Wren.Kennedy@Sun.COM 	 * Update md_mn_commd_pid global to reflect presence or absence of
34530Sstevel@tonic-gate 	 * /usr/sbin/rpc.mdcommd. This allows us to determine if an RPC failure
34540Sstevel@tonic-gate 	 * is expected during a mdmn_ksend_message() handshake. If the commd is
34550Sstevel@tonic-gate 	 * not present then an RPC failure is acceptable. If the commd _is_
34560Sstevel@tonic-gate 	 * present then an RPC failure means we have an inconsistent view across
34570Sstevel@tonic-gate 	 * the cluster.
34580Sstevel@tonic-gate 	 */
34590Sstevel@tonic-gate 	case MD_MN_SET_COMMD_RUNNING:
34600Sstevel@tonic-gate 	{
34610Sstevel@tonic-gate 		if (! (mode & FWRITE))
34620Sstevel@tonic-gate 			return (EACCES);
34630Sstevel@tonic-gate 
34648452SJohn.Wren.Kennedy@Sun.COM 		md_mn_commd_pid = (pid_t)(intptr_t)data;
34650Sstevel@tonic-gate 		err = 0;
34660Sstevel@tonic-gate 		break;
34670Sstevel@tonic-gate 	}
34680Sstevel@tonic-gate 
34690Sstevel@tonic-gate 	case MD_IOCIMP_LOAD:
34700Sstevel@tonic-gate 	{
34710Sstevel@tonic-gate 		if (! (mode & FWRITE))
34720Sstevel@tonic-gate 			return (EACCES);
34730Sstevel@tonic-gate 
34741945Sjeanm 		mddb_config_case = 1;
34751945Sjeanm 
34761945Sjeanm 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
34771945Sjeanm 		    &c_old_devid_addr);
34781945Sjeanm 
34791945Sjeanm 		if (err) {
34801945Sjeanm 			return (err);
34810Sstevel@tonic-gate 		}
34820Sstevel@tonic-gate 
34831945Sjeanm 		err = md_imp_snarf_set((mddb_config_t *)d);
34840Sstevel@tonic-gate 		break;
34850Sstevel@tonic-gate 
34860Sstevel@tonic-gate 	}
34870Sstevel@tonic-gate 
34880Sstevel@tonic-gate 	case MD_DB_LBINITTIME:
34890Sstevel@tonic-gate 	{
34900Sstevel@tonic-gate 		if (! (mode & FWRITE))
34910Sstevel@tonic-gate 			return (EACCES);
34920Sstevel@tonic-gate 
34930Sstevel@tonic-gate 		mddb_config_case = 1;
34940Sstevel@tonic-gate 
34950Sstevel@tonic-gate 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
34960Sstevel@tonic-gate 		    &c_old_devid_addr);
34970Sstevel@tonic-gate 
34980Sstevel@tonic-gate 		if (err)
34990Sstevel@tonic-gate 			return (err);
35000Sstevel@tonic-gate 
35010Sstevel@tonic-gate 		err = get_lb_inittime_ioctl((mddb_config_t *)d);
35020Sstevel@tonic-gate 		break;
35030Sstevel@tonic-gate 	}
35041945Sjeanm 	case MD_IOCUPDATE_NM_RR_DID:
35051945Sjeanm 	{
35061945Sjeanm 		if (! (mode & FWRITE))
35071945Sjeanm 			return (EACCES);
35081945Sjeanm 
35091945Sjeanm 		mddb_config_case = 1;
35101945Sjeanm 
35111945Sjeanm 		err = mddb_config_from_user(&d, data, mode, &c_devid_addr,
35121945Sjeanm 		    &c_old_devid_addr);
35131945Sjeanm 
35141945Sjeanm 		if (err)
35151945Sjeanm 			return (err);
35161945Sjeanm 
35171945Sjeanm 		err = md_update_nm_rr_did_ioctl((mddb_config_t *)d);
35181945Sjeanm 		break;
35191945Sjeanm 	}
35200Sstevel@tonic-gate 	default:
35210Sstevel@tonic-gate 		return (ENOTTY);	/* used by next level up */
35220Sstevel@tonic-gate 	}
35230Sstevel@tonic-gate 
35240Sstevel@tonic-gate 	/*
35250Sstevel@tonic-gate 	 * copyout and free any args
35260Sstevel@tonic-gate 	 */
35270Sstevel@tonic-gate 	if (mddb_config_case) {
35280Sstevel@tonic-gate 		err_to_user = mddb_config_to_user(d, data, mode, c_devid_addr,
35290Sstevel@tonic-gate 		    c_old_devid_addr);
35300Sstevel@tonic-gate 	} else if (mddb_didstat_case) {
35310Sstevel@tonic-gate 		err_to_user = mddb_didstat_to_user(d, data, mode, ds_ctd_addr);
35320Sstevel@tonic-gate 	} else if (sz != 0) {
35330Sstevel@tonic-gate 		if (ddi_copyout(d, data, sz, mode) != 0) {
35340Sstevel@tonic-gate 			err = EFAULT;
35350Sstevel@tonic-gate 		}
35360Sstevel@tonic-gate 		kmem_free(d, sz);
35370Sstevel@tonic-gate 	}
35381623Stw21770 
35390Sstevel@tonic-gate 	if (err)
35400Sstevel@tonic-gate 		return (err);
35410Sstevel@tonic-gate 	return (err_to_user);
35420Sstevel@tonic-gate }
35430Sstevel@tonic-gate 
35440Sstevel@tonic-gate int
md_admin_ioctl(md_dev64_t dev,int cmd,caddr_t data,int mode,IOLOCK * lockp)35450Sstevel@tonic-gate md_admin_ioctl(md_dev64_t dev, int cmd, caddr_t data, int mode, IOLOCK *lockp)
35460Sstevel@tonic-gate {
35470Sstevel@tonic-gate 	md_driver_t	drv;
35480Sstevel@tonic-gate 	int		modindex;
35490Sstevel@tonic-gate 	int		err;
35500Sstevel@tonic-gate 
35510Sstevel@tonic-gate 	/*
35520Sstevel@tonic-gate 	 * see if we can do this without involving the subdriver
35530Sstevel@tonic-gate 	 */
35540Sstevel@tonic-gate 	if ((err = md_base_ioctl(dev, cmd, data, mode, lockp)) != ENOTTY)
35550Sstevel@tonic-gate 		return (err);
35560Sstevel@tonic-gate 
35570Sstevel@tonic-gate 	/*
35580Sstevel@tonic-gate 	 * see what subdriver we need
35590Sstevel@tonic-gate 	 */
35600Sstevel@tonic-gate 	if (! ISMDIOC(cmd))
35610Sstevel@tonic-gate 		return (ENOTTY);
35620Sstevel@tonic-gate 
35630Sstevel@tonic-gate 	if ((!NODBNEEDED(cmd)) && md_snarf_db_set(MD_LOCAL_SET, NULL) != 0)
35640Sstevel@tonic-gate 		return (ENODEV);
35650Sstevel@tonic-gate 
35660Sstevel@tonic-gate 	if (ddi_copyin(data, (caddr_t)&drv, sizeof (drv), mode) != 0)
35670Sstevel@tonic-gate 		return (EFAULT);
35680Sstevel@tonic-gate 
35690Sstevel@tonic-gate 	/*
35700Sstevel@tonic-gate 	 * load subdriver if not already loaded
35710Sstevel@tonic-gate 	 */
35720Sstevel@tonic-gate 	if (((modindex = md_getmodindex(&drv, 0, NODBNEEDED(cmd))) == -1) ||
35730Sstevel@tonic-gate 	    (md_ops[modindex]->md_ioctl == NULL))
35740Sstevel@tonic-gate 		return (ENOTTY);
35750Sstevel@tonic-gate 
35760Sstevel@tonic-gate 	/*
35770Sstevel@tonic-gate 	 * dispatch to subdriver
35780Sstevel@tonic-gate 	 */
35790Sstevel@tonic-gate 	return ((*md_ops[modindex]->md_ioctl)(md_dev64_to_dev(dev), cmd, data,
35805428Spetede 	    mode, lockp));
35810Sstevel@tonic-gate }
35820Sstevel@tonic-gate 
35830Sstevel@tonic-gate void
md_get_geom(md_unit_t * un,struct dk_geom * gp)35840Sstevel@tonic-gate md_get_geom(
35850Sstevel@tonic-gate 	md_unit_t	*un,
35860Sstevel@tonic-gate 	struct dk_geom	*gp
35870Sstevel@tonic-gate )
35880Sstevel@tonic-gate {
35890Sstevel@tonic-gate 	diskaddr_t		tb = un->c.un_total_blocks;
35900Sstevel@tonic-gate 	uint_t			cylsize = un->c.un_nhead * un->c.un_nsect;
35910Sstevel@tonic-gate 
35920Sstevel@tonic-gate 	bzero((caddr_t)gp, sizeof (*gp));
35930Sstevel@tonic-gate 	gp->dkg_nhead = un->c.un_nhead;
35940Sstevel@tonic-gate 	gp->dkg_nsect = un->c.un_nsect;
35950Sstevel@tonic-gate 	gp->dkg_rpm = un->c.un_rpm;
35960Sstevel@tonic-gate 	gp->dkg_write_reinstruct = un->c.un_wr_reinstruct;
35970Sstevel@tonic-gate 	gp->dkg_read_reinstruct = un->c.un_rd_reinstruct;
35980Sstevel@tonic-gate 	gp->dkg_ncyl = (ushort_t)(tb / cylsize);
35990Sstevel@tonic-gate 	if (! (un->c.un_flag & MD_LABELED))	/* skip first cyl */
36000Sstevel@tonic-gate 		gp->dkg_ncyl += 1;
36010Sstevel@tonic-gate 	gp->dkg_pcyl = gp->dkg_ncyl;
36020Sstevel@tonic-gate }
36030Sstevel@tonic-gate 
36040Sstevel@tonic-gate void
md_get_vtoc(md_unit_t * un,struct vtoc * vtoc)36050Sstevel@tonic-gate md_get_vtoc(md_unit_t *un, struct vtoc *vtoc)
36060Sstevel@tonic-gate {
36070Sstevel@tonic-gate 	caddr_t			v;
36080Sstevel@tonic-gate 	mddb_recstatus_t	status;
36090Sstevel@tonic-gate 	struct vtoc32		*vt32;
36100Sstevel@tonic-gate 
36110Sstevel@tonic-gate 	/*
36120Sstevel@tonic-gate 	 * Return vtoc structure fields in the provided VTOC area, addressed
36130Sstevel@tonic-gate 	 * by *vtoc.
36140Sstevel@tonic-gate 	 *
36150Sstevel@tonic-gate 	 */
36160Sstevel@tonic-gate 
36170Sstevel@tonic-gate 	if (un->c.un_vtoc_id) {
36180Sstevel@tonic-gate 		status = mddb_getrecstatus(un->c.un_vtoc_id);
36190Sstevel@tonic-gate 		if (status == MDDB_OK) {
36200Sstevel@tonic-gate 			v = mddb_getrecaddr(un->c.un_vtoc_id);
36210Sstevel@tonic-gate 			/* if this seems to be a sane vtoc, just copy it ... */
36220Sstevel@tonic-gate 			if (((struct vtoc *)v)->v_sanity == VTOC_SANE) {
36230Sstevel@tonic-gate 				bcopy(v, (caddr_t)vtoc, sizeof (struct vtoc));
36240Sstevel@tonic-gate 			} else {
36250Sstevel@tonic-gate 				/* ... else assume a vtoc32 was stored here */
36260Sstevel@tonic-gate 				vt32 = (struct vtoc32 *)v;
36270Sstevel@tonic-gate 				vtoc32tovtoc((*vt32), (*vtoc));
36280Sstevel@tonic-gate 			}
36290Sstevel@tonic-gate 			if (un->c.un_flag & MD_LABELED)
36307563SPrasad.Singamsetty@Sun.COM 				vtoc->v_part[0].p_start = 0ULL;
36310Sstevel@tonic-gate 			else
36327563SPrasad.Singamsetty@Sun.COM 				vtoc->v_part[0].p_start = (diskaddr_t)
36337563SPrasad.Singamsetty@Sun.COM 				    (un->c.un_nhead * un->c.un_nsect);
36340Sstevel@tonic-gate 			vtoc->v_part[0].p_size = un->c.un_total_blocks;
36350Sstevel@tonic-gate 			vtoc->v_version = V_VERSION;
36360Sstevel@tonic-gate 			vtoc->v_sectorsz = DEV_BSIZE;
36370Sstevel@tonic-gate 			return;
36380Sstevel@tonic-gate 		}
36390Sstevel@tonic-gate 
36400Sstevel@tonic-gate 		un->c.un_vtoc_id = 0;
36410Sstevel@tonic-gate 		mddb_commitrec_wrapper(un->c.un_record_id);
36420Sstevel@tonic-gate 	}
36430Sstevel@tonic-gate 
36440Sstevel@tonic-gate 	bzero((caddr_t)vtoc, sizeof (struct vtoc));
36450Sstevel@tonic-gate 	vtoc->v_sanity = VTOC_SANE;
36460Sstevel@tonic-gate 	vtoc->v_nparts = 1;
36470Sstevel@tonic-gate 	vtoc->v_version = V_VERSION;
36480Sstevel@tonic-gate 	vtoc->v_sectorsz = DEV_BSIZE;
36490Sstevel@tonic-gate 	if (un->c.un_flag & MD_LABELED)
36507563SPrasad.Singamsetty@Sun.COM 		vtoc->v_part[0].p_start = 0ULL;
36510Sstevel@tonic-gate 	else
36527563SPrasad.Singamsetty@Sun.COM 		vtoc->v_part[0].p_start = (diskaddr_t)(un->c.un_nhead *
36537563SPrasad.Singamsetty@Sun.COM 		    un->c.un_nsect);
36540Sstevel@tonic-gate 	vtoc->v_part[0].p_size = un->c.un_total_blocks;
36550Sstevel@tonic-gate }
36560Sstevel@tonic-gate 
36570Sstevel@tonic-gate int
md_set_vtoc(md_unit_t * un,struct vtoc * vtoc)36580Sstevel@tonic-gate md_set_vtoc(md_unit_t *un, struct vtoc *vtoc)
36590Sstevel@tonic-gate {
36600Sstevel@tonic-gate 
36610Sstevel@tonic-gate 	struct partition	*vpart;
36620Sstevel@tonic-gate 	int			i;
36630Sstevel@tonic-gate 	mddb_recid_t		recid;
36640Sstevel@tonic-gate 	mddb_recid_t		recids[3];
36650Sstevel@tonic-gate 	mddb_recstatus_t	status;
36660Sstevel@tonic-gate 	caddr_t			v;
36677563SPrasad.Singamsetty@Sun.COM 	diskaddr_t		sb;
36680Sstevel@tonic-gate 
36690Sstevel@tonic-gate 	/*
36700Sstevel@tonic-gate 	 * Sanity-check the vtoc
36710Sstevel@tonic-gate 	 */
36720Sstevel@tonic-gate 	if (vtoc->v_sanity != VTOC_SANE || vtoc->v_nparts != 1)
36730Sstevel@tonic-gate 		return (EINVAL);
36740Sstevel@tonic-gate 
36750Sstevel@tonic-gate 	/* don't allow to create a vtoc for a big metadevice */
36761623Stw21770 	if (un->c.un_revision & MD_64BIT_META_DEV)
36770Sstevel@tonic-gate 		return (ENOTSUP);
36780Sstevel@tonic-gate 	/*
36790Sstevel@tonic-gate 	 * Validate the partition table
36800Sstevel@tonic-gate 	 */
36810Sstevel@tonic-gate 	vpart = vtoc->v_part;
36820Sstevel@tonic-gate 	for (i = 0; i < V_NUMPAR; i++, vpart++) {
36830Sstevel@tonic-gate 		if (i == 0) {
36840Sstevel@tonic-gate 			if (un->c.un_flag & MD_LABELED)
36857563SPrasad.Singamsetty@Sun.COM 				sb = 0ULL;
36860Sstevel@tonic-gate 			else
36877563SPrasad.Singamsetty@Sun.COM 				sb = (diskaddr_t)(un->c.un_nhead *
36887563SPrasad.Singamsetty@Sun.COM 				    un->c.un_nsect);
36890Sstevel@tonic-gate 			if (vpart->p_start != sb)
36900Sstevel@tonic-gate 				return (EINVAL);
36917563SPrasad.Singamsetty@Sun.COM 			if (vpart->p_size != un->c.un_total_blocks)
36920Sstevel@tonic-gate 				return (EINVAL);
36930Sstevel@tonic-gate 			continue;
36940Sstevel@tonic-gate 		}
36950Sstevel@tonic-gate 		/* all other partitions must be zero */
36967563SPrasad.Singamsetty@Sun.COM 		if (vpart->p_start != 0ULL)
36970Sstevel@tonic-gate 			return (EINVAL);
36987563SPrasad.Singamsetty@Sun.COM 		if (vpart->p_size != 0ULL)
36990Sstevel@tonic-gate 			return (EINVAL);
37000Sstevel@tonic-gate 	}
37010Sstevel@tonic-gate 
37020Sstevel@tonic-gate 	if (un->c.un_vtoc_id) {
37030Sstevel@tonic-gate 		recid = un->c.un_vtoc_id;
37040Sstevel@tonic-gate 		status = mddb_getrecstatus(recid);
37050Sstevel@tonic-gate 		if (status == MDDB_OK) {
37060Sstevel@tonic-gate 			/*
37070Sstevel@tonic-gate 			 * If there's enough space in the record, and the
37080Sstevel@tonic-gate 			 * existing record is a vtoc record (not EFI),
37090Sstevel@tonic-gate 			 * we just can use the existing space.
37100Sstevel@tonic-gate 			 * Otherwise, we create a new MDDB_VTOC record for
37110Sstevel@tonic-gate 			 * this unit.
37120Sstevel@tonic-gate 			 */
37130Sstevel@tonic-gate 			if ((mddb_getrecsize(recid) >= sizeof (struct vtoc)) &&
37140Sstevel@tonic-gate 			    ((un->c.un_flag & MD_EFILABEL) == 0)) {
37150Sstevel@tonic-gate 				v = mddb_getrecaddr(recid);
37160Sstevel@tonic-gate 				bcopy((caddr_t)vtoc, v, sizeof (struct vtoc));
37170Sstevel@tonic-gate 				mddb_commitrec_wrapper(recid);
37180Sstevel@tonic-gate 				recids[0] = recid;
37190Sstevel@tonic-gate 				recids[1] = un->c.un_record_id;
37200Sstevel@tonic-gate 				recids[2] = 0;
37210Sstevel@tonic-gate 				un->c.un_flag &= ~MD_EFILABEL;
37220Sstevel@tonic-gate 				mddb_commitrecs_wrapper(recids);
37230Sstevel@tonic-gate 				return (0);
37240Sstevel@tonic-gate 			}
37250Sstevel@tonic-gate 
37260Sstevel@tonic-gate 			un->c.un_vtoc_id = 0;
37270Sstevel@tonic-gate 			mddb_commitrec_wrapper(un->c.un_record_id);
37280Sstevel@tonic-gate 			mddb_deleterec_wrapper(recid);
37290Sstevel@tonic-gate 		}
37300Sstevel@tonic-gate 	}
37310Sstevel@tonic-gate 
37320Sstevel@tonic-gate 	recid = mddb_createrec(sizeof (struct vtoc), MDDB_VTOC, 0,
37335428Spetede 	    MD_CRO_32BIT, MD_UN2SET(un));
37340Sstevel@tonic-gate 
37350Sstevel@tonic-gate 	if (recid < 0) {
37360Sstevel@tonic-gate 		return (ENOSPC);
37370Sstevel@tonic-gate 	}
37380Sstevel@tonic-gate 
37390Sstevel@tonic-gate 	recids[0] = recid;
37400Sstevel@tonic-gate 	recids[1] = un->c.un_record_id;
37410Sstevel@tonic-gate 	recids[2] = 0;
37420Sstevel@tonic-gate 	v = mddb_getrecaddr(recid);
37430Sstevel@tonic-gate 	bcopy((caddr_t)vtoc, v, sizeof (struct vtoc));
37440Sstevel@tonic-gate 
37450Sstevel@tonic-gate 	un->c.un_vtoc_id = recid;
37460Sstevel@tonic-gate 	un->c.un_flag &= ~MD_EFILABEL;
37470Sstevel@tonic-gate 	mddb_commitrecs_wrapper(recids);
37480Sstevel@tonic-gate 	return (0);
37490Sstevel@tonic-gate }
37500Sstevel@tonic-gate 
37517563SPrasad.Singamsetty@Sun.COM void
md_get_extvtoc(md_unit_t * un,struct extvtoc * extvtoc)37527563SPrasad.Singamsetty@Sun.COM md_get_extvtoc(md_unit_t *un, struct extvtoc *extvtoc)
37537563SPrasad.Singamsetty@Sun.COM {
37547563SPrasad.Singamsetty@Sun.COM 	caddr_t			v;
37557563SPrasad.Singamsetty@Sun.COM 	mddb_recstatus_t	status;
37567563SPrasad.Singamsetty@Sun.COM 	struct vtoc32		*vt32;
37577563SPrasad.Singamsetty@Sun.COM 	struct vtoc		*vtoc;
37587563SPrasad.Singamsetty@Sun.COM 
37597563SPrasad.Singamsetty@Sun.COM 	/*
37607563SPrasad.Singamsetty@Sun.COM 	 * Return extvtoc structure fields in the provided VTOC area, addressed
37617563SPrasad.Singamsetty@Sun.COM 	 * by *extvtoc.
37627563SPrasad.Singamsetty@Sun.COM 	 *
37637563SPrasad.Singamsetty@Sun.COM 	 */
37647563SPrasad.Singamsetty@Sun.COM 
37657563SPrasad.Singamsetty@Sun.COM 	bzero((caddr_t)extvtoc, sizeof (struct extvtoc));
37667563SPrasad.Singamsetty@Sun.COM 	if (un->c.un_vtoc_id) {
37677563SPrasad.Singamsetty@Sun.COM 		status = mddb_getrecstatus(un->c.un_vtoc_id);
37687563SPrasad.Singamsetty@Sun.COM 		if (status == MDDB_OK) {
37697563SPrasad.Singamsetty@Sun.COM 			v = mddb_getrecaddr(un->c.un_vtoc_id);
37707563SPrasad.Singamsetty@Sun.COM 			if (un->c.un_flag & MD_EFILABEL) {
37717563SPrasad.Singamsetty@Sun.COM 				bcopy(v, (caddr_t)&(extvtoc->v_volume),
37727563SPrasad.Singamsetty@Sun.COM 				    LEN_DKL_VVOL);
37737563SPrasad.Singamsetty@Sun.COM 			} else {
37747563SPrasad.Singamsetty@Sun.COM 				/*
37757563SPrasad.Singamsetty@Sun.COM 				 * if this seems to be a sane vtoc,
37767563SPrasad.Singamsetty@Sun.COM 				 * just copy it ...
37777563SPrasad.Singamsetty@Sun.COM 				 */
37787563SPrasad.Singamsetty@Sun.COM 				if (((struct vtoc *)v)->v_sanity == VTOC_SANE) {
37797563SPrasad.Singamsetty@Sun.COM 					vtoc = (struct vtoc *)v;
37807563SPrasad.Singamsetty@Sun.COM 					vtoctoextvtoc((*vtoc), (*extvtoc));
37817563SPrasad.Singamsetty@Sun.COM 				} else {
37827563SPrasad.Singamsetty@Sun.COM 					/* assume a vtoc32 was stored here */
37837563SPrasad.Singamsetty@Sun.COM 					vt32 = (struct vtoc32 *)v;
37847563SPrasad.Singamsetty@Sun.COM 					vtoc32toextvtoc((*vt32), (*extvtoc));
37857563SPrasad.Singamsetty@Sun.COM 				}
37867563SPrasad.Singamsetty@Sun.COM 			}
37877563SPrasad.Singamsetty@Sun.COM 		} else {
37887563SPrasad.Singamsetty@Sun.COM 			un->c.un_vtoc_id = 0;
37897563SPrasad.Singamsetty@Sun.COM 			mddb_commitrec_wrapper(un->c.un_record_id);
37907563SPrasad.Singamsetty@Sun.COM 		}
37917563SPrasad.Singamsetty@Sun.COM 	}
37927563SPrasad.Singamsetty@Sun.COM 
37937563SPrasad.Singamsetty@Sun.COM 	extvtoc->v_sanity = VTOC_SANE;
37947563SPrasad.Singamsetty@Sun.COM 	extvtoc->v_nparts = 1;
37957563SPrasad.Singamsetty@Sun.COM 	extvtoc->v_version = V_VERSION;
37967563SPrasad.Singamsetty@Sun.COM 	extvtoc->v_sectorsz = DEV_BSIZE;
37977563SPrasad.Singamsetty@Sun.COM 	if (un->c.un_flag & MD_LABELED)
37987563SPrasad.Singamsetty@Sun.COM 		extvtoc->v_part[0].p_start = 0ULL;
37997563SPrasad.Singamsetty@Sun.COM 	else
38007563SPrasad.Singamsetty@Sun.COM 		extvtoc->v_part[0].p_start = (diskaddr_t)(un->c.un_nhead *
38017563SPrasad.Singamsetty@Sun.COM 		    un->c.un_nsect);
38027563SPrasad.Singamsetty@Sun.COM 	extvtoc->v_part[0].p_size = un->c.un_total_blocks;
38037563SPrasad.Singamsetty@Sun.COM }
38047563SPrasad.Singamsetty@Sun.COM 
38057563SPrasad.Singamsetty@Sun.COM int
md_set_extvtoc(md_unit_t * un,struct extvtoc * extvtoc)38067563SPrasad.Singamsetty@Sun.COM md_set_extvtoc(md_unit_t *un, struct extvtoc *extvtoc)
38077563SPrasad.Singamsetty@Sun.COM {
38087563SPrasad.Singamsetty@Sun.COM 
38097563SPrasad.Singamsetty@Sun.COM 	struct extpartition	*vpart;
38107563SPrasad.Singamsetty@Sun.COM 	int			i;
38117563SPrasad.Singamsetty@Sun.COM 	mddb_recid_t		recid;
38127563SPrasad.Singamsetty@Sun.COM 	mddb_recid_t		recids[3];
38137563SPrasad.Singamsetty@Sun.COM 	mddb_recstatus_t	status;
38147563SPrasad.Singamsetty@Sun.COM 	caddr_t			v;
38157563SPrasad.Singamsetty@Sun.COM 	diskaddr_t		sb;
38167563SPrasad.Singamsetty@Sun.COM 	struct vtoc		vtoc;
38177563SPrasad.Singamsetty@Sun.COM 
38187563SPrasad.Singamsetty@Sun.COM 	/*
38197563SPrasad.Singamsetty@Sun.COM 	 * Sanity-check the vtoc
38207563SPrasad.Singamsetty@Sun.COM 	 */
38217563SPrasad.Singamsetty@Sun.COM 	if (extvtoc->v_sanity != VTOC_SANE || extvtoc->v_nparts != 1)
38227563SPrasad.Singamsetty@Sun.COM 		return (EINVAL);
38237563SPrasad.Singamsetty@Sun.COM 
38247563SPrasad.Singamsetty@Sun.COM 	/*
38257563SPrasad.Singamsetty@Sun.COM 	 * Validate the partition table
38267563SPrasad.Singamsetty@Sun.COM 	 */
38277563SPrasad.Singamsetty@Sun.COM 	vpart = extvtoc->v_part;
38287563SPrasad.Singamsetty@Sun.COM 	for (i = 0; i < V_NUMPAR; i++, vpart++) {
38297563SPrasad.Singamsetty@Sun.COM 		if (i == 0) {
38307563SPrasad.Singamsetty@Sun.COM 			if (un->c.un_flag & MD_LABELED)
38317563SPrasad.Singamsetty@Sun.COM 				sb = 0ULL;
38327563SPrasad.Singamsetty@Sun.COM 			else
38337563SPrasad.Singamsetty@Sun.COM 				sb = (diskaddr_t)(un->c.un_nhead *
38347563SPrasad.Singamsetty@Sun.COM 				    un->c.un_nsect);
38357563SPrasad.Singamsetty@Sun.COM 			if (vpart->p_start != sb)
38367563SPrasad.Singamsetty@Sun.COM 				return (EINVAL);
38377563SPrasad.Singamsetty@Sun.COM 			if (vpart->p_size != un->c.un_total_blocks)
38387563SPrasad.Singamsetty@Sun.COM 				return (EINVAL);
38397563SPrasad.Singamsetty@Sun.COM 			continue;
38407563SPrasad.Singamsetty@Sun.COM 		}
38417563SPrasad.Singamsetty@Sun.COM 		/* all other partitions must be zero */
38427563SPrasad.Singamsetty@Sun.COM 		if (vpart->p_start != 0ULL)
38437563SPrasad.Singamsetty@Sun.COM 			return (EINVAL);
38447563SPrasad.Singamsetty@Sun.COM 		if (vpart->p_size != 0)
38457563SPrasad.Singamsetty@Sun.COM 			return (EINVAL);
38467563SPrasad.Singamsetty@Sun.COM 	}
38477563SPrasad.Singamsetty@Sun.COM 
38487563SPrasad.Singamsetty@Sun.COM 	if (!(un->c.un_revision & MD_64BIT_META_DEV)) {
38497563SPrasad.Singamsetty@Sun.COM 		extvtoctovtoc((*extvtoc), (vtoc));
38507563SPrasad.Singamsetty@Sun.COM 		return (md_set_vtoc(un, &vtoc));
38517563SPrasad.Singamsetty@Sun.COM 	}
38527563SPrasad.Singamsetty@Sun.COM 
38537563SPrasad.Singamsetty@Sun.COM 	/*
38547563SPrasad.Singamsetty@Sun.COM 	 * Since the size is greater than 1 TB the information can either
38557563SPrasad.Singamsetty@Sun.COM 	 * be stored as a VTOC or EFI.  Since EFI uses less space just use
38567563SPrasad.Singamsetty@Sun.COM 	 * it.  md_get_extvtoc can reconstruct the label information from
38577563SPrasad.Singamsetty@Sun.COM 	 * either format.
38587563SPrasad.Singamsetty@Sun.COM 	 */
38597563SPrasad.Singamsetty@Sun.COM 	if (un->c.un_vtoc_id) {
38607563SPrasad.Singamsetty@Sun.COM 		recid = un->c.un_vtoc_id;
38617563SPrasad.Singamsetty@Sun.COM 		status = mddb_getrecstatus(recid);
38627563SPrasad.Singamsetty@Sun.COM 		if (status == MDDB_OK) {
38637563SPrasad.Singamsetty@Sun.COM 			/*
38647563SPrasad.Singamsetty@Sun.COM 			 * If there's enough space in the record, and the
38657563SPrasad.Singamsetty@Sun.COM 			 * existing record is an EFI record (not vtoc),
38667563SPrasad.Singamsetty@Sun.COM 			 * we just can use the existing space.
38677563SPrasad.Singamsetty@Sun.COM 			 * Otherwise, we create a new MDDB_EFILABEL record for
38687563SPrasad.Singamsetty@Sun.COM 			 * this unit.
38697563SPrasad.Singamsetty@Sun.COM 			 */
38707563SPrasad.Singamsetty@Sun.COM 			if ((mddb_getrecsize(recid) >= MD_EFI_PARTNAME_BYTES) &&
38717563SPrasad.Singamsetty@Sun.COM 			    (un->c.un_flag & MD_EFILABEL))  {
38727563SPrasad.Singamsetty@Sun.COM 				v = mddb_getrecaddr(recid);
38737563SPrasad.Singamsetty@Sun.COM 				bzero((caddr_t)v, MD_EFI_PARTNAME_BYTES);
38747563SPrasad.Singamsetty@Sun.COM 				bcopy((caddr_t)&(extvtoc->v_volume),
38757563SPrasad.Singamsetty@Sun.COM 				    v, LEN_DKL_VVOL);
38767563SPrasad.Singamsetty@Sun.COM 				mddb_commitrec_wrapper(recid);
38777563SPrasad.Singamsetty@Sun.COM 				return (0);
38787563SPrasad.Singamsetty@Sun.COM 			}
38797563SPrasad.Singamsetty@Sun.COM 
38807563SPrasad.Singamsetty@Sun.COM 			un->c.un_vtoc_id = 0;
38817563SPrasad.Singamsetty@Sun.COM 			mddb_commitrec_wrapper(un->c.un_record_id);
38827563SPrasad.Singamsetty@Sun.COM 			mddb_deleterec_wrapper(recid);
38837563SPrasad.Singamsetty@Sun.COM 		}
38847563SPrasad.Singamsetty@Sun.COM 	}
38857563SPrasad.Singamsetty@Sun.COM 
38867563SPrasad.Singamsetty@Sun.COM 	recid = mddb_createrec(MD_EFI_PARTNAME_BYTES, MDDB_EFILABEL, 0,
38877563SPrasad.Singamsetty@Sun.COM 	    MD_CRO_32BIT, MD_UN2SET(un));
38887563SPrasad.Singamsetty@Sun.COM 
38897563SPrasad.Singamsetty@Sun.COM 	if (recid < 0) {
38907563SPrasad.Singamsetty@Sun.COM 		return (ENOSPC);
38917563SPrasad.Singamsetty@Sun.COM 	}
38927563SPrasad.Singamsetty@Sun.COM 
38937563SPrasad.Singamsetty@Sun.COM 	recids[0] = recid;
38947563SPrasad.Singamsetty@Sun.COM 	recids[1] = un->c.un_record_id;
38957563SPrasad.Singamsetty@Sun.COM 	recids[2] = 0;
38967563SPrasad.Singamsetty@Sun.COM 	v = mddb_getrecaddr(recid);
38977563SPrasad.Singamsetty@Sun.COM 	bzero((caddr_t)v, MD_EFI_PARTNAME_BYTES);
38987563SPrasad.Singamsetty@Sun.COM 	bcopy((caddr_t)&(extvtoc->v_volume), v, LEN_DKL_VVOL);
38997563SPrasad.Singamsetty@Sun.COM 
39007563SPrasad.Singamsetty@Sun.COM 	un->c.un_vtoc_id = recid;
39017563SPrasad.Singamsetty@Sun.COM 	un->c.un_flag |= MD_EFILABEL;
39027563SPrasad.Singamsetty@Sun.COM 	mddb_commitrecs_wrapper(recids);
39037563SPrasad.Singamsetty@Sun.COM 	return (0);
39047563SPrasad.Singamsetty@Sun.COM }
39057563SPrasad.Singamsetty@Sun.COM 
39060Sstevel@tonic-gate 
39070Sstevel@tonic-gate void
md_get_cgapart(md_unit_t * un,struct dk_map * dkmapp)39080Sstevel@tonic-gate md_get_cgapart(md_unit_t *un, struct dk_map *dkmapp)
39090Sstevel@tonic-gate {
39100Sstevel@tonic-gate 
39110Sstevel@tonic-gate 	/* skip the first cyl */
39120Sstevel@tonic-gate 	dkmapp->dkl_cylno = 1;
39130Sstevel@tonic-gate 
39140Sstevel@tonic-gate 	dkmapp->dkl_nblk = (daddr_t)un->c.un_total_blocks;
39150Sstevel@tonic-gate }
39160Sstevel@tonic-gate 
39170Sstevel@tonic-gate static struct uuid md_efi_reserved = EFI_RESERVED;
39180Sstevel@tonic-gate 
39190Sstevel@tonic-gate /*
39200Sstevel@tonic-gate  * md_get_efi
39210Sstevel@tonic-gate  * INPUT:
39220Sstevel@tonic-gate  *	un; the md_unit
39230Sstevel@tonic-gate  *	buf; the buffer that is preallocated by the calling routine and
39240Sstevel@tonic-gate  *		capable of taking the EFI label for this unit
39250Sstevel@tonic-gate  * OUTPUT:
39260Sstevel@tonic-gate  *	A filled buffer, containing one struct efi_gpt followed by one
39270Sstevel@tonic-gate  *		struct efi_gpe, because a md efi only has one valid partition
39280Sstevel@tonic-gate  *		We fetch that date either from the mddb (like vtoc)
39290Sstevel@tonic-gate  *		or we a fake an EFI label.
39300Sstevel@tonic-gate  *
39310Sstevel@tonic-gate  * NOTES:
39320Sstevel@tonic-gate  *	We do not provide for any global unique identifiers,
39330Sstevel@tonic-gate  *	We also use the field c.un_vtoc_id, as the semantic is very similar
39340Sstevel@tonic-gate  *	When we are called, it's already checked, that this unit has an EFI
39350Sstevel@tonic-gate  *		label and not a vtoc
39360Sstevel@tonic-gate  */
39370Sstevel@tonic-gate 
39380Sstevel@tonic-gate void
md_get_efi(md_unit_t * un,char * buf)39390Sstevel@tonic-gate md_get_efi(md_unit_t *un, char *buf)
39400Sstevel@tonic-gate {
39410Sstevel@tonic-gate 	caddr_t		v;
39420Sstevel@tonic-gate 	efi_gpt_t	*efi_header = (efi_gpt_t *)buf;
39430Sstevel@tonic-gate 	efi_gpe_t	*efi_part = (efi_gpe_t *)(buf + sizeof (efi_gpt_t));
39440Sstevel@tonic-gate 	mddb_recstatus_t	status;
39450Sstevel@tonic-gate 
39460Sstevel@tonic-gate 	/* first comes the header */
39470Sstevel@tonic-gate 	efi_header->efi_gpt_Signature = LE_64(EFI_SIGNATURE);
39480Sstevel@tonic-gate 	efi_header->efi_gpt_HeaderSize = LE_32(sizeof (efi_gpt_t));
39490Sstevel@tonic-gate 	efi_header->efi_gpt_NumberOfPartitionEntries = LE_32(1);
39500Sstevel@tonic-gate 	efi_header->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (efi_gpe_t));
39510Sstevel@tonic-gate 	efi_header->efi_gpt_LastUsableLBA = LE_64(un->c.un_total_blocks - 1);
39520Sstevel@tonic-gate 	efi_header->efi_gpt_FirstUsableLBA = 0;
39530Sstevel@tonic-gate 	efi_header->efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT);
39540Sstevel@tonic-gate 
39550Sstevel@tonic-gate 	/*
39560Sstevel@tonic-gate 	 * We don't fill out any of these:
39570Sstevel@tonic-gate 	 *
39580Sstevel@tonic-gate 	 * efi_header->efi_gpt_HeaderCRC32;
39590Sstevel@tonic-gate 	 * efi_header->efi_gpt_DiskGUID;
39600Sstevel@tonic-gate 	 * efi_header->efi_gpt_PartitionEntryArrayCRC32;
39610Sstevel@tonic-gate 	 * efi_header->efi_gpt_Reserved1;
39620Sstevel@tonic-gate 	 * efi_header->efi_gpt_MyLBA;
39630Sstevel@tonic-gate 	 * efi_header->efi_gpt_AlternateLBA;
39640Sstevel@tonic-gate 	 * efi_header->efi_gpt_Reserved2[LEN_EFI_PAD];
39650Sstevel@tonic-gate 	 * efi_header->efi_gpt_PartitionEntryLBA;
39660Sstevel@tonic-gate 	 */
39670Sstevel@tonic-gate 
39680Sstevel@tonic-gate 	/*
39690Sstevel@tonic-gate 	 * We copy back one partition, of type reserved,
39700Sstevel@tonic-gate 	 * which may contain the name of the metadevice
39710Sstevel@tonic-gate 	 * (this is what was used to be v_volume for a vtoc device)
39720Sstevel@tonic-gate 	 * if no name is stored in the vtoc record, we hand an empty name
39730Sstevel@tonic-gate 	 * to the user
39740Sstevel@tonic-gate 	 */
39750Sstevel@tonic-gate 
39760Sstevel@tonic-gate 	UUID_LE_CONVERT(efi_part->efi_gpe_PartitionTypeGUID, md_efi_reserved);
39771896Sjkennedy 	if (un->c.un_flag & MD_LABELED)
39781896Sjkennedy 		efi_part->efi_gpe_StartingLBA = LE_64(1ULL);
39791896Sjkennedy 	else
39801896Sjkennedy 		efi_part->efi_gpe_StartingLBA = 0;
39811896Sjkennedy 
39820Sstevel@tonic-gate 	efi_part->efi_gpe_EndingLBA = LE_64(un->c.un_total_blocks - 1);
39830Sstevel@tonic-gate 
39840Sstevel@tonic-gate 	if (un->c.un_vtoc_id) {
39850Sstevel@tonic-gate 		status = mddb_getrecstatus(un->c.un_vtoc_id);
39860Sstevel@tonic-gate 		if (status == MDDB_OK) {
39870Sstevel@tonic-gate 			v = mddb_getrecaddr(un->c.un_vtoc_id);
39880Sstevel@tonic-gate 			bcopy(v, (caddr_t)&(efi_part->efi_gpe_PartitionName),
39895428Spetede 			    MD_EFI_PARTNAME_BYTES);
39900Sstevel@tonic-gate 			return;
39910Sstevel@tonic-gate 		}
39920Sstevel@tonic-gate 		un->c.un_vtoc_id = 0;
39930Sstevel@tonic-gate 		mddb_commitrec_wrapper(un->c.un_record_id);
39940Sstevel@tonic-gate 	}
39950Sstevel@tonic-gate 
39960Sstevel@tonic-gate 	/*
39970Sstevel@tonic-gate 	 * We don't fill out any of these
39980Sstevel@tonic-gate 	 * efi_part->efi_gpe_UniquePartitionGUID
39990Sstevel@tonic-gate 	 * efi_part->efi_gpe_Attributes
40000Sstevel@tonic-gate 	 */
40010Sstevel@tonic-gate }
40020Sstevel@tonic-gate 
40030Sstevel@tonic-gate 
40040Sstevel@tonic-gate /*
40050Sstevel@tonic-gate  * md_set_efi
40060Sstevel@tonic-gate  * INPUT:
40070Sstevel@tonic-gate  *	un; a md_unit
40080Sstevel@tonic-gate  *	buf; a buffer that is holding an EFI label for this unit
40090Sstevel@tonic-gate  *
40100Sstevel@tonic-gate  * PURPOSE:
40110Sstevel@tonic-gate  *	Perform some sanity checks on the EFI label provided,
40120Sstevel@tonic-gate  *	Then store efi_gpe_PartitionName in the mddb
40130Sstevel@tonic-gate  *	and link the unit's c.un_vtoc_id field to it.
40140Sstevel@tonic-gate  *
40150Sstevel@tonic-gate  * RETURN:
40160Sstevel@tonic-gate  *	EINVAL if any of the sanity checks fail
40170Sstevel@tonic-gate  *	0 on succes
40180Sstevel@tonic-gate  *
40190Sstevel@tonic-gate  * NOTES:
40200Sstevel@tonic-gate  *	We do not provide for any global unique identifiers,
40210Sstevel@tonic-gate  *	We also use the field c.un_vtoc_id, as the semantic is very similar
40220Sstevel@tonic-gate  *	When we are called, it's already checked, that this unit has an EFI
40230Sstevel@tonic-gate  *		label and not a vtoc
40240Sstevel@tonic-gate  */
40250Sstevel@tonic-gate 
40260Sstevel@tonic-gate 
40270Sstevel@tonic-gate int
md_set_efi(md_unit_t * un,char * buf)40280Sstevel@tonic-gate md_set_efi(md_unit_t *un, char *buf)
40290Sstevel@tonic-gate {
40300Sstevel@tonic-gate 
40310Sstevel@tonic-gate 	mddb_recid_t		recid;
40320Sstevel@tonic-gate 	mddb_recid_t		recids[3];
40330Sstevel@tonic-gate 	mddb_recstatus_t	status;
40340Sstevel@tonic-gate 	caddr_t			v;
40350Sstevel@tonic-gate 	efi_gpt_t	*efi_header = (efi_gpt_t *)buf;
40360Sstevel@tonic-gate 	efi_gpe_t	*efi_part = (efi_gpe_t *)(buf + sizeof (efi_gpt_t));
40370Sstevel@tonic-gate 	struct uuid	md_efi_reserved_le;
40380Sstevel@tonic-gate 
40390Sstevel@tonic-gate 	/*
40400Sstevel@tonic-gate 	 * Sanity-check the EFI label
40410Sstevel@tonic-gate 	 */
40420Sstevel@tonic-gate 	if ((efi_header->efi_gpt_Signature != LE_64(EFI_SIGNATURE)) ||
40430Sstevel@tonic-gate 	    (efi_header->efi_gpt_NumberOfPartitionEntries != LE_32(1)))
40440Sstevel@tonic-gate 		return (EINVAL);
40450Sstevel@tonic-gate 
40460Sstevel@tonic-gate 	UUID_LE_CONVERT(md_efi_reserved_le, md_efi_reserved);
40470Sstevel@tonic-gate 
40480Sstevel@tonic-gate 	/*
40490Sstevel@tonic-gate 	 * Validate the partition
40500Sstevel@tonic-gate 	 */
40510Sstevel@tonic-gate 	if (efi_part->efi_gpe_StartingLBA != 0 ||
40520Sstevel@tonic-gate 	    efi_part->efi_gpe_EndingLBA != LE_64(un->c.un_total_blocks - 1) ||
40530Sstevel@tonic-gate 	    bcmp(&efi_part->efi_gpe_PartitionTypeGUID, &md_efi_reserved_le,
40540Sstevel@tonic-gate 	    sizeof (struct uuid))) {
40550Sstevel@tonic-gate 		return (EINVAL);
40560Sstevel@tonic-gate 	}
40570Sstevel@tonic-gate 	/*
40580Sstevel@tonic-gate 	 * If no name is specified, we have nothing to do and return success.
40590Sstevel@tonic-gate 	 * because efi_gpe_PartitionName is in unicode form, we have to
40600Sstevel@tonic-gate 	 * check the first two bytes of efi_gpe_PartitionName.
40610Sstevel@tonic-gate 	 */
40620Sstevel@tonic-gate 	if (((char *)(uintptr_t)efi_part->efi_gpe_PartitionName[0] == NULL) &&
40630Sstevel@tonic-gate 	    ((char *)(uintptr_t)efi_part->efi_gpe_PartitionName[1] == NULL)) {
40640Sstevel@tonic-gate 		return (0);
40650Sstevel@tonic-gate 	}
40660Sstevel@tonic-gate 
40670Sstevel@tonic-gate 	if (un->c.un_vtoc_id) {
40680Sstevel@tonic-gate 		recid = un->c.un_vtoc_id;
40690Sstevel@tonic-gate 		status = mddb_getrecstatus(recid);
40700Sstevel@tonic-gate 		if (status == MDDB_OK) {
40710Sstevel@tonic-gate 			/*
40720Sstevel@tonic-gate 			 * If there's enough space in the record, and the
40730Sstevel@tonic-gate 			 * existing record is an EFI record (not vtoc),
40740Sstevel@tonic-gate 			 * we just can use the existing space.
40750Sstevel@tonic-gate 			 * Otherwise, we create a new MDDB_EFILABEL record for
40760Sstevel@tonic-gate 			 * this unit.
40770Sstevel@tonic-gate 			 */
40780Sstevel@tonic-gate 			if ((mddb_getrecsize(recid) >= MD_EFI_PARTNAME_BYTES) &&
40790Sstevel@tonic-gate 			    (un->c.un_flag & MD_EFILABEL))  {
40800Sstevel@tonic-gate 				v = mddb_getrecaddr(recid);
40810Sstevel@tonic-gate 				bcopy((caddr_t)&efi_part->efi_gpe_PartitionName,
40825428Spetede 				    v, MD_EFI_PARTNAME_BYTES);
40830Sstevel@tonic-gate 				mddb_commitrec_wrapper(recid);
40840Sstevel@tonic-gate 				return (0);
40850Sstevel@tonic-gate 			}
40860Sstevel@tonic-gate 
40870Sstevel@tonic-gate 			un->c.un_vtoc_id = 0;
40880Sstevel@tonic-gate 			mddb_commitrec_wrapper(un->c.un_record_id);
40890Sstevel@tonic-gate 			mddb_deleterec_wrapper(recid);
40900Sstevel@tonic-gate 		}
40910Sstevel@tonic-gate 	}
40920Sstevel@tonic-gate 
40930Sstevel@tonic-gate 	recid = mddb_createrec(MD_EFI_PARTNAME_BYTES, MDDB_EFILABEL, 0,
40945428Spetede 	    MD_CRO_32BIT, MD_UN2SET(un));
40950Sstevel@tonic-gate 
40960Sstevel@tonic-gate 	if (recid < 0) {
40970Sstevel@tonic-gate 		return (ENOSPC);
40980Sstevel@tonic-gate 	}
40990Sstevel@tonic-gate 
41000Sstevel@tonic-gate 	recids[0] = recid;
41010Sstevel@tonic-gate 	recids[1] = un->c.un_record_id;
41020Sstevel@tonic-gate 	recids[2] = 0;
41030Sstevel@tonic-gate 	v = mddb_getrecaddr(recid);
41040Sstevel@tonic-gate 	bcopy((caddr_t)&efi_part->efi_gpe_PartitionName, v,
41055428Spetede 	    MD_EFI_PARTNAME_BYTES);
41060Sstevel@tonic-gate 
41070Sstevel@tonic-gate 	un->c.un_vtoc_id = recid;
41080Sstevel@tonic-gate 	un->c.un_flag |= MD_EFILABEL;
41090Sstevel@tonic-gate 	mddb_commitrecs_wrapper(recids);
41100Sstevel@tonic-gate 	return (0);
41110Sstevel@tonic-gate }
41120Sstevel@tonic-gate 
41130Sstevel@tonic-gate int
md_dkiocgetefi(minor_t mnum,void * data,int mode)41140Sstevel@tonic-gate md_dkiocgetefi(minor_t mnum, void *data, int mode)
41150Sstevel@tonic-gate {
41160Sstevel@tonic-gate 	dk_efi_t	efi;
41170Sstevel@tonic-gate 	caddr_t		*buf;
41180Sstevel@tonic-gate 	int		rval = 0;
41190Sstevel@tonic-gate 	mdi_unit_t	*ui;
41200Sstevel@tonic-gate 	md_unit_t	*mdun;
41210Sstevel@tonic-gate 
41220Sstevel@tonic-gate 	if (!(mode & FREAD))
41230Sstevel@tonic-gate 		return (EACCES);
41240Sstevel@tonic-gate 
41250Sstevel@tonic-gate 	if (ddi_copyin(data, &efi, sizeof (dk_efi_t), mode))
41260Sstevel@tonic-gate 		return (EFAULT);
41270Sstevel@tonic-gate 
41280Sstevel@tonic-gate 	efi.dki_data = (void *)(uintptr_t)efi.dki_data_64;
41290Sstevel@tonic-gate 
41300Sstevel@tonic-gate 	/*
41310Sstevel@tonic-gate 	 * If the user specified a zero length or a null pointer, we give them
41320Sstevel@tonic-gate 	 * the number of bytes to alloc in user land.
41330Sstevel@tonic-gate 	 */
41340Sstevel@tonic-gate 	if (efi.dki_length == 0 || efi.dki_data == NULL) {
41350Sstevel@tonic-gate 		efi.dki_length = MD_EFI_LABEL_SIZE;
41360Sstevel@tonic-gate 		if (ddi_copyout(&efi, data, sizeof (dk_efi_t), mode))
41370Sstevel@tonic-gate 			return (EFAULT);
41380Sstevel@tonic-gate 		return (0);
41390Sstevel@tonic-gate 	}
41400Sstevel@tonic-gate 	/* Bad size specified, better not answer to that query */
41410Sstevel@tonic-gate 	if (efi.dki_length < MD_EFI_LABEL_SIZE)
41420Sstevel@tonic-gate 		return (EINVAL);
41430Sstevel@tonic-gate 
41440Sstevel@tonic-gate 	if ((ui = MDI_UNIT(mnum)) == NULL)
41450Sstevel@tonic-gate 		return (ENXIO);
41460Sstevel@tonic-gate 
41470Sstevel@tonic-gate 	/*
41480Sstevel@tonic-gate 	 * We don't want to allocate as much bytes as we are told,
41490Sstevel@tonic-gate 	 * because we know the good size is MD_EFI_LABEL_SIZE
41500Sstevel@tonic-gate 	 */
41510Sstevel@tonic-gate 	efi.dki_length = MD_EFI_LABEL_SIZE;
41520Sstevel@tonic-gate 	buf = kmem_zalloc(MD_EFI_LABEL_SIZE, KM_SLEEP);
41530Sstevel@tonic-gate 
41540Sstevel@tonic-gate 	mdun = (md_unit_t *)md_unit_readerlock(ui);
41550Sstevel@tonic-gate 	md_get_efi(mdun, (char *)buf);
41560Sstevel@tonic-gate 	md_unit_readerexit(ui);
41570Sstevel@tonic-gate 
41580Sstevel@tonic-gate 	if (ddi_copyout(buf, efi.dki_data, efi.dki_length, mode))
41590Sstevel@tonic-gate 		rval = EFAULT;
41600Sstevel@tonic-gate 
41610Sstevel@tonic-gate 	kmem_free(buf, MD_EFI_LABEL_SIZE);
41620Sstevel@tonic-gate 	return (rval);
41630Sstevel@tonic-gate }
41640Sstevel@tonic-gate 
41650Sstevel@tonic-gate int
md_dkiocsetefi(minor_t mnum,void * data,int mode)41660Sstevel@tonic-gate md_dkiocsetefi(minor_t mnum, void *data, int mode)
41670Sstevel@tonic-gate {
41680Sstevel@tonic-gate 	dk_efi_t	efi;
41690Sstevel@tonic-gate 	caddr_t		*buf;
41700Sstevel@tonic-gate 	int		rval = 0;
41710Sstevel@tonic-gate 	mdi_unit_t	*ui;
41720Sstevel@tonic-gate 	md_unit_t	*mdun;
41730Sstevel@tonic-gate 
41740Sstevel@tonic-gate 	if (!(mode & FREAD))
41750Sstevel@tonic-gate 		return (EACCES);
41760Sstevel@tonic-gate 
41770Sstevel@tonic-gate 	if ((ui = MDI_UNIT(mnum)) == NULL)
41780Sstevel@tonic-gate 		return (ENXIO);
41790Sstevel@tonic-gate 
41800Sstevel@tonic-gate 	if (ddi_copyin(data, &efi, sizeof (dk_efi_t), mode))
41810Sstevel@tonic-gate 		return (EFAULT);
41820Sstevel@tonic-gate 
41830Sstevel@tonic-gate 	efi.dki_data = (void *)(uintptr_t)efi.dki_data_64;
41840Sstevel@tonic-gate 
41850Sstevel@tonic-gate 	/* Sanity check of the skeleton */
41860Sstevel@tonic-gate 	if ((efi.dki_length > sizeof (efi_gpt_t) + EFI_MIN_ARRAY_SIZE) ||
41870Sstevel@tonic-gate 	    (efi.dki_length < sizeof (efi_gpt_t) + sizeof (efi_gpe_t)) ||
41880Sstevel@tonic-gate 	    (efi.dki_data == NULL))
41890Sstevel@tonic-gate 		return (EINVAL);
41900Sstevel@tonic-gate 
41910Sstevel@tonic-gate 	/*
41920Sstevel@tonic-gate 	 * It's only a real EFI label if the location is 1
41930Sstevel@tonic-gate 	 * in all other cases, we do nothing but say we did.
41940Sstevel@tonic-gate 	 */
41950Sstevel@tonic-gate 	if (efi.dki_lba != 1)
41960Sstevel@tonic-gate 		return (0);	/* success */
41970Sstevel@tonic-gate 
41980Sstevel@tonic-gate 	buf = kmem_alloc(efi.dki_length, KM_SLEEP);
41990Sstevel@tonic-gate 	/* And here we copy in the real data */
42000Sstevel@tonic-gate 	if (ddi_copyin(efi.dki_data, buf, efi.dki_length, mode)) {
42010Sstevel@tonic-gate 		rval = EFAULT;
42020Sstevel@tonic-gate 	} else {
42030Sstevel@tonic-gate 		mdun = (md_unit_t *)md_unit_readerlock(ui);
42040Sstevel@tonic-gate 		rval = md_set_efi(mdun, (char *)buf);
42050Sstevel@tonic-gate 		md_unit_readerexit(ui);
42060Sstevel@tonic-gate 	}
42070Sstevel@tonic-gate 
42080Sstevel@tonic-gate 	kmem_free(buf, efi.dki_length);
42090Sstevel@tonic-gate 	return (rval);
42100Sstevel@tonic-gate }
42110Sstevel@tonic-gate 
42120Sstevel@tonic-gate /*
42130Sstevel@tonic-gate  * md_dkiocpartition()
42140Sstevel@tonic-gate  * Return the appropriate partition64 structure for a given metadevice.
42150Sstevel@tonic-gate  *
42160Sstevel@tonic-gate  * Actually the only real information being returned is the number of blocks
42170Sstevel@tonic-gate  * of the specified metadevice.
42180Sstevel@tonic-gate  * The starting block is always 0, and so is the partition number, because
42190Sstevel@tonic-gate  * metadevices don't have slices.
42200Sstevel@tonic-gate  *
42210Sstevel@tonic-gate  * This function is generic for all types of metadevices.
42220Sstevel@tonic-gate  */
42230Sstevel@tonic-gate int
md_dkiocpartition(minor_t mnum,void * data,int mode)42240Sstevel@tonic-gate md_dkiocpartition(minor_t mnum, void *data, int mode)
42250Sstevel@tonic-gate {
42260Sstevel@tonic-gate 	struct partition64	p64;
42270Sstevel@tonic-gate 	mdi_unit_t		*ui;
42280Sstevel@tonic-gate 	md_unit_t		*un;
42290Sstevel@tonic-gate 	int			rval = 0;
42300Sstevel@tonic-gate 
42310Sstevel@tonic-gate 	if (!(mode & FREAD))
42320Sstevel@tonic-gate 		return (EACCES);
42330Sstevel@tonic-gate 
42340Sstevel@tonic-gate 
42350Sstevel@tonic-gate 	if ((ui = MDI_UNIT(mnum)) == NULL)
42360Sstevel@tonic-gate 		return (ENXIO);
42370Sstevel@tonic-gate 
42380Sstevel@tonic-gate 	if (ddi_copyin(data, &p64, sizeof (struct partition64), mode))
42390Sstevel@tonic-gate 		return (EFAULT);
42400Sstevel@tonic-gate 
42410Sstevel@tonic-gate 	if (p64.p_partno != 0)
42420Sstevel@tonic-gate 		return (ESRCH);
42430Sstevel@tonic-gate 
42440Sstevel@tonic-gate 	un = (md_unit_t *)md_unit_readerlock(ui);
42450Sstevel@tonic-gate 	/* All metadevices share the same PartitionTypeGUID (see md_get_efi) */
42460Sstevel@tonic-gate 	UUID_LE_CONVERT(p64.p_type, md_efi_reserved);
42470Sstevel@tonic-gate 
42480Sstevel@tonic-gate 	p64.p_partno = 0;
42490Sstevel@tonic-gate 	p64.p_start = 0;
42500Sstevel@tonic-gate 	p64.p_size = un->c.un_total_blocks;
42510Sstevel@tonic-gate 	md_unit_readerexit(ui);
42520Sstevel@tonic-gate 
42530Sstevel@tonic-gate 	if (ddi_copyout(&p64, data, sizeof (struct partition64), mode)) {
42540Sstevel@tonic-gate 		rval = EFAULT;
42550Sstevel@tonic-gate 	}
42560Sstevel@tonic-gate 
42570Sstevel@tonic-gate 	return (rval);
42580Sstevel@tonic-gate }
42591623Stw21770 
42601623Stw21770 
42611623Stw21770 /*
42621623Stw21770  * Remove device node
42631623Stw21770  */
42641623Stw21770 void
md_remove_minor_node(minor_t mnum)42651623Stw21770 md_remove_minor_node(minor_t mnum)
42661623Stw21770 {
42671623Stw21770 	char			name[16];
42681623Stw21770 	extern dev_info_t	*md_devinfo;
42691623Stw21770 
42701623Stw21770 	/*
42711623Stw21770 	 * Attempt release of its minor node
42721623Stw21770 	 */
42731623Stw21770 	(void) snprintf(name, sizeof (name), "%d,%d,blk", MD_MIN2SET(mnum),
42745428Spetede 	    MD_MIN2UNIT(mnum));
42751623Stw21770 	ddi_remove_minor_node(md_devinfo, name);
42761623Stw21770 
42771623Stw21770 	(void) snprintf(name, sizeof (name), "%d,%d,raw", MD_MIN2SET(mnum),
42785428Spetede 	    MD_MIN2UNIT(mnum));
42791623Stw21770 	ddi_remove_minor_node(md_devinfo, name);
42801623Stw21770 }
4281