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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <syslog.h> 27 #include <errno.h> 28 #include <unistd.h> 29 #include <stropts.h> 30 31 #include "mp_utils.h" 32 33 #include <libdevinfo.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <fcntl.h> 37 #include <sys/stat.h> 38 39 40 static MP_STATUS doDevInfoStuffForIntPort(MP_OID oid) 41 { 42 di_node_t root_node = DI_NODE_NIL; 43 44 di_node_t vh_node = DI_NODE_NIL; 45 di_node_t ph_node = DI_NODE_NIL; 46 di_node_t sv_node = DI_NODE_NIL; 47 48 49 di_path_t path = DI_PATH_NIL; 50 51 struct stat buffer; 52 53 int instNum = 0; 54 int majorNum = 0; 55 56 int oidInstNum = 0; 57 int oidMajorNum = 0; 58 59 int found = 0; 60 int status = -1; 61 62 63 char *pathName = NULL; 64 char *minorName = "c"; 65 66 char fullName[512]; 67 68 69 70 71 log(LOG_INFO, "doDevInfoStuffForIntPort()", " - enter"); 72 73 74 oidInstNum = (int)MP_GET_INST_FROM_ID(oid.objectSequenceNumber); 75 oidMajorNum = (int)MP_GET_MAJOR_FROM_ID(oid.objectSequenceNumber); 76 77 78 root_node = di_init("/", DINFOCACHE); 79 if (DI_NODE_NIL == root_node) { 80 log(LOG_INFO, "doDevInfoStuffForIntPort()", 81 " - di_init() failed"); 82 83 return (MP_STATUS_FAILED); 84 } 85 86 vh_node = di_vhci_first_node(root_node); 87 88 while (DI_NODE_NIL != vh_node) { 89 if ((di_driver_name(vh_node) != NULL) && 90 (strncmp(di_driver_name(vh_node), "scsi_vhci", 9) == 0)) { 91 ph_node = di_phci_first_node(vh_node); 92 while (DI_NODE_NIL != ph_node) { 93 94 instNum = di_instance(ph_node); 95 majorNum = di_driver_major(ph_node); 96 97 if ((majorNum == oidMajorNum) && 98 (instNum == oidInstNum)) { 99 100 log(LOG_INFO, 101 "doDevInfoStuffForIntPort()", 102 "got a match"); 103 104 found = 1; 105 106 break; 107 } 108 109 ph_node = di_phci_next_node(ph_node); 110 } 111 } 112 113 if (found) { 114 115 break; 116 } 117 118 vh_node = di_vhci_next_node(vh_node); 119 } 120 121 122 if (!found) { 123 124 di_fini(root_node); 125 126 log(LOG_INFO, 127 "doDevInfoStuffForIntPort()", 128 " - no match found, error exit"); 129 130 return (MP_STATUS_OBJECT_NOT_FOUND); 131 } 132 133 134 path = di_path_next(ph_node, DI_PATH_NIL); 135 136 if (DI_PATH_NIL == path) { 137 138 log(LOG_INFO, "doDevInfoStuffForIntPort()", 139 " - path is DI_PATH_NIL"); 140 } 141 142 while (DI_PATH_NIL != path) { 143 144 sv_node = di_path_client_node(path); 145 if (DI_NODE_NIL == sv_node) { 146 147 log(LOG_INFO, "doDevInfoStuffForIntPort()", 148 " - sv_node is DI_NODE_NIL"); 149 150 } else { 151 152 pathName = di_devfs_path(sv_node); 153 (void) snprintf(fullName, 511, "/devices%s:%s", 154 pathName, minorName); 155 156 (void) di_devfs_path_free(pathName); 157 158 status = stat(fullName, &buffer); 159 if (status < 0) { 160 161 log(LOG_INFO, 162 "doDevInfoStuffForIntPort()", 163 " - stat() call failed: %d", status); 164 165 log(LOG_INFO, 166 "doDevInfoStuffForIntPort()", 167 " - errno: [%d].", errno); 168 169 log(LOG_INFO, 170 "doDevInfoStuffForIntPort()", 171 " - strerror(errno): [%s].", 172 strerror(errno)); 173 174 175 di_fini(root_node); 176 177 log(LOG_INFO, 178 "doDevInfoStuffForIntPort()", 179 " - error exit."); 180 181 return (MP_STATUS_FAILED); 182 } 183 } 184 185 path = di_path_next(ph_node, path); 186 } 187 188 189 di_fini(root_node); 190 191 log(LOG_INFO, "doDevInfoStuffForIntPort()", " - exit"); 192 193 return (MP_STATUS_SUCCESS); 194 } 195 196 197 static MP_STATUS doDevInfoStuffForTargetPort(MP_OID oid) 198 { 199 di_node_t root_node = DI_NODE_NIL; 200 di_node_t sv_node = DI_NODE_NIL; 201 di_node_t child_node = DI_NODE_NIL; 202 203 di_path_t path = DI_PATH_NIL; 204 205 int match = 0; 206 int count = 0; 207 int ioctlStatus = 0; 208 int status = -1; 209 210 struct stat buffer; 211 212 char *pathName = NULL; 213 char *minorName = "c"; 214 215 char fullName[512]; 216 217 uchar_t *targetPort = NULL; 218 219 mp_iocdata_t mp_ioctl; 220 221 mp_target_port_prop_t tpInfo; 222 223 MP_STATUS mpStatus = MP_STATUS_SUCCESS; 224 225 226 log(LOG_INFO, "doDevInfoStuffForTargetPort()", " - enter"); 227 228 229 log(LOG_INFO, "doDevInfoStuffForTargetPort()", 230 "oid.objectSequenceNumber = %llx", 231 oid.objectSequenceNumber); 232 233 (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t)); 234 (void) memset(&tpInfo, 0, sizeof (mp_target_port_prop_t)); 235 236 mp_ioctl.mp_cmd = MP_GET_TARGET_PORT_PROP; 237 mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber; 238 mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber); 239 mp_ioctl.mp_obuf = (caddr_t)&tpInfo; 240 mp_ioctl.mp_olen = sizeof (mp_target_port_prop_t); 241 mp_ioctl.mp_xfer = MP_XFER_READ; 242 243 log(LOG_INFO, "doDevInfoStuffForTargetPort()", 244 "mp_ioctl.mp_cmd (MP_GET_TARGET_PORT_PROP) : %d", 245 mp_ioctl.mp_cmd); 246 247 ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl); 248 249 log(LOG_INFO, "doDevInfoStuffForTargetPort()", 250 " IOCTL call returned: %d", ioctlStatus); 251 252 if (ioctlStatus < 0) { 253 ioctlStatus = errno; 254 } 255 256 if (ioctlStatus != 0) { 257 log(LOG_INFO, "doDevInfoStuffForTargetPort()", 258 "IOCTL call failed. IOCTL error is: %d", 259 ioctlStatus); 260 log(LOG_INFO, "doDevInfoStuffForTargetPort()", 261 "IOCTL call failed. IOCTL error is: %s", 262 strerror(ioctlStatus)); 263 log(LOG_INFO, "doDevInfoStuffForTargetPort()", 264 "IOCTL call failed. mp_ioctl.mp_errno: %x", 265 mp_ioctl.mp_errno); 266 267 if (ENOTSUP == ioctlStatus) { 268 mpStatus = MP_STATUS_UNSUPPORTED; 269 } else if (0 == mp_ioctl.mp_errno) { 270 mpStatus = MP_STATUS_FAILED; 271 } else { 272 mpStatus = 273 getStatus4ErrorCode(mp_ioctl.mp_errno); 274 } 275 276 log(LOG_INFO, "doDevInfoStuffForTargetPort()", 277 " - error exit"); 278 279 return (mpStatus); 280 } 281 282 root_node = di_init("/", DINFOCACHE); 283 284 if (DI_NODE_NIL == root_node) { 285 log(LOG_INFO, "doDevInfoStuffForTargetPort()", 286 " - di_init() failed"); 287 288 return (MP_STATUS_FAILED); 289 } 290 291 292 sv_node = di_drv_first_node("scsi_vhci", root_node); 293 if (DI_NODE_NIL == sv_node) { 294 log(LOG_INFO, "doDevInfoStuffForTargetPort()", 295 " - di_drv_first_node() failed"); 296 297 di_fini(root_node); 298 299 return (MP_STATUS_FAILED); 300 } 301 302 child_node = di_child_node(sv_node); 303 304 while (DI_NODE_NIL != child_node) { 305 306 path = di_path_next(child_node, path); 307 308 match = 0; 309 310 while (DI_PATH_NIL != path) { 311 312 count = di_path_prop_lookup_bytes(path, 313 "target-port", 314 &targetPort); 315 316 if (NULL != targetPort) { 317 318 if (0 == memcmp(targetPort, 319 tpInfo.portName, 320 count)) { 321 322 match = 1; 323 324 break; 325 } 326 } 327 328 path = di_path_next(child_node, path); 329 } 330 331 if (match) { 332 333 log(LOG_INFO, "doDevInfoStuffForTargetPort()", 334 " - got a match"); 335 336 pathName = di_devfs_path(child_node); 337 338 (void) snprintf(fullName, 511, "/devices%s:%s", 339 pathName, minorName); 340 341 (void) di_devfs_path_free(pathName); 342 343 status = stat(fullName, &buffer); 344 if (status < 0) { 345 346 log(LOG_INFO, 347 "doDevInfoStuffForTargetPort()", 348 " - stat() call failed: %d", status); 349 350 log(LOG_INFO, 351 "doDevInfoStuffForTargetPort()", 352 " - errno: [%d].", errno); 353 354 log(LOG_INFO, 355 "doDevInfoStuffForTargetPort()", 356 " - strerror(errno): [%s].", 357 strerror(errno)); 358 359 360 di_fini(root_node); 361 362 log(LOG_INFO, 363 "doDevInfoStuffForTargetPort()", 364 " - error exit."); 365 366 return (MP_STATUS_FAILED); 367 } 368 } 369 370 child_node = di_sibling_node(child_node); 371 } 372 373 374 di_fini(root_node); 375 376 log(LOG_INFO, "doDevInfoStuffForTargetPort()", " - exit"); 377 378 return (MP_STATUS_SUCCESS); 379 } 380 381 382 383 MP_STATUS 384 MP_GetAssociatedPathOidList(MP_OID oid, MP_OID_LIST **ppList) 385 { 386 mp_iocdata_t mp_ioctl; 387 388 uint64_t *objList = NULL; 389 390 int numOBJ = 0; 391 int i = 0; 392 int ioctlStatus = 0; 393 394 MP_STATUS mpStatus = MP_STATUS_SUCCESS; 395 396 int request = MP_GET_PATH_LIST_FOR_MP_LU; 397 398 399 log(LOG_INFO, "MP_GetAssociatedPathOidList()", " - enter"); 400 401 402 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 403 " set default request to MP_GET_PATH_LIST_FOR_MP_LU"); 404 405 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 406 "oid.objectSequenceNumber = %llx", 407 oid.objectSequenceNumber); 408 409 410 if (g_scsi_vhci_fd < 0) { 411 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 412 "invalid driver file handle"); 413 log(LOG_INFO, "MP_GetAssociatedPathOidList()", " - error exit"); 414 return (MP_STATUS_FAILED); 415 } 416 417 if (MP_OBJECT_TYPE_INITIATOR_PORT == oid.objectType) { 418 request = MP_GET_PATH_LIST_FOR_INIT_PORT; 419 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 420 " set request to MP_GET_PATH_LIST_FOR_INIT_PORT"); 421 422 mpStatus = doDevInfoStuffForIntPort(oid); 423 if (MP_STATUS_SUCCESS != mpStatus) { 424 425 return (mpStatus); 426 } 427 } else if (MP_OBJECT_TYPE_TARGET_PORT == oid.objectType) { 428 request = MP_GET_PATH_LIST_FOR_TARGET_PORT; 429 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 430 " set request to MP_GET_PATH_LIST_FOR_TARGET_PORT"); 431 432 mpStatus = doDevInfoStuffForTargetPort(oid); 433 if (MP_STATUS_SUCCESS != mpStatus) { 434 435 return (mpStatus); 436 } 437 } 438 439 objList = (uint64_t *)calloc(1, DEFAULT_BUFFER_SIZE_PATH_LIST); 440 if (NULL == objList) { 441 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 442 "no memory for objList(1)"); 443 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 444 " - error exit"); 445 return (MP_STATUS_INSUFFICIENT_MEMORY); 446 } 447 448 (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t)); 449 450 mp_ioctl.mp_cmd = request; 451 mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber; 452 mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber); 453 mp_ioctl.mp_obuf = (caddr_t)objList; 454 mp_ioctl.mp_olen = DEFAULT_BUFFER_SIZE_PATH_LIST; 455 mp_ioctl.mp_xfer = MP_XFER_READ; 456 457 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 458 "mp_ioctl.mp_cmd : %d", mp_ioctl.mp_cmd); 459 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 460 "mp_ioctl.mp_obuf: %x", mp_ioctl.mp_obuf); 461 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 462 "mp_ioctl.mp_olen: %d", mp_ioctl.mp_olen); 463 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 464 "mp_ioctl.mp_xfer: %d (MP_XFER_READ)", 465 mp_ioctl.mp_xfer); 466 467 ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl); 468 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 469 "ioctl call returned ioctlStatus: %d", 470 ioctlStatus); 471 472 if (ioctlStatus < 0) { 473 ioctlStatus = errno; 474 } 475 476 if ((ioctlStatus != 0) && (MP_MORE_DATA != mp_ioctl.mp_errno)) { 477 478 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 479 "IOCTL call failed. IOCTL error is: %d", 480 ioctlStatus); 481 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 482 "IOCTL call failed. IOCTL error is: %s", 483 strerror(ioctlStatus)); 484 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 485 "IOCTL call failed. mp_ioctl.mp_errno: %x", 486 mp_ioctl.mp_errno); 487 488 489 free(objList); 490 491 if (ENOTSUP == ioctlStatus) { 492 mpStatus = MP_STATUS_UNSUPPORTED; 493 } else if (0 == mp_ioctl.mp_errno) { 494 mpStatus = MP_STATUS_FAILED; 495 } else { 496 mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno); 497 } 498 499 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 500 " - error exit"); 501 502 return (mpStatus); 503 } 504 505 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 506 " - mp_ioctl.mp_alen : %d", 507 mp_ioctl.mp_alen); 508 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 509 " - sizeof (uint64_t): %d", 510 sizeof (uint64_t)); 511 512 numOBJ = mp_ioctl.mp_alen / sizeof (uint64_t); 513 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 514 "Length of list: %d", numOBJ); 515 516 if (numOBJ < 1) { 517 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 518 "driver returned empty list."); 519 520 free(objList); 521 522 *ppList = createOidList(1); 523 if (NULL == *ppList) { 524 log(LOG_INFO, 525 "MP_GetAssociatedPathOidList()", 526 "no memory for MP_OID_LIST"); 527 log(LOG_INFO, 528 "MP_GetAssociatedPathOidList()", 529 " - error exit"); 530 return (MP_STATUS_INSUFFICIENT_MEMORY); 531 } 532 533 return (MP_STATUS_SUCCESS); 534 } 535 536 if (mp_ioctl.mp_alen > DEFAULT_BUFFER_SIZE_PATH_LIST) { 537 538 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 539 "buffer size too small, need : %d", 540 mp_ioctl.mp_alen); 541 542 free(objList); 543 544 objList = (uint64_t *)calloc(1, numOBJ * sizeof (uint64_t)); 545 if (NULL == objList) { 546 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 547 "no memory for objList(2)"); 548 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 549 " - error exit"); 550 return (MP_STATUS_INSUFFICIENT_MEMORY); 551 } 552 553 (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t)); 554 555 mp_ioctl.mp_cmd = request; 556 mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber; 557 mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber); 558 mp_ioctl.mp_obuf = (caddr_t)objList; 559 mp_ioctl.mp_olen = numOBJ * sizeof (uint64_t); 560 mp_ioctl.mp_xfer = MP_XFER_READ; 561 562 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 563 "mp_ioctl.mp_cmd : %d", mp_ioctl.mp_cmd); 564 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 565 "mp_ioctl.mp_obuf: %x", mp_ioctl.mp_obuf); 566 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 567 "mp_ioctl.mp_olen: %d", mp_ioctl.mp_olen); 568 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 569 "mp_ioctl.mp_xfer: %d (MP_XFER_READ)", 570 mp_ioctl.mp_xfer); 571 572 573 ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl); 574 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 575 "ioctl call returned ioctlStatus: %d", 576 ioctlStatus); 577 578 if (ioctlStatus < 0) { 579 ioctlStatus = errno; 580 } 581 582 if (ioctlStatus != 0) { 583 584 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 585 "IOCTL call failed. IOCTL error is: %d", 586 ioctlStatus); 587 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 588 "IOCTL call failed. IOCTL error is: %s", 589 strerror(ioctlStatus)); 590 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 591 "IOCTL call failed. mp_ioctl.mp_errno: %x", 592 mp_ioctl.mp_errno); 593 594 595 free(objList); 596 597 if (ENOTSUP == ioctlStatus) { 598 mpStatus = MP_STATUS_UNSUPPORTED; 599 } else if (0 == mp_ioctl.mp_errno) { 600 mpStatus = MP_STATUS_FAILED; 601 } else { 602 mpStatus = 603 getStatus4ErrorCode(mp_ioctl.mp_errno); 604 } 605 606 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 607 " - error exit"); 608 609 return (mpStatus); 610 } 611 } 612 613 614 *ppList = createOidList(numOBJ); 615 if (NULL == *ppList) { 616 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 617 "no memory for *ppList"); 618 free(objList); 619 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 620 " - error exit"); 621 return (MP_STATUS_INSUFFICIENT_MEMORY); 622 } 623 624 (*ppList)->oidCount = numOBJ; 625 626 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 627 "(*ppList)->oidCount = %d", 628 (*ppList)->oidCount); 629 630 for (i = 0; i < numOBJ; i++) { 631 (*ppList)->oids[i].objectType = MP_OBJECT_TYPE_PATH_LU; 632 (*ppList)->oids[i].ownerId = g_pluginOwnerID; 633 (*ppList)->oids[i].objectSequenceNumber = objList[i]; 634 635 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 636 "(*ppList)->oids[%d].objectType = %d", 637 i, (*ppList)->oids[i].objectType); 638 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 639 "(*ppList)->oids[%d].ownerId = %d", 640 i, (*ppList)->oids[i].ownerId); 641 log(LOG_INFO, "MP_GetAssociatedPathOidList()", 642 "(*ppList)->oids[%d].objectSequenceNumber = %llx", 643 i, (*ppList)->oids[i].objectSequenceNumber); 644 } 645 646 free(objList); 647 648 649 log(LOG_INFO, "MP_GetAssociatedPathOidList()", " - exit"); 650 651 return (MP_STATUS_SUCCESS); 652 } 653