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