xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_nameinfo.c (revision 32c22d57860198538fb6b8f261cb76ab26318d34)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50f5425cbSjkennedy  * Common Development and Distribution License (the "License").
60f5425cbSjkennedy  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21342440ecSPrasad Singamsetty 
227c478bd9Sstevel@tonic-gate /*
23*32c22d57SJames Hall  * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <dlfcn.h>
277c478bd9Sstevel@tonic-gate #include <meta.h>
287c478bd9Sstevel@tonic-gate #include <metadyn.h>
297c478bd9Sstevel@tonic-gate #include <ctype.h>
307c478bd9Sstevel@tonic-gate #include <dirent.h>
317c478bd9Sstevel@tonic-gate #include <devid.h>
327c478bd9Sstevel@tonic-gate #include <sys/param.h>
337c478bd9Sstevel@tonic-gate #include <sys/scsi/impl/uscsi.h>
347c478bd9Sstevel@tonic-gate #include <sys/scsi/generic/commands.h>
357c478bd9Sstevel@tonic-gate #include <sys/scsi/generic/inquiry.h>
367c478bd9Sstevel@tonic-gate #include <sys/efi_partition.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate typedef struct ctlr_cache {
397c478bd9Sstevel@tonic-gate 	char			*ctlr_nm;
407c478bd9Sstevel@tonic-gate 	int			ctlr_ty;
417c478bd9Sstevel@tonic-gate 	struct	ctlr_cache	*ctlr_nx;
427c478bd9Sstevel@tonic-gate } ctlr_cache_t;
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate static	ctlr_cache_t	*ctlr_cache = NULL;
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate  * return set for a device
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate mdsetname_t *
metagetset(mdname_t * np,int bypass_daemon,md_error_t * ep)517c478bd9Sstevel@tonic-gate metagetset(
527c478bd9Sstevel@tonic-gate 	mdname_t	*np,
537c478bd9Sstevel@tonic-gate 	int		bypass_daemon,
547c478bd9Sstevel@tonic-gate 	md_error_t	*ep
557c478bd9Sstevel@tonic-gate )
567c478bd9Sstevel@tonic-gate {
577c478bd9Sstevel@tonic-gate 	mdsetname_t	*sp;
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate 	/* metadevice */
607c478bd9Sstevel@tonic-gate 	if (metaismeta(np))
617c478bd9Sstevel@tonic-gate 		return (metasetnosetname(MD_MIN2SET(meta_getminor(np->dev)),
627c478bd9Sstevel@tonic-gate 		    ep));
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 	/* regular device */
657c478bd9Sstevel@tonic-gate 	if (meta_is_drive_in_anyset(np->drivenamep, &sp, bypass_daemon,
667c478bd9Sstevel@tonic-gate 	    ep) != 0)
677c478bd9Sstevel@tonic-gate 		return (NULL);
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 	if (sp != NULL)
707c478bd9Sstevel@tonic-gate 		return (sp);
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	return (metasetnosetname(MD_LOCAL_SET, ep));
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate  * convert system to md types
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate static void
meta_geom_to_md(struct dk_geom * gp,mdgeom_t * mdgp)797c478bd9Sstevel@tonic-gate meta_geom_to_md(
807c478bd9Sstevel@tonic-gate 	struct dk_geom	*gp,
817c478bd9Sstevel@tonic-gate 	mdgeom_t	*mdgp
827c478bd9Sstevel@tonic-gate )
837c478bd9Sstevel@tonic-gate {
847c478bd9Sstevel@tonic-gate 	(void) memset(mdgp, '\0', sizeof (*mdgp));
857c478bd9Sstevel@tonic-gate 	mdgp->ncyl = gp->dkg_ncyl;
867c478bd9Sstevel@tonic-gate 	mdgp->nhead = gp->dkg_nhead;
877c478bd9Sstevel@tonic-gate 	mdgp->nsect = gp->dkg_nsect;
887c478bd9Sstevel@tonic-gate 	mdgp->rpm = gp->dkg_rpm;
897c478bd9Sstevel@tonic-gate 	mdgp->write_reinstruct = gp->dkg_write_reinstruct;
907c478bd9Sstevel@tonic-gate 	mdgp->read_reinstruct = gp->dkg_read_reinstruct;
917c478bd9Sstevel@tonic-gate 	mdgp->blk_sz = DEV_BSIZE;
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  * convert efi to md types
967c478bd9Sstevel@tonic-gate  */
977c478bd9Sstevel@tonic-gate static void
meta_efi_to_mdgeom(md_unit_t * mdev,struct dk_gpt * gpt,mdgeom_t * mdgp)98*32c22d57SJames Hall meta_efi_to_mdgeom(md_unit_t *mdev, struct dk_gpt *gpt, mdgeom_t *mdgp)
997c478bd9Sstevel@tonic-gate {
1007c478bd9Sstevel@tonic-gate 	(void) memset(mdgp, '\0', sizeof (*mdgp));
101*32c22d57SJames Hall 
102*32c22d57SJames Hall 	/*
103*32c22d57SJames Hall 	 * Should always get geom from metadevice unit if metadevice.
104*32c22d57SJames Hall 	 * If metadevice is built on top of efi disks then it will
105*32c22d57SJames Hall 	 * have MD_EFI_FG_ values, otherwise it will have geom from
106*32c22d57SJames Hall 	 * the first component.
107*32c22d57SJames Hall 	 */
108*32c22d57SJames Hall 	if (mdev) {
109*32c22d57SJames Hall 		mdgp->ncyl = (mdev->c.un_total_blocks) /
110*32c22d57SJames Hall 		    (mdev->c.un_nhead * mdev->c.un_nsect);
111*32c22d57SJames Hall 		mdgp->nhead = mdev->c.un_nhead;
112*32c22d57SJames Hall 		mdgp->nsect = mdev->c.un_nsect;
113*32c22d57SJames Hall 	} else {
114*32c22d57SJames Hall 		mdgp->ncyl = (gpt->efi_last_u_lba - gpt->efi_first_u_lba)
115*32c22d57SJames Hall 		    / (MD_EFI_FG_HEADS * MD_EFI_FG_SECTORS);
1167c478bd9Sstevel@tonic-gate 		mdgp->nhead = MD_EFI_FG_HEADS;
1177c478bd9Sstevel@tonic-gate 		mdgp->nsect = MD_EFI_FG_SECTORS;
118*32c22d57SJames Hall 	}
119*32c22d57SJames Hall 
1207c478bd9Sstevel@tonic-gate 	mdgp->rpm = MD_EFI_FG_RPM;
1217c478bd9Sstevel@tonic-gate 	mdgp->write_reinstruct = MD_EFI_FG_WRI;
1227c478bd9Sstevel@tonic-gate 	mdgp->read_reinstruct = MD_EFI_FG_RRI;
1237c478bd9Sstevel@tonic-gate 	mdgp->blk_sz = DEV_BSIZE;
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate static void
meta_efi_to_mdvtoc(struct dk_gpt * gpt,mdvtoc_t * mdvp)1277c478bd9Sstevel@tonic-gate meta_efi_to_mdvtoc(struct dk_gpt *gpt, mdvtoc_t *mdvp)
1287c478bd9Sstevel@tonic-gate {
1297c478bd9Sstevel@tonic-gate 	char		typename[EFI_PART_NAME_LEN];
1307c478bd9Sstevel@tonic-gate 	uint_t		i;
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	(void) memset(mdvp, '\0', sizeof (*mdvp));
1337c478bd9Sstevel@tonic-gate 	mdvp->nparts = gpt->efi_nparts;
1347c478bd9Sstevel@tonic-gate 	if (mdvp->nparts > MD_MAX_PARTS)
1357c478bd9Sstevel@tonic-gate 		return;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	mdvp->first_lba = gpt->efi_first_u_lba;
1387c478bd9Sstevel@tonic-gate 	mdvp->last_lba = gpt->efi_last_u_lba;
1397c478bd9Sstevel@tonic-gate 	mdvp->lbasize = gpt->efi_lbasize;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	for (i = 0; (i < gpt->efi_nparts); ++i) {
1427c478bd9Sstevel@tonic-gate 		mdvp->parts[i].start = gpt->efi_parts[i].p_start;
1437c478bd9Sstevel@tonic-gate 		mdvp->parts[i].size = gpt->efi_parts[i].p_size;
1447c478bd9Sstevel@tonic-gate 		mdvp->parts[i].tag = gpt->efi_parts[i].p_tag;
1457c478bd9Sstevel@tonic-gate 		mdvp->parts[i].flag = gpt->efi_parts[i].p_flag;
1467c478bd9Sstevel@tonic-gate 		/*
1470f5425cbSjkennedy 		 * It is possible to present an efi label but be using vtoc
1480f5425cbSjkennedy 		 * disks to create a > 1 TB metadevice.  In case the first
1490f5425cbSjkennedy 		 * disk in the underlying metadevice is a vtoc disk and starts
1500f5425cbSjkennedy 		 * at the beginning of the disk it is necessary to convey this
1510f5425cbSjkennedy 		 * information to the user.
1520f5425cbSjkennedy 		 */
1530f5425cbSjkennedy 		if (mdvp->parts[i].size > 0 &&
1540f5425cbSjkennedy 		    mdvp->parts[i].start != 0 && mdvp->nparts == 1) {
1550f5425cbSjkennedy 			mdvp->parts[i].label = btodb(DK_LABEL_SIZE);
1560f5425cbSjkennedy 			mdvp->parts[i].start = 0;
1570f5425cbSjkennedy 		}
1580f5425cbSjkennedy 
1590f5425cbSjkennedy 		/*
1607c478bd9Sstevel@tonic-gate 		 * Due to the lack of a label for the entire partition table,
1617c478bd9Sstevel@tonic-gate 		 * we use p_name of the reserved partition
1627c478bd9Sstevel@tonic-gate 		 */
1637c478bd9Sstevel@tonic-gate 		if ((gpt->efi_parts[i].p_tag == V_RESERVED) &&
1647c478bd9Sstevel@tonic-gate 		    (gpt->efi_parts[i].p_name != NULL)) {
1657c478bd9Sstevel@tonic-gate 			(void) strlcpy(typename, gpt->efi_parts[i].p_name,
1667c478bd9Sstevel@tonic-gate 			    EFI_PART_NAME_LEN);
1677c478bd9Sstevel@tonic-gate 			/* Stop at first (if any) space or tab */
1687c478bd9Sstevel@tonic-gate 			(void) strtok(typename, " \t");
1697c478bd9Sstevel@tonic-gate 			mdvp->typename = Strdup(typename);
1707c478bd9Sstevel@tonic-gate 		}
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate static void
meta_mdvtoc_to_efi(mdvtoc_t * mdvp,struct dk_gpt ** gpt)1757c478bd9Sstevel@tonic-gate meta_mdvtoc_to_efi(mdvtoc_t *mdvp, struct dk_gpt **gpt)
1767c478bd9Sstevel@tonic-gate {
1777c478bd9Sstevel@tonic-gate 	uint_t		i;
1787c478bd9Sstevel@tonic-gate 	uint_t		lastpart;
1797c478bd9Sstevel@tonic-gate 	size_t		size;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	/* first we count how many partitions we have to send */
1827c478bd9Sstevel@tonic-gate 	for (i = 0; i < MD_MAX_PARTS; i++) {
1837c478bd9Sstevel@tonic-gate 		if ((mdvp->parts[i].start == 0) &&
1847c478bd9Sstevel@tonic-gate 		    (mdvp->parts[i].size == 0) &&
1857c478bd9Sstevel@tonic-gate 		    (mdvp->parts[i].tag != V_RESERVED)) {
1867c478bd9Sstevel@tonic-gate 			continue;
1877c478bd9Sstevel@tonic-gate 		}
1887c478bd9Sstevel@tonic-gate 		/* if we are here, we know the partition is really used */
1897c478bd9Sstevel@tonic-gate 		lastpart = i;
1907c478bd9Sstevel@tonic-gate 	}
1917c478bd9Sstevel@tonic-gate 	size = sizeof (struct dk_gpt) + (sizeof (struct dk_part) * lastpart);
1927c478bd9Sstevel@tonic-gate 	*gpt = calloc(size, sizeof (char));
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	(*gpt)->efi_nparts = lastpart + 1;
1957c478bd9Sstevel@tonic-gate 	(*gpt)->efi_first_u_lba = mdvp->first_lba;
1967c478bd9Sstevel@tonic-gate 	(*gpt)->efi_last_u_lba = mdvp->last_lba;
1977c478bd9Sstevel@tonic-gate 	(*gpt)->efi_lbasize = mdvp->lbasize;
1987c478bd9Sstevel@tonic-gate 	for (i = 0; (i < (*gpt)->efi_nparts); ++i) {
1997c478bd9Sstevel@tonic-gate 		(*gpt)->efi_parts[i].p_start = mdvp->parts[i].start;
2007c478bd9Sstevel@tonic-gate 		(*gpt)->efi_parts[i].p_size = mdvp->parts[i].size;
2017c478bd9Sstevel@tonic-gate 		(*gpt)->efi_parts[i].p_tag = mdvp->parts[i].tag;
2027c478bd9Sstevel@tonic-gate 		(*gpt)->efi_parts[i].p_flag = mdvp->parts[i].flag;
2037c478bd9Sstevel@tonic-gate 		/*
2047c478bd9Sstevel@tonic-gate 		 * Due to the lack of a label for the entire partition table,
2057c478bd9Sstevel@tonic-gate 		 * we use p_name of the reserved partition
2067c478bd9Sstevel@tonic-gate 		 */
2077c478bd9Sstevel@tonic-gate 		if (((*gpt)->efi_parts[i].p_tag == V_RESERVED) &&
2087c478bd9Sstevel@tonic-gate 		    (mdvp->typename != NULL)) {
209e98fb20aSAndrew Balfour 			(void) strlcpy((*gpt)->efi_parts[i].p_name,
210e98fb20aSAndrew Balfour 			    mdvp->typename, EFI_PART_NAME_LEN);
2117c478bd9Sstevel@tonic-gate 		}
2127c478bd9Sstevel@tonic-gate 	}
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate void
ctlr_cache_add(char * nm,int ty)2177c478bd9Sstevel@tonic-gate ctlr_cache_add(char *nm, int ty)
2187c478bd9Sstevel@tonic-gate {
2197c478bd9Sstevel@tonic-gate 	ctlr_cache_t	**ccpp;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	for (ccpp = &ctlr_cache; *ccpp != NULL; ccpp = &(*ccpp)->ctlr_nx)
2227c478bd9Sstevel@tonic-gate 		if (strcmp((*ccpp)->ctlr_nm, nm) == 0)
2237c478bd9Sstevel@tonic-gate 			return;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	*ccpp = Zalloc(sizeof (ctlr_cache_t));
2267c478bd9Sstevel@tonic-gate 	(*ccpp)->ctlr_nm = Strdup(nm);
2277c478bd9Sstevel@tonic-gate 	(*ccpp)->ctlr_ty = ty;
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate int
ctlr_cache_look(char * nm)2317c478bd9Sstevel@tonic-gate ctlr_cache_look(char *nm)
2327c478bd9Sstevel@tonic-gate {
2337c478bd9Sstevel@tonic-gate 	ctlr_cache_t	*tcp;
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	for (tcp = ctlr_cache; tcp != NULL; tcp = tcp->ctlr_nx)
2367c478bd9Sstevel@tonic-gate 		if (strcmp(tcp->ctlr_nm, nm) == 0)
2377c478bd9Sstevel@tonic-gate 			return (tcp->ctlr_ty);
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	return (-1);
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate void
metaflushctlrcache(void)2447c478bd9Sstevel@tonic-gate metaflushctlrcache(void)
2457c478bd9Sstevel@tonic-gate {
2467c478bd9Sstevel@tonic-gate 	ctlr_cache_t	*cp, *np;
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	for (cp = ctlr_cache, np = NULL; cp != NULL; cp = np) {
2497c478bd9Sstevel@tonic-gate 		np = cp->ctlr_nx;
2507c478bd9Sstevel@tonic-gate 		Free(cp->ctlr_nm);
2517c478bd9Sstevel@tonic-gate 		Free(cp);
2527c478bd9Sstevel@tonic-gate 	}
2537c478bd9Sstevel@tonic-gate 	ctlr_cache = NULL;
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate /*
2577c478bd9Sstevel@tonic-gate  * getdrvnode -- return the driver name based on mdname_t->bname
2587c478bd9Sstevel@tonic-gate  *	Need to free pointer when finished.
2597c478bd9Sstevel@tonic-gate  */
2607c478bd9Sstevel@tonic-gate char *
getdrvnode(mdname_t * np,md_error_t * ep)2617c478bd9Sstevel@tonic-gate getdrvnode(mdname_t *np, md_error_t *ep)
2627c478bd9Sstevel@tonic-gate {
263342440ecSPrasad Singamsetty 	char	*devicespath;
264342440ecSPrasad Singamsetty 	char	*drvnode;
265342440ecSPrasad Singamsetty 	char	*cp;
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	if ((devicespath = metagetdevicesname(np, ep)) == NULL)
2687c478bd9Sstevel@tonic-gate 		return (NULL);
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	/*
2717c478bd9Sstevel@tonic-gate 	 * At this point devicespath should be like the following
2727c478bd9Sstevel@tonic-gate 	 * "/devices/<unknow_and_dont_care>/xxxx@vvvv"
2737c478bd9Sstevel@tonic-gate 	 *
2747c478bd9Sstevel@tonic-gate 	 * There's a couple of 'if' statements below which could
2757c478bd9Sstevel@tonic-gate 	 * return an error condition, but I've decide to allow
2767c478bd9Sstevel@tonic-gate 	 * a more open approach regarding the mapping so as to
2777c478bd9Sstevel@tonic-gate 	 * not restrict possible future projects.
2787c478bd9Sstevel@tonic-gate 	 */
2797c478bd9Sstevel@tonic-gate 	if (drvnode = strrchr(devicespath, '/'))
2807c478bd9Sstevel@tonic-gate 		/*
2817c478bd9Sstevel@tonic-gate 		 * drvnode now just "xxxx@vvvv"
2827c478bd9Sstevel@tonic-gate 		 */
2837c478bd9Sstevel@tonic-gate 		drvnode++;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	if (cp = strrchr(drvnode, '@'))
2867c478bd9Sstevel@tonic-gate 		/*
2877c478bd9Sstevel@tonic-gate 		 * Now drvnode is just the driver name "xxxx"
2887c478bd9Sstevel@tonic-gate 		 */
2897c478bd9Sstevel@tonic-gate 		*cp = '\0';
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	cp = Strdup(drvnode);
2927c478bd9Sstevel@tonic-gate 	Free(devicespath);
2937c478bd9Sstevel@tonic-gate 	np->devicesname = NULL;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	return (cp);
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate /*
2997c478bd9Sstevel@tonic-gate  * meta_load_dl -- open dynamic library using LDLIBRARYPATH, a debug
3007c478bd9Sstevel@tonic-gate  *    environment variable METALDPATH, or the default location.
3017c478bd9Sstevel@tonic-gate  */
3027c478bd9Sstevel@tonic-gate static void *
meta_load_dl(mdname_t * np,md_error_t * ep)3037c478bd9Sstevel@tonic-gate meta_load_dl(mdname_t *np, md_error_t *ep)
3047c478bd9Sstevel@tonic-gate {
305342440ecSPrasad Singamsetty 	char	*drvnode;
306342440ecSPrasad Singamsetty 	char	newpath[MAXPATHLEN];
307342440ecSPrasad Singamsetty 	char	*p;
3087c478bd9Sstevel@tonic-gate 	void	*cookie;
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	if ((drvnode = getdrvnode(np, ep)) != NULL) {
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 		/*
3137c478bd9Sstevel@tonic-gate 		 * Library seach algorithm:
3147c478bd9Sstevel@tonic-gate 		 * 1) Use LDLIBRARYPATH which is implied when a non-absolute
3157c478bd9Sstevel@tonic-gate 		 *    path name is passed to dlopen()
3167c478bd9Sstevel@tonic-gate 		 * 2) Use the value of METALDPATH as the directory. Mainly
3177c478bd9Sstevel@tonic-gate 		 *    used for debugging
3187c478bd9Sstevel@tonic-gate 		 * 3) Last search the default location of "/usr/lib"
3197c478bd9Sstevel@tonic-gate 		 */
3207c478bd9Sstevel@tonic-gate 		(void) snprintf(newpath, sizeof (newpath), "lib%s.so.1",
3217c478bd9Sstevel@tonic-gate 		    drvnode);
3227c478bd9Sstevel@tonic-gate 		if ((cookie = dlopen(newpath, RTLD_LAZY)) == NULL) {
3237c478bd9Sstevel@tonic-gate 			if ((p = getenv("METALDPATH")) == NULL)
3247c478bd9Sstevel@tonic-gate 				p = METALDPATH_DEFAULT;
3257c478bd9Sstevel@tonic-gate 			(void) snprintf(newpath, sizeof (newpath),
3267c478bd9Sstevel@tonic-gate 			    "%s/lib%s.so.1", p, drvnode);
3277c478bd9Sstevel@tonic-gate 			Free(drvnode);
3287c478bd9Sstevel@tonic-gate 			if ((cookie = dlopen(newpath, RTLD_LAZY)) != NULL) {
3297c478bd9Sstevel@tonic-gate 				/*
3307c478bd9Sstevel@tonic-gate 				 * Common failure here would be failing to
3317c478bd9Sstevel@tonic-gate 				 * find a libXX.so.1 such as libsd.so.1
3327c478bd9Sstevel@tonic-gate 				 * Some controllers will not have a library
3337c478bd9Sstevel@tonic-gate 				 * because there's no enclosure or name
3347c478bd9Sstevel@tonic-gate 				 * translation required.
3357c478bd9Sstevel@tonic-gate 				 */
3367c478bd9Sstevel@tonic-gate 				return (cookie);
3377c478bd9Sstevel@tonic-gate 			}
3387c478bd9Sstevel@tonic-gate 		} else {
3397c478bd9Sstevel@tonic-gate 			Free(drvnode);
3407c478bd9Sstevel@tonic-gate 			return (cookie);
3417c478bd9Sstevel@tonic-gate 		}
3427c478bd9Sstevel@tonic-gate 	}
3437c478bd9Sstevel@tonic-gate 	return (NULL);
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate /*
3477c478bd9Sstevel@tonic-gate  * meta_match_names -- possibly convert the driver names returned by CINFO
3487c478bd9Sstevel@tonic-gate  */
3497c478bd9Sstevel@tonic-gate static void
meta_match_names(mdname_t * np,struct dk_cinfo * cp,mdcinfo_t * mdcp,md_error_t * ep)3507c478bd9Sstevel@tonic-gate meta_match_names(mdname_t *np, struct dk_cinfo *cp, mdcinfo_t *mdcp,
3517c478bd9Sstevel@tonic-gate     md_error_t *ep)
3527c478bd9Sstevel@tonic-gate {
3537c478bd9Sstevel@tonic-gate 	void		*cookie;
3547c478bd9Sstevel@tonic-gate 	meta_convert_e	((*fptr)(mdname_t *, struct dk_cinfo *, mdcinfo_t *,
3557c478bd9Sstevel@tonic-gate 	    md_error_t *));
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	if ((cookie = meta_load_dl(np, ep)) != NULL) {
3587c478bd9Sstevel@tonic-gate 		fptr = (meta_convert_e (*)(mdname_t *, struct dk_cinfo *,
3597c478bd9Sstevel@tonic-gate 		    mdcinfo_t *, md_error_t *))dlsym(cookie, "convert_path");
3607c478bd9Sstevel@tonic-gate 		if (fptr != NULL)
3617c478bd9Sstevel@tonic-gate 			(void) (*fptr)(np, cp, mdcp, ep);
3627c478bd9Sstevel@tonic-gate 		(void) dlclose(cookie);
3637c478bd9Sstevel@tonic-gate 	}
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate /*
3677c478bd9Sstevel@tonic-gate  * meta_match_enclosure -- return any enclosure info if found
3687c478bd9Sstevel@tonic-gate  */
3697c478bd9Sstevel@tonic-gate int
meta_match_enclosure(mdname_t * np,mdcinfo_t * mdcp,md_error_t * ep)3707c478bd9Sstevel@tonic-gate meta_match_enclosure(mdname_t *np, mdcinfo_t *mdcp, md_error_t *ep)
3717c478bd9Sstevel@tonic-gate {
372342440ecSPrasad Singamsetty 	meta_enclosure_e	e;
373342440ecSPrasad Singamsetty 	meta_enclosure_e	((*fptr)(mdname_t *, mdcinfo_t *,
3747c478bd9Sstevel@tonic-gate 	    md_error_t *));
3757c478bd9Sstevel@tonic-gate 	void			*cookie;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	if ((cookie = meta_load_dl(np, ep)) != NULL) {
3787c478bd9Sstevel@tonic-gate 		fptr = (meta_enclosure_e (*)(mdname_t *, mdcinfo_t *,
3797c478bd9Sstevel@tonic-gate 		    md_error_t *))dlsym(cookie, "get_enclosure");
3807c478bd9Sstevel@tonic-gate 		if (fptr != NULL) {
3817c478bd9Sstevel@tonic-gate 			e = (*fptr)(np, mdcp, ep);
3827c478bd9Sstevel@tonic-gate 			switch (e) {
3837c478bd9Sstevel@tonic-gate 			case Enclosure_Error:
3847c478bd9Sstevel@tonic-gate 				/*
3857c478bd9Sstevel@tonic-gate 				 * Looks like this library wanted to handle
3867c478bd9Sstevel@tonic-gate 				 * our device and had an internal error.
3877c478bd9Sstevel@tonic-gate 				 */
3887c478bd9Sstevel@tonic-gate 				return (1);
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 			case Enclosure_Okay:
3917c478bd9Sstevel@tonic-gate 				/*
3927c478bd9Sstevel@tonic-gate 				 * Found a library to handle the request so
3937c478bd9Sstevel@tonic-gate 				 * just return with data provided.
3947c478bd9Sstevel@tonic-gate 				 */
3957c478bd9Sstevel@tonic-gate 				return (0);
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 			case Enclosure_Noop:
3987c478bd9Sstevel@tonic-gate 				/*
3997c478bd9Sstevel@tonic-gate 				 * Need to continue the search
4007c478bd9Sstevel@tonic-gate 				 */
4017c478bd9Sstevel@tonic-gate 				break;
4027c478bd9Sstevel@tonic-gate 			}
4037c478bd9Sstevel@tonic-gate 		}
4047c478bd9Sstevel@tonic-gate 		(void) dlclose(cookie);
4057c478bd9Sstevel@tonic-gate 	}
4067c478bd9Sstevel@tonic-gate 	return (0);
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate static int
meta_cinfo_to_md(mdname_t * np,struct dk_cinfo * cp,mdcinfo_t * mdcp,md_error_t * ep)4107c478bd9Sstevel@tonic-gate meta_cinfo_to_md(mdname_t *np, struct dk_cinfo *cp, mdcinfo_t *mdcp,
4117c478bd9Sstevel@tonic-gate     md_error_t *ep)
4127c478bd9Sstevel@tonic-gate {
4137c478bd9Sstevel@tonic-gate 	/* default */
4147c478bd9Sstevel@tonic-gate 	(void) memset(mdcp, '\0', sizeof (*mdcp));
4157c478bd9Sstevel@tonic-gate 	(void) strncpy(mdcp->cname, cp->dki_cname,
4167c478bd9Sstevel@tonic-gate 	    min((sizeof (mdcp->cname) - 1), sizeof (cp->dki_cname)));
4177c478bd9Sstevel@tonic-gate 	mdcp->ctype = MHD_CTLR_GENERIC;
4187c478bd9Sstevel@tonic-gate 	mdcp->cnum = cp->dki_cnum;
4197c478bd9Sstevel@tonic-gate 	(void) strncpy(mdcp->dname, cp->dki_dname,
4207c478bd9Sstevel@tonic-gate 	    min((sizeof (mdcp->dname) - 1), sizeof (cp->dki_dname)));
4217c478bd9Sstevel@tonic-gate 	mdcp->unit = cp->dki_unit;
4227c478bd9Sstevel@tonic-gate 	mdcp->maxtransfer = cp->dki_maxtransfer;
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	/*
4257c478bd9Sstevel@tonic-gate 	 * See if the driver name returned from DKIOCINFO
4267c478bd9Sstevel@tonic-gate 	 * is valid or not. In somecases, such as the ap_dmd
4277c478bd9Sstevel@tonic-gate 	 * driver, we need to modify the name that's return
4287c478bd9Sstevel@tonic-gate 	 * for everything to work.
4297c478bd9Sstevel@tonic-gate 	 */
4307c478bd9Sstevel@tonic-gate 	meta_match_names(np, cp, mdcp, ep);
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	if (meta_match_enclosure(np, mdcp, ep))
4337c478bd9Sstevel@tonic-gate 		return (-1);
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	/* return success */
4367c478bd9Sstevel@tonic-gate 	return (0);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate static void
meta_vtoc_to_md(struct extvtoc * vp,mdvtoc_t * mdvp)4407c478bd9Sstevel@tonic-gate meta_vtoc_to_md(
441342440ecSPrasad Singamsetty 	struct extvtoc	*vp,
4427c478bd9Sstevel@tonic-gate 	mdvtoc_t	*mdvp
4437c478bd9Sstevel@tonic-gate )
4447c478bd9Sstevel@tonic-gate {
4457c478bd9Sstevel@tonic-gate 	char		typename[sizeof (vp->v_asciilabel) + 1];
4467c478bd9Sstevel@tonic-gate 	uint_t		i;
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 	(void) memset(mdvp, '\0', sizeof (*mdvp));
4497c478bd9Sstevel@tonic-gate 	(void) strncpy(typename, vp->v_asciilabel,
4507c478bd9Sstevel@tonic-gate 	    sizeof (vp->v_asciilabel));
4517c478bd9Sstevel@tonic-gate 	typename[sizeof (typename) - 1] = '\0';
4527c478bd9Sstevel@tonic-gate 	for (i = 0; ((i < sizeof (typename)) && (typename[i] != '\0')); ++i) {
4537c478bd9Sstevel@tonic-gate 		if ((typename[i] == ' ') || (typename[i] == '\t')) {
4547c478bd9Sstevel@tonic-gate 			typename[i] = '\0';
4557c478bd9Sstevel@tonic-gate 			break;
4567c478bd9Sstevel@tonic-gate 		}
4577c478bd9Sstevel@tonic-gate 	}
4587c478bd9Sstevel@tonic-gate 	mdvp->typename = Strdup(typename);
4597c478bd9Sstevel@tonic-gate 	mdvp->nparts = vp->v_nparts;
4607c478bd9Sstevel@tonic-gate 	for (i = 0; (i < vp->v_nparts); ++i) {
4617c478bd9Sstevel@tonic-gate 		mdvp->parts[i].start = vp->v_part[i].p_start;
4627c478bd9Sstevel@tonic-gate 		mdvp->parts[i].size = vp->v_part[i].p_size;
4637c478bd9Sstevel@tonic-gate 		mdvp->parts[i].tag = vp->v_part[i].p_tag;
4647c478bd9Sstevel@tonic-gate 		mdvp->parts[i].flag = vp->v_part[i].p_flag;
4657c478bd9Sstevel@tonic-gate 		if (vp->v_part[i].p_start == 0 && vp->v_part[i].p_size > 0)
4667c478bd9Sstevel@tonic-gate 			mdvp->parts[i].label = btodb(DK_LABEL_SIZE);
4677c478bd9Sstevel@tonic-gate 	}
4687c478bd9Sstevel@tonic-gate }
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate /*
4717c478bd9Sstevel@tonic-gate  * free allocations in vtoc
4727c478bd9Sstevel@tonic-gate  */
4737c478bd9Sstevel@tonic-gate void
metafreevtoc(mdvtoc_t * vtocp)4747c478bd9Sstevel@tonic-gate metafreevtoc(
4757c478bd9Sstevel@tonic-gate 	mdvtoc_t	*vtocp
4767c478bd9Sstevel@tonic-gate )
4777c478bd9Sstevel@tonic-gate {
4787c478bd9Sstevel@tonic-gate 	if (vtocp->typename != NULL)
4797c478bd9Sstevel@tonic-gate 		Free(vtocp->typename);
4807c478bd9Sstevel@tonic-gate 	(void) memset(vtocp, 0, sizeof (*vtocp));
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate /*
4847c478bd9Sstevel@tonic-gate  * return md types
4857c478bd9Sstevel@tonic-gate  */
4867c478bd9Sstevel@tonic-gate mdvtoc_t *
metagetvtoc(mdname_t * np,int nocache,uint_t * partnop,md_error_t * ep)4877c478bd9Sstevel@tonic-gate metagetvtoc(
4887c478bd9Sstevel@tonic-gate 	mdname_t	*np,	/* only rname, drivenamep, are setup */
4897c478bd9Sstevel@tonic-gate 	int		nocache,
4907c478bd9Sstevel@tonic-gate 	uint_t		*partnop,
4917c478bd9Sstevel@tonic-gate 	md_error_t	*ep
4927c478bd9Sstevel@tonic-gate )
4937c478bd9Sstevel@tonic-gate {
4947c478bd9Sstevel@tonic-gate 	mddrivename_t	*dnp = np->drivenamep;
4957c478bd9Sstevel@tonic-gate 	struct dk_geom	geom;
4967c478bd9Sstevel@tonic-gate 	char		*minor_name = NULL;
4977c478bd9Sstevel@tonic-gate 	char		*rname = np->rname;
4987c478bd9Sstevel@tonic-gate 	int		fd;
4997c478bd9Sstevel@tonic-gate 	int		partno;
5007c478bd9Sstevel@tonic-gate 	int		err = 0;	    /* saves errno from ioctl */
5017c478bd9Sstevel@tonic-gate 	ddi_devid_t	devid;
5027c478bd9Sstevel@tonic-gate 	char		*p;
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	/* short circuit */
5057c478bd9Sstevel@tonic-gate 	if ((! nocache) && (dnp->vtoc.nparts != 0)) {
5067c478bd9Sstevel@tonic-gate 		if (partnop != NULL) {
5077c478bd9Sstevel@tonic-gate 			/*
5087c478bd9Sstevel@tonic-gate 			 * the following assigment works because the
5097c478bd9Sstevel@tonic-gate 			 * mdname_t structs are always created as part
5107c478bd9Sstevel@tonic-gate 			 * of the drivenamep struct.  When a user
5117c478bd9Sstevel@tonic-gate 			 * creates an mdname_t struct it either
5127c478bd9Sstevel@tonic-gate 			 * uses an existing drivenamep struct or creates
5137c478bd9Sstevel@tonic-gate 			 * a new one and then adds the mdname_t struct
5147c478bd9Sstevel@tonic-gate 			 * as part of its parts_val array.  So what is
5157c478bd9Sstevel@tonic-gate 			 * being computed below is the slice offset in
5167c478bd9Sstevel@tonic-gate 			 * the parts_val array.
5177c478bd9Sstevel@tonic-gate 			 */
5187c478bd9Sstevel@tonic-gate 			*partnop = np - np->drivenamep->parts.parts_val;
5197c478bd9Sstevel@tonic-gate 			assert(*partnop < dnp->parts.parts_len);
5207c478bd9Sstevel@tonic-gate 		}
5217c478bd9Sstevel@tonic-gate 		return (&dnp->vtoc);
5227c478bd9Sstevel@tonic-gate 	}
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 	/* can't get vtoc */
5257c478bd9Sstevel@tonic-gate 	if (! nocache) {
5267c478bd9Sstevel@tonic-gate 		switch (dnp->type) {
5277c478bd9Sstevel@tonic-gate 		case MDT_ACCES:
5287c478bd9Sstevel@tonic-gate 		case MDT_UNKNOWN:
5297c478bd9Sstevel@tonic-gate 			(void) mdsyserror(ep, dnp->errnum, rname);
5307c478bd9Sstevel@tonic-gate 			return (NULL);
5317c478bd9Sstevel@tonic-gate 		}
5327c478bd9Sstevel@tonic-gate 	}
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	/* get all the info */
5357c478bd9Sstevel@tonic-gate 	if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
5367c478bd9Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, rname);
5377c478bd9Sstevel@tonic-gate 		return (NULL);
5387c478bd9Sstevel@tonic-gate 	}
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	/*
5417c478bd9Sstevel@tonic-gate 	 * The disk is open so this is a good point to get the devid
5427c478bd9Sstevel@tonic-gate 	 * otherwise it will need to be done at another time which
5437c478bd9Sstevel@tonic-gate 	 * means reopening it.
5447c478bd9Sstevel@tonic-gate 	 */
5457c478bd9Sstevel@tonic-gate 	if (devid_get(fd, &devid) != 0) {
5467c478bd9Sstevel@tonic-gate 		/* there is no devid for the disk */
5477c478bd9Sstevel@tonic-gate 		if (((p = getenv("MD_DEBUG")) != NULL) &&
5487c478bd9Sstevel@tonic-gate 		    (strstr(p, "DEVID") != NULL)) {
5497c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
5507c478bd9Sstevel@tonic-gate 			    "%s has no device id\n"), np->rname);
5517c478bd9Sstevel@tonic-gate 		}
5527c478bd9Sstevel@tonic-gate 		np->minor_name = (char *)NULL;
5537c478bd9Sstevel@tonic-gate 		dnp->devid = NULL;
5547c478bd9Sstevel@tonic-gate 	} else {
5557c478bd9Sstevel@tonic-gate 		(void) devid_get_minor_name(fd, &minor_name);
5567c478bd9Sstevel@tonic-gate 		/*
5577c478bd9Sstevel@tonic-gate 		 * The minor name could be NULL if the underlying
5587c478bd9Sstevel@tonic-gate 		 * device driver does not support 'minor names'.
5597c478bd9Sstevel@tonic-gate 		 * This means we do not use devid's for this device.
5607c478bd9Sstevel@tonic-gate 		 * SunCluster did driver does not support minor names.
5617c478bd9Sstevel@tonic-gate 		 */
5627c478bd9Sstevel@tonic-gate 		if (minor_name != NULL) {
5637c478bd9Sstevel@tonic-gate 			np->minor_name = Strdup(minor_name);
5647c478bd9Sstevel@tonic-gate 			devid_str_free(minor_name);
5657c478bd9Sstevel@tonic-gate 			dnp->devid = devid_str_encode(devid, NULL);
5667c478bd9Sstevel@tonic-gate 		} else {
5677c478bd9Sstevel@tonic-gate 			np->minor_name = (char *)NULL;
5687c478bd9Sstevel@tonic-gate 			dnp->devid = NULL;
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 			if (((p = getenv("MD_DEBUG")) != NULL) &&
5717c478bd9Sstevel@tonic-gate 			    (strstr(p, "DEVID") != NULL)) {
5727c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
5737c478bd9Sstevel@tonic-gate 				    "%s no minor name (no devid)\n"),
5747c478bd9Sstevel@tonic-gate 				    np->rname);
5757c478bd9Sstevel@tonic-gate 			}
5767c478bd9Sstevel@tonic-gate 		}
5777c478bd9Sstevel@tonic-gate 		devid_free(devid);
5787c478bd9Sstevel@tonic-gate 	}
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	/*
5817c478bd9Sstevel@tonic-gate 	 * if our drivenamep points to a device not supporting DKIOCGGEOM,
5827c478bd9Sstevel@tonic-gate 	 * it's likely to have an EFI label.
5837c478bd9Sstevel@tonic-gate 	 */
5847c478bd9Sstevel@tonic-gate 	(void) memset(&geom, 0, sizeof (geom));
5857c478bd9Sstevel@tonic-gate 	if (ioctl(fd, DKIOCGGEOM, &geom) != 0) {
5867c478bd9Sstevel@tonic-gate 		err = errno;
5877c478bd9Sstevel@tonic-gate 		if (err == ENOTTY) {
5887c478bd9Sstevel@tonic-gate 			(void) mddeverror(ep, MDE_NOT_DISK, NODEV, rname);
5897c478bd9Sstevel@tonic-gate 			(void) close(fd);
5907c478bd9Sstevel@tonic-gate 			return (NULL);
5917c478bd9Sstevel@tonic-gate 		} else if (err != ENOTSUP) {
5927c478bd9Sstevel@tonic-gate 			(void) mdsyserror(ep, err, rname);
5937c478bd9Sstevel@tonic-gate 			(void) close(fd);
5947c478bd9Sstevel@tonic-gate 			return (NULL);
5957c478bd9Sstevel@tonic-gate 		}
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	}
5987c478bd9Sstevel@tonic-gate 	/*
5997c478bd9Sstevel@tonic-gate 	 * If we are here, there was either no failure on DKIOCGGEOM or
6007c478bd9Sstevel@tonic-gate 	 * the failure was ENOTSUP
6017c478bd9Sstevel@tonic-gate 	 */
6027c478bd9Sstevel@tonic-gate 	if (err == ENOTSUP) {
6037c478bd9Sstevel@tonic-gate 		/* DKIOCGGEOM yielded ENOTSUP => try efi_alloc_and_read */
6047c478bd9Sstevel@tonic-gate 		struct dk_gpt	*gpt;
6057c478bd9Sstevel@tonic-gate 		int		save_errno;
606*32c22d57SJames Hall 		md_unit_t	*mdev = NULL;
607*32c22d57SJames Hall 		mdsetname_t	*sp = NULL;
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 		/* this also sets errno */
6107c478bd9Sstevel@tonic-gate 		partno = efi_alloc_and_read(fd, &gpt);
6117c478bd9Sstevel@tonic-gate 		save_errno = errno;
6127c478bd9Sstevel@tonic-gate 		(void) close(fd);
6137c478bd9Sstevel@tonic-gate 		if (partno < 0) {
6147c478bd9Sstevel@tonic-gate 			efi_free(gpt);
6157c478bd9Sstevel@tonic-gate 			(void) mdsyserror(ep, save_errno, rname);
6167c478bd9Sstevel@tonic-gate 			return (NULL);
6177c478bd9Sstevel@tonic-gate 		}
6187c478bd9Sstevel@tonic-gate 		if (partno >= gpt->efi_nparts) {
6197c478bd9Sstevel@tonic-gate 			efi_free(gpt);
6207c478bd9Sstevel@tonic-gate 			(void) mddeverror(ep, MDE_INVALID_PART, NODEV64,
6217c478bd9Sstevel@tonic-gate 			    rname);
6227c478bd9Sstevel@tonic-gate 			return (NULL);
6237c478bd9Sstevel@tonic-gate 		}
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate 		/* convert to our format */
6267c478bd9Sstevel@tonic-gate 		metafreevtoc(&dnp->vtoc);
6277c478bd9Sstevel@tonic-gate 		meta_efi_to_mdvtoc(gpt, &dnp->vtoc);
6287c478bd9Sstevel@tonic-gate 		if (dnp->vtoc.nparts > MD_MAX_PARTS) {
629*32c22d57SJames Hall 			efi_free(gpt);
6307c478bd9Sstevel@tonic-gate 			(void) mddeverror(ep, MDE_TOO_MANY_PARTS, NODEV64,
6317c478bd9Sstevel@tonic-gate 			    rname);
6327c478bd9Sstevel@tonic-gate 			return (NULL);
6337c478bd9Sstevel@tonic-gate 		}
6347c478bd9Sstevel@tonic-gate 		/*
6357c478bd9Sstevel@tonic-gate 		 * libmeta needs at least V_NUMPAR partitions.
6367c478bd9Sstevel@tonic-gate 		 * If we have an EFI partition with less than V_NUMPAR slices,
6377c478bd9Sstevel@tonic-gate 		 * we nevertheless reserve space for V_NUMPAR
6387c478bd9Sstevel@tonic-gate 		 */
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate 		if (dnp->vtoc.nparts < V_NUMPAR) {
6417c478bd9Sstevel@tonic-gate 			dnp->vtoc.nparts = V_NUMPAR;
6427c478bd9Sstevel@tonic-gate 		}
643*32c22d57SJames Hall 
644*32c22d57SJames Hall 		/*
645*32c22d57SJames Hall 		 * Is np a metadevice?
646*32c22d57SJames Hall 		 */
647*32c22d57SJames Hall 		if (metaismeta(np)) {
648*32c22d57SJames Hall 			sp = metasetnosetname(MD_MIN2SET(meta_getminor
649*32c22d57SJames Hall 			    (np->dev)), ep);
650*32c22d57SJames Hall 			if (!sp || (mdev = meta_get_mdunit(sp, np, ep)) ==
651*32c22d57SJames Hall 			    NULL) {
652*32c22d57SJames Hall 				efi_free(gpt);
653*32c22d57SJames Hall 				(void) mddeverror(ep, MDE_NOT_META,
654*32c22d57SJames Hall 				    NODEV64, rname);
655*32c22d57SJames Hall 				return (NULL);
656*32c22d57SJames Hall 			}
657*32c22d57SJames Hall 		}
658*32c22d57SJames Hall 
659*32c22d57SJames Hall 		meta_efi_to_mdgeom(mdev, gpt, &dnp->geom);
660*32c22d57SJames Hall 		Free(mdev);
6617c478bd9Sstevel@tonic-gate 		efi_free(gpt);
6627c478bd9Sstevel@tonic-gate 	} else {
6637c478bd9Sstevel@tonic-gate 		/* no error on DKIOCGGEOM, try meta_getvtoc */
664342440ecSPrasad Singamsetty 		struct extvtoc	vtoc;
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 		if (meta_getvtoc(fd, np->cname, &vtoc, &partno, ep) < 0) {
6677c478bd9Sstevel@tonic-gate 			(void) close(fd);
6687c478bd9Sstevel@tonic-gate 			return (NULL);
6697c478bd9Sstevel@tonic-gate 		}
6707c478bd9Sstevel@tonic-gate 		(void) close(fd);
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 		/* convert to our format */
6737c478bd9Sstevel@tonic-gate 		meta_geom_to_md(&geom, &dnp->geom);
6747c478bd9Sstevel@tonic-gate 		metafreevtoc(&dnp->vtoc);
6757c478bd9Sstevel@tonic-gate 		meta_vtoc_to_md(&vtoc, &dnp->vtoc);
6767c478bd9Sstevel@tonic-gate 	}
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 	/* fix up any drives which are now accessible */
6797c478bd9Sstevel@tonic-gate 	if ((nocache) && (dnp->type == MDT_ACCES) &&
6807c478bd9Sstevel@tonic-gate 	    (dnp->vtoc.nparts == dnp->parts.parts_len)) {
6817c478bd9Sstevel@tonic-gate 		dnp->type = MDT_COMP;
6827c478bd9Sstevel@tonic-gate 		dnp->errnum = 0;
6837c478bd9Sstevel@tonic-gate 	}
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 	/* save partno */
6867c478bd9Sstevel@tonic-gate 	assert(partno < dnp->vtoc.nparts);
6877c478bd9Sstevel@tonic-gate 	if (partnop != NULL)
6887c478bd9Sstevel@tonic-gate 		*partnop = partno;
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	/* return info */
6917c478bd9Sstevel@tonic-gate 	return (&dnp->vtoc);
6927c478bd9Sstevel@tonic-gate }
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate static void
meta_mdvtoc_to_vtoc(mdvtoc_t * mdvp,struct extvtoc * vp)6957c478bd9Sstevel@tonic-gate meta_mdvtoc_to_vtoc(
6967c478bd9Sstevel@tonic-gate 	mdvtoc_t	*mdvp,
697342440ecSPrasad Singamsetty 	struct extvtoc	*vp
6987c478bd9Sstevel@tonic-gate )
6997c478bd9Sstevel@tonic-gate {
7007c478bd9Sstevel@tonic-gate 	uint_t		i;
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	(void) memset(&vp->v_part, '\0', sizeof (vp->v_part));
7037c478bd9Sstevel@tonic-gate 	vp->v_nparts = (ushort_t)mdvp->nparts;
7047c478bd9Sstevel@tonic-gate 	for (i = 0; (i < mdvp->nparts); ++i) {
705342440ecSPrasad Singamsetty 		vp->v_part[i].p_start = mdvp->parts[i].start;
706342440ecSPrasad Singamsetty 		vp->v_part[i].p_size  = mdvp->parts[i].size;
7077c478bd9Sstevel@tonic-gate 		vp->v_part[i].p_tag   = mdvp->parts[i].tag;
7087c478bd9Sstevel@tonic-gate 		vp->v_part[i].p_flag  = mdvp->parts[i].flag;
7097c478bd9Sstevel@tonic-gate 	}
7107c478bd9Sstevel@tonic-gate }
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate /*
7137c478bd9Sstevel@tonic-gate  * Set the vtoc, but use the cached copy to get the info from.
7147c478bd9Sstevel@tonic-gate  * We write np->drivenamep->vtoc to disk.
7157c478bd9Sstevel@tonic-gate  * Before we can do this we read the vtoc in.
7167c478bd9Sstevel@tonic-gate  * if we're dealing with a metadevice and this metadevice is a 64 bit device
7177c478bd9Sstevel@tonic-gate  *	we can use meta_getmdvtoc/meta_setmdvtoc
7187c478bd9Sstevel@tonic-gate  * else
7197c478bd9Sstevel@tonic-gate  * 	we use meta_getvtoc/meta_setvtoc but than we first have to convert
7207c478bd9Sstevel@tonic-gate  *	dnp->vtoc (actually being a mdvtoc_t) into a vtoc_t
7217c478bd9Sstevel@tonic-gate  */
7227c478bd9Sstevel@tonic-gate int
metasetvtoc(mdname_t * np,md_error_t * ep)7237c478bd9Sstevel@tonic-gate metasetvtoc(
7247c478bd9Sstevel@tonic-gate 	mdname_t	*np,
7257c478bd9Sstevel@tonic-gate 	md_error_t	*ep
7267c478bd9Sstevel@tonic-gate )
7277c478bd9Sstevel@tonic-gate {
7287c478bd9Sstevel@tonic-gate 	char		*rname = np->rname;
7297c478bd9Sstevel@tonic-gate 	mddrivename_t	*dnp = np->drivenamep;
7307c478bd9Sstevel@tonic-gate 	int		fd;
7317c478bd9Sstevel@tonic-gate 	int		err;
7327c478bd9Sstevel@tonic-gate 	int 		save_errno;
7337c478bd9Sstevel@tonic-gate 	struct dk_geom	geom;
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 	if ((fd = open(rname, (O_RDONLY | O_NDELAY), 0)) < 0)
7367c478bd9Sstevel@tonic-gate 		return (mdsyserror(ep, errno, rname));
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	err = ioctl(fd, DKIOCGGEOM, &geom);
7397c478bd9Sstevel@tonic-gate 	save_errno = errno;
7407c478bd9Sstevel@tonic-gate 	if (err == 0) {
741342440ecSPrasad Singamsetty 		struct extvtoc	vtoc;
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 		if (meta_getvtoc(fd, np->cname, &vtoc, NULL, ep) < 0) {
7447c478bd9Sstevel@tonic-gate 			(void) close(fd);
7457c478bd9Sstevel@tonic-gate 			return (-1);
7467c478bd9Sstevel@tonic-gate 		}
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 		meta_mdvtoc_to_vtoc(&dnp->vtoc, &vtoc);
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 		if (meta_setvtoc(fd, np->cname, &vtoc, ep) < 0) {
7517c478bd9Sstevel@tonic-gate 			(void) close(fd);
7527c478bd9Sstevel@tonic-gate 			return (-1);
7537c478bd9Sstevel@tonic-gate 		}
7547c478bd9Sstevel@tonic-gate 	} else if (save_errno == ENOTSUP) {
7557c478bd9Sstevel@tonic-gate 		struct dk_gpt	*gpt;
7567c478bd9Sstevel@tonic-gate 		int		ret;
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 		/* allocation of gpt is done in meta_mdvtoc_to_efi */
7597c478bd9Sstevel@tonic-gate 		meta_mdvtoc_to_efi(&dnp->vtoc, &gpt);
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 		ret = efi_write(fd, gpt);
7627c478bd9Sstevel@tonic-gate 		save_errno = errno;
7637c478bd9Sstevel@tonic-gate 		free(gpt);
7647c478bd9Sstevel@tonic-gate 		if (ret != 0) {
7657c478bd9Sstevel@tonic-gate 			(void) close(fd);
7667c478bd9Sstevel@tonic-gate 			return (mdsyserror(ep, save_errno, rname));
7677c478bd9Sstevel@tonic-gate 		} else {
7687c478bd9Sstevel@tonic-gate 			(void) close(fd);
7697c478bd9Sstevel@tonic-gate 			return (0);
7707c478bd9Sstevel@tonic-gate 		}
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 	} else {
7737c478bd9Sstevel@tonic-gate 		(void) close(fd);
7747c478bd9Sstevel@tonic-gate 		return (mdsyserror(ep, save_errno, rname));
7757c478bd9Sstevel@tonic-gate 	}
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	(void) close(fd);
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 	return (0);
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate mdgeom_t *
metagetgeom(mdname_t * np,md_error_t * ep)7837c478bd9Sstevel@tonic-gate metagetgeom(
7847c478bd9Sstevel@tonic-gate 	mdname_t	*np,	/* only rname, drivenamep, are setup */
7857c478bd9Sstevel@tonic-gate 	md_error_t	*ep
7867c478bd9Sstevel@tonic-gate )
7877c478bd9Sstevel@tonic-gate {
7887c478bd9Sstevel@tonic-gate 	if (metagetvtoc(np, FALSE, NULL, ep) == NULL)
7897c478bd9Sstevel@tonic-gate 		return (NULL);
7907c478bd9Sstevel@tonic-gate 	return (&np->drivenamep->geom);
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate mdcinfo_t *
metagetcinfo(mdname_t * np,md_error_t * ep)7947c478bd9Sstevel@tonic-gate metagetcinfo(
7957c478bd9Sstevel@tonic-gate 	mdname_t	*np,	/* only rname, drivenamep, are setup */
7967c478bd9Sstevel@tonic-gate 	md_error_t	*ep
7977c478bd9Sstevel@tonic-gate )
7987c478bd9Sstevel@tonic-gate {
7997c478bd9Sstevel@tonic-gate 	char			*rname = np->rname;
8007c478bd9Sstevel@tonic-gate 	mddrivename_t		*dnp = np->drivenamep;
8017c478bd9Sstevel@tonic-gate 	int			fd;
8027c478bd9Sstevel@tonic-gate 	struct dk_cinfo		cinfo;
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 	/* short circuit */
8057c478bd9Sstevel@tonic-gate 	if (dnp->cinfo.cname[0] != '\0')
8067c478bd9Sstevel@tonic-gate 		return (&dnp->cinfo);
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate 	/* get controller info */
8097c478bd9Sstevel@tonic-gate 	if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
8107c478bd9Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, rname);
8117c478bd9Sstevel@tonic-gate 		return (NULL);
8127c478bd9Sstevel@tonic-gate 	}
8137c478bd9Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &cinfo) != 0) {
8147c478bd9Sstevel@tonic-gate 		int	save = errno;
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 		(void) close(fd);
8177c478bd9Sstevel@tonic-gate 		if (save == ENOTTY) {
8187c478bd9Sstevel@tonic-gate 			(void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname);
8197c478bd9Sstevel@tonic-gate 		} else {
8207c478bd9Sstevel@tonic-gate 			(void) mdsyserror(ep, save, rname);
8217c478bd9Sstevel@tonic-gate 		}
8227c478bd9Sstevel@tonic-gate 		return (NULL);
8237c478bd9Sstevel@tonic-gate 	}
8247c478bd9Sstevel@tonic-gate 	(void) close(fd);	/* sd/ssd bug */
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 	/* convert to our format */
8277c478bd9Sstevel@tonic-gate 	if (meta_cinfo_to_md(np, &cinfo, &dnp->cinfo, ep) != 0)
8287c478bd9Sstevel@tonic-gate 		return (NULL);
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 	/* return info */
8317c478bd9Sstevel@tonic-gate 	return (&dnp->cinfo);
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate /*
8357c478bd9Sstevel@tonic-gate  * get partition number
8367c478bd9Sstevel@tonic-gate  */
8377c478bd9Sstevel@tonic-gate int
metagetpartno(mdname_t * np,md_error_t * ep)8387c478bd9Sstevel@tonic-gate metagetpartno(
8397c478bd9Sstevel@tonic-gate 	mdname_t	*np,
8407c478bd9Sstevel@tonic-gate 	md_error_t	*ep
8417c478bd9Sstevel@tonic-gate )
8427c478bd9Sstevel@tonic-gate {
8437c478bd9Sstevel@tonic-gate 	mdvtoc_t	*vtocp;
8447c478bd9Sstevel@tonic-gate 	uint_t		partno;
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 	if ((vtocp = metagetvtoc(np, FALSE, &partno, ep)) == NULL)
8477c478bd9Sstevel@tonic-gate 		return (-1);
8487c478bd9Sstevel@tonic-gate 	assert(partno < vtocp->nparts);
8497c478bd9Sstevel@tonic-gate 	return (partno);
8507c478bd9Sstevel@tonic-gate }
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate /*
8537c478bd9Sstevel@tonic-gate  * get size of device
8547c478bd9Sstevel@tonic-gate  */
8557c478bd9Sstevel@tonic-gate diskaddr_t
metagetsize(mdname_t * np,md_error_t * ep)8567c478bd9Sstevel@tonic-gate metagetsize(
8577c478bd9Sstevel@tonic-gate 	mdname_t	*np,
8587c478bd9Sstevel@tonic-gate 	md_error_t	*ep
8597c478bd9Sstevel@tonic-gate )
8607c478bd9Sstevel@tonic-gate {
8617c478bd9Sstevel@tonic-gate 	mdvtoc_t	*vtocp;
8627c478bd9Sstevel@tonic-gate 	uint_t		partno;
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	if ((vtocp = metagetvtoc(np, FALSE, &partno, ep)) == NULL)
8657c478bd9Sstevel@tonic-gate 		return (MD_DISKADDR_ERROR);
8667c478bd9Sstevel@tonic-gate 	assert(partno < vtocp->nparts);
8677c478bd9Sstevel@tonic-gate 	return (vtocp->parts[partno].size);
8687c478bd9Sstevel@tonic-gate }
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate /*
8717c478bd9Sstevel@tonic-gate  * get label of device
8727c478bd9Sstevel@tonic-gate  */
8737c478bd9Sstevel@tonic-gate diskaddr_t
metagetlabel(mdname_t * np,md_error_t * ep)8747c478bd9Sstevel@tonic-gate metagetlabel(
8757c478bd9Sstevel@tonic-gate 	mdname_t	*np,
8767c478bd9Sstevel@tonic-gate 	md_error_t	*ep
8777c478bd9Sstevel@tonic-gate )
8787c478bd9Sstevel@tonic-gate {
8797c478bd9Sstevel@tonic-gate 	mdvtoc_t	*vtocp;
8807c478bd9Sstevel@tonic-gate 	uint_t		partno;
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 	if ((vtocp = metagetvtoc(np, FALSE, &partno, ep)) == NULL)
8837c478bd9Sstevel@tonic-gate 		return (MD_DISKADDR_ERROR);
8847c478bd9Sstevel@tonic-gate 	assert(partno < vtocp->nparts);
8857c478bd9Sstevel@tonic-gate 	return (vtocp->parts[partno].label);
8867c478bd9Sstevel@tonic-gate }
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate /*
8897c478bd9Sstevel@tonic-gate  * find out where database replicas end
8907c478bd9Sstevel@tonic-gate  */
8917c478bd9Sstevel@tonic-gate static int
mddb_getendblk(mdsetname_t * sp,mdname_t * np,diskaddr_t * endblkp,md_error_t * ep)8927c478bd9Sstevel@tonic-gate mddb_getendblk(
8937c478bd9Sstevel@tonic-gate 	mdsetname_t		*sp,
8947c478bd9Sstevel@tonic-gate 	mdname_t		*np,
8957c478bd9Sstevel@tonic-gate 	diskaddr_t		*endblkp,
8967c478bd9Sstevel@tonic-gate 	md_error_t		*ep
8977c478bd9Sstevel@tonic-gate )
8987c478bd9Sstevel@tonic-gate {
8997c478bd9Sstevel@tonic-gate 	md_replicalist_t	*rlp = NULL;
9007c478bd9Sstevel@tonic-gate 	md_replicalist_t	*rl;
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 	/* make sure we have a component */
9037c478bd9Sstevel@tonic-gate 	*endblkp = 0;
9047c478bd9Sstevel@tonic-gate 	if (metaismeta(np))
9057c478bd9Sstevel@tonic-gate 		return (0);
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 	/* get replicas, quit if none */
9087c478bd9Sstevel@tonic-gate 	if (metareplicalist(sp, MD_BASICNAME_OK | PRINT_FAST, &rlp, ep) < 0) {
9097c478bd9Sstevel@tonic-gate 		if (! mdismddberror(ep, MDE_DB_NODB))
9107c478bd9Sstevel@tonic-gate 			return (-1);
9117c478bd9Sstevel@tonic-gate 		mdclrerror(ep);
9127c478bd9Sstevel@tonic-gate 		return (0);
9137c478bd9Sstevel@tonic-gate 	} else if (rlp == NULL)
9147c478bd9Sstevel@tonic-gate 		return (0);
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 	/* go through all the replicas */
9177c478bd9Sstevel@tonic-gate 	for (rl = rlp; (rl != NULL); rl = rl->rl_next) {
9187c478bd9Sstevel@tonic-gate 		md_replica_t	*rp = rl->rl_repp;
9197c478bd9Sstevel@tonic-gate 		mdname_t	*repnamep = rp->r_namep;
9207c478bd9Sstevel@tonic-gate 		diskaddr_t	dbend;
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 		if (np->dev != repnamep->dev)
9237c478bd9Sstevel@tonic-gate 			continue;
9247c478bd9Sstevel@tonic-gate 		dbend = rp->r_blkno + rp->r_nblk - 1;
9257c478bd9Sstevel@tonic-gate 		if (dbend > *endblkp)
9267c478bd9Sstevel@tonic-gate 			*endblkp = dbend;
9277c478bd9Sstevel@tonic-gate 	}
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 	/* cleanup, return success */
9307c478bd9Sstevel@tonic-gate 	metafreereplicalist(rlp);
9317c478bd9Sstevel@tonic-gate 	return (0);
9327c478bd9Sstevel@tonic-gate }
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate /*
9357c478bd9Sstevel@tonic-gate  * return cached start block
9367c478bd9Sstevel@tonic-gate  */
9377c478bd9Sstevel@tonic-gate static diskaddr_t
metagetend(mdsetname_t * sp,mdname_t * np,md_error_t * ep)9387c478bd9Sstevel@tonic-gate metagetend(
9397c478bd9Sstevel@tonic-gate 	mdsetname_t	*sp,
9407c478bd9Sstevel@tonic-gate 	mdname_t	*np,
9417c478bd9Sstevel@tonic-gate 	md_error_t	*ep
9427c478bd9Sstevel@tonic-gate )
9437c478bd9Sstevel@tonic-gate {
9447c478bd9Sstevel@tonic-gate 	diskaddr_t	end_blk = MD_DISKADDR_ERROR;
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 	/* short circuit */
9477c478bd9Sstevel@tonic-gate 	if (np->end_blk != MD_DISKADDR_ERROR)
9487c478bd9Sstevel@tonic-gate 		return (np->end_blk);
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 	/* look for database locations */
9517c478bd9Sstevel@tonic-gate 	if (mddb_getendblk(sp, np, &end_blk, ep) != 0)
9527c478bd9Sstevel@tonic-gate 		return (MD_DISKADDR_ERROR);
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate 	/* success */
9557c478bd9Sstevel@tonic-gate 	np->end_blk = end_blk;
9567c478bd9Sstevel@tonic-gate 	return (end_blk);
9577c478bd9Sstevel@tonic-gate }
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate /*
9607c478bd9Sstevel@tonic-gate  * does device have a metadb
9617c478bd9Sstevel@tonic-gate  */
9627c478bd9Sstevel@tonic-gate int
metahasmddb(mdsetname_t * sp,mdname_t * np,md_error_t * ep)9637c478bd9Sstevel@tonic-gate metahasmddb(
9647c478bd9Sstevel@tonic-gate 	mdsetname_t	*sp,
9657c478bd9Sstevel@tonic-gate 	mdname_t	*np,
9667c478bd9Sstevel@tonic-gate 	md_error_t	*ep
9677c478bd9Sstevel@tonic-gate )
9687c478bd9Sstevel@tonic-gate {
9697c478bd9Sstevel@tonic-gate 	if (metagetend(sp, np, ep) == MD_DISKADDR_ERROR)
9707c478bd9Sstevel@tonic-gate 		return (-1);
9717c478bd9Sstevel@tonic-gate 	else if (np->end_blk > 0)
9727c478bd9Sstevel@tonic-gate 		return (1);
9737c478bd9Sstevel@tonic-gate 	else
9747c478bd9Sstevel@tonic-gate 		return (0);
9757c478bd9Sstevel@tonic-gate }
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate /*
9787c478bd9Sstevel@tonic-gate  * return cached start block
9797c478bd9Sstevel@tonic-gate  */
9807c478bd9Sstevel@tonic-gate diskaddr_t
metagetstart(mdsetname_t * sp,mdname_t * np,md_error_t * ep)9817c478bd9Sstevel@tonic-gate metagetstart(
9827c478bd9Sstevel@tonic-gate 	mdsetname_t	*sp,
9837c478bd9Sstevel@tonic-gate 	mdname_t	*np,
9847c478bd9Sstevel@tonic-gate 	md_error_t	*ep
9857c478bd9Sstevel@tonic-gate )
9867c478bd9Sstevel@tonic-gate {
9877c478bd9Sstevel@tonic-gate 	diskaddr_t	start_blk = MD_DISKADDR_ERROR;
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 	/* short circuit */
9907c478bd9Sstevel@tonic-gate 	if (np->start_blk != MD_DISKADDR_ERROR)
9917c478bd9Sstevel@tonic-gate 		return (np->start_blk);
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate 	/* look for database locations */
9947c478bd9Sstevel@tonic-gate 	if ((start_blk = metagetend(sp, np, ep)) == MD_DISKADDR_ERROR)
9957c478bd9Sstevel@tonic-gate 		return (MD_DISKADDR_ERROR);
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate 	/* check for label */
9987c478bd9Sstevel@tonic-gate 	if (start_blk == 0) {
9997c478bd9Sstevel@tonic-gate 		start_blk = metagetlabel(np, ep);
10007c478bd9Sstevel@tonic-gate 		if (start_blk == MD_DISKADDR_ERROR) {
10017c478bd9Sstevel@tonic-gate 			return (MD_DISKADDR_ERROR);
10027c478bd9Sstevel@tonic-gate 		}
10037c478bd9Sstevel@tonic-gate 	}
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	/* roundup to next cylinder */
10067c478bd9Sstevel@tonic-gate 	if (start_blk != 0) {
10077c478bd9Sstevel@tonic-gate 		mdgeom_t	*geomp;
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 		if ((geomp = metagetgeom(np, ep)) == NULL)
10107c478bd9Sstevel@tonic-gate 			return (MD_DISKADDR_ERROR);
10117c478bd9Sstevel@tonic-gate 		start_blk = roundup(start_blk, (geomp->nhead * geomp->nsect));
10127c478bd9Sstevel@tonic-gate 	}
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 	/* success */
10157c478bd9Sstevel@tonic-gate 	np->start_blk = start_blk;
10167c478bd9Sstevel@tonic-gate 	return (start_blk);
10177c478bd9Sstevel@tonic-gate }
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate /*
10207c478bd9Sstevel@tonic-gate  * return cached devices name
10217c478bd9Sstevel@tonic-gate  */
10227c478bd9Sstevel@tonic-gate char *
metagetdevicesname(mdname_t * np,md_error_t * ep)10237c478bd9Sstevel@tonic-gate metagetdevicesname(
10247c478bd9Sstevel@tonic-gate 	mdname_t	*np,
10257c478bd9Sstevel@tonic-gate 	md_error_t	*ep
10267c478bd9Sstevel@tonic-gate )
10277c478bd9Sstevel@tonic-gate {
10287c478bd9Sstevel@tonic-gate 	char		path[MAXPATHLEN + 1];
10297c478bd9Sstevel@tonic-gate 	int		len;
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 	/* short circuit */
10327c478bd9Sstevel@tonic-gate 	if (np->devicesname != NULL)
10337c478bd9Sstevel@tonic-gate 		return (np->devicesname);
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 	/* follow symlink */
10367c478bd9Sstevel@tonic-gate 	if ((len = readlink(np->bname, path, (sizeof (path) - 1))) < 0) {
10377c478bd9Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, np->bname);
10387c478bd9Sstevel@tonic-gate 		return (NULL);
10397c478bd9Sstevel@tonic-gate 	} else if (len >= sizeof (path)) {
10407c478bd9Sstevel@tonic-gate 		(void) mdsyserror(ep, ENAMETOOLONG, np->bname);
10417c478bd9Sstevel@tonic-gate 		return (NULL);
10427c478bd9Sstevel@tonic-gate 	}
10437c478bd9Sstevel@tonic-gate 	path[len] = '\0';
10447c478bd9Sstevel@tonic-gate 	if ((len = strfind(path, "/devices/")) < 0) {
10457c478bd9Sstevel@tonic-gate 		(void) mddeverror(ep, MDE_DEVICES_NAME, np->dev, np->bname);
10467c478bd9Sstevel@tonic-gate 		return (NULL);
10477c478bd9Sstevel@tonic-gate 	}
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 	/* return name */
10507c478bd9Sstevel@tonic-gate 	np->devicesname = Strdup(path + len + strlen("/devices"));
10517c478bd9Sstevel@tonic-gate 	return (np->devicesname);
10527c478bd9Sstevel@tonic-gate }
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate /*
10557c478bd9Sstevel@tonic-gate  * get metadevice misc name
10567c478bd9Sstevel@tonic-gate  */
10577c478bd9Sstevel@tonic-gate char *
metagetmiscname(mdname_t * np,md_error_t * ep)10587c478bd9Sstevel@tonic-gate metagetmiscname(
10597c478bd9Sstevel@tonic-gate 	mdname_t		*np,
10607c478bd9Sstevel@tonic-gate 	md_error_t		*ep
10617c478bd9Sstevel@tonic-gate )
10627c478bd9Sstevel@tonic-gate {
10637c478bd9Sstevel@tonic-gate 	mddrivename_t		*dnp = np->drivenamep;
10647c478bd9Sstevel@tonic-gate 	md_i_driverinfo_t	mid;
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate 	/* short circuit */
10677c478bd9Sstevel@tonic-gate 	if (dnp->miscname != NULL)
10687c478bd9Sstevel@tonic-gate 		return (dnp->miscname);
10697c478bd9Sstevel@tonic-gate 	if (metachkmeta(np, ep) != 0)
10707c478bd9Sstevel@tonic-gate 		return (NULL);
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate 	/* get misc module from driver */
10737c478bd9Sstevel@tonic-gate 	(void) memset(&mid, 0, sizeof (mid));
10747c478bd9Sstevel@tonic-gate 	mid.mnum = meta_getminor(np->dev);
10757c478bd9Sstevel@tonic-gate 	if (metaioctl(MD_IOCGET_DRVNM, &mid, &mid.mde, np->cname) != 0) {
10767c478bd9Sstevel@tonic-gate 		(void) mdstealerror(ep, &mid.mde);
10777c478bd9Sstevel@tonic-gate 		return (NULL);
10787c478bd9Sstevel@tonic-gate 	}
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 	/* return miscname */
10817c478bd9Sstevel@tonic-gate 	dnp->miscname = Strdup(MD_PNTDRIVERNAME(&mid));
10827c478bd9Sstevel@tonic-gate 	return (dnp->miscname);
10837c478bd9Sstevel@tonic-gate }
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate /*
10867c478bd9Sstevel@tonic-gate  * get unit structure from driver
10877c478bd9Sstevel@tonic-gate  */
10887c478bd9Sstevel@tonic-gate md_unit_t *
meta_get_mdunit(mdsetname_t * sp,mdname_t * np,md_error_t * ep)10897c478bd9Sstevel@tonic-gate meta_get_mdunit(
10907c478bd9Sstevel@tonic-gate 	mdsetname_t	*sp,
10917c478bd9Sstevel@tonic-gate 	mdname_t	*np,
10927c478bd9Sstevel@tonic-gate 	md_error_t	*ep
10937c478bd9Sstevel@tonic-gate )
10947c478bd9Sstevel@tonic-gate {
10957c478bd9Sstevel@tonic-gate 	md_i_get_t	mig;
10967c478bd9Sstevel@tonic-gate 	char		*miscname = NULL;
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate 	/* should have a set */
10997c478bd9Sstevel@tonic-gate 	assert(sp != NULL);
11007c478bd9Sstevel@tonic-gate 	assert(sp->setno == MD_MIN2SET(meta_getminor(np->dev)));
11017c478bd9Sstevel@tonic-gate 
11027c478bd9Sstevel@tonic-gate 	/* get size of unit structure */
11037c478bd9Sstevel@tonic-gate 	if (metachkmeta(np, ep) != 0)
11047c478bd9Sstevel@tonic-gate 		return (NULL);
11057c478bd9Sstevel@tonic-gate 	if ((miscname = metagetmiscname(np, ep)) == NULL)
11067c478bd9Sstevel@tonic-gate 		return (NULL);
11077c478bd9Sstevel@tonic-gate 	(void) memset(&mig, '\0', sizeof (mig));
11087c478bd9Sstevel@tonic-gate 	MD_SETDRIVERNAME(&mig, miscname, sp->setno);
11097c478bd9Sstevel@tonic-gate 	mig.id = meta_getminor(np->dev);
11107c478bd9Sstevel@tonic-gate 	if (metaioctl(MD_IOCGET, &mig, &mig.mde, np->cname) != 0) {
11117c478bd9Sstevel@tonic-gate 		(void) mdstealerror(ep, &mig.mde);
11127c478bd9Sstevel@tonic-gate 		return (NULL);
11137c478bd9Sstevel@tonic-gate 	}
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 	/* get actual unit structure */
11167c478bd9Sstevel@tonic-gate 	assert(mig.size > 0);
11177c478bd9Sstevel@tonic-gate 	mig.mdp = (uintptr_t)Zalloc(mig.size);
11187c478bd9Sstevel@tonic-gate 	if (metaioctl(MD_IOCGET, &mig, &mig.mde, np->cname) != 0) {
11197c478bd9Sstevel@tonic-gate 		(void) mdstealerror(ep, &mig.mde);
1120b6c8bd52Sjeanm 		Free((void *)(uintptr_t)mig.mdp);
11217c478bd9Sstevel@tonic-gate 		return (NULL);
11227c478bd9Sstevel@tonic-gate 	}
11237c478bd9Sstevel@tonic-gate 
1124b6c8bd52Sjeanm 	return ((md_unit_t *)(uintptr_t)mig.mdp);
11257c478bd9Sstevel@tonic-gate }
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate /*
11287c478bd9Sstevel@tonic-gate  * free metadevice unit
11297c478bd9Sstevel@tonic-gate  */
11307c478bd9Sstevel@tonic-gate void
meta_free_unit(mddrivename_t * dnp)11317c478bd9Sstevel@tonic-gate meta_free_unit(
11327c478bd9Sstevel@tonic-gate 	mddrivename_t	*dnp
11337c478bd9Sstevel@tonic-gate )
11347c478bd9Sstevel@tonic-gate {
11357c478bd9Sstevel@tonic-gate 	if (dnp->unitp != NULL) {
11367c478bd9Sstevel@tonic-gate 		switch (dnp->unitp->type) {
11377c478bd9Sstevel@tonic-gate 		case MD_DEVICE:
11387c478bd9Sstevel@tonic-gate 			meta_free_stripe((md_stripe_t *)dnp->unitp);
11397c478bd9Sstevel@tonic-gate 			break;
11407c478bd9Sstevel@tonic-gate 		case MD_METAMIRROR:
11417c478bd9Sstevel@tonic-gate 			meta_free_mirror((md_mirror_t *)dnp->unitp);
11427c478bd9Sstevel@tonic-gate 			break;
11437c478bd9Sstevel@tonic-gate 		case MD_METATRANS:
11447c478bd9Sstevel@tonic-gate 			meta_free_trans((md_trans_t *)dnp->unitp);
11457c478bd9Sstevel@tonic-gate 			break;
11467c478bd9Sstevel@tonic-gate 		case MD_METARAID:
11477c478bd9Sstevel@tonic-gate 			meta_free_raid((md_raid_t *)dnp->unitp);
11487c478bd9Sstevel@tonic-gate 			break;
11497c478bd9Sstevel@tonic-gate 		case MD_METASP:
11507c478bd9Sstevel@tonic-gate 			meta_free_sp((md_sp_t *)dnp->unitp);
11517c478bd9Sstevel@tonic-gate 			break;
11527c478bd9Sstevel@tonic-gate 		default:
11537c478bd9Sstevel@tonic-gate 			assert(0);
11547c478bd9Sstevel@tonic-gate 			break;
11557c478bd9Sstevel@tonic-gate 		}
11567c478bd9Sstevel@tonic-gate 		dnp->unitp = NULL;
11577c478bd9Sstevel@tonic-gate 	}
11587c478bd9Sstevel@tonic-gate }
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate /*
11617c478bd9Sstevel@tonic-gate  * free metadevice name info
11627c478bd9Sstevel@tonic-gate  */
11637c478bd9Sstevel@tonic-gate void
meta_invalidate_name(mdname_t * namep)11647c478bd9Sstevel@tonic-gate meta_invalidate_name(
11657c478bd9Sstevel@tonic-gate 	mdname_t	*namep
11667c478bd9Sstevel@tonic-gate )
11677c478bd9Sstevel@tonic-gate {
11687c478bd9Sstevel@tonic-gate 	mddrivename_t	*dnp = namep->drivenamep;
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate 	/* get rid of cached name info */
11717c478bd9Sstevel@tonic-gate 	if (namep->devicesname != NULL) {
11727c478bd9Sstevel@tonic-gate 		Free(namep->devicesname);
11737c478bd9Sstevel@tonic-gate 		namep->devicesname = NULL;
11747c478bd9Sstevel@tonic-gate 	}
11757c478bd9Sstevel@tonic-gate 	namep->key = MD_KEYBAD;
11767c478bd9Sstevel@tonic-gate 	namep->start_blk = -1;
11777c478bd9Sstevel@tonic-gate 	namep->end_blk = -1;
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate 	/* get rid of cached drivename info */
11807c478bd9Sstevel@tonic-gate 	(void) memset(&dnp->geom, 0, sizeof (dnp->geom));
11817c478bd9Sstevel@tonic-gate 	(void) memset(&dnp->cinfo, 0, sizeof (dnp->cinfo));
11827c478bd9Sstevel@tonic-gate 	metafreevtoc(&dnp->vtoc);
11837c478bd9Sstevel@tonic-gate 	metaflushsidenames(dnp);
11847c478bd9Sstevel@tonic-gate 	dnp->side_names_key = MD_KEYBAD;
11857c478bd9Sstevel@tonic-gate 	if (dnp->miscname != NULL) {
11867c478bd9Sstevel@tonic-gate 		Free(dnp->miscname);
11877c478bd9Sstevel@tonic-gate 		dnp->miscname = NULL;
11887c478bd9Sstevel@tonic-gate 	}
11897c478bd9Sstevel@tonic-gate 	meta_free_unit(dnp);
11907c478bd9Sstevel@tonic-gate }
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate /*
11937c478bd9Sstevel@tonic-gate  * get metadevice unit
11947c478bd9Sstevel@tonic-gate  */
11957c478bd9Sstevel@tonic-gate md_common_t *
meta_get_unit(mdsetname_t * sp,mdname_t * np,md_error_t * ep)11967c478bd9Sstevel@tonic-gate meta_get_unit(
11977c478bd9Sstevel@tonic-gate 	mdsetname_t	*sp,
11987c478bd9Sstevel@tonic-gate 	mdname_t	*np,
11997c478bd9Sstevel@tonic-gate 	md_error_t	*ep
12007c478bd9Sstevel@tonic-gate )
12017c478bd9Sstevel@tonic-gate {
12027c478bd9Sstevel@tonic-gate 	char		*miscname;
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 	/* short circuit */
12057c478bd9Sstevel@tonic-gate 	if (np->drivenamep->unitp != NULL)
12067c478bd9Sstevel@tonic-gate 		return (np->drivenamep->unitp);
12077c478bd9Sstevel@tonic-gate 	if (metachkmeta(np, ep) != 0)
12087c478bd9Sstevel@tonic-gate 		return (NULL);
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate 	/* dispatch */
12117c478bd9Sstevel@tonic-gate 	if ((miscname = metagetmiscname(np, ep)) == NULL)
12127c478bd9Sstevel@tonic-gate 		return (NULL);
12137c478bd9Sstevel@tonic-gate 	else if (strcmp(miscname, MD_STRIPE) == 0)
12147c478bd9Sstevel@tonic-gate 		return ((md_common_t *)meta_get_stripe(sp, np, ep));
12157c478bd9Sstevel@tonic-gate 	else if (strcmp(miscname, MD_MIRROR) == 0)
12167c478bd9Sstevel@tonic-gate 		return ((md_common_t *)meta_get_mirror(sp, np, ep));
12177c478bd9Sstevel@tonic-gate 	else if (strcmp(miscname, MD_TRANS) == 0)
12187c478bd9Sstevel@tonic-gate 		return ((md_common_t *)meta_get_trans(sp, np, ep));
12197c478bd9Sstevel@tonic-gate 	else if (strcmp(miscname, MD_RAID) == 0)
12207c478bd9Sstevel@tonic-gate 		return ((md_common_t *)meta_get_raid(sp, np, ep));
12217c478bd9Sstevel@tonic-gate 	else if (strcmp(miscname, MD_SP) == 0)
12227c478bd9Sstevel@tonic-gate 		return ((md_common_t *)meta_get_sp(sp, np, ep));
12237c478bd9Sstevel@tonic-gate 	else {
12247c478bd9Sstevel@tonic-gate 		(void) mdmderror(ep, MDE_UNKNOWN_TYPE, meta_getminor(np->dev),
12257c478bd9Sstevel@tonic-gate 		    np->cname);
12267c478bd9Sstevel@tonic-gate 		return (NULL);
12277c478bd9Sstevel@tonic-gate 	}
12287c478bd9Sstevel@tonic-gate }
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate 
12317c478bd9Sstevel@tonic-gate int
meta_isopen(mdsetname_t * sp,mdname_t * np,md_error_t * ep,mdcmdopts_t options)12327c478bd9Sstevel@tonic-gate meta_isopen(
12337c478bd9Sstevel@tonic-gate 	mdsetname_t	*sp,
12347c478bd9Sstevel@tonic-gate 	mdname_t	*np,
12357c478bd9Sstevel@tonic-gate 	md_error_t	*ep,
12367c478bd9Sstevel@tonic-gate 	mdcmdopts_t	options
12377c478bd9Sstevel@tonic-gate )
12387c478bd9Sstevel@tonic-gate {
12397c478bd9Sstevel@tonic-gate 	md_isopen_t	d;
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate 	if (metachkmeta(np, ep) != 0)
12427c478bd9Sstevel@tonic-gate 		return (-1);
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 	(void) memset(&d, '\0', sizeof (d));
12457c478bd9Sstevel@tonic-gate 	d.dev = np->dev;
12467c478bd9Sstevel@tonic-gate 	if (metaioctl(MD_IOCISOPEN, &d, &d.mde, np->cname) != 0)
12477c478bd9Sstevel@tonic-gate 		return (mdstealerror(ep, &d.mde));
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 	/*
12507c478bd9Sstevel@tonic-gate 	 * shortcut: if the device is open, no need to check on other nodes,
12517c478bd9Sstevel@tonic-gate 	 * even in case of a mn metadevice
12527c478bd9Sstevel@tonic-gate 	 * Also return in case we're told not to check on other nodes.
12537c478bd9Sstevel@tonic-gate 	 */
12547c478bd9Sstevel@tonic-gate 	if ((d.isopen != 0) || ((options & MDCMD_MN_OPEN_CHECK) == 0)) {
12557c478bd9Sstevel@tonic-gate 		return (d.isopen);
12567c478bd9Sstevel@tonic-gate 	}
12577c478bd9Sstevel@tonic-gate 
12587c478bd9Sstevel@tonic-gate 	/*
12597c478bd9Sstevel@tonic-gate 	 * If the device is closed locally, but it's a mn device,
12607c478bd9Sstevel@tonic-gate 	 * check on all other nodes, too
12617c478bd9Sstevel@tonic-gate 	 */
12627c478bd9Sstevel@tonic-gate 	if (sp->setno != MD_LOCAL_SET) {
12637c478bd9Sstevel@tonic-gate 		(void) metaget_setdesc(sp, ep); /* not supposed to fail */
12647c478bd9Sstevel@tonic-gate 		if (sp->setdesc->sd_flags & MD_SR_MN) {
12657c478bd9Sstevel@tonic-gate 			int		err = 0;
12667c478bd9Sstevel@tonic-gate 			md_mn_result_t *resp;
12677c478bd9Sstevel@tonic-gate 			/*
12687c478bd9Sstevel@tonic-gate 			 * This message is never directly issued.
12697c478bd9Sstevel@tonic-gate 			 * So we launch it with a suspend override flag.
12707c478bd9Sstevel@tonic-gate 			 * If the commd is suspended, and this message comes
12717c478bd9Sstevel@tonic-gate 			 * along it must be sent due to replaying a metainit or
12727c478bd9Sstevel@tonic-gate 			 * similar. In that case we don't want this message to
12737c478bd9Sstevel@tonic-gate 			 * be blocked.
12747c478bd9Sstevel@tonic-gate 			 * If the commd is not suspended, the flag does no harm.
12757c478bd9Sstevel@tonic-gate 			 * Additionally we don't want the result of the message
12767c478bd9Sstevel@tonic-gate 			 * cached in the MCT, because we want uptodate results,
12777c478bd9Sstevel@tonic-gate 			 * and the message doesn't need being logged either.
12787c478bd9Sstevel@tonic-gate 			 * Hence NO_LOG and NO_MCT
12797c478bd9Sstevel@tonic-gate 			 */
1280bf85a12bSJohn Wren Kennedy 			err = mdmn_send_message(sp->setno,
1281bf85a12bSJohn Wren Kennedy 			    MD_MN_MSG_CLU_CHECK, MD_MSGF_NO_MCT |
1282bf85a12bSJohn Wren Kennedy 			    MD_MSGF_STOP_ON_ERROR | MD_MSGF_NO_LOG |
1283bf85a12bSJohn Wren Kennedy 			    MD_MSGF_OVERRIDE_SUSPEND, 0, (char *)&d,
1284bf85a12bSJohn Wren Kennedy 			    sizeof (md_isopen_t), &resp, ep);
12857c478bd9Sstevel@tonic-gate 			if (err == 0) {
12867c478bd9Sstevel@tonic-gate 				d.isopen = resp->mmr_exitval;
12877c478bd9Sstevel@tonic-gate 			} else {
12887c478bd9Sstevel@tonic-gate 				/*
12897c478bd9Sstevel@tonic-gate 				 * in case some error occurred,
12907c478bd9Sstevel@tonic-gate 				 * we better say the device is open
12917c478bd9Sstevel@tonic-gate 				 */
12927c478bd9Sstevel@tonic-gate 				d.isopen = 1;
12937c478bd9Sstevel@tonic-gate 			}
12947c478bd9Sstevel@tonic-gate 			if (resp != (md_mn_result_t *)NULL) {
12957c478bd9Sstevel@tonic-gate 				free_result(resp);
12967c478bd9Sstevel@tonic-gate 			}
12977c478bd9Sstevel@tonic-gate 
12987c478bd9Sstevel@tonic-gate 		}
12997c478bd9Sstevel@tonic-gate 	}
13007c478bd9Sstevel@tonic-gate 
13017c478bd9Sstevel@tonic-gate 	return (d.isopen);
13027c478bd9Sstevel@tonic-gate }
1303