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