xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_nameinfo.c (revision 12678:79fad257c978)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51896Sjkennedy  * Common Development and Distribution License (the "License").
61896Sjkennedy  * 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) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <dlfcn.h>
270Sstevel@tonic-gate #include <meta.h>
280Sstevel@tonic-gate #include <metadyn.h>
290Sstevel@tonic-gate #include <ctype.h>
300Sstevel@tonic-gate #include <dirent.h>
310Sstevel@tonic-gate #include <devid.h>
320Sstevel@tonic-gate #include <sys/param.h>
330Sstevel@tonic-gate #include <sys/scsi/impl/uscsi.h>
340Sstevel@tonic-gate #include <sys/scsi/generic/commands.h>
350Sstevel@tonic-gate #include <sys/scsi/generic/inquiry.h>
360Sstevel@tonic-gate #include <sys/efi_partition.h>
370Sstevel@tonic-gate 
380Sstevel@tonic-gate typedef struct ctlr_cache {
390Sstevel@tonic-gate 	char			*ctlr_nm;
400Sstevel@tonic-gate 	int			ctlr_ty;
410Sstevel@tonic-gate 	struct	ctlr_cache	*ctlr_nx;
420Sstevel@tonic-gate } ctlr_cache_t;
430Sstevel@tonic-gate 
440Sstevel@tonic-gate static	ctlr_cache_t	*ctlr_cache = NULL;
450Sstevel@tonic-gate 
460Sstevel@tonic-gate 
470Sstevel@tonic-gate /*
480Sstevel@tonic-gate  * return set for a device
490Sstevel@tonic-gate  */
500Sstevel@tonic-gate mdsetname_t *
metagetset(mdname_t * np,int bypass_daemon,md_error_t * ep)510Sstevel@tonic-gate metagetset(
520Sstevel@tonic-gate 	mdname_t	*np,
530Sstevel@tonic-gate 	int		bypass_daemon,
540Sstevel@tonic-gate 	md_error_t	*ep
550Sstevel@tonic-gate )
560Sstevel@tonic-gate {
570Sstevel@tonic-gate 	mdsetname_t	*sp;
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 	/* metadevice */
600Sstevel@tonic-gate 	if (metaismeta(np))
610Sstevel@tonic-gate 		return (metasetnosetname(MD_MIN2SET(meta_getminor(np->dev)),
627464SAndrew.Balfour@Sun.COM 		    ep));
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 	/* regular device */
650Sstevel@tonic-gate 	if (meta_is_drive_in_anyset(np->drivenamep, &sp, bypass_daemon,
660Sstevel@tonic-gate 	    ep) != 0)
670Sstevel@tonic-gate 		return (NULL);
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	if (sp != NULL)
700Sstevel@tonic-gate 		return (sp);
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	return (metasetnosetname(MD_LOCAL_SET, ep));
730Sstevel@tonic-gate }
740Sstevel@tonic-gate 
750Sstevel@tonic-gate /*
760Sstevel@tonic-gate  * convert system to md types
770Sstevel@tonic-gate  */
780Sstevel@tonic-gate static void
meta_geom_to_md(struct dk_geom * gp,mdgeom_t * mdgp)790Sstevel@tonic-gate meta_geom_to_md(
800Sstevel@tonic-gate 	struct dk_geom	*gp,
810Sstevel@tonic-gate 	mdgeom_t	*mdgp
820Sstevel@tonic-gate )
830Sstevel@tonic-gate {
840Sstevel@tonic-gate 	(void) memset(mdgp, '\0', sizeof (*mdgp));
850Sstevel@tonic-gate 	mdgp->ncyl = gp->dkg_ncyl;
860Sstevel@tonic-gate 	mdgp->nhead = gp->dkg_nhead;
870Sstevel@tonic-gate 	mdgp->nsect = gp->dkg_nsect;
880Sstevel@tonic-gate 	mdgp->rpm = gp->dkg_rpm;
890Sstevel@tonic-gate 	mdgp->write_reinstruct = gp->dkg_write_reinstruct;
900Sstevel@tonic-gate 	mdgp->read_reinstruct = gp->dkg_read_reinstruct;
910Sstevel@tonic-gate 	mdgp->blk_sz = DEV_BSIZE;
920Sstevel@tonic-gate }
930Sstevel@tonic-gate 
940Sstevel@tonic-gate /*
950Sstevel@tonic-gate  * convert efi to md types
960Sstevel@tonic-gate  */
970Sstevel@tonic-gate static void
meta_efi_to_mdgeom(md_unit_t * mdev,struct dk_gpt * gpt,mdgeom_t * mdgp)98*12678SJames.Hall@Sun.COM meta_efi_to_mdgeom(md_unit_t *mdev, struct dk_gpt *gpt, mdgeom_t *mdgp)
990Sstevel@tonic-gate {
1000Sstevel@tonic-gate 	(void) memset(mdgp, '\0', sizeof (*mdgp));
101*12678SJames.Hall@Sun.COM 
102*12678SJames.Hall@Sun.COM 	/*
103*12678SJames.Hall@Sun.COM 	 * Should always get geom from metadevice unit if metadevice.
104*12678SJames.Hall@Sun.COM 	 * If metadevice is built on top of efi disks then it will
105*12678SJames.Hall@Sun.COM 	 * have MD_EFI_FG_ values, otherwise it will have geom from
106*12678SJames.Hall@Sun.COM 	 * the first component.
107*12678SJames.Hall@Sun.COM 	 */
108*12678SJames.Hall@Sun.COM 	if (mdev) {
109*12678SJames.Hall@Sun.COM 		mdgp->ncyl = (mdev->c.un_total_blocks) /
110*12678SJames.Hall@Sun.COM 		    (mdev->c.un_nhead * mdev->c.un_nsect);
111*12678SJames.Hall@Sun.COM 		mdgp->nhead = mdev->c.un_nhead;
112*12678SJames.Hall@Sun.COM 		mdgp->nsect = mdev->c.un_nsect;
113*12678SJames.Hall@Sun.COM 	} else {
114*12678SJames.Hall@Sun.COM 		mdgp->ncyl = (gpt->efi_last_u_lba - gpt->efi_first_u_lba)
115*12678SJames.Hall@Sun.COM 		    / (MD_EFI_FG_HEADS * MD_EFI_FG_SECTORS);
116*12678SJames.Hall@Sun.COM 		mdgp->nhead = MD_EFI_FG_HEADS;
117*12678SJames.Hall@Sun.COM 		mdgp->nsect = MD_EFI_FG_SECTORS;
118*12678SJames.Hall@Sun.COM 	}
119*12678SJames.Hall@Sun.COM 
1200Sstevel@tonic-gate 	mdgp->rpm = MD_EFI_FG_RPM;
1210Sstevel@tonic-gate 	mdgp->write_reinstruct = MD_EFI_FG_WRI;
1220Sstevel@tonic-gate 	mdgp->read_reinstruct = MD_EFI_FG_RRI;
1230Sstevel@tonic-gate 	mdgp->blk_sz = DEV_BSIZE;
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate static void
meta_efi_to_mdvtoc(struct dk_gpt * gpt,mdvtoc_t * mdvp)1270Sstevel@tonic-gate meta_efi_to_mdvtoc(struct dk_gpt *gpt, mdvtoc_t *mdvp)
1280Sstevel@tonic-gate {
1290Sstevel@tonic-gate 	char		typename[EFI_PART_NAME_LEN];
1300Sstevel@tonic-gate 	uint_t		i;
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	(void) memset(mdvp, '\0', sizeof (*mdvp));
1330Sstevel@tonic-gate 	mdvp->nparts = gpt->efi_nparts;
1340Sstevel@tonic-gate 	if (mdvp->nparts > MD_MAX_PARTS)
1350Sstevel@tonic-gate 		return;
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 	mdvp->first_lba = gpt->efi_first_u_lba;
1380Sstevel@tonic-gate 	mdvp->last_lba = gpt->efi_last_u_lba;
1390Sstevel@tonic-gate 	mdvp->lbasize = gpt->efi_lbasize;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	for (i = 0; (i < gpt->efi_nparts); ++i) {
1420Sstevel@tonic-gate 		mdvp->parts[i].start = gpt->efi_parts[i].p_start;
1430Sstevel@tonic-gate 		mdvp->parts[i].size = gpt->efi_parts[i].p_size;
1440Sstevel@tonic-gate 		mdvp->parts[i].tag = gpt->efi_parts[i].p_tag;
1450Sstevel@tonic-gate 		mdvp->parts[i].flag = gpt->efi_parts[i].p_flag;
1460Sstevel@tonic-gate 		/*
1471896Sjkennedy 		 * It is possible to present an efi label but be using vtoc
1481896Sjkennedy 		 * disks to create a > 1 TB metadevice.  In case the first
1491896Sjkennedy 		 * disk in the underlying metadevice is a vtoc disk and starts
1501896Sjkennedy 		 * at the beginning of the disk it is necessary to convey this
1511896Sjkennedy 		 * information to the user.
1521896Sjkennedy 		 */
1531896Sjkennedy 		if (mdvp->parts[i].size > 0 &&
1541896Sjkennedy 		    mdvp->parts[i].start != 0 && mdvp->nparts == 1) {
1551896Sjkennedy 			mdvp->parts[i].label = btodb(DK_LABEL_SIZE);
1561896Sjkennedy 			mdvp->parts[i].start = 0;
1571896Sjkennedy 		}
1581896Sjkennedy 
1591896Sjkennedy 		/*
1600Sstevel@tonic-gate 		 * Due to the lack of a label for the entire partition table,
1610Sstevel@tonic-gate 		 * we use p_name of the reserved partition
1620Sstevel@tonic-gate 		 */
1630Sstevel@tonic-gate 		if ((gpt->efi_parts[i].p_tag == V_RESERVED) &&
1640Sstevel@tonic-gate 		    (gpt->efi_parts[i].p_name != NULL)) {
1650Sstevel@tonic-gate 			(void) strlcpy(typename, gpt->efi_parts[i].p_name,
1667464SAndrew.Balfour@Sun.COM 			    EFI_PART_NAME_LEN);
1670Sstevel@tonic-gate 			/* Stop at first (if any) space or tab */
1680Sstevel@tonic-gate 			(void) strtok(typename, " \t");
1690Sstevel@tonic-gate 			mdvp->typename = Strdup(typename);
1700Sstevel@tonic-gate 		}
1710Sstevel@tonic-gate 	}
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate static void
meta_mdvtoc_to_efi(mdvtoc_t * mdvp,struct dk_gpt ** gpt)1750Sstevel@tonic-gate meta_mdvtoc_to_efi(mdvtoc_t *mdvp, struct dk_gpt **gpt)
1760Sstevel@tonic-gate {
1770Sstevel@tonic-gate 	uint_t		i;
1780Sstevel@tonic-gate 	uint_t		lastpart;
1790Sstevel@tonic-gate 	size_t		size;
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	/* first we count how many partitions we have to send */
1820Sstevel@tonic-gate 	for (i = 0; i < MD_MAX_PARTS; i++) {
1830Sstevel@tonic-gate 		if ((mdvp->parts[i].start == 0) &&
1840Sstevel@tonic-gate 		    (mdvp->parts[i].size == 0) &&
1850Sstevel@tonic-gate 		    (mdvp->parts[i].tag != V_RESERVED)) {
1860Sstevel@tonic-gate 			continue;
1870Sstevel@tonic-gate 		}
1880Sstevel@tonic-gate 		/* if we are here, we know the partition is really used */
1890Sstevel@tonic-gate 		lastpart = i;
1900Sstevel@tonic-gate 	}
1910Sstevel@tonic-gate 	size = sizeof (struct dk_gpt) + (sizeof (struct dk_part) * lastpart);
1920Sstevel@tonic-gate 	*gpt = calloc(size, sizeof (char));
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	(*gpt)->efi_nparts = lastpart + 1;
1950Sstevel@tonic-gate 	(*gpt)->efi_first_u_lba = mdvp->first_lba;
1960Sstevel@tonic-gate 	(*gpt)->efi_last_u_lba = mdvp->last_lba;
1970Sstevel@tonic-gate 	(*gpt)->efi_lbasize = mdvp->lbasize;
1980Sstevel@tonic-gate 	for (i = 0; (i < (*gpt)->efi_nparts); ++i) {
1990Sstevel@tonic-gate 		(*gpt)->efi_parts[i].p_start = mdvp->parts[i].start;
2000Sstevel@tonic-gate 		(*gpt)->efi_parts[i].p_size = mdvp->parts[i].size;
2010Sstevel@tonic-gate 		(*gpt)->efi_parts[i].p_tag = mdvp->parts[i].tag;
2020Sstevel@tonic-gate 		(*gpt)->efi_parts[i].p_flag = mdvp->parts[i].flag;
2030Sstevel@tonic-gate 		/*
2040Sstevel@tonic-gate 		 * Due to the lack of a label for the entire partition table,
2050Sstevel@tonic-gate 		 * we use p_name of the reserved partition
2060Sstevel@tonic-gate 		 */
2070Sstevel@tonic-gate 		if (((*gpt)->efi_parts[i].p_tag == V_RESERVED) &&
2087464SAndrew.Balfour@Sun.COM 		    (mdvp->typename != NULL)) {
2099825SAndrew.Balfour@Sun.COM 			(void) strlcpy((*gpt)->efi_parts[i].p_name,
2109825SAndrew.Balfour@Sun.COM 			    mdvp->typename, EFI_PART_NAME_LEN);
2110Sstevel@tonic-gate 		}
2120Sstevel@tonic-gate 	}
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate void
ctlr_cache_add(char * nm,int ty)2170Sstevel@tonic-gate ctlr_cache_add(char *nm, int ty)
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate 	ctlr_cache_t	**ccpp;
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 	for (ccpp = &ctlr_cache; *ccpp != NULL; ccpp = &(*ccpp)->ctlr_nx)
2220Sstevel@tonic-gate 		if (strcmp((*ccpp)->ctlr_nm, nm) == 0)
2230Sstevel@tonic-gate 			return;
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	*ccpp = Zalloc(sizeof (ctlr_cache_t));
2260Sstevel@tonic-gate 	(*ccpp)->ctlr_nm = Strdup(nm);
2270Sstevel@tonic-gate 	(*ccpp)->ctlr_ty = ty;
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate int
ctlr_cache_look(char * nm)2310Sstevel@tonic-gate ctlr_cache_look(char *nm)
2320Sstevel@tonic-gate {
2330Sstevel@tonic-gate 	ctlr_cache_t	*tcp;
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	for (tcp = ctlr_cache; tcp != NULL; tcp = tcp->ctlr_nx)
2360Sstevel@tonic-gate 		if (strcmp(tcp->ctlr_nm, nm) == 0)
2370Sstevel@tonic-gate 			return (tcp->ctlr_ty);
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 	return (-1);
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate void
metaflushctlrcache(void)2440Sstevel@tonic-gate metaflushctlrcache(void)
2450Sstevel@tonic-gate {
2460Sstevel@tonic-gate 	ctlr_cache_t	*cp, *np;
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 	for (cp = ctlr_cache, np = NULL; cp != NULL; cp = np) {
2490Sstevel@tonic-gate 		np = cp->ctlr_nx;
2500Sstevel@tonic-gate 		Free(cp->ctlr_nm);
2510Sstevel@tonic-gate 		Free(cp);
2520Sstevel@tonic-gate 	}
2530Sstevel@tonic-gate 	ctlr_cache = NULL;
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate /*
2570Sstevel@tonic-gate  * getdrvnode -- return the driver name based on mdname_t->bname
2580Sstevel@tonic-gate  *	Need to free pointer when finished.
2590Sstevel@tonic-gate  */
2600Sstevel@tonic-gate char *
getdrvnode(mdname_t * np,md_error_t * ep)2610Sstevel@tonic-gate getdrvnode(mdname_t *np, md_error_t *ep)
2620Sstevel@tonic-gate {
2637563SPrasad.Singamsetty@Sun.COM 	char	*devicespath;
2647563SPrasad.Singamsetty@Sun.COM 	char	*drvnode;
2657563SPrasad.Singamsetty@Sun.COM 	char	*cp;
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	if ((devicespath = metagetdevicesname(np, ep)) == NULL)
2680Sstevel@tonic-gate 		return (NULL);
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 	/*
2710Sstevel@tonic-gate 	 * At this point devicespath should be like the following
2720Sstevel@tonic-gate 	 * "/devices/<unknow_and_dont_care>/xxxx@vvvv"
2730Sstevel@tonic-gate 	 *
2740Sstevel@tonic-gate 	 * There's a couple of 'if' statements below which could
2750Sstevel@tonic-gate 	 * return an error condition, but I've decide to allow
2760Sstevel@tonic-gate 	 * a more open approach regarding the mapping so as to
2770Sstevel@tonic-gate 	 * not restrict possible future projects.
2780Sstevel@tonic-gate 	 */
2790Sstevel@tonic-gate 	if (drvnode = strrchr(devicespath, '/'))
2800Sstevel@tonic-gate 		/*
2810Sstevel@tonic-gate 		 * drvnode now just "xxxx@vvvv"
2820Sstevel@tonic-gate 		 */
2830Sstevel@tonic-gate 		drvnode++;
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	if (cp = strrchr(drvnode, '@'))
2860Sstevel@tonic-gate 		/*
2870Sstevel@tonic-gate 		 * Now drvnode is just the driver name "xxxx"
2880Sstevel@tonic-gate 		 */
2890Sstevel@tonic-gate 		*cp = '\0';
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	cp = Strdup(drvnode);
2920Sstevel@tonic-gate 	Free(devicespath);
2930Sstevel@tonic-gate 	np->devicesname = NULL;
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	return (cp);
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate /*
2990Sstevel@tonic-gate  * meta_load_dl -- open dynamic library using LDLIBRARYPATH, a debug
3000Sstevel@tonic-gate  *    environment variable METALDPATH, or the default location.
3010Sstevel@tonic-gate  */
3020Sstevel@tonic-gate static void *
meta_load_dl(mdname_t * np,md_error_t * ep)3030Sstevel@tonic-gate meta_load_dl(mdname_t *np, md_error_t *ep)
3040Sstevel@tonic-gate {
3057563SPrasad.Singamsetty@Sun.COM 	char	*drvnode;
3067563SPrasad.Singamsetty@Sun.COM 	char	newpath[MAXPATHLEN];
3077563SPrasad.Singamsetty@Sun.COM 	char	*p;
3080Sstevel@tonic-gate 	void	*cookie;
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	if ((drvnode = getdrvnode(np, ep)) != NULL) {
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 		/*
3130Sstevel@tonic-gate 		 * Library seach algorithm:
3140Sstevel@tonic-gate 		 * 1) Use LDLIBRARYPATH which is implied when a non-absolute
3150Sstevel@tonic-gate 		 *    path name is passed to dlopen()
3160Sstevel@tonic-gate 		 * 2) Use the value of METALDPATH as the directory. Mainly
3170Sstevel@tonic-gate 		 *    used for debugging
3180Sstevel@tonic-gate 		 * 3) Last search the default location of "/usr/lib"
3190Sstevel@tonic-gate 		 */
3200Sstevel@tonic-gate 		(void) snprintf(newpath, sizeof (newpath), "lib%s.so.1",
3210Sstevel@tonic-gate 		    drvnode);
3220Sstevel@tonic-gate 		if ((cookie = dlopen(newpath, RTLD_LAZY)) == NULL) {
3230Sstevel@tonic-gate 			if ((p = getenv("METALDPATH")) == NULL)
3240Sstevel@tonic-gate 				p = METALDPATH_DEFAULT;
3250Sstevel@tonic-gate 			(void) snprintf(newpath, sizeof (newpath),
3260Sstevel@tonic-gate 			    "%s/lib%s.so.1", p, drvnode);
3270Sstevel@tonic-gate 			Free(drvnode);
3280Sstevel@tonic-gate 			if ((cookie = dlopen(newpath, RTLD_LAZY)) != NULL) {
3290Sstevel@tonic-gate 				/*
3300Sstevel@tonic-gate 				 * Common failure here would be failing to
3310Sstevel@tonic-gate 				 * find a libXX.so.1 such as libsd.so.1
3320Sstevel@tonic-gate 				 * Some controllers will not have a library
3330Sstevel@tonic-gate 				 * because there's no enclosure or name
3340Sstevel@tonic-gate 				 * translation required.
3350Sstevel@tonic-gate 				 */
3360Sstevel@tonic-gate 				return (cookie);
3370Sstevel@tonic-gate 			}
3380Sstevel@tonic-gate 		} else {
3390Sstevel@tonic-gate 			Free(drvnode);
3400Sstevel@tonic-gate 			return (cookie);
3410Sstevel@tonic-gate 		}
3420Sstevel@tonic-gate 	}
3430Sstevel@tonic-gate 	return (NULL);
3440Sstevel@tonic-gate }
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate /*
3470Sstevel@tonic-gate  * meta_match_names -- possibly convert the driver names returned by CINFO
3480Sstevel@tonic-gate  */
3490Sstevel@tonic-gate static void
meta_match_names(mdname_t * np,struct dk_cinfo * cp,mdcinfo_t * mdcp,md_error_t * ep)3500Sstevel@tonic-gate meta_match_names(mdname_t *np, struct dk_cinfo *cp, mdcinfo_t *mdcp,
3510Sstevel@tonic-gate     md_error_t *ep)
3520Sstevel@tonic-gate {
3530Sstevel@tonic-gate 	void		*cookie;
3540Sstevel@tonic-gate 	meta_convert_e	((*fptr)(mdname_t *, struct dk_cinfo *, mdcinfo_t *,
3557464SAndrew.Balfour@Sun.COM 	    md_error_t *));
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	if ((cookie = meta_load_dl(np, ep)) != NULL) {
3580Sstevel@tonic-gate 		fptr = (meta_convert_e (*)(mdname_t *, struct dk_cinfo *,
3590Sstevel@tonic-gate 		    mdcinfo_t *, md_error_t *))dlsym(cookie, "convert_path");
3600Sstevel@tonic-gate 		if (fptr != NULL)
3610Sstevel@tonic-gate 			(void) (*fptr)(np, cp, mdcp, ep);
3620Sstevel@tonic-gate 		(void) dlclose(cookie);
3630Sstevel@tonic-gate 	}
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate /*
3670Sstevel@tonic-gate  * meta_match_enclosure -- return any enclosure info if found
3680Sstevel@tonic-gate  */
3690Sstevel@tonic-gate int
meta_match_enclosure(mdname_t * np,mdcinfo_t * mdcp,md_error_t * ep)3700Sstevel@tonic-gate meta_match_enclosure(mdname_t *np, mdcinfo_t *mdcp, md_error_t *ep)
3710Sstevel@tonic-gate {
3727563SPrasad.Singamsetty@Sun.COM 	meta_enclosure_e	e;
3737563SPrasad.Singamsetty@Sun.COM 	meta_enclosure_e	((*fptr)(mdname_t *, mdcinfo_t *,
3747464SAndrew.Balfour@Sun.COM 	    md_error_t *));
3750Sstevel@tonic-gate 	void			*cookie;
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 	if ((cookie = meta_load_dl(np, ep)) != NULL) {
3780Sstevel@tonic-gate 		fptr = (meta_enclosure_e (*)(mdname_t *, mdcinfo_t *,
3790Sstevel@tonic-gate 		    md_error_t *))dlsym(cookie, "get_enclosure");
3800Sstevel@tonic-gate 		if (fptr != NULL) {
3810Sstevel@tonic-gate 			e = (*fptr)(np, mdcp, ep);
3820Sstevel@tonic-gate 			switch (e) {
3830Sstevel@tonic-gate 			case Enclosure_Error:
3840Sstevel@tonic-gate 				/*
3850Sstevel@tonic-gate 				 * Looks like this library wanted to handle
3860Sstevel@tonic-gate 				 * our device and had an internal error.
3870Sstevel@tonic-gate 				 */
3880Sstevel@tonic-gate 				return (1);
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 			case Enclosure_Okay:
3910Sstevel@tonic-gate 				/*
3920Sstevel@tonic-gate 				 * Found a library to handle the request so
3930Sstevel@tonic-gate 				 * just return with data provided.
3940Sstevel@tonic-gate 				 */
3950Sstevel@tonic-gate 				return (0);
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 			case Enclosure_Noop:
3980Sstevel@tonic-gate 				/*
3990Sstevel@tonic-gate 				 * Need to continue the search
4000Sstevel@tonic-gate 				 */
4010Sstevel@tonic-gate 				break;
4020Sstevel@tonic-gate 			}
4030Sstevel@tonic-gate 		}
4040Sstevel@tonic-gate 		(void) dlclose(cookie);
4050Sstevel@tonic-gate 	}
4060Sstevel@tonic-gate 	return (0);
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate static int
meta_cinfo_to_md(mdname_t * np,struct dk_cinfo * cp,mdcinfo_t * mdcp,md_error_t * ep)4100Sstevel@tonic-gate meta_cinfo_to_md(mdname_t *np, struct dk_cinfo *cp, mdcinfo_t *mdcp,
4110Sstevel@tonic-gate     md_error_t *ep)
4120Sstevel@tonic-gate {
4130Sstevel@tonic-gate 	/* default */
4140Sstevel@tonic-gate 	(void) memset(mdcp, '\0', sizeof (*mdcp));
4150Sstevel@tonic-gate 	(void) strncpy(mdcp->cname, cp->dki_cname,
4160Sstevel@tonic-gate 	    min((sizeof (mdcp->cname) - 1), sizeof (cp->dki_cname)));
4170Sstevel@tonic-gate 	mdcp->ctype = MHD_CTLR_GENERIC;
4180Sstevel@tonic-gate 	mdcp->cnum = cp->dki_cnum;
4190Sstevel@tonic-gate 	(void) strncpy(mdcp->dname, cp->dki_dname,
4200Sstevel@tonic-gate 	    min((sizeof (mdcp->dname) - 1), sizeof (cp->dki_dname)));
4210Sstevel@tonic-gate 	mdcp->unit = cp->dki_unit;
4220Sstevel@tonic-gate 	mdcp->maxtransfer = cp->dki_maxtransfer;
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 	/*
4250Sstevel@tonic-gate 	 * See if the driver name returned from DKIOCINFO
4260Sstevel@tonic-gate 	 * is valid or not. In somecases, such as the ap_dmd
4270Sstevel@tonic-gate 	 * driver, we need to modify the name that's return
4280Sstevel@tonic-gate 	 * for everything to work.
4290Sstevel@tonic-gate 	 */
4300Sstevel@tonic-gate 	meta_match_names(np, cp, mdcp, ep);
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	if (meta_match_enclosure(np, mdcp, ep))
4330Sstevel@tonic-gate 		return (-1);
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 	/* return success */
4360Sstevel@tonic-gate 	return (0);
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate static void
meta_vtoc_to_md(struct extvtoc * vp,mdvtoc_t * mdvp)4400Sstevel@tonic-gate meta_vtoc_to_md(
4417563SPrasad.Singamsetty@Sun.COM 	struct extvtoc	*vp,
4420Sstevel@tonic-gate 	mdvtoc_t	*mdvp
4430Sstevel@tonic-gate )
4440Sstevel@tonic-gate {
4450Sstevel@tonic-gate 	char		typename[sizeof (vp->v_asciilabel) + 1];
4460Sstevel@tonic-gate 	uint_t		i;
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	(void) memset(mdvp, '\0', sizeof (*mdvp));
4490Sstevel@tonic-gate 	(void) strncpy(typename, vp->v_asciilabel,
4500Sstevel@tonic-gate 	    sizeof (vp->v_asciilabel));
4510Sstevel@tonic-gate 	typename[sizeof (typename) - 1] = '\0';
4520Sstevel@tonic-gate 	for (i = 0; ((i < sizeof (typename)) && (typename[i] != '\0')); ++i) {
4530Sstevel@tonic-gate 		if ((typename[i] == ' ') || (typename[i] == '\t')) {
4540Sstevel@tonic-gate 			typename[i] = '\0';
4550Sstevel@tonic-gate 			break;
4560Sstevel@tonic-gate 		}
4570Sstevel@tonic-gate 	}
4580Sstevel@tonic-gate 	mdvp->typename = Strdup(typename);
4590Sstevel@tonic-gate 	mdvp->nparts = vp->v_nparts;
4600Sstevel@tonic-gate 	for (i = 0; (i < vp->v_nparts); ++i) {
4610Sstevel@tonic-gate 		mdvp->parts[i].start = vp->v_part[i].p_start;
4620Sstevel@tonic-gate 		mdvp->parts[i].size = vp->v_part[i].p_size;
4630Sstevel@tonic-gate 		mdvp->parts[i].tag = vp->v_part[i].p_tag;
4640Sstevel@tonic-gate 		mdvp->parts[i].flag = vp->v_part[i].p_flag;
4650Sstevel@tonic-gate 		if (vp->v_part[i].p_start == 0 && vp->v_part[i].p_size > 0)
4660Sstevel@tonic-gate 			mdvp->parts[i].label = btodb(DK_LABEL_SIZE);
4670Sstevel@tonic-gate 	}
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate /*
4710Sstevel@tonic-gate  * free allocations in vtoc
4720Sstevel@tonic-gate  */
4730Sstevel@tonic-gate void
metafreevtoc(mdvtoc_t * vtocp)4740Sstevel@tonic-gate metafreevtoc(
4750Sstevel@tonic-gate 	mdvtoc_t	*vtocp
4760Sstevel@tonic-gate )
4770Sstevel@tonic-gate {
4780Sstevel@tonic-gate 	if (vtocp->typename != NULL)
4790Sstevel@tonic-gate 		Free(vtocp->typename);
4800Sstevel@tonic-gate 	(void) memset(vtocp, 0, sizeof (*vtocp));
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate /*
4840Sstevel@tonic-gate  * return md types
4850Sstevel@tonic-gate  */
4860Sstevel@tonic-gate mdvtoc_t *
metagetvtoc(mdname_t * np,int nocache,uint_t * partnop,md_error_t * ep)4870Sstevel@tonic-gate metagetvtoc(
4880Sstevel@tonic-gate 	mdname_t	*np,	/* only rname, drivenamep, are setup */
4890Sstevel@tonic-gate 	int		nocache,
4900Sstevel@tonic-gate 	uint_t		*partnop,
4910Sstevel@tonic-gate 	md_error_t	*ep
4920Sstevel@tonic-gate )
4930Sstevel@tonic-gate {
4940Sstevel@tonic-gate 	mddrivename_t	*dnp = np->drivenamep;
4950Sstevel@tonic-gate 	struct dk_geom	geom;
4960Sstevel@tonic-gate 	char		*minor_name = NULL;
4970Sstevel@tonic-gate 	char		*rname = np->rname;
4980Sstevel@tonic-gate 	int		fd;
4990Sstevel@tonic-gate 	int		partno;
5000Sstevel@tonic-gate 	int		err = 0;	    /* saves errno from ioctl */
5010Sstevel@tonic-gate 	ddi_devid_t	devid;
5020Sstevel@tonic-gate 	char		*p;
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	/* short circuit */
5050Sstevel@tonic-gate 	if ((! nocache) && (dnp->vtoc.nparts != 0)) {
5060Sstevel@tonic-gate 		if (partnop != NULL) {
5070Sstevel@tonic-gate 			/*
5080Sstevel@tonic-gate 			 * the following assigment works because the
5090Sstevel@tonic-gate 			 * mdname_t structs are always created as part
5100Sstevel@tonic-gate 			 * of the drivenamep struct.  When a user
5110Sstevel@tonic-gate 			 * creates an mdname_t struct it either
5120Sstevel@tonic-gate 			 * uses an existing drivenamep struct or creates
5130Sstevel@tonic-gate 			 * a new one and then adds the mdname_t struct
5140Sstevel@tonic-gate 			 * as part of its parts_val array.  So what is
5150Sstevel@tonic-gate 			 * being computed below is the slice offset in
5160Sstevel@tonic-gate 			 * the parts_val array.
5170Sstevel@tonic-gate 			 */
5180Sstevel@tonic-gate 			*partnop = np - np->drivenamep->parts.parts_val;
5190Sstevel@tonic-gate 			assert(*partnop < dnp->parts.parts_len);
5200Sstevel@tonic-gate 		}
5210Sstevel@tonic-gate 		return (&dnp->vtoc);
5220Sstevel@tonic-gate 	}
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate 	/* can't get vtoc */
5250Sstevel@tonic-gate 	if (! nocache) {
5260Sstevel@tonic-gate 		switch (dnp->type) {
5270Sstevel@tonic-gate 		case MDT_ACCES:
5280Sstevel@tonic-gate 		case MDT_UNKNOWN:
5290Sstevel@tonic-gate 			(void) mdsyserror(ep, dnp->errnum, rname);
5300Sstevel@tonic-gate 			return (NULL);
5310Sstevel@tonic-gate 		}
5320Sstevel@tonic-gate 	}
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	/* get all the info */
5350Sstevel@tonic-gate 	if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
5360Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, rname);
5370Sstevel@tonic-gate 		return (NULL);
5380Sstevel@tonic-gate 	}
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	/*
5410Sstevel@tonic-gate 	 * The disk is open so this is a good point to get the devid
5420Sstevel@tonic-gate 	 * otherwise it will need to be done at another time which
5430Sstevel@tonic-gate 	 * means reopening it.
5440Sstevel@tonic-gate 	 */
5450Sstevel@tonic-gate 	if (devid_get(fd, &devid) != 0) {
5460Sstevel@tonic-gate 		/* there is no devid for the disk */
5470Sstevel@tonic-gate 		if (((p = getenv("MD_DEBUG")) != NULL) &&
5480Sstevel@tonic-gate 		    (strstr(p, "DEVID") != NULL)) {
5490Sstevel@tonic-gate 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
5500Sstevel@tonic-gate 			    "%s has no device id\n"), np->rname);
5510Sstevel@tonic-gate 		}
5520Sstevel@tonic-gate 		np->minor_name = (char *)NULL;
5530Sstevel@tonic-gate 		dnp->devid = NULL;
5540Sstevel@tonic-gate 	} else {
5550Sstevel@tonic-gate 		(void) devid_get_minor_name(fd, &minor_name);
5560Sstevel@tonic-gate 		/*
5570Sstevel@tonic-gate 		 * The minor name could be NULL if the underlying
5580Sstevel@tonic-gate 		 * device driver does not support 'minor names'.
5590Sstevel@tonic-gate 		 * This means we do not use devid's for this device.
5600Sstevel@tonic-gate 		 * SunCluster did driver does not support minor names.
5610Sstevel@tonic-gate 		 */
5620Sstevel@tonic-gate 		if (minor_name != NULL) {
5630Sstevel@tonic-gate 			np->minor_name = Strdup(minor_name);
5640Sstevel@tonic-gate 			devid_str_free(minor_name);
5650Sstevel@tonic-gate 			dnp->devid = devid_str_encode(devid, NULL);
5660Sstevel@tonic-gate 		} else {
5670Sstevel@tonic-gate 			np->minor_name = (char *)NULL;
5680Sstevel@tonic-gate 			dnp->devid = NULL;
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 			if (((p = getenv("MD_DEBUG")) != NULL) &&
5710Sstevel@tonic-gate 			    (strstr(p, "DEVID") != NULL)) {
5720Sstevel@tonic-gate 				(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
5730Sstevel@tonic-gate 				    "%s no minor name (no devid)\n"),
5740Sstevel@tonic-gate 				    np->rname);
5750Sstevel@tonic-gate 			}
5760Sstevel@tonic-gate 		}
5770Sstevel@tonic-gate 		devid_free(devid);
5780Sstevel@tonic-gate 	}
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 	/*
5810Sstevel@tonic-gate 	 * if our drivenamep points to a device not supporting DKIOCGGEOM,
5820Sstevel@tonic-gate 	 * it's likely to have an EFI label.
5830Sstevel@tonic-gate 	 */
5840Sstevel@tonic-gate 	(void) memset(&geom, 0, sizeof (geom));
5850Sstevel@tonic-gate 	if (ioctl(fd, DKIOCGGEOM, &geom) != 0) {
5860Sstevel@tonic-gate 		err = errno;
5870Sstevel@tonic-gate 		if (err == ENOTTY) {
5880Sstevel@tonic-gate 			(void) mddeverror(ep, MDE_NOT_DISK, NODEV, rname);
5890Sstevel@tonic-gate 			(void) close(fd);
5900Sstevel@tonic-gate 			return (NULL);
5910Sstevel@tonic-gate 		} else if (err != ENOTSUP) {
5920Sstevel@tonic-gate 			(void) mdsyserror(ep, err, rname);
5930Sstevel@tonic-gate 			(void) close(fd);
5940Sstevel@tonic-gate 			return (NULL);
5950Sstevel@tonic-gate 		}
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 	}
5980Sstevel@tonic-gate 	/*
5990Sstevel@tonic-gate 	 * If we are here, there was either no failure on DKIOCGGEOM or
6000Sstevel@tonic-gate 	 * the failure was ENOTSUP
6010Sstevel@tonic-gate 	 */
6020Sstevel@tonic-gate 	if (err == ENOTSUP) {
6030Sstevel@tonic-gate 		/* DKIOCGGEOM yielded ENOTSUP => try efi_alloc_and_read */
6040Sstevel@tonic-gate 		struct dk_gpt	*gpt;
6050Sstevel@tonic-gate 		int		save_errno;
606*12678SJames.Hall@Sun.COM 		md_unit_t	*mdev = NULL;
607*12678SJames.Hall@Sun.COM 		mdsetname_t	*sp = NULL;
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 		/* this also sets errno */
6100Sstevel@tonic-gate 		partno = efi_alloc_and_read(fd, &gpt);
6110Sstevel@tonic-gate 		save_errno = errno;
6120Sstevel@tonic-gate 		(void) close(fd);
6130Sstevel@tonic-gate 		if (partno < 0) {
6140Sstevel@tonic-gate 			efi_free(gpt);
6150Sstevel@tonic-gate 			(void) mdsyserror(ep, save_errno, rname);
6160Sstevel@tonic-gate 			return (NULL);
6170Sstevel@tonic-gate 		}
6180Sstevel@tonic-gate 		if (partno >= gpt->efi_nparts) {
6190Sstevel@tonic-gate 			efi_free(gpt);
6200Sstevel@tonic-gate 			(void) mddeverror(ep, MDE_INVALID_PART, NODEV64,
6217464SAndrew.Balfour@Sun.COM 			    rname);
6220Sstevel@tonic-gate 			return (NULL);
6230Sstevel@tonic-gate 		}
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate 		/* convert to our format */
6260Sstevel@tonic-gate 		metafreevtoc(&dnp->vtoc);
6270Sstevel@tonic-gate 		meta_efi_to_mdvtoc(gpt, &dnp->vtoc);
6280Sstevel@tonic-gate 		if (dnp->vtoc.nparts > MD_MAX_PARTS) {
629*12678SJames.Hall@Sun.COM 			efi_free(gpt);
6300Sstevel@tonic-gate 			(void) mddeverror(ep, MDE_TOO_MANY_PARTS, NODEV64,
6310Sstevel@tonic-gate 			    rname);
6320Sstevel@tonic-gate 			return (NULL);
6330Sstevel@tonic-gate 		}
6340Sstevel@tonic-gate 		/*
6350Sstevel@tonic-gate 		 * libmeta needs at least V_NUMPAR partitions.
6360Sstevel@tonic-gate 		 * If we have an EFI partition with less than V_NUMPAR slices,
6370Sstevel@tonic-gate 		 * we nevertheless reserve space for V_NUMPAR
6380Sstevel@tonic-gate 		 */
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 		if (dnp->vtoc.nparts < V_NUMPAR) {
6410Sstevel@tonic-gate 			dnp->vtoc.nparts = V_NUMPAR;
6420Sstevel@tonic-gate 		}
643*12678SJames.Hall@Sun.COM 
644*12678SJames.Hall@Sun.COM 		/*
645*12678SJames.Hall@Sun.COM 		 * Is np a metadevice?
646*12678SJames.Hall@Sun.COM 		 */
647*12678SJames.Hall@Sun.COM 		if (metaismeta(np)) {
648*12678SJames.Hall@Sun.COM 			sp = metasetnosetname(MD_MIN2SET(meta_getminor
649*12678SJames.Hall@Sun.COM 			    (np->dev)), ep);
650*12678SJames.Hall@Sun.COM 			if (!sp || (mdev = meta_get_mdunit(sp, np, ep)) ==
651*12678SJames.Hall@Sun.COM 			    NULL) {
652*12678SJames.Hall@Sun.COM 				efi_free(gpt);
653*12678SJames.Hall@Sun.COM 				(void) mddeverror(ep, MDE_NOT_META,
654*12678SJames.Hall@Sun.COM 				    NODEV64, rname);
655*12678SJames.Hall@Sun.COM 				return (NULL);
656*12678SJames.Hall@Sun.COM 			}
657*12678SJames.Hall@Sun.COM 		}
658*12678SJames.Hall@Sun.COM 
659*12678SJames.Hall@Sun.COM 		meta_efi_to_mdgeom(mdev, gpt, &dnp->geom);
660*12678SJames.Hall@Sun.COM 		Free(mdev);
6610Sstevel@tonic-gate 		efi_free(gpt);
6620Sstevel@tonic-gate 	} else {
6630Sstevel@tonic-gate 		/* no error on DKIOCGGEOM, try meta_getvtoc */
6647563SPrasad.Singamsetty@Sun.COM 		struct extvtoc	vtoc;
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate 		if (meta_getvtoc(fd, np->cname, &vtoc, &partno, ep) < 0) {
6670Sstevel@tonic-gate 			(void) close(fd);
6680Sstevel@tonic-gate 			return (NULL);
6690Sstevel@tonic-gate 		}
6700Sstevel@tonic-gate 		(void) close(fd);
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 		/* convert to our format */
6730Sstevel@tonic-gate 		meta_geom_to_md(&geom, &dnp->geom);
6740Sstevel@tonic-gate 		metafreevtoc(&dnp->vtoc);
6750Sstevel@tonic-gate 		meta_vtoc_to_md(&vtoc, &dnp->vtoc);
6760Sstevel@tonic-gate 	}
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate 	/* fix up any drives which are now accessible */
6790Sstevel@tonic-gate 	if ((nocache) && (dnp->type == MDT_ACCES) &&
6800Sstevel@tonic-gate 	    (dnp->vtoc.nparts == dnp->parts.parts_len)) {
6810Sstevel@tonic-gate 		dnp->type = MDT_COMP;
6820Sstevel@tonic-gate 		dnp->errnum = 0;
6830Sstevel@tonic-gate 	}
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate 	/* save partno */
6860Sstevel@tonic-gate 	assert(partno < dnp->vtoc.nparts);
6870Sstevel@tonic-gate 	if (partnop != NULL)
6880Sstevel@tonic-gate 		*partnop = partno;
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 	/* return info */
6910Sstevel@tonic-gate 	return (&dnp->vtoc);
6920Sstevel@tonic-gate }
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate static void
meta_mdvtoc_to_vtoc(mdvtoc_t * mdvp,struct extvtoc * vp)6950Sstevel@tonic-gate meta_mdvtoc_to_vtoc(
6960Sstevel@tonic-gate 	mdvtoc_t	*mdvp,
6977563SPrasad.Singamsetty@Sun.COM 	struct extvtoc	*vp
6980Sstevel@tonic-gate )
6990Sstevel@tonic-gate {
7000Sstevel@tonic-gate 	uint_t		i;
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 	(void) memset(&vp->v_part, '\0', sizeof (vp->v_part));
7030Sstevel@tonic-gate 	vp->v_nparts = (ushort_t)mdvp->nparts;
7040Sstevel@tonic-gate 	for (i = 0; (i < mdvp->nparts); ++i) {
7057563SPrasad.Singamsetty@Sun.COM 		vp->v_part[i].p_start = mdvp->parts[i].start;
7067563SPrasad.Singamsetty@Sun.COM 		vp->v_part[i].p_size  = mdvp->parts[i].size;
7070Sstevel@tonic-gate 		vp->v_part[i].p_tag   = mdvp->parts[i].tag;
7080Sstevel@tonic-gate 		vp->v_part[i].p_flag  = mdvp->parts[i].flag;
7090Sstevel@tonic-gate 	}
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate /*
7130Sstevel@tonic-gate  * Set the vtoc, but use the cached copy to get the info from.
7140Sstevel@tonic-gate  * We write np->drivenamep->vtoc to disk.
7150Sstevel@tonic-gate  * Before we can do this we read the vtoc in.
7160Sstevel@tonic-gate  * if we're dealing with a metadevice and this metadevice is a 64 bit device
7170Sstevel@tonic-gate  *	we can use meta_getmdvtoc/meta_setmdvtoc
7180Sstevel@tonic-gate  * else
7190Sstevel@tonic-gate  * 	we use meta_getvtoc/meta_setvtoc but than we first have to convert
7200Sstevel@tonic-gate  *	dnp->vtoc (actually being a mdvtoc_t) into a vtoc_t
7210Sstevel@tonic-gate  */
7220Sstevel@tonic-gate int
metasetvtoc(mdname_t * np,md_error_t * ep)7230Sstevel@tonic-gate metasetvtoc(
7240Sstevel@tonic-gate 	mdname_t	*np,
7250Sstevel@tonic-gate 	md_error_t	*ep
7260Sstevel@tonic-gate )
7270Sstevel@tonic-gate {
7280Sstevel@tonic-gate 	char		*rname = np->rname;
7290Sstevel@tonic-gate 	mddrivename_t	*dnp = np->drivenamep;
7300Sstevel@tonic-gate 	int		fd;
7310Sstevel@tonic-gate 	int		err;
7320Sstevel@tonic-gate 	int 		save_errno;
7330Sstevel@tonic-gate 	struct dk_geom	geom;
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate 	if ((fd = open(rname, (O_RDONLY | O_NDELAY), 0)) < 0)
7360Sstevel@tonic-gate 		return (mdsyserror(ep, errno, rname));
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate 	err = ioctl(fd, DKIOCGGEOM, &geom);
7390Sstevel@tonic-gate 	save_errno = errno;
7400Sstevel@tonic-gate 	if (err == 0) {
7417563SPrasad.Singamsetty@Sun.COM 		struct extvtoc	vtoc;
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 		if (meta_getvtoc(fd, np->cname, &vtoc, NULL, ep) < 0) {
7440Sstevel@tonic-gate 			(void) close(fd);
7450Sstevel@tonic-gate 			return (-1);
7460Sstevel@tonic-gate 		}
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 		meta_mdvtoc_to_vtoc(&dnp->vtoc, &vtoc);
7490Sstevel@tonic-gate 
7500Sstevel@tonic-gate 		if (meta_setvtoc(fd, np->cname, &vtoc, ep) < 0) {
7510Sstevel@tonic-gate 			(void) close(fd);
7520Sstevel@tonic-gate 			return (-1);
7530Sstevel@tonic-gate 		}
7540Sstevel@tonic-gate 	} else if (save_errno == ENOTSUP) {
7550Sstevel@tonic-gate 		struct dk_gpt	*gpt;
7560Sstevel@tonic-gate 		int		ret;
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 		/* allocation of gpt is done in meta_mdvtoc_to_efi */
7590Sstevel@tonic-gate 		meta_mdvtoc_to_efi(&dnp->vtoc, &gpt);
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate 		ret = efi_write(fd, gpt);
7620Sstevel@tonic-gate 		save_errno = errno;
7630Sstevel@tonic-gate 		free(gpt);
7640Sstevel@tonic-gate 		if (ret != 0) {
7650Sstevel@tonic-gate 			(void) close(fd);
7660Sstevel@tonic-gate 			return (mdsyserror(ep, save_errno, rname));
7670Sstevel@tonic-gate 		} else {
7680Sstevel@tonic-gate 			(void) close(fd);
7690Sstevel@tonic-gate 			return (0);
7700Sstevel@tonic-gate 		}
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 	} else {
7730Sstevel@tonic-gate 		(void) close(fd);
7740Sstevel@tonic-gate 		return (mdsyserror(ep, save_errno, rname));
7750Sstevel@tonic-gate 	}
7760Sstevel@tonic-gate 
7770Sstevel@tonic-gate 	(void) close(fd);
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 	return (0);
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate mdgeom_t *
metagetgeom(mdname_t * np,md_error_t * ep)7830Sstevel@tonic-gate metagetgeom(
7840Sstevel@tonic-gate 	mdname_t	*np,	/* only rname, drivenamep, are setup */
7850Sstevel@tonic-gate 	md_error_t	*ep
7860Sstevel@tonic-gate )
7870Sstevel@tonic-gate {
7880Sstevel@tonic-gate 	if (metagetvtoc(np, FALSE, NULL, ep) == NULL)
7890Sstevel@tonic-gate 		return (NULL);
7900Sstevel@tonic-gate 	return (&np->drivenamep->geom);
7910Sstevel@tonic-gate }
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate mdcinfo_t *
metagetcinfo(mdname_t * np,md_error_t * ep)7940Sstevel@tonic-gate metagetcinfo(
7950Sstevel@tonic-gate 	mdname_t	*np,	/* only rname, drivenamep, are setup */
7960Sstevel@tonic-gate 	md_error_t	*ep
7970Sstevel@tonic-gate )
7980Sstevel@tonic-gate {
7990Sstevel@tonic-gate 	char			*rname = np->rname;
8000Sstevel@tonic-gate 	mddrivename_t		*dnp = np->drivenamep;
8010Sstevel@tonic-gate 	int			fd;
8020Sstevel@tonic-gate 	struct dk_cinfo		cinfo;
8030Sstevel@tonic-gate 
8040Sstevel@tonic-gate 	/* short circuit */
8050Sstevel@tonic-gate 	if (dnp->cinfo.cname[0] != '\0')
8060Sstevel@tonic-gate 		return (&dnp->cinfo);
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 	/* get controller info */
8090Sstevel@tonic-gate 	if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
8100Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, rname);
8110Sstevel@tonic-gate 		return (NULL);
8120Sstevel@tonic-gate 	}
8130Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &cinfo) != 0) {
8140Sstevel@tonic-gate 		int	save = errno;
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 		(void) close(fd);
8170Sstevel@tonic-gate 		if (save == ENOTTY) {
8180Sstevel@tonic-gate 			(void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname);
8190Sstevel@tonic-gate 		} else {
8200Sstevel@tonic-gate 			(void) mdsyserror(ep, save, rname);
8210Sstevel@tonic-gate 		}
8220Sstevel@tonic-gate 		return (NULL);
8230Sstevel@tonic-gate 	}
8240Sstevel@tonic-gate 	(void) close(fd);	/* sd/ssd bug */
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	/* convert to our format */
8270Sstevel@tonic-gate 	if (meta_cinfo_to_md(np, &cinfo, &dnp->cinfo, ep) != 0)
8280Sstevel@tonic-gate 		return (NULL);
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate 	/* return info */
8310Sstevel@tonic-gate 	return (&dnp->cinfo);
8320Sstevel@tonic-gate }
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate /*
8350Sstevel@tonic-gate  * get partition number
8360Sstevel@tonic-gate  */
8370Sstevel@tonic-gate int
metagetpartno(mdname_t * np,md_error_t * ep)8380Sstevel@tonic-gate metagetpartno(
8390Sstevel@tonic-gate 	mdname_t	*np,
8400Sstevel@tonic-gate 	md_error_t	*ep
8410Sstevel@tonic-gate )
8420Sstevel@tonic-gate {
8430Sstevel@tonic-gate 	mdvtoc_t	*vtocp;
8440Sstevel@tonic-gate 	uint_t		partno;
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	if ((vtocp = metagetvtoc(np, FALSE, &partno, ep)) == NULL)
8470Sstevel@tonic-gate 		return (-1);
8480Sstevel@tonic-gate 	assert(partno < vtocp->nparts);
8490Sstevel@tonic-gate 	return (partno);
8500Sstevel@tonic-gate }
8510Sstevel@tonic-gate 
8520Sstevel@tonic-gate /*
8530Sstevel@tonic-gate  * get size of device
8540Sstevel@tonic-gate  */
8550Sstevel@tonic-gate diskaddr_t
metagetsize(mdname_t * np,md_error_t * ep)8560Sstevel@tonic-gate metagetsize(
8570Sstevel@tonic-gate 	mdname_t	*np,
8580Sstevel@tonic-gate 	md_error_t	*ep
8590Sstevel@tonic-gate )
8600Sstevel@tonic-gate {
8610Sstevel@tonic-gate 	mdvtoc_t	*vtocp;
8620Sstevel@tonic-gate 	uint_t		partno;
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate 	if ((vtocp = metagetvtoc(np, FALSE, &partno, ep)) == NULL)
8650Sstevel@tonic-gate 		return (MD_DISKADDR_ERROR);
8660Sstevel@tonic-gate 	assert(partno < vtocp->nparts);
8670Sstevel@tonic-gate 	return (vtocp->parts[partno].size);
8680Sstevel@tonic-gate }
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate /*
8710Sstevel@tonic-gate  * get label of device
8720Sstevel@tonic-gate  */
8730Sstevel@tonic-gate diskaddr_t
metagetlabel(mdname_t * np,md_error_t * ep)8740Sstevel@tonic-gate metagetlabel(
8750Sstevel@tonic-gate 	mdname_t	*np,
8760Sstevel@tonic-gate 	md_error_t	*ep
8770Sstevel@tonic-gate )
8780Sstevel@tonic-gate {
8790Sstevel@tonic-gate 	mdvtoc_t	*vtocp;
8800Sstevel@tonic-gate 	uint_t		partno;
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate 	if ((vtocp = metagetvtoc(np, FALSE, &partno, ep)) == NULL)
8830Sstevel@tonic-gate 		return (MD_DISKADDR_ERROR);
8840Sstevel@tonic-gate 	assert(partno < vtocp->nparts);
8850Sstevel@tonic-gate 	return (vtocp->parts[partno].label);
8860Sstevel@tonic-gate }
8870Sstevel@tonic-gate 
8880Sstevel@tonic-gate /*
8890Sstevel@tonic-gate  * find out where database replicas end
8900Sstevel@tonic-gate  */
8910Sstevel@tonic-gate static int
mddb_getendblk(mdsetname_t * sp,mdname_t * np,diskaddr_t * endblkp,md_error_t * ep)8920Sstevel@tonic-gate mddb_getendblk(
8930Sstevel@tonic-gate 	mdsetname_t		*sp,
8940Sstevel@tonic-gate 	mdname_t		*np,
8950Sstevel@tonic-gate 	diskaddr_t		*endblkp,
8960Sstevel@tonic-gate 	md_error_t		*ep
8970Sstevel@tonic-gate )
8980Sstevel@tonic-gate {
8990Sstevel@tonic-gate 	md_replicalist_t	*rlp = NULL;
9000Sstevel@tonic-gate 	md_replicalist_t	*rl;
9010Sstevel@tonic-gate 
9020Sstevel@tonic-gate 	/* make sure we have a component */
9030Sstevel@tonic-gate 	*endblkp = 0;
9040Sstevel@tonic-gate 	if (metaismeta(np))
9050Sstevel@tonic-gate 		return (0);
9060Sstevel@tonic-gate 
9070Sstevel@tonic-gate 	/* get replicas, quit if none */
9080Sstevel@tonic-gate 	if (metareplicalist(sp, MD_BASICNAME_OK | PRINT_FAST, &rlp, ep) < 0) {
9090Sstevel@tonic-gate 		if (! mdismddberror(ep, MDE_DB_NODB))
9100Sstevel@tonic-gate 			return (-1);
9110Sstevel@tonic-gate 		mdclrerror(ep);
9120Sstevel@tonic-gate 		return (0);
9130Sstevel@tonic-gate 	} else if (rlp == NULL)
9140Sstevel@tonic-gate 		return (0);
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate 	/* go through all the replicas */
9170Sstevel@tonic-gate 	for (rl = rlp; (rl != NULL); rl = rl->rl_next) {
9180Sstevel@tonic-gate 		md_replica_t	*rp = rl->rl_repp;
9190Sstevel@tonic-gate 		mdname_t	*repnamep = rp->r_namep;
9200Sstevel@tonic-gate 		diskaddr_t	dbend;
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 		if (np->dev != repnamep->dev)
9230Sstevel@tonic-gate 			continue;
9240Sstevel@tonic-gate 		dbend = rp->r_blkno + rp->r_nblk - 1;
9250Sstevel@tonic-gate 		if (dbend > *endblkp)
9260Sstevel@tonic-gate 			*endblkp = dbend;
9270Sstevel@tonic-gate 	}
9280Sstevel@tonic-gate 
9290Sstevel@tonic-gate 	/* cleanup, return success */
9300Sstevel@tonic-gate 	metafreereplicalist(rlp);
9310Sstevel@tonic-gate 	return (0);
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate 
9340Sstevel@tonic-gate /*
9350Sstevel@tonic-gate  * return cached start block
9360Sstevel@tonic-gate  */
9370Sstevel@tonic-gate static diskaddr_t
metagetend(mdsetname_t * sp,mdname_t * np,md_error_t * ep)9380Sstevel@tonic-gate metagetend(
9390Sstevel@tonic-gate 	mdsetname_t	*sp,
9400Sstevel@tonic-gate 	mdname_t	*np,
9410Sstevel@tonic-gate 	md_error_t	*ep
9420Sstevel@tonic-gate )
9430Sstevel@tonic-gate {
9440Sstevel@tonic-gate 	diskaddr_t	end_blk = MD_DISKADDR_ERROR;
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate 	/* short circuit */
9470Sstevel@tonic-gate 	if (np->end_blk != MD_DISKADDR_ERROR)
9480Sstevel@tonic-gate 		return (np->end_blk);
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	/* look for database locations */
9510Sstevel@tonic-gate 	if (mddb_getendblk(sp, np, &end_blk, ep) != 0)
9520Sstevel@tonic-gate 		return (MD_DISKADDR_ERROR);
9530Sstevel@tonic-gate 
9540Sstevel@tonic-gate 	/* success */
9550Sstevel@tonic-gate 	np->end_blk = end_blk;
9560Sstevel@tonic-gate 	return (end_blk);
9570Sstevel@tonic-gate }
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate /*
9600Sstevel@tonic-gate  * does device have a metadb
9610Sstevel@tonic-gate  */
9620Sstevel@tonic-gate int
metahasmddb(mdsetname_t * sp,mdname_t * np,md_error_t * ep)9630Sstevel@tonic-gate metahasmddb(
9640Sstevel@tonic-gate 	mdsetname_t	*sp,
9650Sstevel@tonic-gate 	mdname_t	*np,
9660Sstevel@tonic-gate 	md_error_t	*ep
9670Sstevel@tonic-gate )
9680Sstevel@tonic-gate {
9690Sstevel@tonic-gate 	if (metagetend(sp, np, ep) == MD_DISKADDR_ERROR)
9700Sstevel@tonic-gate 		return (-1);
9710Sstevel@tonic-gate 	else if (np->end_blk > 0)
9720Sstevel@tonic-gate 		return (1);
9730Sstevel@tonic-gate 	else
9740Sstevel@tonic-gate 		return (0);
9750Sstevel@tonic-gate }
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate /*
9780Sstevel@tonic-gate  * return cached start block
9790Sstevel@tonic-gate  */
9800Sstevel@tonic-gate diskaddr_t
metagetstart(mdsetname_t * sp,mdname_t * np,md_error_t * ep)9810Sstevel@tonic-gate metagetstart(
9820Sstevel@tonic-gate 	mdsetname_t	*sp,
9830Sstevel@tonic-gate 	mdname_t	*np,
9840Sstevel@tonic-gate 	md_error_t	*ep
9850Sstevel@tonic-gate )
9860Sstevel@tonic-gate {
9870Sstevel@tonic-gate 	diskaddr_t	start_blk = MD_DISKADDR_ERROR;
9880Sstevel@tonic-gate 
9890Sstevel@tonic-gate 	/* short circuit */
9900Sstevel@tonic-gate 	if (np->start_blk != MD_DISKADDR_ERROR)
9910Sstevel@tonic-gate 		return (np->start_blk);
9920Sstevel@tonic-gate 
9930Sstevel@tonic-gate 	/* look for database locations */
9940Sstevel@tonic-gate 	if ((start_blk = metagetend(sp, np, ep)) == MD_DISKADDR_ERROR)
9950Sstevel@tonic-gate 		return (MD_DISKADDR_ERROR);
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate 	/* check for label */
9980Sstevel@tonic-gate 	if (start_blk == 0) {
9990Sstevel@tonic-gate 		start_blk = metagetlabel(np, ep);
10000Sstevel@tonic-gate 		if (start_blk == MD_DISKADDR_ERROR) {
10010Sstevel@tonic-gate 			return (MD_DISKADDR_ERROR);
10020Sstevel@tonic-gate 		}
10030Sstevel@tonic-gate 	}
10040Sstevel@tonic-gate 
10050Sstevel@tonic-gate 	/* roundup to next cylinder */
10060Sstevel@tonic-gate 	if (start_blk != 0) {
10070Sstevel@tonic-gate 		mdgeom_t	*geomp;
10080Sstevel@tonic-gate 
10090Sstevel@tonic-gate 		if ((geomp = metagetgeom(np, ep)) == NULL)
10100Sstevel@tonic-gate 			return (MD_DISKADDR_ERROR);
10110Sstevel@tonic-gate 		start_blk = roundup(start_blk, (geomp->nhead * geomp->nsect));
10120Sstevel@tonic-gate 	}
10130Sstevel@tonic-gate 
10140Sstevel@tonic-gate 	/* success */
10150Sstevel@tonic-gate 	np->start_blk = start_blk;
10160Sstevel@tonic-gate 	return (start_blk);
10170Sstevel@tonic-gate }
10180Sstevel@tonic-gate 
10190Sstevel@tonic-gate /*
10200Sstevel@tonic-gate  * return cached devices name
10210Sstevel@tonic-gate  */
10220Sstevel@tonic-gate char *
metagetdevicesname(mdname_t * np,md_error_t * ep)10230Sstevel@tonic-gate metagetdevicesname(
10240Sstevel@tonic-gate 	mdname_t	*np,
10250Sstevel@tonic-gate 	md_error_t	*ep
10260Sstevel@tonic-gate )
10270Sstevel@tonic-gate {
10280Sstevel@tonic-gate 	char		path[MAXPATHLEN + 1];
10290Sstevel@tonic-gate 	int		len;
10300Sstevel@tonic-gate 
10310Sstevel@tonic-gate 	/* short circuit */
10320Sstevel@tonic-gate 	if (np->devicesname != NULL)
10330Sstevel@tonic-gate 		return (np->devicesname);
10340Sstevel@tonic-gate 
10350Sstevel@tonic-gate 	/* follow symlink */
10360Sstevel@tonic-gate 	if ((len = readlink(np->bname, path, (sizeof (path) - 1))) < 0) {
10370Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, np->bname);
10380Sstevel@tonic-gate 		return (NULL);
10390Sstevel@tonic-gate 	} else if (len >= sizeof (path)) {
10400Sstevel@tonic-gate 		(void) mdsyserror(ep, ENAMETOOLONG, np->bname);
10410Sstevel@tonic-gate 		return (NULL);
10420Sstevel@tonic-gate 	}
10430Sstevel@tonic-gate 	path[len] = '\0';
10440Sstevel@tonic-gate 	if ((len = strfind(path, "/devices/")) < 0) {
10450Sstevel@tonic-gate 		(void) mddeverror(ep, MDE_DEVICES_NAME, np->dev, np->bname);
10460Sstevel@tonic-gate 		return (NULL);
10470Sstevel@tonic-gate 	}
10480Sstevel@tonic-gate 
10490Sstevel@tonic-gate 	/* return name */
10500Sstevel@tonic-gate 	np->devicesname = Strdup(path + len + strlen("/devices"));
10510Sstevel@tonic-gate 	return (np->devicesname);
10520Sstevel@tonic-gate }
10530Sstevel@tonic-gate 
10540Sstevel@tonic-gate /*
10550Sstevel@tonic-gate  * get metadevice misc name
10560Sstevel@tonic-gate  */
10570Sstevel@tonic-gate char *
metagetmiscname(mdname_t * np,md_error_t * ep)10580Sstevel@tonic-gate metagetmiscname(
10590Sstevel@tonic-gate 	mdname_t		*np,
10600Sstevel@tonic-gate 	md_error_t		*ep
10610Sstevel@tonic-gate )
10620Sstevel@tonic-gate {
10630Sstevel@tonic-gate 	mddrivename_t		*dnp = np->drivenamep;
10640Sstevel@tonic-gate 	md_i_driverinfo_t	mid;
10650Sstevel@tonic-gate 
10660Sstevel@tonic-gate 	/* short circuit */
10670Sstevel@tonic-gate 	if (dnp->miscname != NULL)
10680Sstevel@tonic-gate 		return (dnp->miscname);
10690Sstevel@tonic-gate 	if (metachkmeta(np, ep) != 0)
10700Sstevel@tonic-gate 		return (NULL);
10710Sstevel@tonic-gate 
10720Sstevel@tonic-gate 	/* get misc module from driver */
10730Sstevel@tonic-gate 	(void) memset(&mid, 0, sizeof (mid));
10740Sstevel@tonic-gate 	mid.mnum = meta_getminor(np->dev);
10750Sstevel@tonic-gate 	if (metaioctl(MD_IOCGET_DRVNM, &mid, &mid.mde, np->cname) != 0) {
10760Sstevel@tonic-gate 		(void) mdstealerror(ep, &mid.mde);
10770Sstevel@tonic-gate 		return (NULL);
10780Sstevel@tonic-gate 	}
10790Sstevel@tonic-gate 
10800Sstevel@tonic-gate 	/* return miscname */
10810Sstevel@tonic-gate 	dnp->miscname = Strdup(MD_PNTDRIVERNAME(&mid));
10820Sstevel@tonic-gate 	return (dnp->miscname);
10830Sstevel@tonic-gate }
10840Sstevel@tonic-gate 
10850Sstevel@tonic-gate /*
10860Sstevel@tonic-gate  * get unit structure from driver
10870Sstevel@tonic-gate  */
10880Sstevel@tonic-gate md_unit_t *
meta_get_mdunit(mdsetname_t * sp,mdname_t * np,md_error_t * ep)10890Sstevel@tonic-gate meta_get_mdunit(
10900Sstevel@tonic-gate 	mdsetname_t	*sp,
10910Sstevel@tonic-gate 	mdname_t	*np,
10920Sstevel@tonic-gate 	md_error_t	*ep
10930Sstevel@tonic-gate )
10940Sstevel@tonic-gate {
10950Sstevel@tonic-gate 	md_i_get_t	mig;
10960Sstevel@tonic-gate 	char		*miscname = NULL;
10970Sstevel@tonic-gate 
10980Sstevel@tonic-gate 	/* should have a set */
10990Sstevel@tonic-gate 	assert(sp != NULL);
11000Sstevel@tonic-gate 	assert(sp->setno == MD_MIN2SET(meta_getminor(np->dev)));
11010Sstevel@tonic-gate 
11020Sstevel@tonic-gate 	/* get size of unit structure */
11030Sstevel@tonic-gate 	if (metachkmeta(np, ep) != 0)
11040Sstevel@tonic-gate 		return (NULL);
11050Sstevel@tonic-gate 	if ((miscname = metagetmiscname(np, ep)) == NULL)
11060Sstevel@tonic-gate 		return (NULL);
11070Sstevel@tonic-gate 	(void) memset(&mig, '\0', sizeof (mig));
11080Sstevel@tonic-gate 	MD_SETDRIVERNAME(&mig, miscname, sp->setno);
11090Sstevel@tonic-gate 	mig.id = meta_getminor(np->dev);
11100Sstevel@tonic-gate 	if (metaioctl(MD_IOCGET, &mig, &mig.mde, np->cname) != 0) {
11110Sstevel@tonic-gate 		(void) mdstealerror(ep, &mig.mde);
11120Sstevel@tonic-gate 		return (NULL);
11130Sstevel@tonic-gate 	}
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate 	/* get actual unit structure */
11160Sstevel@tonic-gate 	assert(mig.size > 0);
11170Sstevel@tonic-gate 	mig.mdp = (uintptr_t)Zalloc(mig.size);
11180Sstevel@tonic-gate 	if (metaioctl(MD_IOCGET, &mig, &mig.mde, np->cname) != 0) {
11190Sstevel@tonic-gate 		(void) mdstealerror(ep, &mig.mde);
112062Sjeanm 		Free((void *)(uintptr_t)mig.mdp);
11210Sstevel@tonic-gate 		return (NULL);
11220Sstevel@tonic-gate 	}
11230Sstevel@tonic-gate 
112462Sjeanm 	return ((md_unit_t *)(uintptr_t)mig.mdp);
11250Sstevel@tonic-gate }
11260Sstevel@tonic-gate 
11270Sstevel@tonic-gate /*
11280Sstevel@tonic-gate  * free metadevice unit
11290Sstevel@tonic-gate  */
11300Sstevel@tonic-gate void
meta_free_unit(mddrivename_t * dnp)11310Sstevel@tonic-gate meta_free_unit(
11320Sstevel@tonic-gate 	mddrivename_t	*dnp
11330Sstevel@tonic-gate )
11340Sstevel@tonic-gate {
11350Sstevel@tonic-gate 	if (dnp->unitp != NULL) {
11360Sstevel@tonic-gate 		switch (dnp->unitp->type) {
11370Sstevel@tonic-gate 		case MD_DEVICE:
11380Sstevel@tonic-gate 			meta_free_stripe((md_stripe_t *)dnp->unitp);
11390Sstevel@tonic-gate 			break;
11400Sstevel@tonic-gate 		case MD_METAMIRROR:
11410Sstevel@tonic-gate 			meta_free_mirror((md_mirror_t *)dnp->unitp);
11420Sstevel@tonic-gate 			break;
11430Sstevel@tonic-gate 		case MD_METATRANS:
11440Sstevel@tonic-gate 			meta_free_trans((md_trans_t *)dnp->unitp);
11450Sstevel@tonic-gate 			break;
11460Sstevel@tonic-gate 		case MD_METARAID:
11470Sstevel@tonic-gate 			meta_free_raid((md_raid_t *)dnp->unitp);
11480Sstevel@tonic-gate 			break;
11490Sstevel@tonic-gate 		case MD_METASP:
11500Sstevel@tonic-gate 			meta_free_sp((md_sp_t *)dnp->unitp);
11510Sstevel@tonic-gate 			break;
11520Sstevel@tonic-gate 		default:
11530Sstevel@tonic-gate 			assert(0);
11540Sstevel@tonic-gate 			break;
11550Sstevel@tonic-gate 		}
11560Sstevel@tonic-gate 		dnp->unitp = NULL;
11570Sstevel@tonic-gate 	}
11580Sstevel@tonic-gate }
11590Sstevel@tonic-gate 
11600Sstevel@tonic-gate /*
11610Sstevel@tonic-gate  * free metadevice name info
11620Sstevel@tonic-gate  */
11630Sstevel@tonic-gate void
meta_invalidate_name(mdname_t * namep)11640Sstevel@tonic-gate meta_invalidate_name(
11650Sstevel@tonic-gate 	mdname_t	*namep
11660Sstevel@tonic-gate )
11670Sstevel@tonic-gate {
11680Sstevel@tonic-gate 	mddrivename_t	*dnp = namep->drivenamep;
11690Sstevel@tonic-gate 
11700Sstevel@tonic-gate 	/* get rid of cached name info */
11710Sstevel@tonic-gate 	if (namep->devicesname != NULL) {
11720Sstevel@tonic-gate 		Free(namep->devicesname);
11730Sstevel@tonic-gate 		namep->devicesname = NULL;
11740Sstevel@tonic-gate 	}
11750Sstevel@tonic-gate 	namep->key = MD_KEYBAD;
11760Sstevel@tonic-gate 	namep->start_blk = -1;
11770Sstevel@tonic-gate 	namep->end_blk = -1;
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate 	/* get rid of cached drivename info */
11800Sstevel@tonic-gate 	(void) memset(&dnp->geom, 0, sizeof (dnp->geom));
11810Sstevel@tonic-gate 	(void) memset(&dnp->cinfo, 0, sizeof (dnp->cinfo));
11820Sstevel@tonic-gate 	metafreevtoc(&dnp->vtoc);
11830Sstevel@tonic-gate 	metaflushsidenames(dnp);
11840Sstevel@tonic-gate 	dnp->side_names_key = MD_KEYBAD;
11850Sstevel@tonic-gate 	if (dnp->miscname != NULL) {
11860Sstevel@tonic-gate 		Free(dnp->miscname);
11870Sstevel@tonic-gate 		dnp->miscname = NULL;
11880Sstevel@tonic-gate 	}
11890Sstevel@tonic-gate 	meta_free_unit(dnp);
11900Sstevel@tonic-gate }
11910Sstevel@tonic-gate 
11920Sstevel@tonic-gate /*
11930Sstevel@tonic-gate  * get metadevice unit
11940Sstevel@tonic-gate  */
11950Sstevel@tonic-gate md_common_t *
meta_get_unit(mdsetname_t * sp,mdname_t * np,md_error_t * ep)11960Sstevel@tonic-gate meta_get_unit(
11970Sstevel@tonic-gate 	mdsetname_t	*sp,
11980Sstevel@tonic-gate 	mdname_t	*np,
11990Sstevel@tonic-gate 	md_error_t	*ep
12000Sstevel@tonic-gate )
12010Sstevel@tonic-gate {
12020Sstevel@tonic-gate 	char		*miscname;
12030Sstevel@tonic-gate 
12040Sstevel@tonic-gate 	/* short circuit */
12050Sstevel@tonic-gate 	if (np->drivenamep->unitp != NULL)
12060Sstevel@tonic-gate 		return (np->drivenamep->unitp);
12070Sstevel@tonic-gate 	if (metachkmeta(np, ep) != 0)
12080Sstevel@tonic-gate 		return (NULL);
12090Sstevel@tonic-gate 
12100Sstevel@tonic-gate 	/* dispatch */
12110Sstevel@tonic-gate 	if ((miscname = metagetmiscname(np, ep)) == NULL)
12120Sstevel@tonic-gate 		return (NULL);
12130Sstevel@tonic-gate 	else if (strcmp(miscname, MD_STRIPE) == 0)
12140Sstevel@tonic-gate 		return ((md_common_t *)meta_get_stripe(sp, np, ep));
12150Sstevel@tonic-gate 	else if (strcmp(miscname, MD_MIRROR) == 0)
12160Sstevel@tonic-gate 		return ((md_common_t *)meta_get_mirror(sp, np, ep));
12170Sstevel@tonic-gate 	else if (strcmp(miscname, MD_TRANS) == 0)
12180Sstevel@tonic-gate 		return ((md_common_t *)meta_get_trans(sp, np, ep));
12190Sstevel@tonic-gate 	else if (strcmp(miscname, MD_RAID) == 0)
12200Sstevel@tonic-gate 		return ((md_common_t *)meta_get_raid(sp, np, ep));
12210Sstevel@tonic-gate 	else if (strcmp(miscname, MD_SP) == 0)
12220Sstevel@tonic-gate 		return ((md_common_t *)meta_get_sp(sp, np, ep));
12230Sstevel@tonic-gate 	else {
12240Sstevel@tonic-gate 		(void) mdmderror(ep, MDE_UNKNOWN_TYPE, meta_getminor(np->dev),
12250Sstevel@tonic-gate 		    np->cname);
12260Sstevel@tonic-gate 		return (NULL);
12270Sstevel@tonic-gate 	}
12280Sstevel@tonic-gate }
12290Sstevel@tonic-gate 
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate int
meta_isopen(mdsetname_t * sp,mdname_t * np,md_error_t * ep,mdcmdopts_t options)12320Sstevel@tonic-gate meta_isopen(
12330Sstevel@tonic-gate 	mdsetname_t	*sp,
12340Sstevel@tonic-gate 	mdname_t	*np,
12350Sstevel@tonic-gate 	md_error_t	*ep,
12360Sstevel@tonic-gate 	mdcmdopts_t	options
12370Sstevel@tonic-gate )
12380Sstevel@tonic-gate {
12390Sstevel@tonic-gate 	md_isopen_t	d;
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate 	if (metachkmeta(np, ep) != 0)
12420Sstevel@tonic-gate 		return (-1);
12430Sstevel@tonic-gate 
12440Sstevel@tonic-gate 	(void) memset(&d, '\0', sizeof (d));
12450Sstevel@tonic-gate 	d.dev = np->dev;
12460Sstevel@tonic-gate 	if (metaioctl(MD_IOCISOPEN, &d, &d.mde, np->cname) != 0)
12470Sstevel@tonic-gate 		return (mdstealerror(ep, &d.mde));
12480Sstevel@tonic-gate 
12490Sstevel@tonic-gate 	/*
12500Sstevel@tonic-gate 	 * shortcut: if the device is open, no need to check on other nodes,
12510Sstevel@tonic-gate 	 * even in case of a mn metadevice
12520Sstevel@tonic-gate 	 * Also return in case we're told not to check on other nodes.
12530Sstevel@tonic-gate 	 */
12540Sstevel@tonic-gate 	if ((d.isopen != 0) || ((options & MDCMD_MN_OPEN_CHECK) == 0)) {
12550Sstevel@tonic-gate 		return (d.isopen);
12560Sstevel@tonic-gate 	}
12570Sstevel@tonic-gate 
12580Sstevel@tonic-gate 	/*
12590Sstevel@tonic-gate 	 * If the device is closed locally, but it's a mn device,
12600Sstevel@tonic-gate 	 * check on all other nodes, too
12610Sstevel@tonic-gate 	 */
12620Sstevel@tonic-gate 	if (sp->setno != MD_LOCAL_SET) {
12630Sstevel@tonic-gate 		(void) metaget_setdesc(sp, ep); /* not supposed to fail */
12640Sstevel@tonic-gate 		if (sp->setdesc->sd_flags & MD_SR_MN) {
12650Sstevel@tonic-gate 			int		err = 0;
12660Sstevel@tonic-gate 			md_mn_result_t *resp;
12670Sstevel@tonic-gate 			/*
12680Sstevel@tonic-gate 			 * This message is never directly issued.
12690Sstevel@tonic-gate 			 * So we launch it with a suspend override flag.
12700Sstevel@tonic-gate 			 * If the commd is suspended, and this message comes
12710Sstevel@tonic-gate 			 * along it must be sent due to replaying a metainit or
12720Sstevel@tonic-gate 			 * similar. In that case we don't want this message to
12730Sstevel@tonic-gate 			 * be blocked.
12740Sstevel@tonic-gate 			 * If the commd is not suspended, the flag does no harm.
12750Sstevel@tonic-gate 			 * Additionally we don't want the result of the message
12760Sstevel@tonic-gate 			 * cached in the MCT, because we want uptodate results,
12770Sstevel@tonic-gate 			 * and the message doesn't need being logged either.
12780Sstevel@tonic-gate 			 * Hence NO_LOG and NO_MCT
12790Sstevel@tonic-gate 			 */
12808452SJohn.Wren.Kennedy@Sun.COM 			err = mdmn_send_message(sp->setno,
12818452SJohn.Wren.Kennedy@Sun.COM 			    MD_MN_MSG_CLU_CHECK, MD_MSGF_NO_MCT |
12828452SJohn.Wren.Kennedy@Sun.COM 			    MD_MSGF_STOP_ON_ERROR | MD_MSGF_NO_LOG |
12838452SJohn.Wren.Kennedy@Sun.COM 			    MD_MSGF_OVERRIDE_SUSPEND, 0, (char *)&d,
12848452SJohn.Wren.Kennedy@Sun.COM 			    sizeof (md_isopen_t), &resp, ep);
12850Sstevel@tonic-gate 			if (err == 0) {
12860Sstevel@tonic-gate 				d.isopen = resp->mmr_exitval;
12870Sstevel@tonic-gate 			} else {
12880Sstevel@tonic-gate 				/*
12890Sstevel@tonic-gate 				 * in case some error occurred,
12900Sstevel@tonic-gate 				 * we better say the device is open
12910Sstevel@tonic-gate 				 */
12920Sstevel@tonic-gate 				d.isopen = 1;
12930Sstevel@tonic-gate 			}
12940Sstevel@tonic-gate 			if (resp != (md_mn_result_t *)NULL) {
12950Sstevel@tonic-gate 				free_result(resp);
12960Sstevel@tonic-gate 			}
12970Sstevel@tonic-gate 
12980Sstevel@tonic-gate 		}
12990Sstevel@tonic-gate 	}
13000Sstevel@tonic-gate 
13010Sstevel@tonic-gate 	return (d.isopen);
13020Sstevel@tonic-gate }
1303