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 = (uint64_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 = (uint64_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 int 396 add_name( 397 mdsetname_t *sp, 398 side_t sideno, 399 mdkey_t key, 400 char *dname, 401 minor_t mnum, 402 char *bname, 403 md_error_t *ep 404 ) 405 { 406 struct mdnm_params nm; 407 408 (void) memset(&nm, '\0', sizeof (nm)); 409 nm.setno = sp->setno; 410 nm.side = sideno; 411 nm.key = key; 412 nm.mnum = mnum; 413 (void) strncpy(nm.drvnm, dname, sizeof (nm.drvnm)); 414 nm.devname_len = strlen(bname) + 1; 415 nm.devname = (uintptr_t)bname; 416 417 if (metaioctl(MD_IOCSET_NM, &nm, &nm.mde, bname) < 0) 418 return (mdstealerror(ep, &nm.mde)); 419 420 return (nm.key); 421 } 422 423 /* 424 * Remove the device name which corresponds to the given device number. 425 */ 426 int 427 del_name( 428 mdsetname_t *sp, 429 side_t sideno, 430 mdkey_t key, 431 md_error_t *ep 432 ) 433 { 434 struct mdnm_params nm; 435 436 (void) memset(&nm, '\0', sizeof (nm)); 437 nm.setno = sp->setno; 438 nm.side = sideno; 439 nm.key = key; 440 441 if (metaioctl(MD_IOCREM_NM, &nm, &nm.mde, NULL) != 0) 442 return (mdstealerror(ep, &nm.mde)); 443 444 return (0); 445 } 446 447 static void 448 empty_devicelist() 449 { 450 side_t sideno; 451 452 for (sideno = 0; sideno < MD_MNMAXSIDES; sideno++) { 453 if (devlist[sideno].bname != (char *)NULL) { 454 Free(devlist[sideno].bname); 455 Free(devlist[sideno].dname); 456 devlist[sideno].mnum = NODEV; 457 } 458 } 459 } 460 461 static void 462 add_to_devicelist( 463 side_t sideno, 464 char *bname, 465 char *dname, 466 minor_t mnum 467 ) 468 { 469 devlist[sideno].bname = Strdup(bname); 470 devlist[sideno].dname = Strdup(dname); 471 472 devlist[sideno].mnum = mnum; 473 } 474 475 /* 476 * Build a list of the names on the systems, if this fails the caller 477 * will tidy up the entries in the devlist. 478 */ 479 static int 480 build_sidenamelist( 481 mdsetname_t *sp, 482 mdname_t *np, 483 md_error_t *ep 484 ) 485 { 486 side_t sideno = MD_SIDEWILD; 487 minor_t mnum = NODEV; 488 char *bname = NULL; 489 char *dname = NULL; 490 int err; 491 492 /*CONSTCOND*/ 493 while (1) { 494 495 if ((err = meta_getnextside_devinfo(sp, np->bname, &sideno, 496 &bname, &dname, &mnum, ep)) == -1) 497 return (-1); 498 499 if (err == 0) 500 break; 501 502 /* the sideno gives us the index into the array */ 503 add_to_devicelist(sideno, bname, dname, mnum); 504 } 505 return (0); 506 } 507 508 /* 509 * add name key 510 * the meta_create* functions should be the only ones using this. The 511 * adding of a name to the namespace must be done in a particular order 512 * to devid support for the disksets. The order is: add the 'local' side 513 * first of all, so the devid lookup in the kernel will use the correct 514 * device information and then add in the other sides. 515 */ 516 int 517 add_key_name( 518 mdsetname_t *sp, 519 mdname_t *np, 520 mdnamelist_t **nlpp, 521 md_error_t *ep 522 ) 523 { 524 int err; 525 side_t sideno = MD_SIDEWILD; 526 side_t thisside; 527 mdkey_t key = MD_KEYWILD; 528 md_set_desc *sd; 529 int maxsides; 530 531 /* should have a set */ 532 assert(sp != NULL); 533 534 if (! metaislocalset(sp)) { 535 if ((sd = metaget_setdesc(sp, ep)) == NULL) { 536 return (-1); 537 } 538 } 539 540 if (build_sidenamelist(sp, np, ep) == -1) { 541 empty_devicelist(); 542 return (-1); 543 } 544 545 /* 546 * When a disk is added into the namespace the local information for 547 * that disk is added in first of all. For the local set this is not 548 * a concern and for the host that owns the diskset it is not a concern 549 * but when a disk is added in the remote namespace we *must* use the 550 * local information for that disk first of all. This is because when 551 * in the kernel (md_setdevname) the passed in dev_t is used to find 552 * the devid of the disk. This means we have to cater for the following: 553 * 554 * - a disk on the remote host having the dev_t that has been passed 555 * into the kernel and this disk is not actually the disk that is 556 * being added into the diskset. 557 * - the dev_t does not exist on this node 558 * 559 * So putting in the local information first of all makes sure that the 560 * dev_t passed into the kernel is correct with respect to that node 561 * and then any further additions for that name match on the key 562 * passed back. 563 */ 564 thisside = getmyside(sp, ep); 565 566 if (devlist[thisside].dname == NULL || 567 strlen(devlist[thisside].dname) == 0) { 568 /* 569 * Did not find the disk information for the disk. This can 570 * be because of an inconsistancy in the namespace: that is the 571 * devid we have in the namespace does not exist on the 572 * system and thus when looking up the disk information 573 * using this devid we fail to find anything. 574 */ 575 (void) mdcomperror(ep, MDE_SP_COMP_OPEN_ERR, 0, np->dev, 576 np->cname); 577 empty_devicelist(); 578 return (-1); 579 } 580 581 if ((err = add_name(sp, thisside, key, devlist[thisside].dname, 582 devlist[thisside].mnum, devlist[thisside].bname, ep)) == -1) { 583 empty_devicelist(); 584 return (-1); 585 } 586 587 /* We now have a 'key' so add in the other sides */ 588 key = (mdkey_t)err; 589 590 if (metaislocalset(sp)) 591 goto done; 592 593 if (MD_MNSET_DESC(sd)) 594 maxsides = MD_MNMAXSIDES; 595 else 596 maxsides = MD_MAXSIDES; 597 598 for (sideno = 0; sideno < maxsides; sideno++) { 599 /* ignore thisside, as it has been added above */ 600 if (sideno == thisside) 601 continue; 602 603 if (devlist[sideno].dname != NULL) { 604 err = add_name(sp, sideno, key, devlist[sideno].dname, 605 devlist[sideno].mnum, devlist[sideno].bname, ep); 606 if (err == -1) { 607 empty_devicelist(); 608 return (-1); 609 } 610 } 611 } 612 613 done: 614 empty_devicelist(); 615 /* save key, return success */ 616 np->key = key; 617 if (nlpp != NULL) 618 (void) metanamelist_append(nlpp, np); 619 return (0); 620 } 621 622 /* 623 * delete name key 624 * the meta_create* functions should be the only ones using this. The 625 * removal of the names must be done in a particular order: remove the 626 * non-local entries first of all and then finally the local entry. 627 */ 628 int 629 del_key_name( 630 mdsetname_t *sp, 631 mdname_t *np, 632 md_error_t *ep 633 ) 634 { 635 side_t sideno = MD_SIDEWILD; 636 int err; 637 int retval = 0; 638 side_t thisside; 639 640 /* should have a set */ 641 assert(sp != NULL); 642 643 /* should have a key */ 644 assert((np->key != MD_KEYWILD) && (np->key != MD_KEYBAD)); 645 646 thisside = getmyside(sp, ep); 647 648 /* remove the remote sides first of all */ 649 for (;;) { 650 if ((err = meta_getnextside_devinfo(sp, np->bname, &sideno, 651 NULL, NULL, NULL, ep)) == -1) 652 return (-1); 653 654 if (err == 0) 655 break; 656 657 /* ignore thisside */ 658 if (thisside == sideno) { 659 continue; 660 } 661 if ((err = del_name(sp, sideno, np->key, ep)) == -1) 662 retval = -1; 663 } 664 665 /* now remove this side */ 666 if (retval == 0) 667 if ((err = del_name(sp, thisside, np->key, ep)) == -1) 668 retval = -1; 669 670 np->key = MD_KEYBAD; 671 return (retval); 672 } 673 674 /* 675 * delete namelist keys 676 * the meta_create* functions should be the only ones using this 677 */ 678 int 679 del_key_names( 680 mdsetname_t *sp, 681 mdnamelist_t *nlp, 682 md_error_t *ep 683 ) 684 { 685 mdnamelist_t *p; 686 md_error_t status = mdnullerror; 687 int rval = 0; 688 689 /* if ignoring errors */ 690 if (ep == NULL) 691 ep = &status; 692 693 /* delete names */ 694 for (p = nlp; (p != NULL); p = p->next) { 695 mdname_t *np = p->namep; 696 697 if (del_key_name(sp, np, ep) != 0) 698 rval = -1; 699 } 700 701 /* cleanup, return success */ 702 if (ep == &status) 703 mdclrerror(&status); 704 return (rval); 705 } 706 707 708 /* 709 * This routine when is called will store the metadevice name 710 * when it is first created 711 */ 712 mdkey_t 713 add_self_name( 714 mdsetname_t *sp, 715 char *uname, 716 md_mkdev_params_t *params, 717 md_error_t *ep 718 ) 719 { 720 char *p, *devname; 721 side_t myside, side; 722 mdkey_t key; 723 md_set_desc *sd; 724 int len; 725 char *drvname = params->md_driver.md_drivername; 726 minor_t minor = MD_MKMIN(sp->setno, params->un); 727 md_mnnode_desc *mnside; 728 729 p = strrchr(uname, '/'); 730 p = (p == NULL? uname : ++p); 731 732 /* 733 * The valid qualified name 734 */ 735 if (metaislocalset(sp)) { 736 len = strlen(p) + strlen("/dev/md/dsk/") + 1; 737 devname = Malloc(len); 738 (void) strcpy(devname, "/dev/md/dsk/"); 739 (void) strcat(devname, p); 740 } else { 741 len = strlen(sp->setname) + strlen(p) + 742 strlen("/dev/md//dsk/") + 1; 743 devname = Malloc(len); 744 (void) snprintf(devname, len, "/dev/md/%s/dsk/%s", 745 sp->setname, p); 746 } 747 748 /* 749 * Add self to the namespace 750 */ 751 if ((myside = getmyside(sp, ep)) == MD_SIDEWILD) { 752 Free(devname); 753 return (-1); 754 } 755 756 if (metaislocalset(sp)) { 757 if ((key = add_name(sp, myside, MD_KEYWILD, drvname, 758 minor, devname, ep)) == MD_KEYBAD) { 759 Free(devname); 760 return (-1); 761 } 762 } else { 763 /* 764 * Add myside first and use the returned key to add other sides 765 */ 766 if ((key = add_name(sp, myside, MD_KEYWILD, drvname, 767 minor, devname, ep)) == MD_KEYBAD) { 768 Free(devname); 769 return (-1); 770 } 771 772 /* 773 * Add for all other sides 774 */ 775 if ((sd = metaget_setdesc(sp, ep)) == NULL) { 776 Free(devname); 777 return (-1); 778 } 779 780 if (MD_MNSET_DESC(sd)) { 781 for (mnside = sd->sd_nodelist; mnside != NULL; 782 mnside = mnside->nd_next) { 783 if (mnside->nd_nodeid == myside) 784 continue; 785 if (add_name(sp, mnside->nd_nodeid, key, drvname, 786 minor, devname, ep) == -1) { 787 Free(devname); 788 return (-1); 789 } 790 } 791 } else { 792 for (side = 0; side < MD_MAXSIDES; side++) { 793 if (sd->sd_nodes[side][0] == '\0') 794 continue; 795 if (side == myside) 796 continue; 797 if (add_name(sp, side, key, drvname, minor, devname, 798 ep) == -1) { 799 Free(devname); 800 return (-1); 801 } 802 } 803 } 804 } 805 806 Free(devname); 807 return (key); 808 } 809 810 811 /* 812 * This routine when is called will remove the metadevice name 813 * from the namespace and it is the last thing to do in the 814 * metaclear operation 815 */ 816 int 817 del_self_name( 818 mdsetname_t *sp, 819 mdkey_t key, 820 md_error_t *ep 821 ) 822 { 823 side_t myside; 824 int rval = 0; 825 side_t side; 826 md_set_desc *sd; 827 md_mnnode_desc *mnside; 828 829 assert(key != MD_KEYBAD); 830 831 if ((myside = getmyside(sp, ep)) == MD_SIDEWILD) 832 return (-1); 833 834 if (metaislocalset(sp)) { 835 rval = del_name(sp, myside, key, ep); 836 } else { 837 /* 838 * Remove all other sides first 839 */ 840 if ((sd = metaget_setdesc(sp, ep)) == NULL) { 841 return (-1); 842 } 843 844 if (MD_MNSET_DESC(sd)) { 845 for (mnside = sd->sd_nodelist; mnside != NULL; 846 mnside = mnside->nd_next) { 847 if (mnside->nd_nodeid == myside) 848 continue; 849 if ((rval = del_name(sp, mnside->nd_nodeid, key, 850 ep)) == -1) { 851 goto out; 852 } 853 } 854 } else { 855 for (side = 0; side < MD_MAXSIDES; side++) { 856 if (sd->sd_nodes[side][0] == '\0') 857 continue; 858 if (side == myside) 859 continue; 860 if ((rval = del_name(sp, side, key, ep)) == -1) { 861 goto out; 862 } 863 } 864 } 865 866 /* 867 * del myside 868 */ 869 rval = del_name(sp, myside, key, ep); 870 } 871 872 out: 873 return (rval); 874 } 875