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 /* 23 * Copyright 2006 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 "cfga_scsi.h" 30 31 struct larg { 32 int ndevs; 33 int nelem; 34 char *dev; 35 char **dev_list; 36 }; 37 38 #define ETC_VFSTAB "/etc/vfstab" 39 #define SCFGA_LOCK "/var/run/cfgadm_scsi" 40 41 /* Function prototypes */ 42 43 static scfga_ret_t quiesce_confirm(apid_t *apidp, 44 msgid_t cmd_msg, prompt_t *pt, int *okp, int *quiesce, int *l_errnop); 45 static scfga_ret_t dev_hotplug(apid_t *apidp, 46 prompt_t *pt, cfga_flags_t flags, int quiesce, char **errstring); 47 static int disconnect(struct cfga_confirm *confp); 48 static int critical_ctrlr(const char *hba_phys); 49 static cfga_stat_t bus_devctl_to_recep_state(uint_t bus_dc_state); 50 static int get_hba_children(char *bus_path, char *dev_excl, char ***dev_list); 51 static char *get_node_path(char *minor_path); 52 static void free_dev_list_elements(char **dev_list); 53 static void free_dev_list(char **dev_list); 54 static int alloc_dev_list(struct larg *largp); 55 56 /* 57 * Single thread all implicit quiesce operations 58 */ 59 static mutex_t quiesce_mutex = DEFAULTMUTEX; 60 61 /*ARGSUSED*/ 62 scfga_ret_t 63 bus_change_state( 64 cfga_cmd_t state_change_cmd, 65 apid_t *apidp, 66 struct cfga_confirm *confp, 67 cfga_flags_t flags, 68 char **errstring) 69 { 70 int l_errno = 0, force; 71 uint_t state = 0; 72 cfga_stat_t bus_state; 73 scfga_cmd_t cmd; 74 msgid_t errid; 75 cfga_stat_t prereq; 76 scfga_ret_t ret; 77 char **dev_list = NULL; 78 79 assert(apidp->path != NULL); 80 assert(apidp->hba_phys != NULL); 81 82 /* 83 * No dynamic components allowed 84 */ 85 if (apidp->dyncomp != NULL) { 86 cfga_err(errstring, 0, ERR_NOT_BUSAPID, 0); 87 return (SCFGA_ERR); 88 } 89 90 /* Get bus state */ 91 if (devctl_cmd(apidp->path, SCFGA_BUS_GETSTATE, &state, 92 &l_errno) != SCFGA_OK) { 93 cfga_err(errstring, l_errno, ERR_BUS_GETSTATE, 0); 94 return (SCFGA_ERR); 95 } 96 97 bus_state = bus_devctl_to_recep_state(state); 98 force = ((flags & CFGA_FLAG_FORCE) == CFGA_FLAG_FORCE) ? 1 : 0; 99 assert(confp->confirm != NULL); 100 101 switch (state_change_cmd) { 102 case CFGA_CMD_DISCONNECT: /* quiesce bus */ 103 /* 104 * If force flag not specified, check if controller is 105 * critical. 106 */ 107 if (!force) { 108 /* 109 * This check is not foolproof, get user confirmation 110 * if test passes. 111 */ 112 if (critical_ctrlr(apidp->path)) { 113 cfga_err(errstring, 0, ERR_CTRLR_CRIT, 0); 114 ret = SCFGA_ERR; 115 break; 116 } else if (!disconnect(confp)) { 117 ret = SCFGA_NACK; 118 break; 119 } 120 } 121 122 cmd = SCFGA_BUS_QUIESCE; 123 errid = ERR_BUS_QUIESCE; 124 prereq = CFGA_STAT_CONNECTED; 125 126 goto common; 127 128 case CFGA_CMD_CONNECT: /* unquiesce bus */ 129 cmd = SCFGA_BUS_UNQUIESCE; 130 errid = ERR_BUS_UNQUIESCE; 131 prereq = CFGA_STAT_DISCONNECTED; 132 133 goto common; 134 135 case CFGA_CMD_CONFIGURE: 136 cmd = SCFGA_BUS_CONFIGURE; 137 errid = ERR_BUS_CONFIGURE; 138 prereq = CFGA_STAT_CONNECTED; 139 140 goto common; 141 142 case CFGA_CMD_UNCONFIGURE: 143 cmd = SCFGA_BUS_UNCONFIGURE; 144 errid = ERR_BUS_UNCONFIGURE; 145 prereq = CFGA_STAT_CONNECTED; 146 147 /* FALLTHROUGH */ 148 common: 149 if (bus_state != prereq) { 150 cfga_err(errstring, 0, 151 (prereq == CFGA_STAT_CONNECTED) 152 ? ERR_BUS_NOTCONNECTED 153 : ERR_BUS_CONNECTED, 0); 154 ret = SCFGA_ERR; 155 break; 156 } 157 158 /* 159 * When quiescing or unconfiguring a bus, first suspend or 160 * offline it through RCM. 161 * For unquiescing, we simple build the dev_list for 162 * resume notification. 163 */ 164 if (((apidp->flags & FLAG_DISABLE_RCM) == 0) && 165 ((cmd == SCFGA_BUS_QUIESCE) || 166 (cmd == SCFGA_BUS_UNQUIESCE) || 167 (cmd == SCFGA_BUS_UNCONFIGURE))) { 168 ret = get_hba_children(apidp->path, NULL, &dev_list); 169 if (ret != SCFGA_OK) { 170 break; 171 } 172 if (cmd == SCFGA_BUS_QUIESCE) { 173 if ((ret = scsi_rcm_suspend(dev_list, 174 errstring, flags, 1)) != SCFGA_OK) { 175 break; 176 } 177 } else if (cmd == SCFGA_BUS_UNCONFIGURE) { 178 if ((ret = scsi_rcm_offline(dev_list, 179 errstring, flags)) != SCFGA_OK) { 180 break; 181 } 182 } 183 } 184 185 ret = devctl_cmd(apidp->path, cmd, NULL, &l_errno); 186 if (ret != SCFGA_OK) { 187 /* 188 * EIO when child devices are busy may confuse user. 189 * So explain it. 190 */ 191 if (cmd == SCFGA_BUS_UNCONFIGURE && l_errno == EIO) 192 errid = ERR_MAYBE_BUSY; 193 194 cfga_err(errstring, l_errno, errid, 0); 195 196 /* 197 * If the bus was suspended in RCM, then cancel the RCM 198 * operation. Discard RCM failures here because the 199 * devctl's failure is what is most relevant. 200 */ 201 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) { 202 if (cmd == SCFGA_BUS_QUIESCE) 203 (void) scsi_rcm_resume(dev_list, 204 errstring, 205 (flags & (~CFGA_FLAG_FORCE)), 1); 206 else if (cmd == SCFGA_BUS_UNCONFIGURE) { 207 (void) devctl_cmd(apidp->path, 208 SCFGA_BUS_CONFIGURE, NULL, 209 &l_errno); 210 (void) scsi_rcm_online(dev_list, 211 errstring, 212 (flags & (~CFGA_FLAG_FORCE))); 213 } 214 } 215 216 break; 217 } 218 219 /* 220 * When unquiescing or configuring a bus, resume or online it 221 * in RCM when the devctl command is complete. 222 * When unconfiguring a bus, notify removal of devices. 223 */ 224 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) { 225 if (cmd == SCFGA_BUS_UNQUIESCE) { 226 ret = scsi_rcm_resume(dev_list, errstring, 227 (flags & (~CFGA_FLAG_FORCE)), 1); 228 } else if (cmd == SCFGA_BUS_UNCONFIGURE) { 229 ret = scsi_rcm_remove(dev_list, errstring, 230 (flags & (~CFGA_FLAG_FORCE))); 231 } 232 } 233 break; 234 235 case CFGA_CMD_LOAD: 236 case CFGA_CMD_UNLOAD: 237 ret = SCFGA_OPNOTSUPP; 238 break; 239 240 default: 241 cfga_err(errstring, 0, ERR_CMD_INVAL, 0); 242 ret = SCFGA_ERR; 243 break; 244 } 245 246 free_dev_list(dev_list); 247 return (ret); 248 } 249 250 scfga_ret_t 251 dev_change_state( 252 cfga_cmd_t state_change_cmd, 253 apid_t *apidp, 254 cfga_flags_t flags, 255 char **errstring) 256 { 257 uint_t state = 0; 258 int l_errno = 0; 259 cfga_stat_t bus_state; 260 scfga_cmd_t cmd; 261 msgid_t errid; 262 scfga_ret_t ret; 263 char *dev_list[2] = {NULL}; 264 265 assert(apidp->path != NULL); 266 assert(apidp->hba_phys != NULL); 267 268 /* 269 * For a device, dynamic component must be present 270 */ 271 if (apidp->dyncomp == NULL) { 272 cfga_err(errstring, 0, ERR_APID_INVAL, 0); 273 return (SCFGA_ERR); 274 } 275 276 /* Get bus state */ 277 if (devctl_cmd(apidp->hba_phys, SCFGA_BUS_GETSTATE, &state, 278 &l_errno) != SCFGA_OK) { 279 cfga_err(errstring, l_errno, ERR_BUS_GETSTATE, 0); 280 return (SCFGA_ERR); 281 } 282 283 bus_state = bus_devctl_to_recep_state(state); 284 285 switch (state_change_cmd) { 286 case CFGA_CMD_CONFIGURE: /* online device */ 287 cmd = SCFGA_DEV_CONFIGURE; 288 errid = ERR_DEV_CONFIGURE; 289 goto common; 290 291 case CFGA_CMD_UNCONFIGURE: /* offline device */ 292 cmd = SCFGA_DEV_UNCONFIGURE; 293 errid = ERR_DEV_UNCONFIGURE; 294 /* FALLTHROUGH */ 295 common: 296 if (bus_state != CFGA_STAT_CONNECTED) { 297 cfga_err(errstring, 0, ERR_BUS_NOTCONNECTED, 0); 298 ret = SCFGA_ERR; 299 break; 300 } 301 302 /* When unconfiguring a device, first offline it through RCM. */ 303 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) { 304 if (cmd == SCFGA_DEV_UNCONFIGURE) { 305 dev_list[0] = get_node_path(apidp->path); 306 if (dev_list[0] == NULL) { 307 ret = SCFGA_ERR; 308 break; 309 } 310 if ((ret = scsi_rcm_offline(dev_list, 311 errstring, flags)) != SCFGA_OK) { 312 break; 313 } 314 } 315 } 316 317 ret = devctl_cmd(apidp->path, cmd, NULL, &l_errno); 318 if (ret != SCFGA_OK) { 319 cfga_err(errstring, l_errno, errid, 0); 320 321 /* 322 * If an unconfigure fails, cancel the RCM offline. 323 * Discard any RCM failures so that the devctl 324 * failure will still be reported. 325 */ 326 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) { 327 if (cmd == SCFGA_DEV_UNCONFIGURE) 328 (void) scsi_rcm_online(dev_list, 329 errstring, flags); 330 } 331 break; 332 } 333 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) { 334 /* 335 * Unconfigure succeeded, call the RCM notify_remove. 336 */ 337 if (cmd == SCFGA_DEV_UNCONFIGURE) 338 (void) scsi_rcm_remove(dev_list, 339 errstring, flags); 340 } 341 break; 342 343 /* 344 * Cannot disconnect/connect individual devices without affecting 345 * other devices on the bus. So we don't support these ops. 346 */ 347 case CFGA_CMD_DISCONNECT: 348 case CFGA_CMD_CONNECT: 349 cfga_err(errstring, 0, ERR_NOT_DEVOP, 0); 350 ret = SCFGA_ERR; 351 break; 352 case CFGA_CMD_LOAD: 353 case CFGA_CMD_UNLOAD: 354 ret = SCFGA_OPNOTSUPP; 355 break; 356 default: 357 cfga_err(errstring, 0, ERR_CMD_INVAL, 0); 358 ret = SCFGA_ERR; 359 break; 360 } 361 362 free_dev_list_elements(dev_list); 363 return (ret); 364 } 365 366 /*ARGSUSED*/ 367 scfga_ret_t 368 dev_remove( 369 const char *func, 370 scfga_cmd_t cmd, 371 apid_t *apidp, 372 prompt_t *prp, 373 cfga_flags_t flags, 374 char **errstring) 375 { 376 int proceed, l_errno = 0; 377 scfga_ret_t ret; 378 int do_quiesce; 379 char *dev_list[2] = {NULL}; 380 381 assert(apidp->hba_phys != NULL); 382 assert(apidp->path != NULL); 383 384 /* device operation only */ 385 if (apidp->dyncomp == NULL) { 386 cfga_err(errstring, 0, ERR_NOT_BUSOP, 0); 387 return (SCFGA_ERR); 388 } 389 390 proceed = 1; 391 ret = quiesce_confirm(apidp, MSG_RMDEV, prp, &proceed, &do_quiesce, 392 &l_errno); 393 if (ret != SCFGA_OK) { 394 cfga_err(errstring, l_errno, ERR_DEV_REMOVE, 0); 395 return (ret); 396 } 397 398 if (!proceed) { 399 return (SCFGA_NACK); 400 } 401 402 /* 403 * Offline the device in RCM 404 */ 405 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) { 406 dev_list[0] = get_node_path(apidp->path); 407 if (dev_list[0] == NULL) 408 return (SCFGA_ERR); 409 if ((ret = scsi_rcm_offline(dev_list, errstring, flags)) 410 != SCFGA_OK) { 411 free_dev_list_elements(dev_list); 412 return (ret); 413 } 414 } 415 416 /* 417 * Offline the device 418 */ 419 ret = devctl_cmd(apidp->path, SCFGA_DEV_UNCONFIGURE, NULL, &l_errno); 420 if (ret != SCFGA_OK) { 421 422 cfga_err(errstring, l_errno, ERR_DEV_REMOVE, 0); 423 424 /* 425 * Cancel the RCM offline. Discard the RCM failures so that 426 * the above devctl failure is still reported. 427 */ 428 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) 429 (void) scsi_rcm_online(dev_list, errstring, flags); 430 free_dev_list_elements(dev_list); 431 return (ret); 432 } 433 434 /* Do the physical removal */ 435 ret = dev_hotplug(apidp, prp, flags, do_quiesce, errstring); 436 437 if (ret == SCFGA_OK) { 438 /* 439 * Complete the remove. 440 * Since the device is already offlined, remove shouldn't 441 * fail. Even if remove fails, there is no side effect. 442 */ 443 (void) devctl_cmd(apidp->path, SCFGA_DEV_REMOVE, 444 NULL, &l_errno); 445 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) 446 ret = scsi_rcm_remove(dev_list, errstring, flags); 447 } else { 448 /* 449 * Reconfigure the device and restore the device's RCM state. 450 * If reconfigure succeeds, restore the state to online. 451 * If reconfigure fails (e.g. a typo from user), we treat 452 * the device as removed. 453 */ 454 if (devctl_cmd(apidp->path, SCFGA_DEV_CONFIGURE, NULL, &l_errno) 455 == SCFGA_OK) { 456 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) 457 (void) scsi_rcm_online(dev_list, errstring, 458 flags); 459 } else { 460 char *cp = strrchr(apidp->path, ':'); 461 if (cp) 462 *cp = '\0'; 463 cfga_err(errstring, l_errno, ERR_DEV_RECONFIGURE, 464 apidp->path, 0); 465 if (cp) 466 *cp = ':'; 467 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) 468 (void) scsi_rcm_remove(dev_list, errstring, 469 flags); 470 } 471 } 472 473 free_dev_list_elements(dev_list); 474 return (ret); 475 } 476 477 /*ARGSUSED*/ 478 scfga_ret_t 479 dev_insert( 480 const char *func, 481 scfga_cmd_t cmd, 482 apid_t *apidp, 483 prompt_t *prp, 484 cfga_flags_t flags, 485 char **errstring) 486 { 487 int proceed, l_errno = 0; 488 scfga_ret_t ret; 489 int do_quiesce; 490 491 assert(apidp->hba_phys != NULL); 492 assert(apidp->path != NULL); 493 494 /* Currently, insert operation only allowed for bus */ 495 if (apidp->dyncomp != NULL) { 496 cfga_err(errstring, 0, ERR_NOT_DEVOP, 0); 497 return (SCFGA_ERR); 498 } 499 500 proceed = 1; 501 ret = quiesce_confirm(apidp, MSG_INSDEV, prp, &proceed, &do_quiesce, 502 &l_errno); 503 if (ret != SCFGA_OK) { 504 cfga_err(errstring, l_errno, ERR_DEV_INSERT, 0); 505 return (ret); 506 } 507 508 if (!proceed) { 509 return (SCFGA_NACK); 510 } 511 512 /* Do the physical addition */ 513 ret = dev_hotplug(apidp, prp, flags, do_quiesce, errstring); 514 if (ret != SCFGA_OK) { 515 return (ret); 516 } 517 518 /* 519 * Configure bus to online new device(s). 520 * Previously offlined devices will not be onlined. 521 */ 522 ret = devctl_cmd(apidp->hba_phys, SCFGA_BUS_CONFIGURE, NULL, &l_errno); 523 if (ret != SCFGA_OK) { 524 cfga_err(errstring, l_errno, ERR_DEV_INSERT, 0); 525 return (SCFGA_ERR); 526 } 527 528 return (SCFGA_OK); 529 } 530 531 /*ARGSUSED*/ 532 scfga_ret_t 533 dev_replace( 534 const char *func, 535 scfga_cmd_t cmd, 536 apid_t *apidp, 537 prompt_t *prp, 538 cfga_flags_t flags, 539 char **errstring) 540 { 541 int proceed, l_errno = 0; 542 scfga_ret_t ret, ret2; 543 int do_quiesce; 544 char *dev_list[2] = {NULL}; 545 546 assert(apidp->hba_phys != NULL); 547 assert(apidp->path != NULL); 548 549 /* device operation only */ 550 if (apidp->dyncomp == NULL) { 551 cfga_err(errstring, 0, ERR_NOT_BUSOP, 0); 552 return (SCFGA_ERR); 553 } 554 555 proceed = 1; 556 ret = quiesce_confirm(apidp, MSG_REPLDEV, prp, &proceed, &do_quiesce, 557 &l_errno); 558 if (ret != SCFGA_OK) { 559 cfga_err(errstring, l_errno, ERR_DEV_REPLACE, 0); 560 return (ret); 561 } 562 563 if (!proceed) { 564 return (SCFGA_NACK); 565 } 566 567 /* Offline the device in RCM */ 568 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) { 569 dev_list[0] = get_node_path(apidp->path); 570 if (dev_list[0] == NULL) 571 return (SCFGA_ERR); 572 if ((ret = scsi_rcm_offline(dev_list, errstring, flags)) 573 != SCFGA_OK) { 574 free_dev_list_elements(dev_list); 575 return (ret); 576 } 577 } 578 579 ret = devctl_cmd(apidp->path, SCFGA_DEV_REMOVE, NULL, &l_errno); 580 if (ret != SCFGA_OK) { 581 582 /* 583 * Cancel the RCM offline. Discard any RCM failures so that 584 * the devctl failure can still be reported. 585 */ 586 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) 587 (void) scsi_rcm_online(dev_list, errstring, flags); 588 589 cfga_err(errstring, l_errno, ERR_DEV_REPLACE, 0); 590 free_dev_list_elements(dev_list); 591 return (ret); 592 } 593 594 /* do the physical replace */ 595 ret = dev_hotplug(apidp, prp, flags, do_quiesce, errstring); 596 597 /* Online the replacement, or restore state on error */ 598 ret2 = devctl_cmd(apidp->path, SCFGA_DEV_CONFIGURE, NULL, &l_errno); 599 600 if (ret2 != SCFGA_OK) { 601 cfga_err(errstring, l_errno, ERR_DEV_REPLACE, 0); 602 } 603 604 /* 605 * Remove the replaced device in RCM, or online the device in RCM 606 * to recover. 607 */ 608 if ((apidp->flags & FLAG_DISABLE_RCM) == 0) { 609 if (ret == SCFGA_OK) 610 ret = scsi_rcm_remove(dev_list, errstring, flags); 611 else if (ret2 == SCFGA_OK) 612 ret2 = scsi_rcm_online(dev_list, errstring, flags); 613 } 614 free_dev_list_elements(dev_list); 615 616 return (ret == SCFGA_OK ? ret2 : ret); 617 } 618 619 #pragma weak plat_dev_led 620 /*ARGSUSED*/ 621 scfga_ret_t 622 dev_led( 623 const char *func, 624 scfga_cmd_t cmd, 625 apid_t *apidp, 626 prompt_t *prp, 627 cfga_flags_t flags, 628 char **errstring) 629 { 630 631 /* 632 * The implementation of the led command is platform-specific, so 633 * the default behavior is to say that the functionality is not 634 * available for this device. 635 */ 636 if (plat_dev_led) { 637 return (plat_dev_led(func, cmd, apidp, prp, flags, errstring)); 638 } 639 cfga_err(errstring, 0, ERR_UNAVAILABLE, 0); 640 return (SCFGA_ERR); 641 } 642 643 /*ARGSUSED*/ 644 scfga_ret_t 645 reset_common( 646 const char *func, 647 scfga_cmd_t cmd, 648 apid_t *apidp, 649 prompt_t *prp, 650 cfga_flags_t flags, 651 char **errstring) 652 { 653 int l_errno = 0; 654 scfga_ret_t ret; 655 656 657 assert(apidp->path != NULL); 658 assert(apidp->hba_phys != NULL); 659 660 switch (cmd) { 661 case SCFGA_RESET_DEV: 662 if (apidp->dyncomp == NULL) { 663 cfga_err(errstring, 0, ERR_NOT_BUSOP, 0); 664 return (SCFGA_ERR); 665 } 666 break; 667 668 case SCFGA_RESET_BUS: 669 case SCFGA_RESET_ALL: 670 if (apidp->dyncomp != NULL) { 671 cfga_err(errstring, 0, ERR_NOT_DEVOP, 0); 672 return (SCFGA_ERR); 673 } 674 break; 675 default: 676 cfga_err(errstring, 0, ERR_CMD_INVAL, 0); 677 return (SCFGA_ERR); 678 } 679 680 ret = devctl_cmd(apidp->path, cmd, NULL, &l_errno); 681 if (ret != SCFGA_OK) { 682 cfga_err(errstring, l_errno, ERR_RESET, 0); 683 } 684 685 return (ret); 686 } 687 688 static int 689 disconnect(struct cfga_confirm *confp) 690 { 691 int ans, append_newline; 692 char *cq; 693 694 append_newline = 0; 695 cq = cfga_str(append_newline, WARN_DISCONNECT, 0); 696 697 ans = confp->confirm(confp->appdata_ptr, cq); 698 699 S_FREE(cq); 700 701 return (ans == 1); 702 } 703 704 /* 705 * Check for "scsi-no-quiesce" property 706 * Return code: -1 error, 0 quiesce not required, 1 quiesce required 707 */ 708 static int 709 quiesce_required(apid_t *apidp, int *l_errnop) 710 { 711 di_node_t bus_node, dev_node; 712 char *bus_path, *bus_end; 713 char *dev_path, *dev_end; 714 int *propval; 715 716 /* take libdevinfo snapshot of subtree at hba */ 717 bus_path = apidp->hba_phys + strlen(DEVICES_DIR); 718 bus_end = strrchr(bus_path, ':'); 719 if (bus_end) 720 *bus_end = '\0'; 721 722 bus_node = di_init(bus_path, DINFOSUBTREE|DINFOPROP); 723 if (bus_end) 724 *bus_end = ':'; 725 if (bus_node == DI_NODE_NIL) { 726 *l_errnop = errno; 727 return (-1); /* error */ 728 } 729 730 /* check bus node for property */ 731 if (di_prop_lookup_ints(DDI_DEV_T_ANY, bus_node, SCSI_NO_QUIESCE, 732 &propval) == 1) { 733 di_fini(bus_node); 734 return (0); /* quiesce not required */ 735 } 736 737 /* if this ap is HBA, return with quiesce required */ 738 if (apidp->dyncomp == NULL) { 739 di_fini(bus_node); 740 return (1); 741 } 742 743 /* check device node for property */ 744 dev_path = apidp->path + strlen(DEVICES_DIR); 745 dev_end = strrchr(dev_path, ':'); 746 if (dev_end) 747 *dev_end = '\0'; 748 749 dev_node = di_child_node(bus_node); 750 while (dev_node != DI_NODE_NIL) { 751 char *child_path; 752 child_path = di_devfs_path(dev_node); 753 if (strcmp(child_path, dev_path) == 0) { 754 di_devfs_path_free(child_path); 755 break; 756 } 757 di_devfs_path_free(child_path); 758 dev_node = di_sibling_node(dev_node); 759 } 760 761 if (dev_end) 762 *dev_end = ':'; 763 if (dev_node == DI_NODE_NIL) { 764 di_fini(bus_node); 765 return (1); /* dev not found (insert case) */ 766 } 767 768 /* check child node for property */ 769 if (di_prop_lookup_ints(DDI_DEV_T_ANY, dev_node, "scsi-no-quiesce", 770 &propval) == 1) { 771 di_fini(bus_node); 772 return (0); /* quiesce not required */ 773 } 774 return (1); /* quiesce required */ 775 } 776 777 static scfga_ret_t 778 quiesce_confirm( 779 apid_t *apidp, 780 msgid_t cmd_msg, 781 prompt_t *prp, 782 int *okp, 783 int *quiesce, 784 int *l_errnop) 785 { 786 char *buf = NULL, *hbap = NULL, *cq1 = NULL, *cq2 = NULL; 787 char *cp; 788 size_t len = 0; 789 int i = 0, append_newline; 790 scfga_ret_t ret; 791 792 assert(apidp->path != NULL); 793 assert(apidp->hba_phys != NULL); 794 795 *quiesce = quiesce_required(apidp, l_errnop); 796 if (*quiesce == -1) 797 return (SCFGA_ERR); 798 else if (*quiesce == 0) 799 return (SCFGA_OK); 800 801 /* 802 * Try to create HBA logical ap_id. 803 * If that fails use physical path 804 */ 805 ret = make_hba_logid(apidp->hba_phys, &hbap, &i); 806 if (ret != SCFGA_OK) { 807 if ((hbap = get_node_path(apidp->hba_phys)) == NULL) { 808 *l_errnop = errno; 809 return (SCFGA_LIB_ERR); 810 } 811 } 812 813 assert(hbap != NULL); 814 815 append_newline = 0; 816 cq1 = cfga_str(append_newline, CONF_QUIESCE_1, hbap, 0); 817 cq2 = cfga_str(append_newline, CONF_QUIESCE_2, 0); 818 len = strlen(cq1) + strlen(cq2) + 1; /* Includes term. NULL */ 819 820 if ((buf = calloc(1, len)) == NULL) { 821 *l_errnop = errno; 822 ret = SCFGA_LIB_ERR; 823 S_FREE(cq1); 824 S_FREE(cq2); 825 goto out; 826 } 827 (void) strcpy(buf, cq1); 828 (void) strcat(buf, cq2); 829 830 S_FREE(cq1); 831 S_FREE(cq2); 832 833 834 /* Remove minor name (if any) from phys path */ 835 if ((cp = strrchr(apidp->path, ':')) != NULL) { 836 *cp = '\0'; 837 } 838 839 /* describe operation being attempted */ 840 cfga_msg(prp->msgp, cmd_msg, apidp->path, 0); 841 842 /* Restore minor name */ 843 if (cp != NULL) { 844 *cp = ':'; 845 } 846 847 /* request permission to quiesce */ 848 assert(prp->confp != NULL && prp->confp->confirm != NULL); 849 *okp = prp->confp->confirm(prp->confp->appdata_ptr, buf); 850 851 ret = SCFGA_OK; 852 /*FALLTHRU*/ 853 out: 854 S_FREE(buf); 855 S_FREE(hbap); 856 return (ret); 857 } 858 859 static scfga_ret_t 860 suspend_in_rcm( 861 apid_t *apidp, 862 char ***suspend_list_ptr, 863 char **errstring, 864 cfga_flags_t flags) 865 { 866 scfga_ret_t ret; 867 char *bus_path = NULL; 868 char *dev_path = NULL; 869 char **suspend_list = NULL; 870 871 *suspend_list_ptr = NULL; 872 873 /* Suspend the bus through RCM */ 874 if (apidp->flags & FLAG_DISABLE_RCM) 875 return (SCFGA_OK); 876 877 /* The bus_path is the HBA path without its minor */ 878 if ((bus_path = get_node_path(apidp->hba_phys)) == NULL) 879 return (SCFGA_ERR); 880 881 /* 882 * The dev_path is already initialized to NULL. If the AP Id 883 * path differs from the HBA path, then the dev_path should 884 * instead be set to the AP Id path without its minor. 885 */ 886 if (strcmp(apidp->hba_phys, apidp->path) != 0) { 887 if ((dev_path = get_node_path(apidp->path)) == NULL) { 888 ret = SCFGA_ERR; 889 goto out; 890 } 891 } 892 893 if ((ret = get_hba_children(bus_path, dev_path, &suspend_list)) 894 != SCFGA_OK) { 895 free_dev_list(suspend_list); 896 goto out; 897 } 898 899 if (scsi_rcm_suspend(suspend_list, errstring, flags, 0) != SCFGA_OK) { 900 ret = SCFGA_ERR; 901 free_dev_list(suspend_list); 902 } else { 903 ret = SCFGA_OK; 904 *suspend_list_ptr = suspend_list; 905 } 906 /*FALLTHROUGH*/ 907 out: 908 S_FREE(bus_path); 909 S_FREE(dev_path); 910 return (ret); 911 } 912 913 /* 914 * Resume the bus through RCM if it successfully 915 * unquiesced. 916 */ 917 static void 918 resume_in_rcm( 919 apid_t *apidp, 920 char **suspend_list, 921 char **errstring, 922 cfga_flags_t flags) 923 { 924 if (apidp->flags & FLAG_DISABLE_RCM) 925 return; 926 927 (void) scsi_rcm_resume(suspend_list, errstring, flags, 0); 928 929 free_dev_list(suspend_list); 930 } 931 932 static scfga_ret_t 933 wait_for_hotplug(prompt_t *pt, int msg) 934 { 935 char *cu = NULL; 936 int append_newline = 0; 937 scfga_ret_t ret; 938 939 cu = cfga_str(append_newline, msg, 0); 940 if (pt->confp->confirm(pt->confp->appdata_ptr, cu) != 1) { 941 ret = SCFGA_NACK; 942 } else { 943 ret = SCFGA_OK; 944 } 945 S_FREE(cu); 946 return (ret); 947 } 948 949 static scfga_ret_t 950 bus_quiesce(apid_t *apidp, prompt_t *pt, char **errstring, cfga_flags_t flags) 951 { 952 int l_errno; 953 scfga_ret_t ret; 954 scfga_ret_t hpret; 955 char **suspend_list = NULL; 956 957 ret = suspend_in_rcm(apidp, &suspend_list, errstring, flags); 958 if (ret != SCFGA_OK) { 959 return (ret); 960 } 961 962 /* 963 * If the quiesce fails, then cancel the RCM suspend. 964 * Discard any RCM failures so that the devctl failure 965 * can still be reported. 966 */ 967 l_errno = 0; 968 ret = devctl_cmd(apidp->hba_phys, SCFGA_BUS_QUIESCE, NULL, &l_errno); 969 if (ret != SCFGA_OK) { 970 resume_in_rcm(apidp, suspend_list, errstring, flags); 971 cfga_err(errstring, l_errno, ERR_BUS_QUIESCE, 0); 972 return (ret); 973 } 974 975 /* 976 * Prompt user to proceed with physical hotplug 977 * and wait until they are done. 978 */ 979 hpret = wait_for_hotplug(pt, CONF_UNQUIESCE); 980 981 /* 982 * The unquiesce may fail with EALREADY (which is ok) 983 * or some other error (which is not ok). 984 */ 985 l_errno = 0; 986 ret = devctl_cmd(apidp->hba_phys, SCFGA_BUS_UNQUIESCE, NULL, &l_errno); 987 if (ret != SCFGA_OK && l_errno != EALREADY) { 988 free_dev_list(suspend_list); 989 cfga_err(errstring, l_errno, ERR_BUS_UNQUIESCE, 0); 990 return (SCFGA_ERR); 991 } 992 993 resume_in_rcm(apidp, suspend_list, errstring, flags); 994 995 return (hpret); 996 } 997 998 #define MAX_LOCK_TRIES 20 999 #define MAX_UNLINK_TRIES 60 1000 #define s_getpid (int)getpid /* else lint causes problems */ 1001 1002 static void 1003 s_unlink(char *file) 1004 { 1005 int count = 0; 1006 1007 retry: 1008 if (unlink(file) == -1) { 1009 if (errno != EINTR && errno != EAGAIN) { 1010 CFGA_TRACE1((stdout, "s_unlink[%d]: unlink failed: " 1011 "%s: %s\n", s_getpid(), file, strerror(errno))); 1012 return; 1013 } 1014 1015 if (++count < MAX_UNLINK_TRIES) { 1016 (void) sleep(1); 1017 goto retry; 1018 } 1019 CFGA_TRACE1((stdout, "s_unlink[%d]: retry limit: %s\n", 1020 s_getpid(), file)); 1021 } else { 1022 CFGA_TRACE3((stdout, "s_unlink[%d]: unlinked: %s\n", 1023 s_getpid(), file)); 1024 } 1025 } 1026 1027 static scfga_ret_t 1028 create_lock(int *fdp, struct cfga_msg *msgp, char **errstring) 1029 { 1030 FILE *fp; 1031 int count; 1032 struct extmnttab ent; 1033 int mnted; 1034 1035 1036 *fdp = -1; 1037 1038 /* 1039 * Check that /var/run is mounted. In the unlikely event 1040 * that the lock file is left behind, we want it 1041 * cleared on the next reboot. 1042 */ 1043 errno = 0; 1044 if ((fp = fopen(MNTTAB, "r")) == NULL) { 1045 cfga_err(errstring, errno, ERRARG_OPEN, MNTTAB, 0); 1046 return (SCFGA_LIB_ERR); 1047 } 1048 1049 resetmnttab(fp); 1050 1051 mnted = 0; 1052 while (getextmntent(fp, &ent, sizeof (ent)) == 0) { 1053 if (strcmp(ent.mnt_mountp, "/var/run") == 0) { 1054 mnted = 1; 1055 break; 1056 } 1057 } 1058 1059 (void) fclose(fp); 1060 1061 if (!mnted) { 1062 cfga_err(errstring, 0, ERR_VAR_RUN, 0); 1063 return (SCFGA_LIB_ERR); 1064 } 1065 1066 /* 1067 * Wait for a short period of time if we cannot O_EXCL create 1068 * lock file. If some other cfgadm process is finishing up, we 1069 * can get in. If the wait required is long however, just 1070 * return SYSTEM_BUSY to the user - a hotplug operation is 1071 * probably in progress. 1072 */ 1073 count = 0; 1074 retry: 1075 *fdp = open(SCFGA_LOCK, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); 1076 if (*fdp == -1 && errno == EEXIST) { 1077 if (++count < MAX_LOCK_TRIES) { 1078 if (count == 1) 1079 cfga_msg(msgp, MSG_WAIT_LOCK, 0); 1080 (void) sleep(1); 1081 goto retry; 1082 } 1083 } 1084 1085 if (*fdp == -1 && errno == EEXIST) { 1086 cfga_err(errstring, 0, ERRARG_QUIESCE_LOCK, SCFGA_LOCK, 0); 1087 return (SCFGA_SYSTEM_BUSY); 1088 } else if (*fdp == -1) { 1089 cfga_err(errstring, errno, ERRARG_QUIESCE_LOCK, SCFGA_LOCK, 0); 1090 return (SCFGA_LIB_ERR); 1091 } 1092 1093 CFGA_TRACE3((stdout, "create_lock[%d]: created lockfile: %s\n", 1094 s_getpid(), SCFGA_LOCK)); 1095 1096 return (SCFGA_OK); 1097 } 1098 1099 static scfga_ret_t 1100 syslock(int fd, char **errstring) 1101 { 1102 struct flock lock; 1103 int count; 1104 int rval; 1105 1106 assert(fd != -1); 1107 1108 CFGA_TRACE3((stdout, "syslock[%d]: trying lock: %s\n", 1109 s_getpid(), SCFGA_LOCK)); 1110 1111 lock.l_type = F_WRLCK; 1112 lock.l_whence = SEEK_SET; 1113 lock.l_start = 0; 1114 lock.l_len = 0; 1115 1116 count = 0; 1117 while ((rval = fcntl(fd, F_SETLKW, &lock)) == -1 && errno == EINTR) { 1118 if (++count >= MAX_LOCK_TRIES) { 1119 CFGA_TRACE1((stdout, "syslock[%d]: retry limit: %s\n", 1120 s_getpid(), SCFGA_LOCK)); 1121 goto badlock; 1122 } 1123 (void) sleep(1); 1124 } 1125 1126 if (rval != -1) { 1127 CFGA_TRACE3((stdout, "syslock[%d]: locked file: %s\n", 1128 s_getpid(), SCFGA_LOCK)); 1129 return (SCFGA_OK); 1130 } 1131 1132 /*FALLTHROUGH*/ 1133 badlock: 1134 cfga_err(errstring, errno, ERRARG_LOCK, SCFGA_LOCK, 0); 1135 /* trace message to display pid */ 1136 CFGA_TRACE1((stdout, "syslock[%d]: cannot lock %s\n", 1137 s_getpid(), SCFGA_LOCK)); 1138 return (SCFGA_LIB_ERR); 1139 } 1140 1141 static void 1142 wait_for_child(pid_t cpid) 1143 { 1144 int status; 1145 pid_t rval; 1146 1147 CFGA_TRACE2((stdout, "wait_for_child[%d]: child[%d]\n", 1148 s_getpid(), (int)cpid)); 1149 1150 for (;;) { 1151 while ((rval = waitpid(cpid, &status, 0)) != cpid) { 1152 if (errno == ECHILD) { 1153 CFGA_TRACE1((stdout, "waitpid[%d]: child[%d] " 1154 "doesn't exist\n", s_getpid(), (int)cpid)); 1155 return; 1156 } 1157 1158 CFGA_TRACE3((stdout, "waitpid[%d]: returned: %d" 1159 ": errno: %s\n", s_getpid(), (int)rval, 1160 strerror(errno))); 1161 } 1162 1163 if (WIFEXITED(status)) { 1164 CFGA_TRACE2((stdout, "waitpid[%d]: child[%d]: " 1165 "normal exit\n", s_getpid(), (int)cpid)); 1166 return; 1167 } 1168 1169 if (WIFSIGNALED(status)) { 1170 CFGA_TRACE2((stdout, "waitpid[%d]: child[%d]: " 1171 "signal exit\n", s_getpid(), (int)cpid)); 1172 return; 1173 } 1174 1175 /* 1176 * The child has not terminated. We received status 1177 * because the child was either stopped or continued. 1178 * Wait for child termination by calling waitpid() again. 1179 */ 1180 } 1181 } 1182 1183 static void 1184 wait_and_cleanup(int fd, apid_t *apidp) 1185 { 1186 int l_errno; 1187 scfga_ret_t ret; 1188 1189 /* This is the child */ 1190 CFGA_TRACE2((stdout, "child[%d]: Entering wait_cleanup\n", s_getpid())); 1191 1192 if (syslock(fd, NULL) != SCFGA_OK) { 1193 CFGA_TRACE1((stdout, "child[%d]: lock failure " 1194 " - _exit(1)\n", s_getpid())); 1195 /* 1196 * As a last resort, unlink the lock file. This is relatively 1197 * safe as the child doesn't unquiesce the bus in this case. 1198 */ 1199 s_unlink(SCFGA_LOCK); 1200 _exit(1); 1201 } 1202 1203 l_errno = 0; 1204 ret = devctl_cmd(apidp->hba_phys, SCFGA_BUS_UNQUIESCE, NULL, &l_errno); 1205 if (ret != SCFGA_OK) { 1206 if (l_errno == EALREADY) 1207 CFGA_TRACE3((stdout, "child[%d]: bus already " 1208 "unquiesced: %s\n", s_getpid(), apidp->hba_phys)); 1209 else 1210 CFGA_TRACE1((stdout, "child[%d]: unquiesce failed: " 1211 "%s\n", s_getpid(), strerror(l_errno))); 1212 } else { 1213 CFGA_TRACE1((stdout, "child[%d]: unquiesced bus: %s\n", 1214 s_getpid(), apidp->hba_phys)); 1215 } 1216 1217 s_unlink(SCFGA_LOCK); 1218 1219 CFGA_TRACE2((stdout, "child[%d]: _exit(0)\n", s_getpid())); 1220 1221 _exit(0); 1222 } 1223 1224 static void 1225 sigblk(sigset_t *osp) 1226 { 1227 sigset_t set; 1228 1229 (void) sigemptyset(&set); 1230 (void) sigemptyset(osp); 1231 (void) sigaddset(&set, SIGHUP); 1232 (void) sigaddset(&set, SIGINT); 1233 (void) sigaddset(&set, SIGQUIT); 1234 (void) sigaddset(&set, SIGTERM); 1235 (void) sigaddset(&set, SIGUSR1); 1236 (void) sigaddset(&set, SIGUSR2); 1237 (void) sigprocmask(SIG_BLOCK, &set, osp); 1238 } 1239 1240 static void 1241 sigunblk(sigset_t *osp) 1242 { 1243 (void) sigprocmask(SIG_SETMASK, osp, NULL); 1244 } 1245 1246 /* 1247 * Here is the algorithm used to ensure that a SCSI bus is not 1248 * left in the quiesced state: 1249 * 1250 * lock quiesce mutex // single threads this code 1251 * open(O_CREAT|O_EXCL) lock file // only 1 process at a time 1252 * exclusive record lock on lock file 1253 * fork1() 1254 * quiesce bus 1255 * do the physical hotplug operation 1256 * unquiesce bus 1257 * unlock record lock 1258 * -> *child* 1259 * -> wait for record lock 1260 * -> unconditionally unquiesce bus 1261 * -> unlink lock file 1262 * -> exit 1263 * wait for child to exit 1264 * unlock quiesce mutex 1265 * 1266 * NOTE1: since record locks are per-process and a close() can 1267 * release a lock, to keep things MT-safe we need a quiesce mutex. 1268 * 1269 * NOTE2: To ensure that the child does not unquiesce a bus quiesced 1270 * by an unrelated cfgadm_scsi operation, exactly 1 process in the 1271 * system can be doing an implicit quiesce operation The exclusive 1272 * creation of the lock file guarantees this. 1273 * 1274 * NOTE3: This works even if the parent process dumps core and/or is 1275 * abnormally terminated. If the parent dies before the child is 1276 * forked, the bus is not quiesced. If the parent dies after the 1277 * bus is quiesced, the child process will ensure that the bus is 1278 * unquiesced. 1279 */ 1280 static scfga_ret_t 1281 dev_hotplug( 1282 apid_t *apidp, 1283 prompt_t *pt, 1284 cfga_flags_t flags, 1285 int do_quiesce, 1286 char **errstring) 1287 { 1288 scfga_ret_t ret; 1289 pid_t cpid; 1290 int fd; 1291 sigset_t oset; 1292 1293 assert(apidp->hba_phys != NULL); 1294 assert(apidp->path != NULL); 1295 1296 /* If no quiesce required, prompt the user to do the operation */ 1297 if (!do_quiesce) 1298 return (wait_for_hotplug(pt, CONF_NO_QUIESCE)); 1299 1300 (void) mutex_lock(&quiesce_mutex); 1301 1302 ret = create_lock(&fd, pt->msgp, errstring); 1303 if (ret != SCFGA_OK) { 1304 (void) mutex_unlock(&quiesce_mutex); 1305 return (ret); 1306 } 1307 1308 ret = syslock(fd, errstring); 1309 if (ret != SCFGA_OK) { 1310 goto bad; 1311 } 1312 1313 /* 1314 * block signals in the child. Parent may 1315 * exit, causing signal to be sent to child. 1316 */ 1317 sigblk(&oset); 1318 1319 switch (cpid = fork1()) { 1320 case 0: 1321 /* child */ 1322 wait_and_cleanup(fd, apidp); 1323 _exit(0); /* paranoia */ 1324 /*NOTREACHED*/ 1325 case -1: 1326 cfga_err(errstring, errno, ERR_FORK, 0); 1327 sigunblk(&oset); 1328 ret = SCFGA_LIB_ERR; 1329 goto bad; 1330 default: 1331 /* parent */ 1332 break; 1333 } 1334 1335 sigunblk(&oset); 1336 1337 /* We have forked successfully - this is the parent */ 1338 ret = bus_quiesce(apidp, pt, errstring, flags); 1339 1340 (void) close(fd); /* also unlocks */ 1341 1342 wait_for_child(cpid); 1343 1344 (void) mutex_unlock(&quiesce_mutex); 1345 1346 return (ret); 1347 bad: 1348 (void) close(fd); 1349 s_unlink(SCFGA_LOCK); 1350 (void) mutex_unlock(&quiesce_mutex); 1351 return (ret); 1352 } 1353 1354 /* 1355 * Checks if HBA controls a critical file-system (/, /usr or swap) 1356 * This routine reads /etc/vfstab and is NOT foolproof. 1357 * If an error occurs, assumes that controller is NOT critical. 1358 */ 1359 static int 1360 critical_ctrlr(const char *hba_phys) 1361 { 1362 FILE *fp; 1363 struct vfstab vfst; 1364 int vfsret = 1, rv = -1; 1365 char *bufp; 1366 const size_t buflen = PATH_MAX; 1367 char mount[MAXPATHLEN], fstype[MAXPATHLEN], spec[MAXPATHLEN]; 1368 1369 1370 if ((bufp = calloc(1, buflen)) == NULL) { 1371 return (0); 1372 } 1373 1374 fp = NULL; 1375 if ((fp = fopen(ETC_VFSTAB, "r")) == NULL) { 1376 rv = 0; 1377 goto out; 1378 } 1379 1380 while ((vfsret = getvfsent(fp, &vfst)) == 0) { 1381 1382 (void) strcpy(mount, S_STR(vfst.vfs_mountp)); 1383 (void) strcpy(fstype, S_STR(vfst.vfs_fstype)); 1384 (void) strcpy(spec, S_STR(vfst.vfs_special)); 1385 1386 /* Ignore non-critical entries */ 1387 if (strcmp(mount, "/") && strcmp(mount, "/usr") && 1388 strcmp(fstype, "swap")) { 1389 continue; 1390 } 1391 1392 /* get physical path */ 1393 if (realpath(spec, bufp) == NULL) { 1394 continue; 1395 } 1396 1397 /* Check if critical partition is on the HBA */ 1398 if (!(rv = hba_dev_cmp(hba_phys, bufp))) { 1399 break; 1400 } 1401 } 1402 1403 rv = !vfsret; 1404 1405 /*FALLTHRU*/ 1406 out: 1407 S_FREE(bufp); 1408 if (fp != NULL) { 1409 (void) fclose(fp); 1410 } 1411 return (rv); 1412 } 1413 1414 /* 1415 * Convert bus state to receptacle state 1416 */ 1417 static cfga_stat_t 1418 bus_devctl_to_recep_state(uint_t bus_dc_state) 1419 { 1420 cfga_stat_t rs; 1421 1422 switch (bus_dc_state) { 1423 case BUS_ACTIVE: 1424 rs = CFGA_STAT_CONNECTED; 1425 break; 1426 case BUS_QUIESCED: 1427 case BUS_SHUTDOWN: 1428 rs = CFGA_STAT_DISCONNECTED; 1429 break; 1430 default: 1431 rs = CFGA_STAT_NONE; 1432 break; 1433 } 1434 1435 return (rs); 1436 } 1437 1438 static int 1439 add_dev(di_node_t node, void *arg) 1440 { 1441 int ndevs, len; 1442 char *path, *p; 1443 struct larg *largp = (struct larg *)arg; 1444 1445 /* ignore hba itself and all detached nodes */ 1446 if (di_parent_node(node) == DI_NODE_NIL || 1447 di_node_state(node) < DS_ATTACHED) 1448 return (DI_WALK_CONTINUE); 1449 1450 if ((path = di_devfs_path(node)) == NULL) { 1451 largp->ndevs = -1; 1452 return (DI_WALK_TERMINATE); 1453 } 1454 1455 /* sizeof (DEVICES_DIR) includes the null terminator */ 1456 len = strlen(path) + sizeof (DEVICES_DIR); 1457 if ((p = malloc(len)) == NULL) { 1458 di_devfs_path_free(path); 1459 largp->ndevs = -1; 1460 return (DI_WALK_TERMINATE); 1461 } 1462 (void) snprintf(p, len, "%s%s", DEVICES_DIR, path); 1463 di_devfs_path_free(path); 1464 1465 /* ignore device to be excluded */ 1466 if (largp->dev && strcmp(largp->dev, p) == 0) { 1467 free(p); 1468 return (DI_WALK_CONTINUE); 1469 } 1470 1471 /* grow dev_list to allow room for one more device */ 1472 if (alloc_dev_list(largp) != 0) { 1473 free(p); 1474 return (DI_WALK_TERMINATE); 1475 } 1476 ndevs = largp->ndevs; 1477 largp->ndevs++; 1478 largp->dev_list[ndevs] = p; 1479 largp->dev_list[ndevs + 1] = NULL; 1480 return (DI_WALK_CONTINUE); 1481 } 1482 1483 /* 1484 * Get list of children excluding dev_excl (if not null). 1485 */ 1486 static int 1487 get_hba_children(char *bus_path, char *dev_excl, char ***dev_listp) 1488 { 1489 int err, ret; 1490 walkarg_t u; 1491 struct larg larg; 1492 1493 *dev_listp = NULL; 1494 1495 u.node_args.flags = DI_WALK_CLDFIRST; 1496 u.node_args.fcn = add_dev; 1497 1498 larg.ndevs = 0; 1499 larg.nelem = 0; 1500 larg.dev = dev_excl; 1501 larg.dev_list = NULL; 1502 1503 ret = walk_tree(bus_path, &larg, DINFOSUBTREE, &u, SCFGA_WALK_NODE, 1504 &err); 1505 if (larg.ndevs == -1) { 1506 free_dev_list(larg.dev_list); 1507 return (SCFGA_ERR); 1508 } 1509 *dev_listp = larg.dev_list; 1510 return (ret); 1511 } 1512 1513 static char * 1514 get_node_path(char *minor_path) 1515 { 1516 char *path, *cp; 1517 1518 if ((path = strdup(minor_path)) == NULL) 1519 return (NULL); 1520 if ((cp = strrchr(path, ':')) != NULL) 1521 *cp = '\0'; 1522 return (path); 1523 } 1524 1525 /* 1526 * Ensure largp->dev_list has room for one more device. 1527 * Returns 0 on success, -1 on failure. 1528 */ 1529 static int 1530 alloc_dev_list(struct larg *largp) 1531 { 1532 int nelem; 1533 char **p; 1534 1535 if (largp->nelem > largp->ndevs + 2) /* +1 for NULL termination */ 1536 return (0); 1537 1538 nelem = largp->nelem + 16; 1539 p = realloc(largp->dev_list, nelem * sizeof (char *)); 1540 if (p == NULL) 1541 return (-1); 1542 1543 largp->dev_list = p; 1544 largp->nelem = nelem; 1545 return (0); 1546 } 1547 1548 static void 1549 free_dev_list_elements(char **dev_list) 1550 { 1551 while (*dev_list) { 1552 free(*dev_list); 1553 dev_list++; 1554 } 1555 } 1556 1557 static void 1558 free_dev_list(char **dev_list) 1559 { 1560 if (dev_list == NULL) 1561 return; 1562 1563 free_dev_list_elements(dev_list); 1564 free(dev_list); 1565 } 1566