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