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