xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_nameinfo.c (revision 47644099886aa8d3f43120b9eede3044342be473)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <dlfcn.h>
30 #include <meta.h>
31 #include <metadyn.h>
32 #include <ctype.h>
33 #include <dirent.h>
34 #include <devid.h>
35 #include <sys/param.h>
36 #include <sys/scsi/impl/uscsi.h>
37 #include <sys/scsi/generic/commands.h>
38 #include <sys/scsi/generic/inquiry.h>
39 #include <sys/efi_partition.h>
40 
41 #define	MD_EFI_FG_HEADS		128
42 #define	MD_EFI_FG_SECTORS	256
43 #define	MD_EFI_FG_RPM		7200
44 #define	MD_EFI_FG_WRI		1
45 #define	MD_EFI_FG_RRI		1
46 
47 
48 typedef struct ctlr_cache {
49 	char			*ctlr_nm;
50 	int			ctlr_ty;
51 	struct	ctlr_cache	*ctlr_nx;
52 } ctlr_cache_t;
53 
54 static	ctlr_cache_t	*ctlr_cache = NULL;
55 
56 
57 /*
58  * return set for a device
59  */
60 mdsetname_t *
61 metagetset(
62 	mdname_t	*np,
63 	int		bypass_daemon,
64 	md_error_t	*ep
65 )
66 {
67 	mdsetname_t	*sp;
68 
69 	/* metadevice */
70 	if (metaismeta(np))
71 		return (metasetnosetname(MD_MIN2SET(meta_getminor(np->dev)),
72 						ep));
73 
74 	/* regular device */
75 	if (meta_is_drive_in_anyset(np->drivenamep, &sp, bypass_daemon,
76 	    ep) != 0)
77 		return (NULL);
78 
79 	if (sp != NULL)
80 		return (sp);
81 
82 	return (metasetnosetname(MD_LOCAL_SET, ep));
83 }
84 
85 /*
86  * convert system to md types
87  */
88 static void
89 meta_geom_to_md(
90 	struct dk_geom	*gp,
91 	mdgeom_t	*mdgp
92 )
93 {
94 	(void) memset(mdgp, '\0', sizeof (*mdgp));
95 	mdgp->ncyl = gp->dkg_ncyl;
96 	mdgp->nhead = gp->dkg_nhead;
97 	mdgp->nsect = gp->dkg_nsect;
98 	mdgp->rpm = gp->dkg_rpm;
99 	mdgp->write_reinstruct = gp->dkg_write_reinstruct;
100 	mdgp->read_reinstruct = gp->dkg_read_reinstruct;
101 	mdgp->blk_sz = DEV_BSIZE;
102 }
103 
104 /*
105  * convert efi to md types
106  */
107 static void
108 meta_efi_to_mdgeom(struct dk_gpt *gpt, mdgeom_t	*mdgp)
109 {
110 	(void) memset(mdgp, '\0', sizeof (*mdgp));
111 	mdgp->ncyl = (gpt->efi_last_u_lba - gpt->efi_first_u_lba) /
112 					(MD_EFI_FG_HEADS * MD_EFI_FG_SECTORS);
113 	mdgp->nhead = MD_EFI_FG_HEADS;
114 	mdgp->nsect = MD_EFI_FG_SECTORS;
115 	mdgp->rpm = MD_EFI_FG_RPM;
116 	mdgp->write_reinstruct = MD_EFI_FG_WRI;
117 	mdgp->read_reinstruct = MD_EFI_FG_RRI;
118 	mdgp->blk_sz = DEV_BSIZE;
119 }
120 
121 static void
122 meta_efi_to_mdvtoc(struct dk_gpt *gpt, mdvtoc_t *mdvp)
123 {
124 	char		typename[EFI_PART_NAME_LEN];
125 	uint_t		i;
126 
127 	(void) memset(mdvp, '\0', sizeof (*mdvp));
128 	mdvp->nparts = gpt->efi_nparts;
129 	if (mdvp->nparts > MD_MAX_PARTS)
130 		return;
131 
132 	mdvp->first_lba = gpt->efi_first_u_lba;
133 	mdvp->last_lba = gpt->efi_last_u_lba;
134 	mdvp->lbasize = gpt->efi_lbasize;
135 
136 	for (i = 0; (i < gpt->efi_nparts); ++i) {
137 		mdvp->parts[i].start = gpt->efi_parts[i].p_start;
138 		mdvp->parts[i].size = gpt->efi_parts[i].p_size;
139 		mdvp->parts[i].tag = gpt->efi_parts[i].p_tag;
140 		mdvp->parts[i].flag = gpt->efi_parts[i].p_flag;
141 		/*
142 		 * Due to the lack of a label for the entire partition table,
143 		 * we use p_name of the reserved partition
144 		 */
145 		if ((gpt->efi_parts[i].p_tag == V_RESERVED) &&
146 		    (gpt->efi_parts[i].p_name != NULL)) {
147 			(void) strlcpy(typename, gpt->efi_parts[i].p_name,
148 					EFI_PART_NAME_LEN);
149 			/* Stop at first (if any) space or tab */
150 			(void) strtok(typename, " \t");
151 			mdvp->typename = Strdup(typename);
152 		}
153 	}
154 }
155 
156 static void
157 meta_mdvtoc_to_efi(mdvtoc_t *mdvp, struct dk_gpt **gpt)
158 {
159 	char		typename[EFI_PART_NAME_LEN];
160 	uint_t		i;
161 	uint_t		lastpart;
162 	size_t		size;
163 
164 	/* first we count how many partitions we have to send */
165 	for (i = 0; i < MD_MAX_PARTS; i++) {
166 		if ((mdvp->parts[i].start == 0) &&
167 		    (mdvp->parts[i].size == 0) &&
168 		    (mdvp->parts[i].tag != V_RESERVED)) {
169 			continue;
170 		}
171 		/* if we are here, we know the partition is really used */
172 		lastpart = i;
173 	}
174 	size = sizeof (struct dk_gpt) + (sizeof (struct dk_part) * lastpart);
175 	*gpt = calloc(size, sizeof (char));
176 
177 	(*gpt)->efi_nparts = lastpart + 1;
178 	(*gpt)->efi_first_u_lba = mdvp->first_lba;
179 	(*gpt)->efi_last_u_lba = mdvp->last_lba;
180 	(*gpt)->efi_lbasize = mdvp->lbasize;
181 	for (i = 0; (i < (*gpt)->efi_nparts); ++i) {
182 		(*gpt)->efi_parts[i].p_start = mdvp->parts[i].start;
183 		(*gpt)->efi_parts[i].p_size = mdvp->parts[i].size;
184 		(*gpt)->efi_parts[i].p_tag = mdvp->parts[i].tag;
185 		(*gpt)->efi_parts[i].p_flag = mdvp->parts[i].flag;
186 		/*
187 		 * Due to the lack of a label for the entire partition table,
188 		 * we use p_name of the reserved partition
189 		 */
190 		if (((*gpt)->efi_parts[i].p_tag == V_RESERVED) &&
191 			(mdvp->typename != NULL)) {
192 			(void) strlcpy((*gpt)->efi_parts[i].p_name, typename,
193 				EFI_PART_NAME_LEN);
194 		}
195 	}
196 }
197 
198 
199 void
200 ctlr_cache_add(char *nm, int ty)
201 {
202 	ctlr_cache_t	**ccpp;
203 
204 	for (ccpp = &ctlr_cache; *ccpp != NULL; ccpp = &(*ccpp)->ctlr_nx)
205 		if (strcmp((*ccpp)->ctlr_nm, nm) == 0)
206 			return;
207 
208 	*ccpp = Zalloc(sizeof (ctlr_cache_t));
209 	(*ccpp)->ctlr_nm = Strdup(nm);
210 	(*ccpp)->ctlr_ty = ty;
211 }
212 
213 int
214 ctlr_cache_look(char *nm)
215 {
216 	ctlr_cache_t	*tcp;
217 
218 	for (tcp = ctlr_cache; tcp != NULL; tcp = tcp->ctlr_nx)
219 		if (strcmp(tcp->ctlr_nm, nm) == 0)
220 			return (tcp->ctlr_ty);
221 
222 	return (-1);
223 }
224 
225 
226 void
227 metaflushctlrcache(void)
228 {
229 	ctlr_cache_t	*cp, *np;
230 
231 	for (cp = ctlr_cache, np = NULL; cp != NULL; cp = np) {
232 		np = cp->ctlr_nx;
233 		Free(cp->ctlr_nm);
234 		Free(cp);
235 	}
236 	ctlr_cache = NULL;
237 }
238 
239 /*
240  * getdrvnode -- return the driver name based on mdname_t->bname
241  *	Need to free pointer when finished.
242  */
243 char *
244 getdrvnode(mdname_t *np, md_error_t *ep)
245 {
246 	char	*devicespath,
247 		*drvnode,
248 		*cp;
249 
250 	if ((devicespath = metagetdevicesname(np, ep)) == NULL)
251 		return (NULL);
252 
253 	/*
254 	 * At this point devicespath should be like the following
255 	 * "/devices/<unknow_and_dont_care>/xxxx@vvvv"
256 	 *
257 	 * There's a couple of 'if' statements below which could
258 	 * return an error condition, but I've decide to allow
259 	 * a more open approach regarding the mapping so as to
260 	 * not restrict possible future projects.
261 	 */
262 	if (drvnode = strrchr(devicespath, '/'))
263 		/*
264 		 * drvnode now just "xxxx@vvvv"
265 		 */
266 		drvnode++;
267 
268 	if (cp = strrchr(drvnode, '@'))
269 		/*
270 		 * Now drvnode is just the driver name "xxxx"
271 		 */
272 		*cp = '\0';
273 
274 	cp = Strdup(drvnode);
275 	Free(devicespath);
276 	np->devicesname = NULL;
277 
278 	return (cp);
279 }
280 
281 /*
282  * meta_load_dl -- open dynamic library using LDLIBRARYPATH, a debug
283  *    environment variable METALDPATH, or the default location.
284  */
285 static void *
286 meta_load_dl(mdname_t *np, md_error_t *ep)
287 {
288 	char	*drvnode,
289 		newpath[MAXPATHLEN],
290 		*p;
291 	void	*cookie;
292 
293 	if ((drvnode = getdrvnode(np, ep)) != NULL) {
294 
295 		/*
296 		 * Library seach algorithm:
297 		 * 1) Use LDLIBRARYPATH which is implied when a non-absolute
298 		 *    path name is passed to dlopen()
299 		 * 2) Use the value of METALDPATH as the directory. Mainly
300 		 *    used for debugging
301 		 * 3) Last search the default location of "/usr/lib"
302 		 */
303 		(void) snprintf(newpath, sizeof (newpath), "lib%s.so.1",
304 		    drvnode);
305 		if ((cookie = dlopen(newpath, RTLD_LAZY)) == NULL) {
306 			if ((p = getenv("METALDPATH")) == NULL)
307 				p = METALDPATH_DEFAULT;
308 			(void) snprintf(newpath, sizeof (newpath),
309 			    "%s/lib%s.so.1", p, drvnode);
310 			Free(drvnode);
311 			if ((cookie = dlopen(newpath, RTLD_LAZY)) != NULL) {
312 				/*
313 				 * Common failure here would be failing to
314 				 * find a libXX.so.1 such as libsd.so.1
315 				 * Some controllers will not have a library
316 				 * because there's no enclosure or name
317 				 * translation required.
318 				 */
319 				return (cookie);
320 			}
321 		} else {
322 			Free(drvnode);
323 			return (cookie);
324 		}
325 	}
326 	return (NULL);
327 }
328 
329 /*
330  * meta_match_names -- possibly convert the driver names returned by CINFO
331  */
332 static void
333 meta_match_names(mdname_t *np, struct dk_cinfo *cp, mdcinfo_t *mdcp,
334     md_error_t *ep)
335 {
336 	void		*cookie;
337 	meta_convert_e	((*fptr)(mdname_t *, struct dk_cinfo *, mdcinfo_t *,
338 			    md_error_t *));
339 
340 	if ((cookie = meta_load_dl(np, ep)) != NULL) {
341 		fptr = (meta_convert_e (*)(mdname_t *, struct dk_cinfo *,
342 		    mdcinfo_t *, md_error_t *))dlsym(cookie, "convert_path");
343 		if (fptr != NULL)
344 			(void) (*fptr)(np, cp, mdcp, ep);
345 		(void) dlclose(cookie);
346 	}
347 }
348 
349 /*
350  * meta_match_enclosure -- return any enclosure info if found
351  */
352 int
353 meta_match_enclosure(mdname_t *np, mdcinfo_t *mdcp, md_error_t *ep)
354 {
355 	meta_enclosure_e	e,
356 				((*fptr)(mdname_t *, mdcinfo_t *,
357 				    md_error_t *));
358 	void			*cookie;
359 
360 	if ((cookie = meta_load_dl(np, ep)) != NULL) {
361 		fptr = (meta_enclosure_e (*)(mdname_t *, mdcinfo_t *,
362 		    md_error_t *))dlsym(cookie, "get_enclosure");
363 		if (fptr != NULL) {
364 			e = (*fptr)(np, mdcp, ep);
365 			switch (e) {
366 			case Enclosure_Error:
367 				/*
368 				 * Looks like this library wanted to handle
369 				 * our device and had an internal error.
370 				 */
371 				return (1);
372 
373 			case Enclosure_Okay:
374 				/*
375 				 * Found a library to handle the request so
376 				 * just return with data provided.
377 				 */
378 				return (0);
379 
380 			case Enclosure_Noop:
381 				/*
382 				 * Need to continue the search
383 				 */
384 				break;
385 			}
386 		}
387 		(void) dlclose(cookie);
388 	}
389 	return (0);
390 }
391 
392 static int
393 meta_cinfo_to_md(mdname_t *np, struct dk_cinfo *cp, mdcinfo_t *mdcp,
394     md_error_t *ep)
395 {
396 	/* default */
397 	(void) memset(mdcp, '\0', sizeof (*mdcp));
398 	(void) strncpy(mdcp->cname, cp->dki_cname,
399 	    min((sizeof (mdcp->cname) - 1), sizeof (cp->dki_cname)));
400 	mdcp->ctype = MHD_CTLR_GENERIC;
401 	mdcp->cnum = cp->dki_cnum;
402 	(void) strncpy(mdcp->dname, cp->dki_dname,
403 	    min((sizeof (mdcp->dname) - 1), sizeof (cp->dki_dname)));
404 	mdcp->unit = cp->dki_unit;
405 	mdcp->maxtransfer = cp->dki_maxtransfer;
406 
407 	/*
408 	 * See if the driver name returned from DKIOCINFO
409 	 * is valid or not. In somecases, such as the ap_dmd
410 	 * driver, we need to modify the name that's return
411 	 * for everything to work.
412 	 */
413 	meta_match_names(np, cp, mdcp, ep);
414 
415 	if (meta_match_enclosure(np, mdcp, ep))
416 		return (-1);
417 
418 	/* return success */
419 	return (0);
420 }
421 
422 static void
423 meta_vtoc_to_md(
424 	struct vtoc	*vp,
425 	mdvtoc_t	*mdvp
426 )
427 {
428 	char		typename[sizeof (vp->v_asciilabel) + 1];
429 	uint_t		i;
430 
431 	(void) memset(mdvp, '\0', sizeof (*mdvp));
432 	(void) strncpy(typename, vp->v_asciilabel,
433 	    sizeof (vp->v_asciilabel));
434 	typename[sizeof (typename) - 1] = '\0';
435 	for (i = 0; ((i < sizeof (typename)) && (typename[i] != '\0')); ++i) {
436 		if ((typename[i] == ' ') || (typename[i] == '\t')) {
437 			typename[i] = '\0';
438 			break;
439 		}
440 	}
441 	mdvp->typename = Strdup(typename);
442 	mdvp->nparts = vp->v_nparts;
443 	for (i = 0; (i < vp->v_nparts); ++i) {
444 		mdvp->parts[i].start = vp->v_part[i].p_start;
445 		mdvp->parts[i].size = vp->v_part[i].p_size;
446 		mdvp->parts[i].tag = vp->v_part[i].p_tag;
447 		mdvp->parts[i].flag = vp->v_part[i].p_flag;
448 		if (vp->v_part[i].p_start == 0 && vp->v_part[i].p_size > 0)
449 			mdvp->parts[i].label = btodb(DK_LABEL_SIZE);
450 	}
451 }
452 
453 /*
454  * free allocations in vtoc
455  */
456 void
457 metafreevtoc(
458 	mdvtoc_t	*vtocp
459 )
460 {
461 	if (vtocp->typename != NULL)
462 		Free(vtocp->typename);
463 	(void) memset(vtocp, 0, sizeof (*vtocp));
464 }
465 
466 /*
467  * return md types
468  */
469 mdvtoc_t *
470 metagetvtoc(
471 	mdname_t	*np,	/* only rname, drivenamep, are setup */
472 	int		nocache,
473 	uint_t		*partnop,
474 	md_error_t	*ep
475 )
476 {
477 	mddrivename_t	*dnp = np->drivenamep;
478 	struct dk_geom	geom;
479 	char		*minor_name = NULL;
480 	char		*rname = np->rname;
481 	int		fd;
482 	int		partno;
483 	int		err = 0;	    /* saves errno from ioctl */
484 	ddi_devid_t	devid;
485 	char		*p;
486 
487 	/* short circuit */
488 	if ((! nocache) && (dnp->vtoc.nparts != 0)) {
489 		if (partnop != NULL) {
490 			/*
491 			 * the following assigment works because the
492 			 * mdname_t structs are always created as part
493 			 * of the drivenamep struct.  When a user
494 			 * creates an mdname_t struct it either
495 			 * uses an existing drivenamep struct or creates
496 			 * a new one and then adds the mdname_t struct
497 			 * as part of its parts_val array.  So what is
498 			 * being computed below is the slice offset in
499 			 * the parts_val array.
500 			 */
501 			*partnop = np - np->drivenamep->parts.parts_val;
502 			assert(*partnop < dnp->parts.parts_len);
503 		}
504 		return (&dnp->vtoc);
505 	}
506 
507 	/* can't get vtoc */
508 	if (! nocache) {
509 		switch (dnp->type) {
510 		case MDT_ACCES:
511 		case MDT_UNKNOWN:
512 			(void) mdsyserror(ep, dnp->errnum, rname);
513 			return (NULL);
514 		}
515 	}
516 
517 	/* get all the info */
518 	if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
519 		(void) mdsyserror(ep, errno, rname);
520 		return (NULL);
521 	}
522 
523 	/*
524 	 * The disk is open so this is a good point to get the devid
525 	 * otherwise it will need to be done at another time which
526 	 * means reopening it.
527 	 */
528 	if (devid_get(fd, &devid) != 0) {
529 		/* there is no devid for the disk */
530 		if (((p = getenv("MD_DEBUG")) != NULL) &&
531 		    (strstr(p, "DEVID") != NULL)) {
532 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
533 			    "%s has no device id\n"), np->rname);
534 		}
535 		np->minor_name = (char *)NULL;
536 		dnp->devid = NULL;
537 	} else {
538 		(void) devid_get_minor_name(fd, &minor_name);
539 		/*
540 		 * The minor name could be NULL if the underlying
541 		 * device driver does not support 'minor names'.
542 		 * This means we do not use devid's for this device.
543 		 * SunCluster did driver does not support minor names.
544 		 */
545 		if (minor_name != NULL) {
546 			np->minor_name = Strdup(minor_name);
547 			devid_str_free(minor_name);
548 			dnp->devid = devid_str_encode(devid, NULL);
549 		} else {
550 			np->minor_name = (char *)NULL;
551 			dnp->devid = NULL;
552 
553 			if (((p = getenv("MD_DEBUG")) != NULL) &&
554 			    (strstr(p, "DEVID") != NULL)) {
555 				(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
556 				    "%s no minor name (no devid)\n"),
557 				    np->rname);
558 			}
559 		}
560 		devid_free(devid);
561 	}
562 
563 	/*
564 	 * if our drivenamep points to a device not supporting DKIOCGGEOM,
565 	 * it's likely to have an EFI label.
566 	 */
567 	(void) memset(&geom, 0, sizeof (geom));
568 	if (ioctl(fd, DKIOCGGEOM, &geom) != 0) {
569 		err = errno;
570 		if (err == ENOTTY) {
571 			(void) mddeverror(ep, MDE_NOT_DISK, NODEV, rname);
572 			(void) close(fd);
573 			return (NULL);
574 		} else if (err != ENOTSUP) {
575 			(void) mdsyserror(ep, err, rname);
576 			(void) close(fd);
577 			return (NULL);
578 		}
579 
580 	}
581 	/*
582 	 * If we are here, there was either no failure on DKIOCGGEOM or
583 	 * the failure was ENOTSUP
584 	 */
585 	if (err == ENOTSUP) {
586 		/* DKIOCGGEOM yielded ENOTSUP => try efi_alloc_and_read */
587 		struct dk_gpt	*gpt;
588 		int		save_errno;
589 
590 		/* this also sets errno */
591 		partno = efi_alloc_and_read(fd, &gpt);
592 		save_errno = errno;
593 		(void) close(fd);
594 		if (partno < 0) {
595 			efi_free(gpt);
596 			(void) mdsyserror(ep, save_errno, rname);
597 			return (NULL);
598 		}
599 		if (partno >= gpt->efi_nparts) {
600 			efi_free(gpt);
601 			(void) mddeverror(ep, MDE_INVALID_PART, NODEV64,
602 						rname);
603 			return (NULL);
604 		}
605 
606 		/* convert to our format */
607 		metafreevtoc(&dnp->vtoc);
608 		meta_efi_to_mdvtoc(gpt, &dnp->vtoc);
609 		if (dnp->vtoc.nparts > MD_MAX_PARTS) {
610 			(void) mddeverror(ep, MDE_TOO_MANY_PARTS, NODEV64,
611 			    rname);
612 			return (NULL);
613 		}
614 		/*
615 		 * libmeta needs at least V_NUMPAR partitions.
616 		 * If we have an EFI partition with less than V_NUMPAR slices,
617 		 * we nevertheless reserve space for V_NUMPAR
618 		 */
619 
620 		if (dnp->vtoc.nparts < V_NUMPAR) {
621 			dnp->vtoc.nparts = V_NUMPAR;
622 		}
623 		meta_efi_to_mdgeom(gpt, &dnp->geom);
624 		efi_free(gpt);
625 	} else {
626 		/* no error on DKIOCGGEOM, try meta_getvtoc */
627 		struct vtoc	vtoc;
628 
629 		if (meta_getvtoc(fd, np->cname, &vtoc, &partno, ep) < 0) {
630 			(void) close(fd);
631 			return (NULL);
632 		}
633 		(void) close(fd);
634 
635 		/* convert to our format */
636 		meta_geom_to_md(&geom, &dnp->geom);
637 		metafreevtoc(&dnp->vtoc);
638 		meta_vtoc_to_md(&vtoc, &dnp->vtoc);
639 	}
640 
641 	/* fix up any drives which are now accessible */
642 	if ((nocache) && (dnp->type == MDT_ACCES) &&
643 	    (dnp->vtoc.nparts == dnp->parts.parts_len)) {
644 		dnp->type = MDT_COMP;
645 		dnp->errnum = 0;
646 	}
647 
648 	/* save partno */
649 	assert(partno < dnp->vtoc.nparts);
650 	if (partnop != NULL)
651 		*partnop = partno;
652 
653 	/* return info */
654 	return (&dnp->vtoc);
655 }
656 
657 static void
658 meta_mdvtoc_to_vtoc(
659 	mdvtoc_t	*mdvp,
660 	struct vtoc	*vp
661 )
662 {
663 	uint_t		i;
664 
665 	(void) memset(&vp->v_part, '\0', sizeof (vp->v_part));
666 	vp->v_nparts = (ushort_t)mdvp->nparts;
667 	for (i = 0; (i < mdvp->nparts); ++i) {
668 		vp->v_part[i].p_start = (daddr32_t)mdvp->parts[i].start;
669 		vp->v_part[i].p_size  = (daddr32_t)mdvp->parts[i].size;
670 		vp->v_part[i].p_tag   = mdvp->parts[i].tag;
671 		vp->v_part[i].p_flag  = mdvp->parts[i].flag;
672 	}
673 }
674 
675 /*
676  * Set the vtoc, but use the cached copy to get the info from.
677  * We write np->drivenamep->vtoc to disk.
678  * Before we can do this we read the vtoc in.
679  * if we're dealing with a metadevice and this metadevice is a 64 bit device
680  *	we can use meta_getmdvtoc/meta_setmdvtoc
681  * else
682  * 	we use meta_getvtoc/meta_setvtoc but than we first have to convert
683  *	dnp->vtoc (actually being a mdvtoc_t) into a vtoc_t
684  */
685 int
686 metasetvtoc(
687 	mdname_t	*np,
688 	md_error_t	*ep
689 )
690 {
691 	char		*rname = np->rname;
692 	mddrivename_t	*dnp = np->drivenamep;
693 	int		fd;
694 	int		err;
695 	int 		save_errno;
696 	struct dk_geom	geom;
697 
698 	if ((fd = open(rname, (O_RDONLY | O_NDELAY), 0)) < 0)
699 		return (mdsyserror(ep, errno, rname));
700 
701 	err = ioctl(fd, DKIOCGGEOM, &geom);
702 	save_errno = errno;
703 	if (err == 0) {
704 		struct vtoc	vtoc;
705 
706 		if (meta_getvtoc(fd, np->cname, &vtoc, NULL, ep) < 0) {
707 			(void) close(fd);
708 			return (-1);
709 		}
710 
711 		meta_mdvtoc_to_vtoc(&dnp->vtoc, &vtoc);
712 
713 		if (meta_setvtoc(fd, np->cname, &vtoc, ep) < 0) {
714 			(void) close(fd);
715 			return (-1);
716 		}
717 	} else if (save_errno == ENOTSUP) {
718 		struct dk_gpt	*gpt;
719 		int		ret;
720 
721 		/* allocation of gpt is done in meta_mdvtoc_to_efi */
722 		meta_mdvtoc_to_efi(&dnp->vtoc, &gpt);
723 
724 		ret = efi_write(fd, gpt);
725 		save_errno = errno;
726 		free(gpt);
727 		if (ret != 0) {
728 			(void) close(fd);
729 			return (mdsyserror(ep, save_errno, rname));
730 		} else {
731 			(void) close(fd);
732 			return (0);
733 		}
734 
735 	} else {
736 		(void) close(fd);
737 		return (mdsyserror(ep, save_errno, rname));
738 	}
739 
740 	(void) close(fd);
741 
742 	return (0);
743 }
744 
745 mdgeom_t *
746 metagetgeom(
747 	mdname_t	*np,	/* only rname, drivenamep, are setup */
748 	md_error_t	*ep
749 )
750 {
751 	if (metagetvtoc(np, FALSE, NULL, ep) == NULL)
752 		return (NULL);
753 	return (&np->drivenamep->geom);
754 }
755 
756 mdcinfo_t *
757 metagetcinfo(
758 	mdname_t	*np,	/* only rname, drivenamep, are setup */
759 	md_error_t	*ep
760 )
761 {
762 	char			*rname = np->rname;
763 	mddrivename_t		*dnp = np->drivenamep;
764 	int			fd;
765 	struct dk_cinfo		cinfo;
766 
767 	/* short circuit */
768 	if (dnp->cinfo.cname[0] != '\0')
769 		return (&dnp->cinfo);
770 
771 	/* get controller info */
772 	if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
773 		(void) mdsyserror(ep, errno, rname);
774 		return (NULL);
775 	}
776 	if (ioctl(fd, DKIOCINFO, &cinfo) != 0) {
777 		int	save = errno;
778 
779 		(void) close(fd);
780 		if (save == ENOTTY) {
781 			(void) mddeverror(ep, MDE_NOT_DISK, NODEV64, rname);
782 		} else {
783 			(void) mdsyserror(ep, save, rname);
784 		}
785 		return (NULL);
786 	}
787 	(void) close(fd);	/* sd/ssd bug */
788 
789 	/* convert to our format */
790 	if (meta_cinfo_to_md(np, &cinfo, &dnp->cinfo, ep) != 0)
791 		return (NULL);
792 
793 	/* return info */
794 	return (&dnp->cinfo);
795 }
796 
797 /*
798  * get partition number
799  */
800 int
801 metagetpartno(
802 	mdname_t	*np,
803 	md_error_t	*ep
804 )
805 {
806 	mdvtoc_t	*vtocp;
807 	uint_t		partno;
808 
809 	if ((vtocp = metagetvtoc(np, FALSE, &partno, ep)) == NULL)
810 		return (-1);
811 	assert(partno < vtocp->nparts);
812 	return (partno);
813 }
814 
815 /*
816  * get size of device
817  */
818 diskaddr_t
819 metagetsize(
820 	mdname_t	*np,
821 	md_error_t	*ep
822 )
823 {
824 	mdvtoc_t	*vtocp;
825 	uint_t		partno;
826 
827 	if ((vtocp = metagetvtoc(np, FALSE, &partno, ep)) == NULL)
828 		return (MD_DISKADDR_ERROR);
829 	assert(partno < vtocp->nparts);
830 	return (vtocp->parts[partno].size);
831 }
832 
833 /*
834  * get label of device
835  */
836 diskaddr_t
837 metagetlabel(
838 	mdname_t	*np,
839 	md_error_t	*ep
840 )
841 {
842 	mdvtoc_t	*vtocp;
843 	uint_t		partno;
844 
845 	if ((vtocp = metagetvtoc(np, FALSE, &partno, ep)) == NULL)
846 		return (MD_DISKADDR_ERROR);
847 	assert(partno < vtocp->nparts);
848 	return (vtocp->parts[partno].label);
849 }
850 
851 /*
852  * find out where database replicas end
853  */
854 static int
855 mddb_getendblk(
856 	mdsetname_t		*sp,
857 	mdname_t		*np,
858 	diskaddr_t		*endblkp,
859 	md_error_t		*ep
860 )
861 {
862 	md_replicalist_t	*rlp = NULL;
863 	md_replicalist_t	*rl;
864 
865 	/* make sure we have a component */
866 	*endblkp = 0;
867 	if (metaismeta(np))
868 		return (0);
869 
870 	/* get replicas, quit if none */
871 	if (metareplicalist(sp, MD_BASICNAME_OK | PRINT_FAST, &rlp, ep) < 0) {
872 		if (! mdismddberror(ep, MDE_DB_NODB))
873 			return (-1);
874 		mdclrerror(ep);
875 		return (0);
876 	} else if (rlp == NULL)
877 		return (0);
878 
879 	/* go through all the replicas */
880 	for (rl = rlp; (rl != NULL); rl = rl->rl_next) {
881 		md_replica_t	*rp = rl->rl_repp;
882 		mdname_t	*repnamep = rp->r_namep;
883 		diskaddr_t	dbend;
884 
885 		if (np->dev != repnamep->dev)
886 			continue;
887 		dbend = rp->r_blkno + rp->r_nblk - 1;
888 		if (dbend > *endblkp)
889 			*endblkp = dbend;
890 	}
891 
892 	/* cleanup, return success */
893 	metafreereplicalist(rlp);
894 	return (0);
895 }
896 
897 /*
898  * return cached start block
899  */
900 static diskaddr_t
901 metagetend(
902 	mdsetname_t	*sp,
903 	mdname_t	*np,
904 	md_error_t	*ep
905 )
906 {
907 	diskaddr_t	end_blk = MD_DISKADDR_ERROR;
908 
909 	/* short circuit */
910 	if (np->end_blk != MD_DISKADDR_ERROR)
911 		return (np->end_blk);
912 
913 	/* look for database locations */
914 	if (mddb_getendblk(sp, np, &end_blk, ep) != 0)
915 		return (MD_DISKADDR_ERROR);
916 
917 	/* success */
918 	np->end_blk = end_blk;
919 	return (end_blk);
920 }
921 
922 /*
923  * does device have a metadb
924  */
925 int
926 metahasmddb(
927 	mdsetname_t	*sp,
928 	mdname_t	*np,
929 	md_error_t	*ep
930 )
931 {
932 	if (metagetend(sp, np, ep) == MD_DISKADDR_ERROR)
933 		return (-1);
934 	else if (np->end_blk > 0)
935 		return (1);
936 	else
937 		return (0);
938 }
939 
940 /*
941  * return cached start block
942  */
943 diskaddr_t
944 metagetstart(
945 	mdsetname_t	*sp,
946 	mdname_t	*np,
947 	md_error_t	*ep
948 )
949 {
950 	diskaddr_t	start_blk = MD_DISKADDR_ERROR;
951 
952 	/* short circuit */
953 	if (np->start_blk != MD_DISKADDR_ERROR)
954 		return (np->start_blk);
955 
956 	/* look for database locations */
957 	if ((start_blk = metagetend(sp, np, ep)) == MD_DISKADDR_ERROR)
958 		return (MD_DISKADDR_ERROR);
959 
960 	/* check for label */
961 	if (start_blk == 0) {
962 		start_blk = metagetlabel(np, ep);
963 		if (start_blk == MD_DISKADDR_ERROR) {
964 			return (MD_DISKADDR_ERROR);
965 		}
966 	}
967 
968 	/* roundup to next cylinder */
969 	if (start_blk != 0) {
970 		mdgeom_t	*geomp;
971 
972 		if ((geomp = metagetgeom(np, ep)) == NULL)
973 			return (MD_DISKADDR_ERROR);
974 		start_blk = roundup(start_blk, (geomp->nhead * geomp->nsect));
975 	}
976 
977 	/* success */
978 	np->start_blk = start_blk;
979 	return (start_blk);
980 }
981 
982 /*
983  * return cached devices name
984  */
985 char *
986 metagetdevicesname(
987 	mdname_t	*np,
988 	md_error_t	*ep
989 )
990 {
991 	char		path[MAXPATHLEN + 1];
992 	int		len;
993 
994 	/* short circuit */
995 	if (np->devicesname != NULL)
996 		return (np->devicesname);
997 
998 	/* follow symlink */
999 	if ((len = readlink(np->bname, path, (sizeof (path) - 1))) < 0) {
1000 		(void) mdsyserror(ep, errno, np->bname);
1001 		return (NULL);
1002 	} else if (len >= sizeof (path)) {
1003 		(void) mdsyserror(ep, ENAMETOOLONG, np->bname);
1004 		return (NULL);
1005 	}
1006 	path[len] = '\0';
1007 	if ((len = strfind(path, "/devices/")) < 0) {
1008 		(void) mddeverror(ep, MDE_DEVICES_NAME, np->dev, np->bname);
1009 		return (NULL);
1010 	}
1011 
1012 	/* return name */
1013 	np->devicesname = Strdup(path + len + strlen("/devices"));
1014 	return (np->devicesname);
1015 }
1016 
1017 /*
1018  * get metadevice misc name
1019  */
1020 char *
1021 metagetmiscname(
1022 	mdname_t		*np,
1023 	md_error_t		*ep
1024 )
1025 {
1026 	mddrivename_t		*dnp = np->drivenamep;
1027 	md_i_driverinfo_t	mid;
1028 
1029 	/* short circuit */
1030 	if (dnp->miscname != NULL)
1031 		return (dnp->miscname);
1032 	if (metachkmeta(np, ep) != 0)
1033 		return (NULL);
1034 
1035 	/* get misc module from driver */
1036 	(void) memset(&mid, 0, sizeof (mid));
1037 	mid.mnum = meta_getminor(np->dev);
1038 	if (metaioctl(MD_IOCGET_DRVNM, &mid, &mid.mde, np->cname) != 0) {
1039 		(void) mdstealerror(ep, &mid.mde);
1040 		return (NULL);
1041 	}
1042 
1043 	/* return miscname */
1044 	dnp->miscname = Strdup(MD_PNTDRIVERNAME(&mid));
1045 	return (dnp->miscname);
1046 }
1047 
1048 /*
1049  * get unit structure from driver
1050  */
1051 md_unit_t *
1052 meta_get_mdunit(
1053 	mdsetname_t	*sp,
1054 	mdname_t	*np,
1055 	md_error_t	*ep
1056 )
1057 {
1058 	md_i_get_t	mig;
1059 	char		*miscname = NULL;
1060 
1061 	/* should have a set */
1062 	assert(sp != NULL);
1063 	assert(sp->setno == MD_MIN2SET(meta_getminor(np->dev)));
1064 
1065 	/* get size of unit structure */
1066 	if (metachkmeta(np, ep) != 0)
1067 		return (NULL);
1068 	if ((miscname = metagetmiscname(np, ep)) == NULL)
1069 		return (NULL);
1070 	(void) memset(&mig, '\0', sizeof (mig));
1071 	MD_SETDRIVERNAME(&mig, miscname, sp->setno);
1072 	mig.id = meta_getminor(np->dev);
1073 	if (metaioctl(MD_IOCGET, &mig, &mig.mde, np->cname) != 0) {
1074 		(void) mdstealerror(ep, &mig.mde);
1075 		return (NULL);
1076 	}
1077 
1078 	/* get actual unit structure */
1079 	assert(mig.size > 0);
1080 	mig.mdp = (uintptr_t)Zalloc(mig.size);
1081 	if (metaioctl(MD_IOCGET, &mig, &mig.mde, np->cname) != 0) {
1082 		(void) mdstealerror(ep, &mig.mde);
1083 		Free((void *)(uintptr_t)mig.mdp);
1084 		return (NULL);
1085 	}
1086 
1087 	return ((md_unit_t *)(uintptr_t)mig.mdp);
1088 }
1089 
1090 /*
1091  * free metadevice unit
1092  */
1093 void
1094 meta_free_unit(
1095 	mddrivename_t	*dnp
1096 )
1097 {
1098 	if (dnp->unitp != NULL) {
1099 		switch (dnp->unitp->type) {
1100 		case MD_DEVICE:
1101 			meta_free_stripe((md_stripe_t *)dnp->unitp);
1102 			break;
1103 		case MD_METAMIRROR:
1104 			meta_free_mirror((md_mirror_t *)dnp->unitp);
1105 			break;
1106 		case MD_METATRANS:
1107 			meta_free_trans((md_trans_t *)dnp->unitp);
1108 			break;
1109 		case MD_METARAID:
1110 			meta_free_raid((md_raid_t *)dnp->unitp);
1111 			break;
1112 		case MD_METASP:
1113 			meta_free_sp((md_sp_t *)dnp->unitp);
1114 			break;
1115 		default:
1116 			assert(0);
1117 			break;
1118 		}
1119 		dnp->unitp = NULL;
1120 	}
1121 }
1122 
1123 /*
1124  * free metadevice name info
1125  */
1126 void
1127 meta_invalidate_name(
1128 	mdname_t	*namep
1129 )
1130 {
1131 	mddrivename_t	*dnp = namep->drivenamep;
1132 
1133 	/* get rid of cached name info */
1134 	if (namep->devicesname != NULL) {
1135 		Free(namep->devicesname);
1136 		namep->devicesname = NULL;
1137 	}
1138 	namep->key = MD_KEYBAD;
1139 	namep->start_blk = -1;
1140 	namep->end_blk = -1;
1141 
1142 	/* get rid of cached drivename info */
1143 	(void) memset(&dnp->geom, 0, sizeof (dnp->geom));
1144 	(void) memset(&dnp->cinfo, 0, sizeof (dnp->cinfo));
1145 	metafreevtoc(&dnp->vtoc);
1146 	metaflushsidenames(dnp);
1147 	dnp->side_names_key = MD_KEYBAD;
1148 	if (dnp->miscname != NULL) {
1149 		Free(dnp->miscname);
1150 		dnp->miscname = NULL;
1151 	}
1152 	meta_free_unit(dnp);
1153 }
1154 
1155 /*
1156  * get metadevice unit
1157  */
1158 md_common_t *
1159 meta_get_unit(
1160 	mdsetname_t	*sp,
1161 	mdname_t	*np,
1162 	md_error_t	*ep
1163 )
1164 {
1165 	char		*miscname;
1166 
1167 	/* short circuit */
1168 	if (np->drivenamep->unitp != NULL)
1169 		return (np->drivenamep->unitp);
1170 	if (metachkmeta(np, ep) != 0)
1171 		return (NULL);
1172 
1173 	/* dispatch */
1174 	if ((miscname = metagetmiscname(np, ep)) == NULL)
1175 		return (NULL);
1176 	else if (strcmp(miscname, MD_STRIPE) == 0)
1177 		return ((md_common_t *)meta_get_stripe(sp, np, ep));
1178 	else if (strcmp(miscname, MD_MIRROR) == 0)
1179 		return ((md_common_t *)meta_get_mirror(sp, np, ep));
1180 	else if (strcmp(miscname, MD_TRANS) == 0)
1181 		return ((md_common_t *)meta_get_trans(sp, np, ep));
1182 	else if (strcmp(miscname, MD_RAID) == 0)
1183 		return ((md_common_t *)meta_get_raid(sp, np, ep));
1184 	else if (strcmp(miscname, MD_SP) == 0)
1185 		return ((md_common_t *)meta_get_sp(sp, np, ep));
1186 	else {
1187 		(void) mdmderror(ep, MDE_UNKNOWN_TYPE, meta_getminor(np->dev),
1188 		    np->cname);
1189 		return (NULL);
1190 	}
1191 }
1192 
1193 
1194 int
1195 meta_isopen(
1196 	mdsetname_t	*sp,
1197 	mdname_t	*np,
1198 	md_error_t	*ep,
1199 	mdcmdopts_t	options
1200 )
1201 {
1202 	md_isopen_t	d;
1203 
1204 	if (metachkmeta(np, ep) != 0)
1205 		return (-1);
1206 
1207 	(void) memset(&d, '\0', sizeof (d));
1208 	d.dev = np->dev;
1209 	if (metaioctl(MD_IOCISOPEN, &d, &d.mde, np->cname) != 0)
1210 		return (mdstealerror(ep, &d.mde));
1211 
1212 	/*
1213 	 * shortcut: if the device is open, no need to check on other nodes,
1214 	 * even in case of a mn metadevice
1215 	 * Also return in case we're told not to check on other nodes.
1216 	 */
1217 	if ((d.isopen != 0) || ((options & MDCMD_MN_OPEN_CHECK) == 0)) {
1218 		return (d.isopen);
1219 	}
1220 
1221 	/*
1222 	 * If the device is closed locally, but it's a mn device,
1223 	 * check on all other nodes, too
1224 	 */
1225 	if (sp->setno != MD_LOCAL_SET) {
1226 		(void) metaget_setdesc(sp, ep); /* not supposed to fail */
1227 		if (sp->setdesc->sd_flags & MD_SR_MN) {
1228 			int		err = 0;
1229 			md_mn_result_t *resp;
1230 			/*
1231 			 * This message is never directly issued.
1232 			 * So we launch it with a suspend override flag.
1233 			 * If the commd is suspended, and this message comes
1234 			 * along it must be sent due to replaying a metainit or
1235 			 * similar. In that case we don't want this message to
1236 			 * be blocked.
1237 			 * If the commd is not suspended, the flag does no harm.
1238 			 * Additionally we don't want the result of the message
1239 			 * cached in the MCT, because we want uptodate results,
1240 			 * and the message doesn't need being logged either.
1241 			 * Hence NO_LOG and NO_MCT
1242 			 */
1243 			err = mdmn_send_message(
1244 				sp->setno,
1245 				MD_MN_MSG_CLU_CHECK,
1246 				MD_MSGF_NO_MCT | MD_MSGF_STOP_ON_ERROR |
1247 				MD_MSGF_NO_LOG | MD_MSGF_OVERRIDE_SUSPEND,
1248 				(char *)&d, sizeof (md_isopen_t),
1249 				&resp, ep);
1250 			if (err == 0) {
1251 				d.isopen = resp->mmr_exitval;
1252 			} else {
1253 				/*
1254 				 * in case some error occurred,
1255 				 * we better say the device is open
1256 				 */
1257 				d.isopen = 1;
1258 			}
1259 			if (resp != (md_mn_result_t *)NULL) {
1260 				free_result(resp);
1261 			}
1262 
1263 		}
1264 	}
1265 
1266 	return (d.isopen);
1267 }
1268