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