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 * namespace utilities 30 */ 31 32 #include <meta.h> 33 34 typedef struct deviceinfo { 35 char *bname; /* block name of the device */ 36 char *dname; /* driver for the device */ 37 minor_t mnum; /* minor number for the device */ 38 } deviceinfo_t; 39 40 static deviceinfo_t devlist[MD_MNMAXSIDES]; 41 42 /* 43 * Ask the driver for the device name, driver name, and minor number; 44 * which has been stored in the metadevice state database 45 * (on behalf of the utilities). 46 * (by key) 47 */ 48 char * 49 meta_getnmentbykey( 50 set_t setno, 51 side_t sideno, 52 mdkey_t key, 53 char **drvnm, 54 minor_t *mnum, 55 md_dev64_t *dev, 56 md_error_t *ep 57 ) 58 { 59 struct mdnm_params nm; 60 static char device_name[MAXPATHLEN]; 61 62 (void) memset(&nm, '\0', sizeof (nm)); 63 nm.setno = setno; 64 nm.side = sideno; 65 nm.key = key; 66 nm.devname = (uint64_t)device_name; 67 68 if (metaioctl(MD_IOCGET_NM, &nm, &nm.mde, NULL) != 0) { 69 (void) mdstealerror(ep, &nm.mde); 70 return (NULL); 71 } 72 73 if (drvnm != NULL) 74 *drvnm = Strdup(nm.drvnm); 75 76 if (mnum != NULL) 77 *mnum = nm.mnum; 78 79 if (dev != NULL) 80 *dev = meta_expldev(makedevice(nm.major, nm.mnum)); 81 82 return (Strdup(device_name)); 83 } 84 85 /* 86 * Ask the driver for the hsp name, driver name, and minor number; 87 * which has been stored in the metadevice state database 88 * (on behalf of the utilities). 89 * (by key) 90 */ 91 char * 92 meta_gethspnmentbyid( 93 set_t setno, 94 side_t sideno, 95 hsp_t hspid, 96 md_error_t *ep 97 ) 98 { 99 struct mdhspnm_params nm; 100 char *device_name; 101 102 device_name = Malloc(MAXPATHLEN); 103 device_name[0] = '\0'; 104 105 (void) memset(&nm, '\0', sizeof (nm)); 106 nm.setno = setno; 107 nm.side = sideno; 108 nm.hspid = hspid; 109 nm.ret_hspid = MD_HSPID_WILD; 110 nm.hspname_len = MAXPATHLEN; 111 nm.hspname = (uintptr_t)device_name; 112 113 if (metaioctl(MD_IOCGET_HSP_NM, &nm, &nm.mde, NULL) != 0) { 114 (void) mdstealerror(ep, &nm.mde); 115 Free(device_name); 116 return (NULL); 117 } 118 119 return (device_name); 120 } 121 122 /* 123 * Ask the driver for the hsp_self_id; 124 * which has been stored in the metadevice state database 125 * (on behalf of the utilities). 126 * (by hsp name) 127 */ 128 hsp_t 129 meta_gethspnmentbyname( 130 set_t setno, 131 side_t sideno, 132 char *hspname, 133 md_error_t *ep 134 ) 135 { 136 struct mdhspnm_params nm; 137 char *device_name; 138 139 /* must have a hsp name */ 140 assert(hspname != NULL); 141 142 device_name = Malloc(MAXPATHLEN); 143 (void) strcpy(device_name, hspname); 144 145 (void) memset(&nm, '\0', sizeof (nm)); 146 nm.setno = setno; 147 nm.side = sideno; 148 nm.hspid = MD_HSPID_WILD; 149 nm.ret_hspid = MD_HSPID_WILD; 150 nm.hspname_len = strlen(device_name) + 1; 151 nm.hspname = (uintptr_t)device_name; 152 153 /* 154 * The ioctl expects the a hsp name and return its hsp_self_id. 155 */ 156 if (metaioctl(MD_IOCGET_HSP_NM, &nm, &nm.mde, NULL) != 0) { 157 (void) mdstealerror(ep, &nm.mde); 158 Free(device_name); 159 return (MD_HSP_NONE); 160 } 161 162 if (nm.ret_hspid == MD_HSPID_WILD) { 163 Free(device_name); 164 return (MD_HSP_NONE); 165 } 166 167 Free(device_name); 168 return (nm.ret_hspid); 169 } 170 171 172 /* 173 * Ask the driver for the minor name which has been stored in the 174 * metadevice state database. 175 * (by key) 176 */ 177 char * 178 meta_getdidminorbykey( 179 set_t setno, 180 side_t sideno, 181 mdkey_t key, 182 md_error_t *ep 183 ) 184 { 185 struct mdnm_params nm; 186 static char minorname[MAXPATHLEN]; 187 188 (void) memset(&nm, '\0', sizeof (nm)); 189 nm.setno = setno; 190 nm.side = sideno; 191 nm.key = key; 192 nm.minorname = (uint64_t)minorname; 193 194 if (metaioctl(MD_IOCGET_DIDMIN, &nm, &nm.mde, NULL) != 0) { 195 (void) mdstealerror(ep, &nm.mde); 196 return (NULL); 197 } 198 199 return (Strdup(minorname)); 200 } 201 202 /* 203 * Ask the driver for the device id string which has been stored in the 204 * metadevice state database (on behalf of the utilities). 205 * (by key) 206 */ 207 ddi_devid_t 208 meta_getdidbykey( 209 set_t setno, 210 side_t sideno, 211 mdkey_t key, 212 md_error_t *ep 213 ) 214 { 215 struct mdnm_params nm; 216 217 (void) memset(&nm, '\0', sizeof (nm)); 218 nm.setno = setno; 219 nm.side = sideno; 220 nm.key = key; 221 222 /* 223 * First ask the driver for the size of the device id string. This is 224 * signaled by passing the driver a devid_size of zero. 225 */ 226 nm.devid_size = 0; 227 if (metaioctl(MD_IOCGET_DID, &nm, &nm.mde, NULL) != 0) { 228 (void) mdstealerror(ep, &nm.mde); 229 return (NULL); 230 } 231 232 /* 233 * If the devid_size is still zero then something is wrong. 234 */ 235 if (nm.devid_size == 0) { 236 (void) mdstealerror(ep, &nm.mde); 237 return (NULL); 238 } 239 240 /* 241 * Now go get the actual device id string. Caller is responsible for 242 * free'ing device id memory buffer. 243 */ 244 if ((nm.devid = (uintptr_t)malloc(nm.devid_size)) == NULL) { 245 return (NULL); 246 } 247 if (metaioctl(MD_IOCGET_DID, &nm, &nm.mde, NULL) != 0) { 248 (void) mdstealerror(ep, &nm.mde); 249 (void) free((void *)(uintptr_t)nm.devid); 250 return (NULL); 251 } 252 253 return ((void *)(uintptr_t)nm.devid); 254 } 255 256 /* 257 * set the devid. 258 */ 259 int 260 meta_setdid( 261 set_t setno, 262 side_t sideno, 263 mdkey_t key, 264 md_error_t *ep 265 ) 266 { 267 struct mdnm_params nm; 268 int i; 269 270 (void) memset(&nm, '\0', sizeof (nm)); 271 nm.setno = setno; 272 nm.side = sideno; 273 nm.key = key; 274 275 if (metaioctl(MD_IOCSET_DID, &nm, &nm.mde, NULL) != 0) { 276 (void) mdstealerror(ep, &nm.mde); 277 return (-1); 278 } 279 280 if (setno == MD_LOCAL_SET) { 281 /* 282 * If this is the local set then we are adding in the devids 283 * for the disks in the diskset and so this means adding 284 * a reference count for each side. Need to do this after 285 * the initial add so that the correct devid is picked up. 286 * The key is the key of the drive record and as such this 287 * means the minor number of the device which is used to 288 * get the devid. If the wrong side is used then it would 289 * be possible to get the wrong devid in the namespace, hence 290 * the requirement to process the local side first of all. 291 */ 292 for (i = 0 + SKEW; i < MD_MAXSIDES; i++) { 293 /* 294 * We can just call the ioctl again because it will 295 * fail with ENOENT if the side does not exist, and 296 * more importantly does not increment the usage count 297 * on the devid. 298 */ 299 nm.side = (side_t)i; 300 if (nm.side == sideno) 301 continue; 302 if (metaioctl(MD_IOCSET_DID, &nm, &nm.mde, NULL) != 0) { 303 if (mdissyserror(&nm.mde, ENODEV)) { 304 mdclrerror(&nm.mde); 305 } else { 306 (void) mdstealerror(ep, &nm.mde); 307 return (-1); 308 } 309 } 310 } 311 } 312 return (0); 313 } 314 /* 315 * Ask the driver for the name, which has been stored in the 316 * metadevice state database (on behalf of the utilities). 317 * (by key) 318 */ 319 char * 320 meta_getnmbykey( 321 set_t setno, 322 side_t sideno, 323 mdkey_t key, 324 md_error_t *ep 325 ) 326 { 327 return (meta_getnmentbykey(setno, sideno, key, NULL, NULL, NULL, ep)); 328 } 329 330 /* 331 * Ask the driver for the device name, driver name, minor number, and key; 332 * which has been stored in the metadevice state database 333 * (on behalf of the utilities). 334 * (by md_dev64_t) 335 */ 336 char * 337 meta_getnmentbydev( 338 set_t setno, 339 side_t sideno, 340 md_dev64_t dev, 341 char **drvnm, 342 minor_t *mnum, 343 mdkey_t *key, 344 md_error_t *ep 345 ) 346 { 347 struct mdnm_params nm; 348 static char device_name[MAXPATHLEN]; 349 350 /* must have a dev */ 351 assert(dev != NODEV64); 352 353 (void) memset(&nm, '\0', sizeof (nm)); 354 nm.setno = setno; 355 nm.side = sideno; 356 nm.key = MD_KEYWILD; 357 nm.major = meta_getmajor(dev); 358 nm.mnum = meta_getminor(dev); 359 nm.devname = (uint64_t)device_name; 360 361 if (metaioctl(MD_IOCGET_NM, &nm, &nm.mde, NULL) != 0) { 362 (void) mdstealerror(ep, &nm.mde); 363 return (NULL); 364 } 365 366 /* 367 * With the friendly name work, each metadevice will have 368 * an NM entry. However, to allow backward compatibility, 369 * systems upgraded to a friendly name release won't have 370 * NM entries for the pre-existing top level metadevices. This 371 * implementation allows users to downgrade to a pre-friendly 372 * name release since the configuration information (mddb) is 373 * not modified. 374 * 375 * meta_getnmentbydev is called to get nm entry for all metadevices 376 * and expects the minor and major number and returns a key and 377 * name. For upgraded systems with pre-existing metadevices, 378 * the only returning value will be the name since there's no nm 379 * entry for pre-friendly name top level metadevices. So a return 380 * key for the device will not be available and will be NULL. 381 * Thus, the caller is responsible for making sure the returned key 382 * is valid, not NULL. 383 */ 384 if (drvnm != NULL) 385 *drvnm = Strdup(nm.drvnm); 386 if (mnum != NULL) 387 *mnum = nm.mnum; 388 389 if (key != NULL) 390 *key = nm.retkey; 391 392 return (Strdup(device_name)); 393 } 394 395 /* 396 * The arguments, minorname and devid, are only used with the partial 397 * import code and should be NULL otherwise. 398 */ 399 int 400 add_name( 401 mdsetname_t *sp, 402 side_t sideno, 403 mdkey_t key, 404 char *dname, 405 minor_t mnum, 406 char *bname, 407 char *minorname, /* only used with a partial import */ 408 ddi_devid_t devid, /* only used with a partial import */ 409 md_error_t *ep 410 ) 411 { 412 struct mdnm_params nm; 413 414 (void) memset(&nm, '\0', sizeof (nm)); 415 nm.setno = sp->setno; 416 nm.side = sideno; 417 nm.key = key; 418 nm.mnum = mnum; 419 (void) strncpy(nm.drvnm, dname, sizeof (nm.drvnm)); 420 nm.devname_len = strlen(bname) + 1; 421 nm.devname = (uintptr_t)bname; 422 if (devid && minorname) { 423 nm.minorname_len = strlen(minorname) + 1; 424 nm.minorname = (uintptr_t)minorname; 425 nm.devid_size = devid_sizeof(devid); 426 nm.devid = (uintptr_t)devid; 427 nm.imp_flag = MDDB_C_IMPORT; 428 } 429 if (metaioctl(MD_IOCSET_NM, &nm, &nm.mde, bname) < 0) 430 return (mdstealerror(ep, &nm.mde)); 431 432 return (nm.key); 433 } 434 435 /* 436 * Remove the device name which corresponds to the given device number. 437 */ 438 int 439 del_name( 440 mdsetname_t *sp, 441 side_t sideno, 442 mdkey_t key, 443 md_error_t *ep 444 ) 445 { 446 struct mdnm_params nm; 447 448 (void) memset(&nm, '\0', sizeof (nm)); 449 nm.setno = sp->setno; 450 nm.side = sideno; 451 nm.key = key; 452 453 if (metaioctl(MD_IOCREM_NM, &nm, &nm.mde, NULL) != 0) 454 return (mdstealerror(ep, &nm.mde)); 455 456 return (0); 457 } 458 459 static void 460 empty_devicelist() 461 { 462 side_t sideno; 463 464 for (sideno = 0; sideno < MD_MNMAXSIDES; sideno++) { 465 if (devlist[sideno].bname != (char *)NULL) { 466 Free(devlist[sideno].bname); 467 Free(devlist[sideno].dname); 468 devlist[sideno].mnum = NODEV; 469 } 470 } 471 } 472 473 static void 474 add_to_devicelist( 475 side_t sideno, 476 char *bname, 477 char *dname, 478 minor_t mnum 479 ) 480 { 481 devlist[sideno].bname = Strdup(bname); 482 devlist[sideno].dname = Strdup(dname); 483 484 devlist[sideno].mnum = mnum; 485 } 486 487 /* 488 * Build a list of the names on the systems, if this fails the caller 489 * will tidy up the entries in the devlist. 490 */ 491 static int 492 build_sidenamelist( 493 mdsetname_t *sp, 494 mdname_t *np, 495 md_error_t *ep 496 ) 497 { 498 side_t sideno = MD_SIDEWILD; 499 minor_t mnum = NODEV; 500 char *bname = NULL; 501 char *dname = NULL; 502 int err; 503 504 /*CONSTCOND*/ 505 while (1) { 506 507 if ((err = meta_getnextside_devinfo(sp, np->bname, &sideno, 508 &bname, &dname, &mnum, ep)) == -1) 509 return (-1); 510 511 if (err == 0) 512 break; 513 514 /* the sideno gives us the index into the array */ 515 add_to_devicelist(sideno, bname, dname, mnum); 516 } 517 return (0); 518 } 519 520 /* 521 * add name key 522 * the meta_create* functions should be the only ones using this. The 523 * adding of a name to the namespace must be done in a particular order 524 * to devid support for the disksets. The order is: add the 'local' side 525 * first of all, so the devid lookup in the kernel will use the correct 526 * device information and then add in the other sides. 527 */ 528 int 529 add_key_name( 530 mdsetname_t *sp, 531 mdname_t *np, 532 mdnamelist_t **nlpp, 533 md_error_t *ep 534 ) 535 { 536 int err; 537 side_t sideno = MD_SIDEWILD; 538 side_t thisside; 539 mdkey_t key = MD_KEYWILD; 540 md_set_desc *sd; 541 int maxsides; 542 543 /* should have a set */ 544 assert(sp != NULL); 545 546 if (! metaislocalset(sp)) { 547 if ((sd = metaget_setdesc(sp, ep)) == NULL) { 548 return (-1); 549 } 550 } 551 552 if (build_sidenamelist(sp, np, ep) == -1) { 553 empty_devicelist(); 554 return (-1); 555 } 556 557 /* 558 * When a disk is added into the namespace the local information for 559 * that disk is added in first of all. For the local set this is not 560 * a concern and for the host that owns the diskset it is not a concern 561 * but when a disk is added in the remote namespace we *must* use the 562 * local information for that disk first of all. This is because when 563 * in the kernel (md_setdevname) the passed in dev_t is used to find 564 * the devid of the disk. This means we have to cater for the following: 565 * 566 * - a disk on the remote host having the dev_t that has been passed 567 * into the kernel and this disk is not actually the disk that is 568 * being added into the diskset. 569 * - the dev_t does not exist on this node 570 * 571 * So putting in the local information first of all makes sure that the 572 * dev_t passed into the kernel is correct with respect to that node 573 * and then any further additions for that name match on the key 574 * passed back. 575 */ 576 thisside = getmyside(sp, ep); 577 578 if (devlist[thisside].dname == NULL || 579 strlen(devlist[thisside].dname) == 0) { 580 /* 581 * Did not find the disk information for the disk. This can 582 * be because of an inconsistancy in the namespace: that is the 583 * devid we have in the namespace does not exist on the 584 * system and thus when looking up the disk information 585 * using this devid we fail to find anything. 586 */ 587 (void) mdcomperror(ep, MDE_SP_COMP_OPEN_ERR, 0, np->dev, 588 np->cname); 589 empty_devicelist(); 590 return (-1); 591 } 592 593 if ((err = add_name(sp, thisside, key, devlist[thisside].dname, 594 devlist[thisside].mnum, devlist[thisside].bname, NULL, 595 NULL, ep)) == -1) { 596 empty_devicelist(); 597 return (-1); 598 } 599 600 /* We now have a 'key' so add in the other sides */ 601 key = (mdkey_t)err; 602 603 if (metaislocalset(sp)) 604 goto done; 605 606 if (MD_MNSET_DESC(sd)) 607 maxsides = MD_MNMAXSIDES; 608 else 609 maxsides = MD_MAXSIDES; 610 611 for (sideno = 0; sideno < maxsides; sideno++) { 612 /* ignore thisside, as it has been added above */ 613 if (sideno == thisside) 614 continue; 615 616 if (devlist[sideno].dname != NULL) { 617 err = add_name(sp, sideno, key, devlist[sideno].dname, 618 devlist[sideno].mnum, devlist[sideno].bname, 619 NULL, NULL, ep); 620 if (err == -1) { 621 empty_devicelist(); 622 return (-1); 623 } 624 } 625 } 626 627 done: 628 empty_devicelist(); 629 /* save key, return success */ 630 np->key = key; 631 if (nlpp != NULL) 632 (void) metanamelist_append(nlpp, np); 633 return (0); 634 } 635 636 /* 637 * delete name key 638 * the meta_create* functions should be the only ones using this. The 639 * removal of the names must be done in a particular order: remove the 640 * non-local entries first of all and then finally the local entry. 641 */ 642 int 643 del_key_name( 644 mdsetname_t *sp, 645 mdname_t *np, 646 md_error_t *ep 647 ) 648 { 649 side_t sideno = MD_SIDEWILD; 650 int err; 651 int retval = 0; 652 side_t thisside; 653 654 /* should have a set */ 655 assert(sp != NULL); 656 657 /* should have a key */ 658 assert((np->key != MD_KEYWILD) && (np->key != MD_KEYBAD)); 659 660 thisside = getmyside(sp, ep); 661 662 /* remove the remote sides first of all */ 663 for (;;) { 664 if ((err = meta_getnextside_devinfo(sp, np->bname, &sideno, 665 NULL, NULL, NULL, ep)) == -1) 666 return (-1); 667 668 if (err == 0) 669 break; 670 671 /* ignore thisside */ 672 if (thisside == sideno) { 673 continue; 674 } 675 if ((err = del_name(sp, sideno, np->key, ep)) == -1) 676 retval = -1; 677 } 678 679 /* now remove this side */ 680 if (retval == 0) 681 if ((err = del_name(sp, thisside, np->key, ep)) == -1) 682 retval = -1; 683 684 np->key = MD_KEYBAD; 685 return (retval); 686 } 687 688 /* 689 * delete namelist keys 690 * the meta_create* functions should be the only ones using this 691 */ 692 int 693 del_key_names( 694 mdsetname_t *sp, 695 mdnamelist_t *nlp, 696 md_error_t *ep 697 ) 698 { 699 mdnamelist_t *p; 700 md_error_t status = mdnullerror; 701 int rval = 0; 702 703 /* if ignoring errors */ 704 if (ep == NULL) 705 ep = &status; 706 707 /* delete names */ 708 for (p = nlp; (p != NULL); p = p->next) { 709 mdname_t *np = p->namep; 710 711 if (del_key_name(sp, np, ep) != 0) 712 rval = -1; 713 } 714 715 /* cleanup, return success */ 716 if (ep == &status) 717 mdclrerror(&status); 718 return (rval); 719 } 720 721 722 /* 723 * This routine when is called will store the metadevice name 724 * when it is first created 725 */ 726 mdkey_t 727 add_self_name( 728 mdsetname_t *sp, 729 char *uname, 730 md_mkdev_params_t *params, 731 md_error_t *ep 732 ) 733 { 734 char *p, *devname; 735 side_t myside, side; 736 mdkey_t key; 737 md_set_desc *sd; 738 int len; 739 char *drvname = params->md_driver.md_drivername; 740 minor_t minor = MD_MKMIN(sp->setno, params->un); 741 md_mnnode_desc *mnside; 742 743 p = strrchr(uname, '/'); 744 if (p == NULL) 745 p = uname; 746 else 747 p++; 748 749 /* 750 * The valid qualified name 751 */ 752 if (metaislocalset(sp)) { 753 len = strlen(p) + strlen("/dev/md/dsk/") + 1; 754 devname = Malloc(len); 755 (void) strcpy(devname, "/dev/md/dsk/"); 756 (void) strcat(devname, p); 757 } else { 758 len = strlen(sp->setname) + strlen(p) + 759 strlen("/dev/md//dsk/") + 1; 760 devname = Malloc(len); 761 (void) snprintf(devname, len, "/dev/md/%s/dsk/%s", 762 sp->setname, p); 763 } 764 765 /* 766 * Add self to the namespace 767 */ 768 if ((myside = getmyside(sp, ep)) == MD_SIDEWILD) { 769 Free(devname); 770 return (-1); 771 } 772 773 if (metaislocalset(sp)) { 774 if ((key = add_name(sp, myside, MD_KEYWILD, drvname, 775 minor, devname, NULL, NULL, ep)) == MD_KEYBAD) { 776 Free(devname); 777 return (-1); 778 } 779 } else { 780 /* 781 * Add myside first and use the returned key to add other sides 782 */ 783 if ((key = add_name(sp, myside, MD_KEYWILD, drvname, 784 minor, devname, NULL, NULL, ep)) == MD_KEYBAD) { 785 Free(devname); 786 return (-1); 787 } 788 789 /* 790 * Add for all other sides 791 */ 792 if ((sd = metaget_setdesc(sp, ep)) == NULL) { 793 Free(devname); 794 return (-1); 795 } 796 797 if (MD_MNSET_DESC(sd)) { 798 for (mnside = sd->sd_nodelist; mnside != NULL; 799 mnside = mnside->nd_next) { 800 if (mnside->nd_nodeid == myside) 801 continue; 802 if (add_name(sp, mnside->nd_nodeid, key, drvname, 803 minor, devname, NULL, NULL, ep) == -1) { 804 Free(devname); 805 return (-1); 806 } 807 } 808 } else { 809 for (side = 0; side < MD_MAXSIDES; side++) { 810 if (sd->sd_nodes[side][0] == '\0') 811 continue; 812 if (side == myside) 813 continue; 814 if (add_name(sp, side, key, drvname, minor, devname, 815 NULL, NULL, ep) == -1) { 816 Free(devname); 817 return (-1); 818 } 819 } 820 } 821 } 822 823 Free(devname); 824 return (key); 825 } 826 827 828 /* 829 * This routine when is called will remove the metadevice name 830 * from the namespace and it is the last thing to do in the 831 * metaclear operation 832 */ 833 int 834 del_self_name( 835 mdsetname_t *sp, 836 mdkey_t key, 837 md_error_t *ep 838 ) 839 { 840 side_t myside; 841 int rval = 0; 842 side_t side; 843 md_set_desc *sd; 844 md_mnnode_desc *mnside; 845 846 assert(key != MD_KEYBAD); 847 848 if ((myside = getmyside(sp, ep)) == MD_SIDEWILD) 849 return (-1); 850 851 if (metaislocalset(sp)) { 852 rval = del_name(sp, myside, key, ep); 853 } else { 854 /* 855 * Remove all other sides first 856 */ 857 if ((sd = metaget_setdesc(sp, ep)) == NULL) { 858 return (-1); 859 } 860 861 if (MD_MNSET_DESC(sd)) { 862 for (mnside = sd->sd_nodelist; mnside != NULL; 863 mnside = mnside->nd_next) { 864 if (mnside->nd_nodeid == myside) 865 continue; 866 if ((rval = del_name(sp, mnside->nd_nodeid, key, 867 ep)) == -1) { 868 goto out; 869 } 870 } 871 } else { 872 for (side = 0; side < MD_MAXSIDES; side++) { 873 if (sd->sd_nodes[side][0] == '\0') 874 continue; 875 if (side == myside) 876 continue; 877 if ((rval = del_name(sp, side, key, ep)) == -1) { 878 goto out; 879 } 880 } 881 } 882 883 /* 884 * del myside 885 */ 886 rval = del_name(sp, myside, key, ep); 887 } 888 889 out: 890 return (rval); 891 } 892