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 #include <stdio.h> 29 #include <stdarg.h> 30 #include <ctype.h> 31 #include <sys/fcntl.h> 32 #include <sys/types.h> 33 #include <devid.h> 34 #include <ftw.h> 35 #include <string.h> 36 #include <mdiox.h> 37 #include <sys/lvm/mdio.h> 38 #include <meta.h> 39 #include <syslog.h> 40 #include <sdssc.h> 41 #include "meta_set_prv.h" 42 43 /* 44 * Just in case we're not in a build environment, make sure that 45 * TEXT_DOMAIN gets set to something. 46 */ 47 #if !defined(TEXT_DOMAIN) 48 #define TEXT_DOMAIN "SYS_TEST" 49 #endif 50 51 #define RAW_PATH 0x001 /* rdsk */ 52 #define BLOCK_PATH 0x002 /* dsk */ 53 #define DSK_TYPE 0x004 /* normal /dev/[r]dsk */ 54 #define TEST_TYPE 0x008 /* test driver path */ 55 #define DID_TYPE 0x010 /* cluster did path */ 56 #define AP_TYPE 0x020 /* should be obsolete */ 57 58 typedef struct path_list { 59 char *search_path; 60 char *search_type; 61 int path_type; 62 } path_list_t; 63 64 /* 65 * A table of the supported path types - this should ideally be generated 66 * by reading the /etc/lvm/devpath file 67 */ 68 static path_list_t plist[] = { 69 {"/dev/rdsk", DEVID_MINOR_NAME_ALL_CHR, RAW_PATH|DSK_TYPE}, 70 {"/dev/dsk", DEVID_MINOR_NAME_ALL_BLK, BLOCK_PATH|DSK_TYPE}, 71 {"/dev/did/rdsk", DEVID_MINOR_NAME_ALL_CHR, RAW_PATH|DID_TYPE}, 72 {"/dev/did/dsk", DEVID_MINOR_NAME_ALL_BLK, BLOCK_PATH|DID_TYPE}, 73 {"/dev/td/dsk", DEVID_MINOR_NAME_ALL_BLK, BLOCK_PATH|TEST_TYPE}, 74 {"/dev/td/rdsk", DEVID_MINOR_NAME_ALL_CHR, RAW_PATH|TEST_TYPE}, 75 }; 76 static int num = sizeof (plist)/sizeof (path_list_t); 77 78 static mddevopts_t dev_options = 0; 79 80 /* indicate whether to print an error message or not */ 81 static int firsttime = 1; 82 83 #define DEV_MATCH 0x1 84 #define NAME_MATCH 0x2 85 86 #define DEBUGON 1 87 #define DEBUGOFF 2 88 89 /* 90 * Debug function: to turn on devadm function debugging include DEVADM 91 * in the MD_DEBUG enviroment variable: MD_DEBUG=...,DEVADM... 92 */ 93 /*PRINTFLIKE1*/ 94 static void 95 mda_debug(char *format, ...) 96 { 97 char *p; 98 static int debug_set = 0; 99 va_list ap; 100 101 if (debug_set == 0) { 102 if (((p = getenv("MD_DEBUG")) != NULL) && 103 (strstr(p, "DEVADM") != NULL)) 104 debug_set = DEBUGON; 105 else 106 debug_set = DEBUGOFF; 107 } 108 if (debug_set == DEBUGON) { 109 va_start(ap, format); 110 (void) vfprintf(stderr, format, ap); 111 va_end(ap); 112 } 113 } 114 115 /* print error messages to the terminal or syslog */ 116 /*PRINTFLIKE1*/ 117 static void 118 mda_print(char *message, ...) 119 { 120 va_list ap; 121 122 va_start(ap, message); 123 if (dev_options & DEV_LOG) { 124 /* 125 * The program is a daemon in the sense that it 126 * is a system utility. 127 */ 128 (void) vsyslog((LOG_ERR | LOG_DAEMON), message, ap); 129 } else { 130 (void) vfprintf(stderr, message, ap); 131 } 132 va_end(ap); 133 } 134 135 /* 136 * Utility to find the correct options to use for the devid search 137 * based upon the path of the device. 138 * 139 * RETURN: 140 * -1 Error, the path passed in is not in the table 141 * >= 0 The element number for the options within the table 142 */ 143 static int 144 mda_findpath(char *path) 145 { 146 int i = 0; 147 148 for (i = 0; i < num; i++) { 149 if (strncmp(plist[i].search_path, path, 150 strlen(plist[i].search_path)) == 0) 151 return (i); 152 } 153 return (-1); 154 } 155 156 /* 157 * Utility to get the path of a device 158 */ 159 static char * 160 mda_getpath(char *devname) 161 { 162 char *ptr; 163 char *pathname; 164 size_t len; 165 166 if ((ptr = strrchr(devname, '/')) == NULL) { 167 mda_debug("Invalid format: %s\n", devname); 168 return (NULL); 169 } 170 ptr++; 171 len = strlen(devname) - strlen(ptr); 172 pathname = Malloc(len + 1); 173 (void) strncpy(pathname, devname, len); 174 pathname[len] = '\0'; 175 return (pathname); 176 } 177 178 /* 179 * update_locator_namespace -- Contains the ioctl call that will update 180 * the ctds and pathname (ie. /dev/dsk etc) within the 181 * locator block namespace. 182 * 183 * RETURN 184 * METADEVADM_ERR ioctl failed and ep is updated with the error 185 * METADEVADM_SUCCESS success 186 */ 187 static int 188 update_locator_namespace( 189 set_t setno, 190 side_t sideno, 191 char *devname, 192 md_dev64_t dev, 193 char *pname, 194 md_error_t *ep 195 ) 196 { 197 mdnm_params_t nm; 198 199 (void) memset(&nm, '\0', sizeof (nm)); 200 nm.mde = mdnullerror; 201 nm.setno = setno; 202 nm.side = sideno; 203 nm.devname = (uintptr_t)devname; 204 nm.devname_len = strlen(devname); 205 nm.devt = dev; 206 nm.pathname = (uintptr_t)pname; 207 nm.pathname_len = strlen(pname); 208 if (metaioctl(MD_IOCUPD_LOCNM, &nm, &nm.mde, NULL) != 0) { 209 (void) mdstealerror(ep, &nm.mde); 210 return (METADEVADM_ERR); 211 } 212 return (METADEVADM_SUCCESS); 213 } 214 215 /* 216 * update_namespace -- Contains the ioctl call that will update the 217 * device name and pathname in the namespace area. 218 * 219 * RETURN 220 * METADEVADM_ERR ioctl failed and ep is updated with the error 221 * METADEVADM_SUCCESS success 222 */ 223 static int 224 update_namespace( 225 set_t setno, 226 side_t sideno, 227 char *devname, 228 md_dev64_t dev, 229 mdkey_t key, 230 char *pname, 231 md_error_t *ep 232 ) 233 { 234 mdnm_params_t nm; 235 236 (void) memset(&nm, '\0', sizeof (nm)); 237 nm.mde = mdnullerror; 238 nm.setno = setno; 239 nm.side = sideno; 240 nm.devname = (uintptr_t)devname; 241 nm.devname_len = strlen(devname); 242 nm.mnum = meta_getminor(dev); 243 nm.key = key; 244 nm.pathname = (uintptr_t)pname; 245 nm.pathname_len = strlen(pname); 246 if (metaioctl(MD_IOCUPD_NM, &nm, &nm.mde, NULL) != 0) { 247 (void) mdstealerror(ep, &nm.mde); 248 return (METADEVADM_ERR); 249 } 250 return (METADEVADM_SUCCESS); 251 } 252 253 /* 254 * stripS - Strip s<digits> off the end of the ctds name if it exists 255 */ 256 static void 257 stripS(char *name) 258 { 259 char *p; 260 261 /* gobble number and 's' */ 262 p = name + strlen(name) - 1; 263 for (; (p > name); --p) { 264 if (!isdigit(*p)) 265 break; 266 } 267 268 if (*p == 's') { 269 *p = '\0'; 270 } 271 } 272 273 /* 274 * getdiskname -- to be used when scanning the input from the -u arg. 275 * This routine will strip off input that is anything but cxtxdx. 276 * ie. it will call stripS to get rid of slice info. Will also 277 * strip off /dev/dsk, /dev/rdsk, /dev/ap/dsk, /dev/ap/rdsk, 278 * /dev/did/dsk, or /dev/did/rdsk. The caller will need to free 279 * the return value. 280 * 281 * RETURN 282 * string that has the disk name in it ie. c0t0d0 283 */ 284 static char * 285 getdiskname( 286 char *name 287 ) 288 { 289 char *p; 290 char *diskname; 291 292 /* regular device */ 293 if ((strncmp(name, "/dev/dsk/", strlen("/dev/dsk/")) == 0) && 294 (strchr((p = name + strlen("/dev/dsk/")), '/') == NULL)) { 295 diskname = Strdup(p); 296 stripS(diskname); 297 return (diskname); 298 } 299 300 if ((strncmp(name, "/dev/rdsk/", strlen("/dev/rdsk/")) == 0) && 301 (strchr((p = name + strlen("/dev/rdsk/")), '/') == NULL)) { 302 diskname = Strdup(p); 303 stripS(diskname); 304 return (diskname); 305 } 306 307 if ((strncmp(name, "/dev/ap/dsk/", strlen("/dev/ap/dsk/")) == 0) && 308 (strchr((p = name + strlen("/dev/ap/dsk/")), '/') == NULL)) { 309 diskname = Strdup(p); 310 stripS(diskname); 311 return (diskname); 312 } 313 314 if ((strncmp(name, "/dev/ap/rdsk/", strlen("/dev/ap/rdsk/")) == 0) && 315 (strchr((p = name + strlen("/dev/ap/rdsk/")), '/') == NULL)) { 316 diskname = Strdup(p); 317 stripS(diskname); 318 return (diskname); 319 } 320 321 if ((strncmp(name, "/dev/did/dsk/", strlen("/dev/did/dsk/")) == 0) && 322 (strchr((p = name + strlen("/dev/did/dsk/")), '/') == NULL)) { 323 diskname = Strdup(p); 324 stripS(diskname); 325 return (diskname); 326 } 327 328 if ((strncmp(name, "/dev/did/rdsk/", strlen("/dev/did/rdsk/")) == 0) && 329 (strchr((p = name + strlen("/dev/did/rdsk/")), '/') == NULL)) { 330 diskname = Strdup(p); 331 stripS(diskname); 332 return (diskname); 333 } 334 335 diskname = Strdup(name); 336 stripS(diskname); 337 return (diskname); 338 } 339 340 /* 341 * has_devid -- return the device ID for a given key 342 * 343 * RETURN 344 * NULL error 345 * devid devid found that corresponds to the given key. 346 */ 347 static ddi_devid_t 348 has_devid(set_t setno, side_t sideno, mdkey_t key, md_error_t *ep) 349 { 350 return (meta_getdidbykey(setno, sideno, key, ep)); 351 } 352 353 /* 354 * Go through the existing list of replicas and check to see 355 * if their disk has moved, if so update the replica list 356 * 357 * RETURN 358 * -1 error 359 * 0 success 360 */ 361 static int 362 fix_replicanames( 363 mdsetname_t *sp, 364 md_error_t *ep 365 ) 366 { 367 md_replicalist_t *rlp = NULL; 368 md_replicalist_t *rl; 369 int ret = -1; 370 int match_type = 0; 371 devid_nmlist_t *disklist = NULL; 372 dev_t small_dev = (dev_t)NODEV; 373 side_t sideno; 374 set_t setno = sp->setno; 375 char *search_path; 376 int search_number; 377 char *ctds_name; 378 char *path_name; 379 int i; 380 381 sideno = getmyside(sp, ep); 382 if (sideno == MD_SIDEWILD) { 383 mda_debug("Failed to find the side number\n"); 384 return (-1); 385 } 386 387 if (metareplicalist(sp, MD_BASICNAME_OK | PRINT_FAST, &rlp, ep) < 0) { 388 mda_debug("Unable to get a list of replicas\n"); 389 return (METADEVADM_ERR); 390 } 391 392 for (rl = rlp; (rl != NULL); rl = rl->rl_next) { 393 md_replica_t *r = rl->rl_repp; 394 395 small_dev = meta_cmpldev(r->r_namep->dev); 396 search_number = mda_findpath(r->r_namep->bname); 397 if (search_number == -1) { 398 mda_debug("replica update: invalid path: %s", 399 r->r_namep->bname); 400 continue; 401 } else { 402 search_path = plist[search_number].search_path; 403 } 404 405 if (r->r_devid == NULL) 406 continue; 407 408 ret = meta_deviceid_to_nmlist(search_path, r->r_devid, 409 r->r_minor_name, &disklist); 410 411 mda_debug("replica update: search_path %s\n", search_path); 412 413 if (ret != 0) { 414 /* 415 * Failed to find the disk, nothing can be done. 416 * The replica will be marked as bad later. 417 */ 418 mda_debug("replica update: failed to find disk %s\n", 419 r->r_namep->cname); 420 continue; 421 } 422 mda_debug("replica update: current %s (%p)\n", 423 r->r_namep->bname, (void *) small_dev); 424 425 /* 426 * Check to see if the returned disk matches the stored one 427 */ 428 for (i = 0; disklist[i].dev != NODEV; i++) { 429 match_type = 0; 430 431 mda_debug("replica update: devid list: %s (%p)\n", 432 disklist[i].devname, (void *) disklist[i].dev); 433 434 if (disklist[i].dev == small_dev) { 435 match_type |= DEV_MATCH; 436 } 437 438 if (strncmp(r->r_namep->bname, disklist[i].devname, 439 strlen(r->r_namep->bname)) == 0) { 440 match_type |= NAME_MATCH; 441 } 442 443 /* 444 * break out if some sort of match is found because 445 * we already match on the devid. 446 */ 447 if (match_type != 0) 448 break; 449 } 450 451 mda_debug("fix_replicanames: match: %x i: %d\n", match_type, i); 452 453 if (match_type == (DEV_MATCH|NAME_MATCH)) { 454 /* no change */ 455 mda_debug("replica update: no change %s\n", 456 disklist[i].devname); 457 devid_free_nmlist(disklist); 458 continue; 459 } 460 461 /* No match found - use the first entry in disklist */ 462 if (disklist[i].dev == NODEV) 463 i = 0; 464 465 mda_debug("replica update: reloading %s %p\n", 466 disklist[i].devname, 467 (void *)(uintptr_t)meta_expldev(disklist[i].dev)); 468 469 if (firsttime) { 470 mda_print(dgettext(TEXT_DOMAIN, 471 "Disk movement detected\n")); 472 mda_print(dgettext(TEXT_DOMAIN, 473 "Updating device names in Solaris Volume " 474 "Manager\n")); 475 firsttime = 0; 476 } 477 478 if (dev_options & DEV_VERBOSE) { 479 char *devidstr; 480 481 devidstr = 482 devid_str_encode(r->r_devid, r->r_minor_name); 483 if (devidstr == NULL) { 484 mda_print(dgettext(TEXT_DOMAIN, 485 "Failed to encode the devid\n")); 486 continue; 487 } 488 mda_print(dgettext(TEXT_DOMAIN, 489 "%s changed to %s from device relocation " 490 "information %s\n"), 491 (char *)r->r_namep->cname, disklist[i].devname, 492 devidstr); 493 } 494 495 if (!(dev_options & DEV_NOACTION)) { 496 mda_debug("Updating locator name\n"); 497 ctds_name = strrchr(disklist[i].devname, '/'); 498 ctds_name++; 499 if ((path_name = mda_getpath(disklist[i].devname)) 500 == NULL) { 501 continue; 502 } 503 if (update_locator_namespace(setno, sideno, 504 ctds_name, meta_expldev(disklist[i].dev), 505 path_name, ep) != 0) { 506 mda_debug("replica update: ioctl failed\n"); 507 if (dev_options & DEV_VERBOSE) { 508 mda_print(dgettext(TEXT_DOMAIN, 509 "Failed to update locator " 510 "namespace on change from %s " 511 "to %s\n"), ctds_name, 512 disklist[i].devname); 513 } 514 } 515 } 516 Free(path_name); 517 devid_free_nmlist(disklist); 518 } 519 metafreereplicalist(rlp); 520 return (0); 521 } 522 523 /* 524 * pathname_reload - main function for the -r option. Will reload the 525 * pathname in both the main namespace and the locator namespace. 526 * Also, checks both areas for invalid device ID's and prints them 527 * out. 528 * 529 * If the set is a multi-node diskset that means there are no devid's 530 * so just return. 531 * 532 * RETURN 533 * METADEVADM_ERR error 534 * METADEVADM_SUCCESS success 535 * METADEVADM_DEVIDINVALID success, but invalid devids detected 536 */ 537 int 538 pathname_reload( 539 mdsetname_t **spp, 540 set_t setno, 541 md_error_t *ep) 542 { 543 char *drvnmp; 544 minor_t mnum = 0; 545 md_dev64_t dev = 0; 546 mdnm_params_t nm; 547 char *ctds_name; 548 ddi_devid_t devidp; 549 md_i_didstat_t ds; 550 side_t sideno; 551 char *search_path = NULL; 552 int search_number; 553 devid_nmlist_t *disklist = NULL; 554 char *minor_name = NULL; 555 char *devidstr = NULL; 556 char *path = NULL; 557 int ret; 558 dev_t small_dev = (dev_t)NODEV; 559 int match_type; 560 char *tmp = NULL; 561 mdsetname_t *sp = *spp; 562 md_set_desc *sd; 563 int i; 564 565 /* 566 * Check for multi-node diskset and return if it is one. 567 */ 568 if (!metaislocalset(sp)) { 569 if ((sd = metaget_setdesc(sp, ep)) == NULL) 570 return (METADEVADM_ERR); 571 572 if (MD_MNSET_DESC(sd)) 573 return (METADEVADM_SUCCESS); 574 } 575 576 /* 577 * Get the entry of the namespace via the key. To do this 578 * call MD_IOCNXTKEY until no more. 579 * For each entry in the namespace we want to check 580 * for devid and update 581 */ 582 583 (void) memset(&nm, '\0', sizeof (nm)); 584 nm.key = MD_KEYWILD; 585 586 sideno = getmyside(*spp, ep); 587 if (sideno == MD_SIDEWILD) { 588 /* failed to find this node in the set */ 589 mda_debug("Failed to find the side number\n"); 590 return (METADEVADM_ERR); 591 } 592 593 /* LINTED */ 594 while (1) { 595 nm.mde = mdnullerror; 596 nm.setno = setno; 597 nm.side = sideno; 598 /* look at each key in the namespace */ 599 if (metaioctl(MD_IOCNXTKEY_NM, &nm, &nm.mde, NULL) != 0) { 600 (void) mdstealerror(ep, &nm.mde); 601 return (METADEVADM_ERR); 602 } 603 604 if (nm.key == MD_KEYWILD) { 605 /* no more entries */ 606 break; 607 } 608 609 /* 610 * get the nm entry using the key. Then check to see if 611 * there's a devid associated with this entry 612 * If not, go onto next key. 613 */ 614 if ((nm.devname = (uintptr_t)meta_getnmentbykey(setno, sideno, 615 nm.key, &drvnmp, &mnum, &dev, ep)) == NULL) { 616 mda_debug("pathname_reload: no name for key: %d\n", 617 nm.key); 618 continue; 619 } 620 621 mda_debug("pathname_reload: examining %s\n", 622 (char *)(uintptr_t)nm.devname); 623 624 if ((devidp = has_devid(setno, sideno, nm.key, ep)) == NULL) { 625 /* metadevices do not have devid's in them */ 626 mda_debug("pathname_reload: no devid for %s\n", 627 (char *)(uintptr_t)nm.devname); 628 /* Clear error if no devid and go to next nm entry */ 629 mdclrerror(ep); 630 continue; 631 } 632 633 if ((minor_name = meta_getdidminorbykey(setno, sideno, 634 nm.key, ep)) == NULL) { 635 /* 636 * In theory this is impossible because if the 637 * devidp is non-null then the minor_name has 638 * already been looked up. 639 */ 640 mda_debug("No minor name for %s\n", 641 (char *)(uintptr_t)nm.devname); 642 free(devidp); 643 continue; 644 } 645 /* 646 * If there is a devid then we have a real device that 647 * could have moved. 648 */ 649 devidstr = devid_str_encode(devidp, minor_name); 650 if (devidstr == NULL) { 651 mda_debug("Failed to encode the devid\n"); 652 free(devidp); 653 continue; 654 } 655 mda_debug("devid: %s\n", devidstr); 656 657 /* 658 * Find the search path that should be used. This is an 659 * optimization to try and prevent a search for the complete 660 * /dev namespace. 661 */ 662 search_number = mda_findpath((char *)(uintptr_t)nm.devname); 663 if (search_number == -1) { 664 search_path = "/dev"; 665 } else { 666 search_path = plist[search_number].search_path; 667 } 668 669 /* now look for the disk name using the devid */ 670 ret = meta_deviceid_to_nmlist(search_path, devidp, 671 minor_name, &disklist); 672 free(devidp); 673 674 if (ret != 0) { 675 /* 676 * Failed to find the disk 677 */ 678 devid_str_free(devidstr); 679 continue; 680 } 681 682 small_dev = meta_cmpldev(dev); 683 mda_debug("Old device lookup: %s (%p)\n", 684 (char *)(uintptr_t)nm.devname, (void *)small_dev); 685 686 /* 687 * Check to see if the returned disk matches the stored one 688 */ 689 for (i = 0; disklist[i].dev != NODEV; i++) { 690 match_type = 0; 691 mda_debug("From devid lookup: %s (%p)\n", 692 (char *)disklist[i].devname, 693 (void *)disklist[i].dev); 694 695 if (disklist[i].dev == small_dev) { 696 match_type |= DEV_MATCH; 697 } 698 699 if (strncmp((char *)(uintptr_t)nm.devname, 700 disklist[i].devname, 701 strlen((char *)(uintptr_t)nm.devname)) == 0) { 702 mda_debug("Name match: %s and %s (%d)\n", 703 disklist[i].devname, 704 (char *)(uintptr_t)nm.devname, 705 strlen((char *)(uintptr_t)nm.devname)); 706 match_type |= NAME_MATCH; 707 } 708 709 if (match_type == (DEV_MATCH|NAME_MATCH)) 710 break; 711 } 712 713 if (match_type == (DEV_MATCH|NAME_MATCH)) { 714 /* no change */ 715 devid_str_free(devidstr); 716 mda_debug("All matched %s\n", disklist[i].devname); 717 devid_free_nmlist(disklist); 718 continue; 719 } 720 721 /* No match found - use the first entry in disklist */ 722 i = 0; 723 724 if (firsttime) { 725 mda_print(dgettext(TEXT_DOMAIN, 726 "Disk movement detected\n")); 727 mda_print(dgettext(TEXT_DOMAIN, 728 "Updating device names in " 729 "Solaris Volume Manager\n")); 730 firsttime = 0; 731 } 732 if (dev_options & DEV_VERBOSE) { 733 mda_print(dgettext(TEXT_DOMAIN, 734 "%s changed to %s from device relocation " 735 "information %s\n"), 736 (char *)(uintptr_t)nm.devname, disklist[i].devname, 737 devidstr); 738 } 739 devid_str_free(devidstr); 740 741 /* need to build up the path of the disk */ 742 if ((path = Strdup(disklist[i].devname)) == NULL) { 743 mda_debug("Failed to duplicate path: %s\n", 744 disklist[i].devname); 745 devid_free_nmlist(disklist); 746 continue; 747 } 748 if ((tmp = strrchr(path, '/')) == NULL) { 749 mda_debug("Failed to parse %s\n", path); 750 devid_free_nmlist(disklist); 751 Free(path); 752 continue; 753 } 754 tmp += sizeof (char); 755 *tmp = '\0'; 756 757 if ((ctds_name = strrchr(disklist[i].devname, '/')) == NULL) { 758 mda_debug("Failed to parse ctds name: %s\n", 759 disklist[i].devname); 760 devid_free_nmlist(disklist); 761 Free(path); 762 continue; 763 } 764 ctds_name += sizeof (char); 765 766 mda_debug("Reloading disk %s %s %p\n", 767 ctds_name, path, 768 (void *)(uintptr_t)meta_expldev(disklist[i].dev)); 769 770 if (!(dev_options & DEV_NOACTION)) { 771 /* Something has changed so update the namespace */ 772 if (update_namespace(setno, sideno, ctds_name, 773 meta_expldev(disklist[i].dev), nm.key, path, 774 ep) != 0) { 775 mda_debug("Failed to update namespace\n"); 776 if (dev_options & DEV_VERBOSE) { 777 mda_print(dgettext(TEXT_DOMAIN, 778 "Failed to update namespace on " 779 "change from %s to %s\n"), 780 ctds_name, disklist[i].devname); 781 } 782 } 783 } 784 devid_free_nmlist(disklist); 785 Free(path); 786 } 787 788 if (fix_replicanames(*spp, ep) == -1) 789 mda_debug("Failed to update replicas\n"); 790 791 /* 792 * check for invalid device id's 793 */ 794 (void) memset(&ds, '\0', sizeof (ds)); 795 ds.setno = setno; 796 ds.side = sideno; 797 ds.mode = MD_FIND_INVDID; 798 /* get count of number of invalid device id's */ 799 if (metaioctl(MD_IOCDID_STAT, &ds, &ds.mde, NULL) != 0) { 800 (void) mdstealerror(ep, &ds.mde); 801 return (METADEVADM_ERR); 802 } 803 if (ds.cnt != 0) { 804 char *ctdptr, *ctdp; 805 /* 806 * we have some invalid device id's so we need to 807 * print them out 808 */ 809 ds.mode = MD_GET_INVDID; 810 /* malloc buffer for kernel to place devid list into */ 811 if ((ctdptr = (char *)Malloc((ds.cnt * ds.maxsz) + 1)) == 0) { 812 return (METADEVADM_ERR); 813 } 814 ds.ctdp = (uintptr_t)ctdptr; 815 /* get actual list of invalid device id's */ 816 if (metaioctl(MD_IOCDID_STAT, &ds, &ds.mde, NULL) != 0) { 817 Free(ctdptr); 818 (void) mdstealerror(ep, &ds.mde); 819 return (METADEVADM_ERR); 820 } 821 822 /* print out the invalid devid's */ 823 mda_print(dgettext(TEXT_DOMAIN, 824 "Invalid device relocation information " 825 "detected in Solaris Volume Manager\n")); 826 mda_print(dgettext(TEXT_DOMAIN, 827 "Please check the status of the following disk(s):\n")); 828 ctdp = (char *)(uintptr_t)ds.ctdp; 829 while (*ctdp != NULL) { 830 mda_print("\t%s\n", ctdp); 831 ctdp += ds.maxsz; 832 } 833 Free(ctdptr); 834 return (METADEVADM_DEVIDINVALID); 835 } 836 return (METADEVADM_SUCCESS); 837 } 838 839 /* 840 * replica_update_devid - cycle through the replica list, rlp, and 841 * update the device ids on all of the replicas that are on the 842 * device specified by lp. A side effect is to update the value of 843 * cdevidpp to contain the character representation of the device 844 * id before updating if it is not already set. 845 * 846 * RETURN 847 * METADEVADM_ERR error 848 * METADEVADM_SUCCESS success 849 */ 850 static int 851 replica_update_devid( 852 md_replicalist_t *rlp, 853 mddrivename_t *dnp, 854 set_t setno, 855 char **cdevidpp, 856 md_error_t *ep 857 ) 858 { 859 mddb_config_t db_c; 860 md_replicalist_t *rl; 861 ddi_devid_t devidp; 862 int ret; 863 864 if (cdevidpp == NULL) 865 return (METADEVADM_ERR); 866 867 ret = devid_str_decode(dnp->devid, &devidp, NULL); 868 if (ret != 0) { 869 /* failed to encode the devid */ 870 mda_debug("Failed to decode %s into a valid devid\n", 871 dnp->devid); 872 return (METADEVADM_ERR); 873 } 874 875 /* search replica list for give ctd name */ 876 for (rl = rlp; (rl != NULL); rl = rl->rl_next) { 877 md_replica_t *r = rl->rl_repp; 878 mdname_t *rnp = r->r_namep; 879 880 if (strncmp(rnp->cname, dnp->cname, strlen(dnp->cname)) == 0) { 881 882 /* found the replica, now grab the devid */ 883 if (*cdevidpp == NULL) { 884 *cdevidpp = devid_str_encode(r->r_devid, NULL); 885 } 886 887 if (*cdevidpp == NULL) { 888 devid_free(devidp); 889 return (METADEVADM_ERR); 890 } 891 892 mda_debug("Updating replica %s, set %d, old devid %s\n", 893 rnp->cname, setno, *cdevidpp); 894 895 if (dev_options & DEV_VERBOSE) { 896 mda_print(dgettext(TEXT_DOMAIN, 897 "Updating replica %s of set number %d from " 898 "device id %s to device id %s\n"), 899 rnp->cname, setno, *cdevidpp, dnp->devid); 900 } 901 902 (void) memset(&db_c, '\0', sizeof (db_c)); 903 904 db_c.c_setno = setno; 905 db_c.c_devt = rnp->dev; 906 907 if (!(dev_options & DEV_NOACTION)) { 908 909 mda_debug("Updating replica\n"); 910 911 /* 912 * call into kernel to update lb 913 * namespace device id 914 * of given devt 915 */ 916 if (metaioctl(MD_DB_SETDID, &db_c, 917 &db_c.c_mde, NULL) != 0) { 918 devid_free(devidp); 919 (void) mdstealerror(ep, &db_c.c_mde); 920 return (METADEVADM_ERR); 921 } 922 } 923 924 } 925 } 926 devid_free(devidp); 927 return (METADEVADM_SUCCESS); 928 } 929 930 /* 931 * devid_update -- main routine for the -u option. Will update both the 932 * namespace and the locator block with the correct devid for the 933 * disk specified. 934 * 935 * RETURN 936 * METADEVADM_ERR error 937 * METADEVADM_SUCCESS success 938 */ 939 static int 940 devid_update( 941 mdsetname_t **spp, 942 set_t setno, 943 char *ctd, 944 md_error_t *ep 945 ) 946 { 947 md_drive_desc *dd, *ddp; 948 mddrivename_t *dnp; 949 mdnm_params_t nm; 950 ddi_devid_t devidp; 951 side_t side; 952 char *old_cdevidp = NULL; 953 md_replicalist_t *rlp = NULL; 954 int rval = METADEVADM_ERR; 955 mdname_t *np = NULL; 956 uint_t rep_slice; 957 char *pathname = NULL; 958 char *diskname = NULL; 959 int fd = -1; 960 int len; 961 char *fp; 962 963 side = getmyside(*spp, ep); 964 if (side == MD_SIDEWILD) { 965 /* failed to find this node in the set */ 966 mda_debug("Failed to find the side number\n"); 967 return (METADEVADM_ERR); 968 } 969 970 if ((dnp = metadrivename(spp, ctd, ep)) == NULL) { 971 mda_debug("Failed to create a dnp for %s\n", ctd); 972 return (METADEVADM_ERR); 973 } 974 if (dnp->devid == NULL) { 975 /* 976 * Disk does not have a devid! So cannot update the 977 * devid within the replica. 978 */ 979 mda_debug("%s does not have a devid\n", dnp->cname); 980 if (dev_options & DEV_VERBOSE) { 981 mda_print(dgettext(TEXT_DOMAIN, 982 "%s does not have a device id. Cannot update " 983 "device id if none exists\n"), ctd); 984 } 985 return (METADEVADM_ERR); 986 } 987 988 mda_debug("Devid update to: %s\n", dnp->devid); 989 990 /* 991 * Check if we own the set, if we do then do some processing 992 * on the replicas. 993 */ 994 if (meta_check_ownership(*spp, ep) == 0) { 995 996 /* get the replicas */ 997 if (metareplicalist(*spp, MD_BASICNAME_OK | PRINT_FAST, &rlp, 998 ep) < 0) 999 return (METADEVADM_ERR); 1000 1001 /* update the devids in the replicas if necessary */ 1002 if (replica_update_devid(rlp, dnp, setno, &old_cdevidp, 1003 ep) != METADEVADM_SUCCESS) { 1004 metafreereplicalist(rlp); 1005 return (METADEVADM_ERR); 1006 } 1007 1008 metafreereplicalist(rlp); 1009 } 1010 1011 /* 1012 * If this is not the LOCAL set then need to update the LOCAL 1013 * replica with the new disk record. 1014 */ 1015 1016 if (setno != MD_LOCAL_SET) { 1017 mda_debug("Non-local set: %d side %d\n", setno, side); 1018 1019 /* 1020 * Need to find the disk record within the set and then 1021 * update it. 1022 */ 1023 if ((dd = 1024 metaget_drivedesc(*spp, MD_FULLNAME_ONLY, ep)) == NULL) { 1025 if (! mdisok(ep)) 1026 goto out; 1027 /* no disks in the set - no point continuing */ 1028 mda_debug("No disks in diskset\n"); 1029 rval = METADEVADM_SUCCESS; 1030 goto out; 1031 } 1032 1033 for (ddp = dd; ddp != NULL; ddp = ddp->dd_next) { 1034 if (strncmp(ddp->dd_dnp->cname, dnp->cname, 1035 strlen(dnp->cname)) == 0) 1036 break; 1037 } 1038 1039 if (ddp == NULL) { 1040 /* failed to finddisk in the set */ 1041 mda_print(dgettext(TEXT_DOMAIN, 1042 "%s not found in set %s. Check your syntax\n"), 1043 ctd, (*spp)->setname); 1044 (void) mddserror(ep, MDE_DS_DRIVENOTINSET, setno, NULL, 1045 ctd, (*spp)->setname); 1046 goto out; 1047 } 1048 1049 /* 1050 * Now figure out the correct slice, for a diskset the slice 1051 * we care about is always the 'replica' slice. 1052 */ 1053 if (meta_replicaslice(dnp, &rep_slice, ep) != 0) { 1054 mda_debug("Unable to find replica slice for %s\n", 1055 dnp->cname); 1056 goto out; 1057 } 1058 1059 mda_debug("slice no: %d disk %s\n", rep_slice, dnp->cname); 1060 1061 if ((np = metaslicename(dnp, rep_slice, ep)) == NULL) { 1062 mda_debug("Unable to build namespace\n"); 1063 goto out; 1064 } 1065 1066 mda_debug("check: ctdname: %s\n", np->cname); 1067 mda_debug("check: ctdname: %s\n", np->rname); 1068 mda_debug("check: ctdname: %s\n", np->bname); 1069 1070 if (!(dev_options & DEV_NOACTION)) { 1071 1072 mda_debug("Updating record: key %d name %s\n", 1073 ddp->dd_dnp->side_names_key, np->cname); 1074 1075 pathname = mda_getpath(np->bname); 1076 1077 if (update_namespace(MD_LOCAL_SET, side + SKEW, 1078 np->cname, np->dev, ddp->dd_dnp->side_names_key, 1079 pathname, ep) != 0) { 1080 goto out; 1081 } 1082 1083 /* 1084 * Now update the devid entry as well, this works 1085 * correctly because the prior call to 1086 * update_namespace() above puts the correct dev_t 1087 * in the namespace which will then be resolved 1088 * to the new devid by the ioctl now called. 1089 */ 1090 nm.mde = mdnullerror; 1091 nm.setno = MD_LOCAL_SET; 1092 nm.side = side + SKEW; 1093 nm.key = ddp->dd_dnp->side_names_key; 1094 if (metaioctl(MD_SETNMDID, &nm, &nm.mde, NULL) != 0) { 1095 (void) mdstealerror(ep, &nm.mde); 1096 goto out; 1097 } 1098 } 1099 } 1100 1101 if ((dev_options & DEV_LOCAL_SET) && (setno != MD_LOCAL_SET)) { 1102 /* 1103 * Only want to update the local set so do not continue. 1104 */ 1105 rval = METADEVADM_SUCCESS; 1106 goto out; 1107 } 1108 1109 /* 1110 * Iterate through all of the metadevices looking for the 1111 * passed in ctd. If found then update the devid 1112 */ 1113 (void) memset(&nm, '\0', sizeof (nm)); 1114 nm.key = MD_KEYWILD; 1115 /* LINTED */ 1116 while (1) { 1117 nm.mde = mdnullerror; 1118 nm.setno = setno; 1119 nm.side = side; 1120 1121 /* search each namespace entry */ 1122 if (metaioctl(MD_IOCNXTKEY_NM, &nm, &nm.mde, NULL) != 0) { 1123 (void) mdstealerror(ep, &nm.mde); 1124 rval = METADEVADM_ERR; 1125 goto out; 1126 } 1127 if (nm.key == MD_KEYWILD) { 1128 if (setno != MD_LOCAL_SET) { 1129 mda_print(dgettext(TEXT_DOMAIN, 1130 "%s not found in set %s. Check your " 1131 "syntax\n"), ctd, (*spp)->setname); 1132 goto out; 1133 } else { 1134 mda_print(dgettext(TEXT_DOMAIN, 1135 "%s not found in local set. " 1136 "Check your syntax\n"), ctd); 1137 goto out; 1138 } 1139 } 1140 1141 nm.devname = (uintptr_t)meta_getnmentbykey(setno, side, nm.key, 1142 NULL, NULL, NULL, ep); 1143 if (nm.devname == NULL) { 1144 rval = METADEVADM_ERR; 1145 goto out; 1146 } 1147 1148 diskname = getdiskname((char *)(uintptr_t)nm.devname); 1149 1150 mda_debug("Checking %s with %s\n", diskname, dnp->cname); 1151 if (strcmp(diskname, dnp->cname) != 0) 1152 continue; 1153 1154 mda_debug("Updating device %s in namespace\n", 1155 (char *)(uintptr_t)nm.devname); 1156 1157 /* 1158 * found disk, does it have a devid within the namespace ? 1159 * It might not because it does not support devid's or was 1160 * put into the namespace when there was no devid support 1161 */ 1162 if ((devidp = has_devid(setno, side, nm.key, ep)) == NULL) { 1163 mda_debug("%s has no devid in the namespace", 1164 (char *)(uintptr_t)nm.devname); 1165 if (dev_options & DEV_VERBOSE) { 1166 mda_print(dgettext(TEXT_DOMAIN, 1167 "SVM has no device id for " 1168 "%s, cannot update.\n"), 1169 (char *)(uintptr_t)nm.devname); 1170 } 1171 continue; /* no devid. go on to next */ 1172 } 1173 if (old_cdevidp == NULL) { 1174 old_cdevidp = devid_str_encode(devidp, NULL); 1175 } 1176 free(devidp); 1177 1178 /* 1179 * has devid so update namespace, note the key has been set 1180 * by the prior MD_IOCNXTKEY_NM ioctl. 1181 */ 1182 nm.mde = mdnullerror; 1183 nm.setno = setno; 1184 nm.side = side; 1185 if (!(dev_options & DEV_NOACTION)) { 1186 /* 1187 * The call below may fail if the -u option is being 1188 * used to update a disk that has been replaced. 1189 * The -u option to metadevadm should not be used 1190 * for this purpose because we trust the dev_t of 1191 * the device in the replica and if we have replaced 1192 * the device and it is a fibre one then the dev_t 1193 * will have changed. This means we end up looking for 1194 * the devid of a non-existant disk and we subsequently 1195 * fail with NODEVID. 1196 */ 1197 if (metaioctl(MD_SETNMDID, &nm, 1198 &nm.mde, NULL) != 0) { 1199 if (dev_options & DEV_VERBOSE) { 1200 mda_print(dgettext(TEXT_DOMAIN, 1201 "SVM failed to update the device " 1202 "id for %s probably due to both " 1203 "devt and device id changing.\n"), 1204 (char *)(uintptr_t)nm.devname); 1205 } 1206 (void) mdstealerror(ep, &nm.mde); 1207 mde_perror(ep, ""); 1208 rval = METADEVADM_ERR; 1209 goto out; 1210 } 1211 } 1212 if (old_cdevidp == NULL) { 1213 rval = METADEVADM_ERR; 1214 goto out; 1215 } 1216 break; 1217 } /* end while */ 1218 1219 mda_print(dgettext(TEXT_DOMAIN, 1220 "Updating Solaris Volume Manager device relocation " 1221 "information for %s\n"), ctd); 1222 1223 mda_print(dgettext(TEXT_DOMAIN, 1224 "Old device reloc information:\n\t%s\n"), old_cdevidp); 1225 1226 len = strlen(dnp->rname) + strlen("s0"); 1227 if ((fp = (char *)Malloc(len + 1)) == NULL) { 1228 mda_print(dgettext(TEXT_DOMAIN, 1229 "insufficient memory, device Reloc info not " 1230 "available\n")); 1231 } else { 1232 (void) snprintf(fp, len + 1, "%ss0", dnp->rname); 1233 if ((fd = open(fp, O_RDONLY|O_NDELAY)) < 0) { 1234 mda_print(dgettext(TEXT_DOMAIN, 1235 "Open of %s failed\n"), fp); 1236 } else { 1237 int rc = -1; 1238 ddi_devid_t devid1 = NULL; 1239 char *cdevidp; 1240 1241 rc = devid_get(fd, &devid1); 1242 if (close(fd) < 0) { 1243 mda_print(dgettext(TEXT_DOMAIN, 1244 "Close of %s failed\n"), fp); 1245 } 1246 if (rc != 0) { 1247 mda_print(dgettext(TEXT_DOMAIN, 1248 "Unable to obtain device " 1249 "Reloc info for %s\n"), fp); 1250 } else { 1251 cdevidp = devid_str_encode(devid1, NULL); 1252 if (cdevidp == NULL) { 1253 mda_print(dgettext(TEXT_DOMAIN, 1254 "Unable to print " 1255 "device Reloc info for %s\n"), fp); 1256 } else { 1257 mda_print(dgettext(TEXT_DOMAIN, 1258 "New device reloc " 1259 "information:\n\t%s\n"), cdevidp); 1260 devid_str_free(cdevidp); 1261 } 1262 devid_free(devid1); 1263 } 1264 } 1265 Free(fp); 1266 } 1267 1268 rval = METADEVADM_SUCCESS; 1269 1270 out: 1271 if (diskname) 1272 Free(diskname); 1273 if (pathname) 1274 Free(pathname); 1275 if (old_cdevidp) { 1276 devid_str_free(old_cdevidp); 1277 } 1278 return (rval); 1279 1280 } 1281 1282 /* 1283 * Check the ctd name of the disk to see if the disk has moved. If it 1284 * has moved then the newname is returned in 'newname', it is up to 1285 * the caller to free the memory associated with it. 1286 * 1287 * RETURN 1288 * METADEVADM_ERR error 1289 * METADEVADM_SUCCESS success 1290 * METADEVADM_DISKMOVE success, and the disk has moved 1291 * METADEVADM_DSKNAME_ERR error creating the disk name structures. 1292 */ 1293 int 1294 meta_upd_ctdnames( 1295 mdsetname_t **spp, 1296 set_t setno, 1297 side_t sideno, 1298 mddrivename_t *dnp, 1299 char **newname, 1300 md_error_t *ep 1301 ) 1302 { 1303 char *drvnmp; 1304 int i; 1305 minor_t mnum = 0; 1306 md_dev64_t dev = 0; 1307 dev_t small_dev = (dev_t)NODEV; 1308 mdnm_params_t nm; 1309 char *pathname; 1310 char *minor_name = NULL; 1311 ddi_devid_t devidp; 1312 devid_nmlist_t *disklist = NULL; 1313 int ret = 0; 1314 mdsidenames_t *snp; 1315 int match_type; 1316 int search_number = -1; 1317 char *search_type = NULL; 1318 char *search_path = NULL; 1319 uint_t rep_slice; 1320 mddrivename_t *newdnp; 1321 mdname_t *np; 1322 mdsetname_t *sp = *spp; 1323 md_set_desc *sd; 1324 1325 /* 1326 * setno should always be 0 but we're going to 1327 * check for multi-node diskset and return if it is one. 1328 */ 1329 if (!metaislocalset(sp)) { 1330 if ((sd = metaget_setdesc(sp, ep)) == NULL) 1331 return (METADEVADM_ERR); 1332 1333 if (MD_MNSET_DESC(sd)) 1334 return (METADEVADM_SUCCESS); 1335 } 1336 1337 if (dnp->devid == NULL) { 1338 /* no devid, nothing can be done */ 1339 mda_debug("meta_upd_ctdnames: %s has no devid\n", dnp->cname); 1340 if (dev_options & DEV_VERBOSE) { 1341 mda_print(dgettext(TEXT_DOMAIN, 1342 "%s has no devid, cannot detect " 1343 "disk movement for this disk.\n"), dnp->cname); 1344 } 1345 return (ret); 1346 } 1347 1348 /* 1349 * Find the correct side name for the disk. There is a sidename 1350 * for each host associated with the diskset. 1351 */ 1352 for (snp = dnp->side_names; snp != NULL; snp = snp->next) { 1353 mda_debug("meta_upd_ctdnames: %s %d args: setno %d sideno %d\n", 1354 snp->cname, snp->sideno, setno, sideno); 1355 /* only use SKEW for the local replica */ 1356 if (setno == 0) { 1357 if (snp->sideno + SKEW == sideno) 1358 break; 1359 } else { 1360 if (snp->sideno == sideno) 1361 break; 1362 } 1363 } 1364 1365 if (snp == NULL) { 1366 /* 1367 * Failed to find the side name, this should not 1368 * be possible. However if it does happen this is an 1369 * indication of an inconsistant replica - something 1370 * might have gone wrong during an add or a delete of 1371 * a host. 1372 */ 1373 mda_debug("Unable to find the side information for disk %s", 1374 dnp->cname); 1375 (void) mddserror(ep, MDE_DS_HOSTNOSIDE, (*spp)->setno, mynode(), 1376 NULL, dnp->cname); 1377 return (METADEVADM_ERR); 1378 } 1379 /* 1380 * Find the type of device we are to be searching on 1381 */ 1382 search_number = mda_findpath(snp->cname); 1383 if (search_number == -1) { 1384 search_path = "/dev"; 1385 search_type = DEVID_MINOR_NAME_ALL; 1386 } else { 1387 search_path = plist[search_number].search_path; 1388 search_type = plist[search_number].search_type; 1389 } 1390 1391 mda_debug("Search path :%s searth_type: %x\n", 1392 search_path, (int)search_type); 1393 (void) memset(&nm, '\0', sizeof (nm)); 1394 1395 nm.mde = mdnullerror; 1396 nm.setno = setno; 1397 nm.side = sideno; 1398 1399 /* 1400 * Get the devname from the name space. 1401 */ 1402 if ((nm.devname = (uintptr_t)meta_getnmentbykey(setno, sideno, 1403 dnp->side_names_key, &drvnmp, &mnum, &dev, ep)) == NULL) { 1404 return (METADEVADM_ERR); 1405 } 1406 1407 ret = devid_str_decode(dnp->devid, &devidp, &minor_name); 1408 devid_str_free(minor_name); 1409 1410 if (ret != 0) { 1411 /* 1412 * Failed to encode the devid. 1413 */ 1414 devid_free(devidp); 1415 return (METADEVADM_ERR); 1416 } 1417 1418 /* 1419 * Use the stored devid to find the existing device node and check 1420 * to see if the disk has moved. Use the raw devices as the name 1421 * of the disk is stored as the raw device, if this is not done 1422 * then the disk will not be found. 1423 */ 1424 ret = meta_deviceid_to_nmlist(search_path, devidp, 1425 search_type, &disklist); 1426 1427 if (ret != 0) { 1428 if (dev_options & DEV_VERBOSE) { 1429 mda_print(dgettext(TEXT_DOMAIN, 1430 "Device ID %s last associated with " 1431 "disk %s no longer found in system\n"), 1432 dnp->devid, dnp->cname); 1433 } 1434 devid_free(devidp); 1435 devid_free_nmlist(disklist); 1436 return (METADEVADM_SUCCESS); 1437 } 1438 1439 small_dev = meta_cmpldev(dev); 1440 mda_debug("Old device lookup: %s (%p)\n", 1441 (char *)(uintptr_t)nm.devname, (void *)small_dev); 1442 /* 1443 * Check to see if the returned disk matches the stored one 1444 */ 1445 for (i = 0; disklist[i].dev != NODEV; i++) { 1446 match_type = 0; 1447 mda_debug("From devid lookup: %s (%p)\n", 1448 disklist[i].devname, (void *)disklist[i].dev); 1449 1450 if (disklist[i].dev == small_dev) { 1451 match_type |= DEV_MATCH; 1452 } 1453 1454 if (strncmp((char *)(uintptr_t)nm.devname, disklist[i].devname, 1455 strlen((char *)(uintptr_t)nm.devname)) == 0) { 1456 match_type |= NAME_MATCH; 1457 } 1458 1459 if (match_type != 0) 1460 break; 1461 } 1462 devid_free(devidp); 1463 1464 mda_debug("meta_upd_ctdnames: match: %x i: %d\n", match_type, i); 1465 1466 if (match_type == (DEV_MATCH|NAME_MATCH)) { 1467 /* no change */ 1468 devid_free_nmlist(disklist); 1469 return (METADEVADM_SUCCESS); 1470 } 1471 1472 /* No match found - use the first entry in disklist */ 1473 if (disklist[i].dev == NODEV) 1474 i = 0; 1475 1476 if (!(match_type & DEV_MATCH)) { 1477 /* did not match on the dev, so dev_t has changed */ 1478 mda_debug("Did not match on dev: %p %p\n", 1479 (void *) small_dev, (void *) disklist[i].dev); 1480 dev = meta_expldev(disklist[i].dev); 1481 } 1482 1483 if (!(match_type & NAME_MATCH)) { 1484 mda_debug("Did not match on name: %s (%p)\n", 1485 (char *)(uintptr_t)nm.devname, (void *) disklist[i].dev); 1486 } 1487 1488 /* 1489 * If here, then the name in the disklist is the one we 1490 * want in any case so use it. 1491 */ 1492 mda_debug("devname: %s\n", disklist[i].devname); 1493 /* 1494 * Need to remove the slice as metadrivename() expects a diskname 1495 */ 1496 stripS(disklist[i].devname); 1497 /* 1498 * Build an mddrivename_t to use 1499 */ 1500 if ((newdnp = metadrivename(spp, disklist[i].devname, ep)) == NULL) { 1501 mda_debug("Unable to make a dnp out of %s\n", 1502 disklist[i].devname); 1503 return (METADEVADM_DSKNAME_ERR); 1504 } 1505 /* 1506 * Need to find the correct slice used for the replica 1507 */ 1508 if (meta_replicaslice(newdnp, &rep_slice, ep) != 0) { 1509 return (METADEVADM_DSKNAME_ERR); 1510 } 1511 1512 if ((np = metaslicename(newdnp, rep_slice, ep)) == NULL) { 1513 mda_debug("Failed to build an np for %s\n", dnp->rname); 1514 return (METADEVADM_DSKNAME_ERR); 1515 } 1516 mda_debug("check: cname: %s\n", np->cname); 1517 mda_debug("check: rname: %s\n", np->rname); 1518 mda_debug("check: bname: %s\n", np->bname); 1519 1520 if (newname != NULL) 1521 *newname = Strdup(np->bname); 1522 1523 if (!(dev_options & DEV_NOACTION)) { 1524 1525 mda_debug("update namespace\n"); 1526 1527 /* get the block path */ 1528 pathname = mda_getpath(np->bname); 1529 1530 if (update_namespace(setno, sideno, np->cname, 1531 dev, dnp->side_names_key, pathname, ep) != 0) { 1532 /* finished with the list so return the memory */ 1533 Free(pathname); 1534 devid_free_nmlist(disklist); 1535 return (METADEVADM_ERR); 1536 } 1537 } 1538 /* finished with the list so return the memory */ 1539 Free(pathname); 1540 devid_free_nmlist(disklist); 1541 ret = METADEVADM_DISKMOVE; 1542 return (ret); 1543 } 1544 1545 int 1546 meta_fixdevid( 1547 mdsetname_t *sp, 1548 mddevopts_t options, 1549 char *diskname, 1550 md_error_t *ep 1551 ) 1552 { 1553 set_t setno = sp->setno; 1554 int ret = 0; 1555 char *pathname = NULL; 1556 mdsetname_t *local_sp = NULL; 1557 md_drive_desc *d = NULL; 1558 char *newname = NULL; 1559 md_drive_desc *dd; 1560 side_t sideno; 1561 md_set_desc *sd; 1562 1563 /* if MN diskset just return */ 1564 if (!metaislocalset(sp)) { 1565 if ((sd = metaget_setdesc(sp, ep)) == NULL) { 1566 return (METADEVADM_ERR); 1567 } 1568 if (MD_MNSET_DESC(sd)) 1569 return (METADEVADM_SUCCESS); 1570 } 1571 1572 dev_options |= options; 1573 mda_debug("dev_options: %x\n", dev_options); 1574 if (dev_options & DEV_RELOAD) { 1575 /* 1576 * If it's not the local set we need to check the local 1577 * namespace to see if disks have moved as it contains 1578 * entries for the disks in the set. 1579 */ 1580 if (setno != MD_LOCAL_SET) { 1581 if ((dd = metaget_drivedesc(sp, MD_BASICNAME_OK | 1582 PRINT_FAST, ep)) == NULL) { 1583 mde_perror(ep, ""); 1584 mdclrerror(ep); 1585 return (METADEVADM_ERR); 1586 } 1587 local_sp = metasetname(MD_LOCAL_NAME, ep); 1588 sideno = getmyside(sp, ep) + SKEW; 1589 for (d = dd; d != NULL; d = d->dd_next) { 1590 /* 1591 * Actually do the check of the disks. 1592 */ 1593 ret = meta_upd_ctdnames(&local_sp, 0, sideno, 1594 d->dd_dnp, &newname, ep); 1595 1596 if ((ret == METADEVADM_ERR) || 1597 (ret == METADEVADM_DSKNAME_ERR)) { 1598 /* check failed in unknown manner */ 1599 mda_debug("meta_upd_ctdnames failed\n"); 1600 return (METADEVADM_ERR); 1601 } 1602 } 1603 } 1604 1605 /* do a reload of the devid namespace */ 1606 ret = pathname_reload(&sp, setno, ep); 1607 } else if (dev_options & DEV_UPDATE) { 1608 pathname = getdiskname(diskname); 1609 ret = devid_update(&sp, setno, pathname, ep); 1610 free(pathname); 1611 } 1612 return (ret); 1613 } 1614