xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_set_prv.c (revision 1945:74cee1cd404b)
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  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Metadevice diskset interfaces
30  */
31 
32 #include "meta_set_prv.h"
33 #include <meta.h>
34 #include <sys/lvm/md_mddb.h>
35 #include <sys/cladm.h>
36 #include <devid.h>
37 #include <sys/lvm/md_convert.h>
38 
39 /*
40  * Exported Entry Points
41  */
42 
43 int
44 checkdrive_onnode(
45 	mdsetname_t	*sp,
46 	mddrivename_t	*dnp,
47 	char		*node,
48 	md_error_t	*ep)
49 {
50 	time_t			mystamp, otherstamp;
51 	md_dev64_t		otherdev;
52 	mdname_t		*np, *remote_np;
53 	mddrivename_t		*remote_dnp;
54 	int			release = 0;
55 	md_drive_desc		dd;
56 	int			rval = 0;
57 	int			ret = -1;
58 	mhd_mhiargs_t		mhiargs;
59 	md_set_desc		*sd;
60 	int			is_efi = 0;
61 	int			do_fallback = 0;
62 
63 	(void) memset(&mhiargs, '\0', sizeof (mhiargs));
64 
65 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
66 		return (-1);
67 
68 	if (meta_is_drive_in_thisset(sp, dnp, FALSE, ep)) {
69 		release = 1;
70 		dd.dd_next = NULL;
71 		dd.dd_dbcnt = 0;
72 		dd.dd_dbsize = 0;
73 		dd.dd_dnp = dnp;
74 		if (clnt_gtimeout(mynode(), sp, &mhiargs, ep) != 0)
75 			return (-1);
76 		if (!(MD_MNSET_DESC(sd)) && !MD_ATSET_DESC(sd)) {
77 			if (rel_own_bydd(sp, &dd, TRUE, ep))
78 				return (-1);
79 		}
80 	}
81 	if ((np = metaslicename(dnp, MD_SLICE0, ep)) == NULL) {
82 		rval = -1;
83 		goto out;
84 	}
85 
86 	/*
87 	 * First try and operate assuming the other side
88 	 * is running a SVM version that supports device id
89 	 * in disksets i.e. is running SVM RPC version 2.
90 	 *
91 	 * If this call fails due to the other side running
92 	 * a SVM version that does not support device id
93 	 * in disksets i.e. is running SVM RPC version 1, we
94 	 * fallback to the old behaviour.
95 	 */
96 	if ((dnp->devid != NULL) && (!(MD_MNSET_DESC(sd)))) {
97 		char		*rname = NULL;
98 		md_dev64_t	dev = NODEV64;
99 
100 		/*
101 		 * If the disk is connected to the remote node then the
102 		 * only thing we can be certain of is that the disk will
103 		 * have the same devid on that node, it may not have the
104 		 * same minor number nor the same ctd name. But if it
105 		 * does have the same ctd name then use it.  In most cases
106 		 * there will only be a single entry returned but if the
107 		 * system has multi-path disks with MPXIO turned off there
108 		 * will be multiple entries. Attempting to choose the same
109 		 * name will give  the user as consistent a view across the
110 		 * nodes as possible.
111 		 */
112 		ret = clnt_devinfo_by_devid(node, sp, dnp->devid, &dev,
113 			np->rname, &rname, NULL, ep);
114 
115 		/*
116 		 * If the return value was ENOTSUP, we know the
117 		 * other side is not running a SVM version that
118 		 * supports device id in disksets. We fallback
119 		 * to the previous behaviour in that case.
120 		 */
121 		if (ret == ENOTSUP) {
122 			do_fallback++;
123 			goto fallback;
124 		} else if (ret == -1) {
125 			rval = -1;
126 			goto out;
127 		}
128 
129 		/*
130 		 * If the device does not exist on the remote node then
131 		 * the returned dev should indicate this (NODEV64) but
132 		 * we also check to make sure the returned name is not
133 		 * empty to make sure that the namespace does not get
134 		 * created with a NULL/empty entry (should not be possbile
135 		 * but being paranoid).
136 		 */
137 		if (dev == NODEV64 || rname == (char *)NULL ||
138 		    strcmp(rname, "") == 0) {
139 			rval = mddserror(ep, MDE_DS_DRIVENOTCOMMON, sp->setno,
140 					node, dnp->cname, sp->setname);
141 			goto out;
142 		}
143 
144 		/*
145 		 * The rname returned from the remote node maybe different
146 		 * to the rname on this node, therefore we need to build up
147 		 * a dnp for this new rname.
148 		 */
149 		if (strcmp(np->rname, rname) != 0) {
150 			/* different rname */
151 			remote_np = metaname_fast(&sp, rname,
152 			    LOGICAL_DEVICE, ep);
153 			if (remote_np != NULL) {
154 				remote_dnp = remote_np->drivenamep;
155 			}
156 		} else {
157 			remote_dnp = dnp;
158 		}
159 	} else {
160 		do_fallback++;
161 	}
162 
163 fallback:
164 	if (do_fallback) {
165 		ret = setdevstamp(dnp, &mystamp, ep);
166 		/*
167 		 * Check if the disk in question is an EFI disk.
168 		 */
169 		if (ret == ENOTSUP)
170 			is_efi++;
171 		else if (ret == -1)
172 			return (-1);
173 
174 		if ((np = metaslicename(dnp, MD_SLICE0, ep)) == NULL) {
175 			rval = -1;
176 			goto out;
177 		}
178 
179 		if (is_efi) {
180 			/*
181 			 * For EFI disks, we compare the device
182 			 * id for the disks in question.
183 			 */
184 			ddi_devid_t	thisdevid, otherdevid;
185 			char		*encoded_otherdevid = NULL;
186 			char		*encoded_thisdevid = NULL;
187 
188 			if (clnt_devinfo(node, sp, dnp, &otherdev, NULL, ep)
189 			    == -1) {
190 				rval = -1;
191 				goto out;
192 			}
193 			if (np->dev != otherdev) {
194 				rval = mddserror(ep, MDE_DS_DRIVENOTCOMMON,
195 				    sp->setno, node, dnp->cname, sp->setname);
196 				goto out;
197 			}
198 
199 			if (clnt_devid(node, sp, dnp, &encoded_otherdevid,
200 			    ep) == -1) {
201 				rval = -1;
202 				goto out;
203 			}
204 			if (encoded_otherdevid == NULL) {
205 				rval = -1;
206 				goto out;
207 			}
208 			if (devid_str_decode(encoded_otherdevid, &otherdevid,
209 			    NULL) == 0) {
210 				/*
211 				 * If we are here, it means that dnp->devid
212 				 * is NULL. This will typically happen if
213 				 * we are dealing with SunCluster DID devices.
214 				 *
215 				 * We want to explicitly get the device id
216 				 * for such a disk
217 				 */
218 				encoded_thisdevid = meta_get_devid(dnp->rname);
219 				ret = devid_str_decode(encoded_thisdevid,
220 				    &thisdevid, NULL);
221 				if (ret == 0) {
222 					ret = devid_compare(thisdevid,
223 					    otherdevid);
224 					devid_free(thisdevid);
225 				}
226 				devid_free(otherdevid);
227 				if (encoded_thisdevid)
228 					Free(encoded_thisdevid);
229 			}
230 
231 			Free(encoded_otherdevid);
232 			if (ret != 0) {
233 				rval = mddserror(ep, MDE_DS_DRIVENOTCOMMON,
234 				    sp->setno, node, dnp->cname, sp->setname);
235 				goto out;
236 			}
237 		} else {
238 			/*
239 			 * For VTOC disks, we compare the dev_t and
240 			 * timestamp for the disks in question.
241 			 */
242 			if (clnt_devinfo(node, sp, dnp, &otherdev,
243 			    &otherstamp, ep) == -1) {
244 				rval = -1;
245 				goto out;
246 			}
247 			if ((mystamp != otherstamp) || (np->dev != otherdev)) {
248 				rval = mddserror(ep, MDE_DS_DRIVENOTCOMMON,
249 				    sp->setno, node, dnp->cname, sp->setname);
250 				goto out;
251 			}
252 		}
253 		remote_dnp = dnp;
254 	}
255 
256 	if (clnt_drvused(node, sp, remote_dnp, ep) == -1)
257 		rval = -1;
258 
259 out:
260 	if (release)
261 		if (!(MD_MNSET_DESC(sd)) && !MD_ATSET_DESC(sd)) {
262 			if (tk_own_bydd(sp, &dd, &mhiargs, TRUE, ep))
263 				rval = -1;
264 		}
265 
266 	return (rval);
267 }
268 
269 side_t
270 getnodeside(char *node, md_set_desc *sd)
271 {
272 	side_t			sideno;
273 	int			nid;
274 	md_mnnode_desc		*nd;
275 
276 	if (MD_MNSET_DESC(sd)) {
277 		nd = sd->sd_nodelist;
278 		while (nd) {
279 			if (strcmp(nd->nd_nodename, node) == 0) {
280 				return (nd->nd_nodeid);
281 			}
282 			nd = nd->nd_next;
283 		}
284 		return (MD_SIDEWILD);
285 	}
286 
287 
288 	/* If regular diskset */
289 	for (sideno = 0; sideno < MD_MAXSIDES; sideno++) {
290 		if (sd->sd_nodes[sideno] == NULL ||
291 		    sd->sd_nodes[sideno][0] == '\0')
292 			continue;
293 
294 		if (strcmp(sd->sd_nodes[sideno], node) == 0) {
295 			return (sideno);
296 		}
297 	}
298 
299 	/*
300 	 * If the first loop fails we may be in a situation where this host
301 	 * is configured as part of a cluster yet not running in the cluster
302 	 * mode. If so, the names stored in sd->sd_nodes[] are going to be
303 	 * nodeid's instead of hostnames. See if we can find a match that way.
304 	 */
305 	if (_cladm(CL_CONFIG, CL_NODEID, &nid) == 0) {
306 		for (sideno = 0; sideno < MD_MAXSIDES; sideno++) {
307 			if (sd->sd_nodes[sideno] == NULL ||
308 			    sd->sd_nodes[sideno][0] == '\0')
309 				continue;
310 			if (atoi(sd->sd_nodes[sideno]) == nid)
311 				return (sideno);
312 		}
313 	}
314 
315 	return (MD_SIDEWILD);
316 }
317 
318 int
319 halt_set(mdsetname_t *sp, md_error_t *ep)
320 {
321 	mddb_config_t	c;
322 
323 	(void) memset(&c, 0, sizeof (c));
324 	c.c_setno = sp->setno;
325 	if ((c.c_sideno = getmyside(sp, ep)) == MD_SIDEWILD)
326 		return (-1);
327 
328 	if (s_ownset(sp->setno, ep) == MD_SETOWNER_YES) {
329 		/* Don't need device id information from this ioctl */
330 		c.c_locator.l_devid = (uint64_t)0;
331 		c.c_locator.l_devid_flags = 0;
332 		/* Kill any resyncs that are running on mirrors in this set */
333 		meta_mirror_resync_kill(sp);
334 		if (metaioctl(MD_RELEASE_SET, &c, &c.c_mde, NULL) != 0)
335 			return (mdstealerror(ep, &c.c_mde));
336 	}
337 
338 	return (0);
339 }
340 
341 md_drive_desc *
342 metadrivedesc_append(
343 	md_drive_desc	**dd,
344 	mddrivename_t	*dnp,
345 	int		dbcnt,
346 	int		dbsize,
347 	md_timeval32_t	timestamp,
348 	ulong_t		genid,
349 	uint_t		flags
350 )
351 {
352 	md_drive_desc	*p;
353 
354 	/* run to end of list */
355 	for (/* void */; (*dd != NULL); dd = &(*dd)->dd_next)
356 		/* void */;
357 
358 	/* allocate new list element */
359 	p = *dd = Zalloc(sizeof (*p));
360 
361 	p->dd_dnp = dnp;
362 	p->dd_dbcnt = dbcnt;
363 	p->dd_dbsize = dbsize;
364 	p->dd_ctime = timestamp;
365 	p->dd_genid = genid;
366 	p->dd_flags = flags;
367 	return (p);
368 }
369 
370 int
371 nodehasset(
372 	mdsetname_t	*sp,
373 	char		*node,
374 	uint_t		match_flag,
375 	md_error_t	*ep
376 )
377 {
378 	md_set_desc	*sd;
379 	md_set_record	*sr;
380 	int		rval = 0;
381 
382 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
383 		return (-1);
384 
385 	/* Don't care if set record is MN or not */
386 	if (clnt_getset(node, sp->setname, MD_SET_BAD, &sr, ep))
387 		return (-1);
388 
389 	if (sr == NULL) {
390 		if (! mdisok(ep))
391 			return (-1);
392 		return (0);
393 	}
394 
395 	/* Looking for name only match */
396 	if ((match_flag & NHS_N_EQ) == NHS_N_EQ) {
397 		rval = 1;
398 		goto out;
399 	}
400 
401 	if (sd->sd_setno != sr->sr_setno)
402 		goto out;
403 
404 	/* Looking for name and setno match */
405 	if ((match_flag & NHS_NS_EQ) == NHS_NS_EQ) {
406 		rval = 1;
407 		goto out;
408 	}
409 
410 	if (sd->sd_ctime.tv_sec != sr->sr_ctime.tv_sec ||
411 	    sd->sd_ctime.tv_usec != sr->sr_ctime.tv_usec)
412 		goto out;
413 
414 	/* Looking for name, setno, and timestamp match */
415 	if ((match_flag & NHS_NST_EQ) == NHS_NST_EQ) {
416 		rval = 1;
417 		goto out;
418 	}
419 
420 	if (sd->sd_genid != sr->sr_genid) {
421 		if (sd->sd_genid < sr->sr_genid) {
422 			/*
423 			 * Looking for name, setno, timestamp, and genid on
424 			 * other host is GT than other host.
425 			 */
426 			if ((match_flag & NHS_NST_EQ_G_GT) == NHS_NST_EQ_G_GT) {
427 				rval = 1;
428 				goto out;
429 			}
430 		}
431 		goto out;
432 	}
433 
434 	/* Looking for name, setno, timestamp, and genid match */
435 	if ((match_flag & NHS_NSTG_EQ) == NHS_NSTG_EQ)
436 		rval = 1;
437 
438 out:
439 	/*
440 	 * Set record structure was allocated from RPC routine getset
441 	 * so this structure is only of size md_set_record even if
442 	 * the MN flag is set.  So, clear the flag so that the free
443 	 * code doesn't attempt to free a structure the size of
444 	 * md_mnset_record.
445 	 */
446 	sr->sr_flags &= ~MD_SR_MN;
447 	free_sr(sr);
448 
449 	return (rval);
450 }
451 
452 int
453 nodesuniq(mdsetname_t *sp, int cnt, char **strings, md_error_t *ep)
454 {
455 	int i, j;
456 	for (i = 0; i < cnt; i++)
457 		for (j = i + 1; j < cnt; j++)
458 			if (strcmp(strings[i], strings[j]) == 0)
459 				return (mddserror(ep, MDE_DS_DUPHOST,
460 				    sp->setno, strings[i], NULL, sp->setname));
461 	return (0);
462 }
463 
464 int
465 own_set(mdsetname_t *sp, char **owner_of_set, int forceflg, md_error_t *ep)
466 {
467 	md_set_desc		*sd;
468 	int			am_i_owner;
469 	int			i;
470 
471 	if (metaislocalset(sp)) {
472 		if (owner_of_set != NULL)
473 			*owner_of_set = Strdup(mynode());
474 		return (MD_SETOWNER_YES);
475 	}
476 
477 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
478 		return (-1);
479 
480 	if (clnt_ownset(mynode(), sp, &am_i_owner, ep) == -1)
481 		return (-1);
482 
483 	if (MD_MNSET_DESC(sd)) {
484 		if (am_i_owner == TRUE)
485 			return (MD_SETOWNER_YES);
486 		else
487 			return (MD_SETOWNER_NO);
488 	}
489 
490 	if (forceflg == TRUE) {
491 		if (am_i_owner == TRUE) {
492 			if (owner_of_set != NULL)
493 				*owner_of_set = Strdup(mynode());
494 			return (MD_SETOWNER_YES);
495 		}
496 
497 		if (owner_of_set != NULL)
498 			*owner_of_set = NULL;
499 		return (MD_SETOWNER_NONE);
500 	}
501 
502 	if (am_i_owner == TRUE) {
503 		if (owner_of_set != NULL)
504 			*owner_of_set = Strdup(mynode());
505 		return (MD_SETOWNER_YES);
506 	}
507 
508 
509 	for (i = 0; i < MD_MAXSIDES; i++) {
510 		/*
511 		 * Skip empty slots, and my own slot.
512 		 */
513 		if (sd->sd_nodes[i][0] == '\0' ||
514 		    strcmp(sd->sd_nodes[i], mynode()) == 0)
515 			continue;
516 
517 		if (clnt_ownset(sd->sd_nodes[i], sp, &am_i_owner, ep) == -1)
518 			return (-1);
519 
520 		if (am_i_owner == TRUE) {
521 			if (owner_of_set != NULL)
522 				*owner_of_set = Strdup(sd->sd_nodes[i]);
523 			return (MD_SETOWNER_NO);
524 		}
525 	}
526 
527 	/* We get here, we currently have no owner. */
528 	if (owner_of_set != NULL)
529 		*owner_of_set = NULL;
530 	return (MD_SETOWNER_NONE);
531 }
532 
533 void
534 resync_genid(
535 	mdsetname_t		*sp,
536 	md_set_desc		*sd,
537 	ulong_t			max_genid,
538 	int			node_c,
539 	char			**node_v
540 )
541 {
542 	int			i, j;
543 	ulong_t			cur_genid[MD_MAXSIDES];
544 	md_set_record		*sr;
545 	md_error_t		xep = mdnullerror;
546 	md_mnnode_desc		*nd;
547 	md_mnset_record		*mnsr;
548 
549 	if (node_c > 0 && node_v && *node_v) {
550 		/*
551 		 * Mark the set record MD_SR_OK.
552 		 */
553 		for (i = 0; i < node_c; i++)
554 			if (clnt_upd_sr_flags(node_v[i], sp, MD_SR_OK, &xep))
555 				mdclrerror(&xep);
556 		max_genid++;
557 	}
558 
559 	if (MD_MNSET_DESC(sd)) {
560 		nd = sd->sd_nodelist;
561 		while (nd) {
562 			if (!(nd->nd_flags & MD_MN_NODE_ALIVE)) {
563 				nd = nd->nd_next;
564 				continue;
565 			}
566 			/* Will only return a multi-node diskset record */
567 			if (clnt_mngetset(nd->nd_nodename, sp->setname,
568 			    MD_SET_BAD, &mnsr, &xep) == -1) {
569 				mdclrerror(&xep);
570 				nd = nd->nd_next;
571 				continue;
572 			}
573 			for (j = mnsr->sr_genid; j < max_genid; j++) {
574 				if (clnt_upd_sr_flags(nd->nd_nodename, sp,
575 				    MD_SR_OK, &xep))
576 					mdclrerror(&xep);
577 			}
578 			free_sr((struct md_set_record *)mnsr);
579 			nd = nd->nd_next;
580 		}
581 		return;
582 	}
583 
584 	/*
585 	 * Get current genid for each node.
586 	 */
587 	for (i = 0; i < MD_MAXSIDES; i++) {
588 		cur_genid[i] = 0;
589 
590 		/* Skip empty slots */
591 		if (sd->sd_nodes[i][0] == '\0')
592 			continue;
593 
594 		/* Should be a non-multinode diskset */
595 		if (clnt_getset(sd->sd_nodes[i], sp->setname,
596 		    MD_SET_BAD, &sr, &xep) == -1) {
597 			mdclrerror(&xep);
598 			continue;
599 		}
600 
601 		if (MD_MNSET_REC(sr)) {
602 			/*
603 			 * Set record structure was allocated from RPC routine
604 			 * getset so this structure is only of size
605 			 * md_set_record even if the MN flag is set.  So,
606 			 * clear the flag so that the free code doesn't
607 			 * attempt to free a structure the size of
608 			 * md_mnset_record.
609 			 */
610 			sr->sr_flags &= ~MD_SR_MN;
611 			free_sr(sr);
612 			continue;
613 		}
614 
615 		cur_genid[i] = sr->sr_genid;
616 
617 		free_sr(sr);
618 	}
619 
620 	/*
621 	 * Mark the set record MD_SR_OK
622 	 */
623 	for (i = 0; i < MD_MAXSIDES; i++) {
624 		/* Skip empty slots */
625 		if (sd->sd_nodes[i][0] == '\0')
626 			continue;
627 
628 		for (j = cur_genid[i]; j < max_genid; j++)
629 			if (clnt_upd_sr_flags(sd->sd_nodes[i], sp, MD_SR_OK,
630 			    &xep))
631 				mdclrerror(&xep);
632 
633 	}
634 }
635 
636 int
637 setup_db_bydd(mdsetname_t *sp, md_drive_desc *dd, int force, md_error_t *ep)
638 {
639 	md_drive_desc		*p;
640 	struct mddb_config	c;
641 	int			i;
642 	md_set_desc		*sd;
643 	int			use_devid = 1;
644 	ddi_devid_t		devidp, new_devidp;
645 	char			*minor_name = NULL;
646 	size_t			sz;
647 	char			*devid_str = NULL;
648 	int			need_to_free_devidp = 0;
649 
650 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
651 		return (-1);
652 	(void) memset(&c, 0, sizeof (c));
653 
654 	c.c_setno = sp->setno;
655 	(void) strcpy(c.c_setname, sp->setname);
656 	if ((c.c_sideno = getmyside(sp, ep)) == MD_SIDEWILD)
657 		return (-1);
658 
659 	c.c_timestamp = sd->sd_ctime;
660 
661 	if (setup_med_cfg(sp, &c, force, ep))
662 		return (-1);
663 
664 	for (p = dd; p != NULL; p = p->dd_next) {
665 		mddrivename_t	*dnp;
666 		mdname_t	*np;
667 		mdcinfo_t	*cinfo;
668 		mdsidenames_t	*sn = NULL;
669 
670 		if (p->dd_dbcnt == 0)
671 			continue;
672 
673 		dnp = p->dd_dnp;
674 
675 		assert(dnp != NULL);
676 
677 		for (sn = dnp->side_names; sn != NULL; sn = sn->next) {
678 			if (sn->sideno == c.c_sideno)
679 				break;
680 		}
681 
682 		/*
683 		 * The disk has no side name information
684 		 */
685 		if (sn == NULL) {
686 			uint_t	rep_slice;
687 
688 			if ((meta_replicaslice(dnp, &rep_slice, ep) != 0) ||
689 			    ((np = metaslicename(dnp, rep_slice, ep))
690 				== NULL)) {
691 				mdclrerror(ep);
692 				continue;
693 			}
694 
695 			if (np->dev == NODEV64)
696 				continue;
697 
698 			c.c_locator.l_dev = meta_cmpldev(np->dev);
699 			c.c_locator.l_mnum = meta_getminor(np->dev);
700 
701 			if (!MD_MNSET_DESC(sd)) {
702 				/*
703 				 * minor_name will be NULL if dnp->devid == NULL
704 				 * - see metagetvtoc()
705 				 */
706 				if (np->minor_name != NULL) {
707 					minor_name = Strdup(np->minor_name);
708 				}
709 			}
710 
711 			if ((cinfo = metagetcinfo(np, ep)) == NULL) {
712 				mdclrerror(ep);
713 				continue;
714 			}
715 
716 			(void) strncpy(c.c_locator.l_driver, cinfo->dname,
717 			    sizeof (c.c_locator.l_driver));
718 		} else {
719 			c.c_locator.l_dev = NODEV32;
720 			c.c_locator.l_mnum = sn->mnum;
721 			(void) strncpy(c.c_locator.l_driver, sn->dname,
722 			    sizeof (c.c_locator.l_driver));
723 
724 			if (!MD_MNSET_DESC(sd)) {
725 				if (dnp->devid != NULL) {
726 					minor_name = meta_getdidminorbykey(
727 					    MD_LOCAL_SET, sn->sideno + SKEW,
728 					    dnp->side_names_key, ep);
729 				}
730 			}
731 		}
732 
733 		if ((dnp->devid == NULL) || MD_MNSET_DESC(sd)) {
734 			use_devid = 0;
735 		}
736 
737 		if (use_devid) {
738 			/*
739 			 * The devid associated with the dnp does not have
740 			 * a minor name and so we must add it in.
741 			 */
742 			size_t	len = strlen(dnp->devid) +
743 			    strlen(minor_name) + 2;
744 			devid_str = (char *)Malloc(len);
745 			(void) snprintf(devid_str, len, "%s/%s", dnp->devid,
746 			    minor_name);
747 			(void) devid_str_decode(devid_str, &devidp, NULL);
748 			need_to_free_devidp = 1;
749 
750 			/* If need to fix LB then setup old_devid info */
751 			if (p->dd_flags & MD_DR_FIX_LB_NM_DID) {
752 				sz = devid_sizeof(devidp);
753 				c.c_locator.l_old_devid_sz = sz;
754 				c.c_locator.l_old_devid = (uintptr_t)malloc(sz);
755 				(void) memcpy((void *)(uintptr_t)
756 				    c.c_locator.l_old_devid,
757 				    devidp, sz);
758 
759 				new_devidp = replicated_list_lookup(
760 				    devid_sizeof((ddi_devid_t)devidp),
761 				    (void *)(uintptr_t)devidp);
762 				devid_free(devidp);
763 				need_to_free_devidp = 0;
764 				devidp = new_devidp;
765 
766 			}
767 			sz = devid_sizeof(devidp);
768 			c.c_locator.l_devid = (uintptr_t)malloc(sz);
769 			c.c_locator.l_devid_sz = sz;
770 			(void) memcpy((void *)(uintptr_t)
771 			    c.c_locator.l_devid,
772 			    devidp, sz);
773 			if (need_to_free_devidp) {
774 				devid_free(devidp);
775 				need_to_free_devidp = 0;
776 			}
777 			if (minor_name == NULL) {
778 				/* ERROR fix up */
779 				Free(devid_str);
780 				Free((void *)(uintptr_t)c.c_locator.l_devid);
781 				if (c.c_locator.l_old_devid_sz) {
782 					Free((void *)
783 					    (uintptr_t)c.c_locator.l_old_devid);
784 					c.c_locator.l_old_devid_sz = 0;
785 					c.c_locator.l_old_devid =
786 						(uintptr_t)NULL;
787 				}
788 				return (-1);
789 			}
790 			(void) strcpy(c.c_locator.l_minor_name,
791 			    minor_name);
792 			c.c_locator.l_devid_flags = MDDB_DEVID_VALID |
793 			    MDDB_DEVID_SPACE | MDDB_DEVID_SZ;
794 		} else {
795 			/*
796 			 * Don't need device id information from
797 			 * this ioctl
798 			 */
799 			c.c_locator.l_devid = (uint64_t)0;
800 			c.c_locator.l_devid_flags = 0;
801 		}
802 
803 
804 		for (i = 0; i < p->dd_dbcnt; i++) {
805 			c.c_locator.l_flags = 0;
806 			c.c_locator.l_blkno = 16 + i * p->dd_dbsize;
807 
808 			if (metaioctl(MD_DB_USEDEV, &c, &c.c_mde, NULL) != 0) {
809 				if (use_devid) {
810 					Free(devid_str);
811 					Free((void *)
812 					    (uintptr_t)c.c_locator.l_devid);
813 					if (c.c_locator.l_old_devid_sz) {
814 						Free((void *)(uintptr_t)
815 						    c.c_locator.l_old_devid);
816 						c.c_locator.l_old_devid_sz = 0;
817 						c.c_locator.l_old_devid =
818 						    (uintptr_t)NULL;
819 					}
820 				}
821 				Free(minor_name);
822 				return (mdstealerror(ep, &c.c_mde));
823 			}
824 		}
825 		if (use_devid) {
826 			Free(devid_str);
827 			Free((void *)(uintptr_t)c.c_locator.l_devid);
828 			if (c.c_locator.l_old_devid_sz) {
829 				Free((void *)
830 				    (uintptr_t)c.c_locator.l_old_devid);
831 				c.c_locator.l_old_devid_sz = 0;
832 				c.c_locator.l_old_devid = (uintptr_t)NULL;
833 			}
834 		}
835 		Free(minor_name);
836 	}
837 
838 	/* return success */
839 	return (0);
840 }
841 
842 int
843 snarf_set(mdsetname_t *sp, bool_t stale_bool, md_error_t *ep)
844 {
845 	mddb_config_t	c;
846 
847 	(void) memset(&c, '\0', sizeof (c));
848 
849 	c.c_setno = sp->setno;
850 	if ((c.c_sideno = getmyside(sp, ep)) == MD_SIDEWILD)
851 		return (-1);
852 
853 	/* Don't need device id information from this ioctl */
854 	c.c_locator.l_devid = (uint64_t)0;
855 	c.c_locator.l_devid_flags = 0;
856 	if (stale_bool == TRUE) {
857 		c.c_flags = MDDB_C_STALE;
858 	}
859 	if (metaioctl(MD_GRAB_SET, &c, &c.c_mde, NULL) != 0)
860 		return (mdstealerror(ep, &c.c_mde));
861 
862 	if (c.c_flags & MDDB_C_STALE)
863 		return (mdmddberror(ep, MDE_DB_STALE, (minor_t)NODEV64,
864 		    sp->setno, 0, NULL));
865 
866 	return (0);
867 }
868