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