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