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