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 #include <sdssc.h> 39 40 /* 41 * Exported Entry Points 42 */ 43 44 int 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) && (!(MD_MNSET_DESC(sd)))) { 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 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 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 * 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 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 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 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 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 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; 646 char *minor_name = NULL; 647 size_t sz; 648 char *devid_str = NULL; 649 sdssc_version_t version; 650 651 if ((sd = metaget_setdesc(sp, ep)) == NULL) 652 return (-1); 653 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 758 sz = devid_sizeof(devidp); 759 c.c_locator.l_devid = (uintptr_t)malloc(sz); 760 c.c_locator.l_devid_sz = sz; 761 (void) memcpy((void *)(uintptr_t)c.c_locator.l_devid, 762 devidp, sz); 763 if (minor_name == NULL) { 764 /* ERROR fix up */ 765 Free(devid_str); 766 return (-1); 767 } 768 (void) strcpy(c.c_locator.l_minor_name, minor_name); 769 c.c_locator.l_devid_flags = MDDB_DEVID_VALID | 770 MDDB_DEVID_SPACE | MDDB_DEVID_SZ; 771 } else { 772 /* 773 * Don't need device id information from 774 * this ioctl 775 */ 776 c.c_locator.l_devid = (uint64_t)0; 777 c.c_locator.l_devid_flags = 0; 778 } 779 780 781 for (i = 0; i < p->dd_dbcnt; i++) { 782 c.c_locator.l_flags = 0; 783 c.c_locator.l_blkno = 16 + i * p->dd_dbsize; 784 785 if (metaioctl(MD_DB_USEDEV, &c, &c.c_mde, NULL) != 0) { 786 if (use_devid) { 787 Free(devid_str); 788 } 789 Free(minor_name); 790 return (mdstealerror(ep, &c.c_mde)); 791 } 792 } 793 if (use_devid) { 794 Free(devid_str); 795 } 796 Free(minor_name); 797 } 798 799 /* return success */ 800 return (0); 801 } 802 803 int 804 snarf_set(mdsetname_t *sp, bool_t stale_bool, md_error_t *ep) 805 { 806 mddb_config_t c; 807 808 (void) memset(&c, '\0', sizeof (c)); 809 810 c.c_setno = sp->setno; 811 if ((c.c_sideno = getmyside(sp, ep)) == MD_SIDEWILD) 812 return (-1); 813 814 /* Don't need device id information from this ioctl */ 815 c.c_locator.l_devid = (uint64_t)0; 816 c.c_locator.l_devid_flags = 0; 817 if (stale_bool == TRUE) { 818 c.c_flags = MDDB_C_STALE; 819 } 820 if (metaioctl(MD_GRAB_SET, &c, &c.c_mde, NULL) != 0) 821 return (mdstealerror(ep, &c.c_mde)); 822 823 if (c.c_flags & MDDB_C_STALE) 824 return (mdmddberror(ep, MDE_DB_STALE, (minor_t)NODEV64, 825 sp->setno, 0, NULL)); 826 827 return (0); 828 } 829