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 <stdlib.h> 27 #include <stdio.h> 28 #include <wchar.h> 29 #include <strings.h> 30 #include <sys/types.h> 31 #include <sys/stat.h> 32 #include <fcntl.h> 33 #include <unistd.h> 34 #include <libintl.h> 35 #include <errno.h> 36 #include <string.h> 37 #include <assert.h> 38 #include <libnvpair.h> 39 #include <pthread.h> 40 #include <syslog.h> 41 #include <libstmf.h> 42 #include <netinet/in.h> 43 #include <inttypes.h> 44 #include <store.h> 45 #include <locale.h> 46 #include <sys/stmf_ioctl.h> 47 48 #define STMF_PATH "/devices/pseudo/stmf@0:admin" 49 50 #define EUI "eui." 51 #define WWN "wwn." 52 #define IQN "iqn." 53 #define WWN_ASCII_SIZE 16 54 #define IDENT_LENGTH_BYTE 3 55 56 #define MAX_LU 2<<16 - 1 57 #define MAX_TARGET_PORT 1024 58 #define MAX_PROVIDER 1024 59 #define MAX_GROUP 1024 60 #define MAX_SESSION 1024 61 #define MAX_ISCSI_NAME 223 62 63 #define OPEN_STMF 0 64 #define OPEN_EXCL_STMF O_EXCL 65 66 #define LOGICAL_UNIT_TYPE 0 67 #define TARGET_TYPE 1 68 #define STMF_SERVICE_TYPE 2 69 70 static int openStmf(int, int *fd); 71 static int groupIoctl(int fd, int cmd, stmfGroupName *); 72 static int loadStore(int fd); 73 static int initializeConfig(); 74 static int groupMemberIoctl(int fd, int cmd, stmfGroupName *, stmfDevid *); 75 static int guidCompare(const void *, const void *); 76 static int addViewEntryIoctl(int fd, stmfGuid *, stmfViewEntry *); 77 static int loadHostGroups(int fd, stmfGroupList *); 78 static int loadTargetGroups(int fd, stmfGroupList *); 79 static int getStmfState(stmf_state_desc_t *); 80 static int setStmfState(int fd, stmf_state_desc_t *, int); 81 static int setProviderData(int fd, char *, nvlist_t *, int); 82 83 /* 84 * Open for stmf module 85 * 86 * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF) 87 * fd - pointer to integer. On success, contains the stmf file descriptor 88 */ 89 static int 90 openStmf(int flag, int *fd) 91 { 92 int ret = STMF_STATUS_ERROR; 93 94 if ((*fd = open(STMF_PATH, O_NDELAY | O_RDONLY | flag)) != -1) { 95 ret = STMF_STATUS_SUCCESS; 96 } else { 97 if (errno == EBUSY) { 98 ret = STMF_ERROR_BUSY; 99 } else { 100 ret = STMF_STATUS_ERROR; 101 } 102 syslog(LOG_DEBUG, "openStmf:open failure:%s:errno(%d)", 103 STMF_PATH, errno); 104 } 105 106 return (ret); 107 } 108 109 /* 110 * initializeConfig 111 * 112 * This routine should be called before any ioctl requiring initialization 113 * which is basically everything except stmfGetState(), setStmfState() and 114 * stmfLoadConfig(). 115 */ 116 static int 117 initializeConfig() 118 { 119 int ret; 120 stmfState state; 121 122 123 ret = stmfGetState(&state); 124 if (ret != STMF_STATUS_SUCCESS) { 125 return (ret); 126 } 127 128 /* if we've already initialized or in the process, return success */ 129 if (state.configState == STMF_CONFIG_STATE_INIT_DONE || 130 state.configState == STMF_CONFIG_STATE_INIT) { 131 return (STMF_STATUS_SUCCESS); 132 } 133 134 ret = stmfLoadConfig(); 135 if (ret != STMF_STATUS_SUCCESS) { 136 syslog(LOG_DEBUG, 137 "initializeConfig:stmfLoadConfig:error(%d)", ret); 138 return (ret); 139 } 140 141 ret = stmfGetState(&state); 142 if (ret != STMF_STATUS_SUCCESS) { 143 syslog(LOG_DEBUG, 144 "initializeConfig:stmfGetState:error(%d)", ret); 145 return (ret); 146 } 147 148 if (state.configState != STMF_CONFIG_STATE_INIT_DONE) { 149 syslog(LOG_DEBUG, "initializeConfig:state.configState(%d)", 150 state.configState); 151 ret = STMF_STATUS_ERROR; 152 } 153 154 return (ret); 155 } 156 157 158 /* 159 * groupIoctl 160 * 161 * Purpose: issue ioctl for create/delete on group 162 * 163 * cmd - valid STMF ioctl group cmd 164 * groupName - groupName to create or delete 165 */ 166 static int 167 groupIoctl(int fd, int cmd, stmfGroupName *groupName) 168 { 169 int ret = STMF_STATUS_SUCCESS; 170 int ioctlRet; 171 stmf_iocdata_t stmfIoctl; 172 stmf_group_name_t iGroupName; 173 174 bzero(&iGroupName, sizeof (iGroupName)); 175 176 bcopy(groupName, &iGroupName.name, strlen((char *)groupName)); 177 178 iGroupName.name_size = strlen((char *)groupName); 179 180 bzero(&stmfIoctl, sizeof (stmfIoctl)); 181 /* 182 * Issue ioctl to create the host group 183 */ 184 stmfIoctl.stmf_version = STMF_VERSION_1; 185 stmfIoctl.stmf_ibuf_size = sizeof (iGroupName); 186 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName; 187 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 188 if (ioctlRet != 0) { 189 switch (errno) { 190 case EACCES: 191 ret = STMF_ERROR_PERM; 192 break; 193 default: 194 switch (stmfIoctl.stmf_error) { 195 case STMF_IOCERR_TG_EXISTS: 196 case STMF_IOCERR_HG_EXISTS: 197 ret = STMF_ERROR_EXISTS; 198 break; 199 case STMF_IOCERR_TG_IN_USE: 200 case STMF_IOCERR_HG_IN_USE: 201 ret = STMF_ERROR_GROUP_IN_USE; 202 break; 203 case STMF_IOCERR_INVALID_HG: 204 case STMF_IOCERR_INVALID_TG: 205 ret = STMF_ERROR_NOT_FOUND; 206 break; 207 default: 208 syslog(LOG_DEBUG, 209 "groupIoctl:error(%d)", 210 stmfIoctl.stmf_error); 211 ret = STMF_STATUS_ERROR; 212 break; 213 } 214 break; 215 } 216 } 217 done: 218 return (ret); 219 } 220 221 /* 222 * groupIoctl 223 * 224 * Purpose: issue ioctl for add/remove member on group 225 * 226 * cmd - valid STMF ioctl group member cmd 227 * groupName - groupName to add to or remove from 228 * devid - group member to add or remove 229 */ 230 static int 231 groupMemberIoctl(int fd, int cmd, stmfGroupName *groupName, stmfDevid *devid) 232 { 233 int ret = STMF_STATUS_SUCCESS; 234 int ioctlRet; 235 stmf_iocdata_t stmfIoctl; 236 stmf_group_op_data_t stmfGroupData; 237 238 bzero(&stmfGroupData, sizeof (stmfGroupData)); 239 240 bcopy(groupName, &stmfGroupData.group.name, strlen((char *)groupName)); 241 242 stmfGroupData.group.name_size = strlen((char *)groupName); 243 stmfGroupData.ident[IDENT_LENGTH_BYTE] = devid->identLength; 244 bcopy(&(devid->ident), &stmfGroupData.ident[IDENT_LENGTH_BYTE + 1], 245 devid->identLength); 246 247 bzero(&stmfIoctl, sizeof (stmfIoctl)); 248 /* 249 * Issue ioctl to add to the host group 250 */ 251 stmfIoctl.stmf_version = STMF_VERSION_1; 252 stmfIoctl.stmf_ibuf_size = sizeof (stmfGroupData); 253 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&stmfGroupData; 254 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 255 if (ioctlRet != 0) { 256 switch (errno) { 257 case EBUSY: 258 ret = STMF_ERROR_BUSY; 259 break; 260 case EACCES: 261 ret = STMF_ERROR_PERM; 262 break; 263 default: 264 switch (stmfIoctl.stmf_error) { 265 case STMF_IOCERR_TG_ENTRY_EXISTS: 266 case STMF_IOCERR_HG_ENTRY_EXISTS: 267 ret = STMF_ERROR_EXISTS; 268 break; 269 case STMF_IOCERR_INVALID_TG_ENTRY: 270 case STMF_IOCERR_INVALID_HG_ENTRY: 271 ret = 272 STMF_ERROR_MEMBER_NOT_FOUND; 273 break; 274 case STMF_IOCERR_INVALID_TG: 275 case STMF_IOCERR_INVALID_HG: 276 ret = 277 STMF_ERROR_GROUP_NOT_FOUND; 278 break; 279 default: 280 syslog(LOG_DEBUG, 281 "groupMemberIoctl:error" 282 "(%d)", 283 stmfIoctl.stmf_error); 284 ret = STMF_STATUS_ERROR; 285 break; 286 } 287 break; 288 } 289 } 290 done: 291 return (ret); 292 } 293 294 /* 295 * guidCompare 296 * 297 * qsort function 298 * sort on guid 299 */ 300 static int 301 guidCompare(const void *p1, const void *p2) 302 { 303 304 stmfGuid *g1 = (stmfGuid *)p1, *g2 = (stmfGuid *)p2; 305 int i; 306 307 for (i = 0; i < sizeof (stmfGuid); i++) { 308 if (g1->guid[i] > g2->guid[i]) 309 return (1); 310 if (g1->guid[i] < g2->guid[i]) 311 return (-1); 312 } 313 314 return (0); 315 } 316 317 /* 318 * stmfAddToHostGroup 319 * 320 * Purpose: Adds an initiator to an existing host group 321 * 322 * hostGroupName - name of an existing host group 323 * hostName - name of initiator to add 324 */ 325 int 326 stmfAddToHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName) 327 { 328 int ret; 329 int fd; 330 331 if (hostGroupName == NULL || 332 (strnlen((char *)hostGroupName, sizeof (stmfGroupName)) 333 == sizeof (stmfGroupName)) || hostName == NULL) { 334 return (STMF_ERROR_INVALID_ARG); 335 } 336 337 /* call init */ 338 ret = initializeConfig(); 339 if (ret != STMF_STATUS_SUCCESS) { 340 return (ret); 341 } 342 343 /* 344 * Open control node for stmf 345 */ 346 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 347 return (ret); 348 349 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, hostGroupName, 350 hostName)) != STMF_STATUS_SUCCESS) { 351 goto done; 352 } 353 354 ret = psAddHostGroupMember((char *)hostGroupName, 355 (char *)hostName->ident); 356 switch (ret) { 357 case STMF_PS_SUCCESS: 358 ret = STMF_STATUS_SUCCESS; 359 break; 360 case STMF_PS_ERROR_EXISTS: 361 ret = STMF_ERROR_EXISTS; 362 break; 363 case STMF_PS_ERROR_GROUP_NOT_FOUND: 364 ret = STMF_ERROR_GROUP_NOT_FOUND; 365 break; 366 case STMF_PS_ERROR_BUSY: 367 ret = STMF_ERROR_BUSY; 368 break; 369 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 370 ret = STMF_ERROR_SERVICE_NOT_FOUND; 371 break; 372 case STMF_PS_ERROR_VERSION_MISMATCH: 373 ret = STMF_ERROR_SERVICE_DATA_VERSION; 374 break; 375 default: 376 syslog(LOG_DEBUG, 377 "stmfAddToHostGroup:psAddHostGroupMember:error(%d)", 378 ret); 379 ret = STMF_STATUS_ERROR; 380 break; 381 } 382 383 done: 384 (void) close(fd); 385 return (ret); 386 } 387 388 /* 389 * stmfAddToTargetGroup 390 * 391 * Purpose: Adds a local port to an existing target group 392 * 393 * targetGroupName - name of an existing target group 394 * targetName - name of target to add 395 */ 396 int 397 stmfAddToTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName) 398 { 399 int ret; 400 int fd; 401 stmfState state; 402 403 if (targetGroupName == NULL || 404 (strnlen((char *)targetGroupName, sizeof (stmfGroupName)) 405 == sizeof (stmfGroupName)) || targetName == NULL) { 406 return (STMF_ERROR_INVALID_ARG); 407 } 408 409 ret = stmfGetState(&state); 410 if (ret == STMF_STATUS_SUCCESS) { 411 if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) { 412 return (STMF_ERROR_SERVICE_ONLINE); 413 } 414 } else { 415 return (STMF_STATUS_ERROR); 416 } 417 418 /* call init */ 419 ret = initializeConfig(); 420 if (ret != STMF_STATUS_SUCCESS) { 421 return (ret); 422 } 423 424 /* 425 * Open control node for stmf 426 */ 427 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 428 return (ret); 429 430 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY, 431 targetGroupName, targetName)) != STMF_STATUS_SUCCESS) { 432 goto done; 433 } 434 435 ret = psAddTargetGroupMember((char *)targetGroupName, 436 (char *)targetName->ident); 437 switch (ret) { 438 case STMF_PS_SUCCESS: 439 ret = STMF_STATUS_SUCCESS; 440 break; 441 case STMF_PS_ERROR_EXISTS: 442 ret = STMF_ERROR_EXISTS; 443 break; 444 case STMF_PS_ERROR_GROUP_NOT_FOUND: 445 ret = STMF_ERROR_GROUP_NOT_FOUND; 446 break; 447 case STMF_PS_ERROR_BUSY: 448 ret = STMF_ERROR_BUSY; 449 break; 450 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 451 ret = STMF_ERROR_SERVICE_NOT_FOUND; 452 break; 453 case STMF_PS_ERROR_VERSION_MISMATCH: 454 ret = STMF_ERROR_SERVICE_DATA_VERSION; 455 break; 456 default: 457 syslog(LOG_DEBUG, 458 "stmfAddToTargetGroup:psAddTargetGroupMember:" 459 "error(%d)", ret); 460 ret = STMF_STATUS_ERROR; 461 break; 462 } 463 464 done: 465 (void) close(fd); 466 return (ret); 467 } 468 469 /* 470 * addViewEntryIoctl 471 * 472 * Purpose: Issues ioctl to add a view entry 473 * 474 * lu - Logical Unit identifier to which the view entry is added 475 * viewEntry - view entry to add 476 * init - When set to B_TRUE, we are in the init state, i.e. don't call open 477 */ 478 static int 479 addViewEntryIoctl(int fd, stmfGuid *lu, stmfViewEntry *viewEntry) 480 { 481 int ret = STMF_STATUS_SUCCESS; 482 int ioctlRet; 483 stmf_iocdata_t stmfIoctl; 484 stmf_view_op_entry_t ioctlViewEntry; 485 486 bzero(&ioctlViewEntry, sizeof (ioctlViewEntry)); 487 /* 488 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be 489 * false on input 490 */ 491 ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid; 492 ioctlViewEntry.ve_all_hosts = viewEntry->allHosts; 493 ioctlViewEntry.ve_all_targets = viewEntry->allTargets; 494 495 if (viewEntry->allHosts == B_FALSE) { 496 bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name, 497 sizeof (stmfGroupName)); 498 ioctlViewEntry.ve_host_group.name_size = 499 strlen((char *)viewEntry->hostGroup); 500 } 501 if (viewEntry->allTargets == B_FALSE) { 502 bcopy(viewEntry->targetGroup, 503 &ioctlViewEntry.ve_target_group.name, 504 sizeof (stmfGroupName)); 505 ioctlViewEntry.ve_target_group.name_size = 506 strlen((char *)viewEntry->targetGroup); 507 } 508 if (viewEntry->luNbrValid) { 509 bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr, 510 sizeof (ioctlViewEntry.ve_lu_nbr)); 511 } 512 bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid)); 513 514 bzero(&stmfIoctl, sizeof (stmfIoctl)); 515 /* 516 * Issue ioctl to add to the view entry 517 */ 518 stmfIoctl.stmf_version = STMF_VERSION_1; 519 stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry); 520 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry; 521 stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry); 522 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry; 523 ioctlRet = ioctl(fd, STMF_IOCTL_ADD_VIEW_ENTRY, &stmfIoctl); 524 if (ioctlRet != 0) { 525 switch (errno) { 526 case EBUSY: 527 ret = STMF_ERROR_BUSY; 528 break; 529 case EACCES: 530 switch (stmfIoctl.stmf_error) { 531 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 532 ret = STMF_ERROR_CONFIG_NONE; 533 break; 534 default: 535 ret = STMF_ERROR_PERM; 536 break; 537 } 538 break; 539 default: 540 switch (stmfIoctl.stmf_error) { 541 case STMF_IOCERR_LU_NUMBER_IN_USE: 542 ret = STMF_ERROR_LUN_IN_USE; 543 break; 544 case STMF_IOCERR_VIEW_ENTRY_CONFLICT: 545 ret = STMF_ERROR_VE_CONFLICT; 546 break; 547 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 548 ret = STMF_ERROR_CONFIG_NONE; 549 break; 550 case STMF_IOCERR_INVALID_HG: 551 ret = STMF_ERROR_INVALID_HG; 552 break; 553 case STMF_IOCERR_INVALID_TG: 554 ret = STMF_ERROR_INVALID_TG; 555 break; 556 default: 557 syslog(LOG_DEBUG, 558 "addViewEntryIoctl" 559 ":error(%d)", 560 stmfIoctl.stmf_error); 561 ret = STMF_STATUS_ERROR; 562 break; 563 } 564 break; 565 } 566 goto done; 567 } 568 569 /* copy lu nbr back to caller's view entry on success */ 570 viewEntry->veIndex = ioctlViewEntry.ve_ndx; 571 if (ioctlViewEntry.ve_lu_number_valid) { 572 bcopy(&ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr, 573 sizeof (ioctlViewEntry.ve_lu_nbr)); 574 } 575 viewEntry->luNbrValid = B_TRUE; 576 577 done: 578 return (ret); 579 } 580 581 /* 582 * stmfAddViewEntry 583 * 584 * Purpose: Adds a view entry to a logical unit 585 * 586 * lu - guid of the logical unit to which the view entry is added 587 * viewEntry - view entry structure to add 588 */ 589 int 590 stmfAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry) 591 { 592 int ret; 593 int fd; 594 stmfViewEntry iViewEntry; 595 596 if (lu == NULL || viewEntry == NULL) { 597 return (STMF_ERROR_INVALID_ARG); 598 } 599 600 /* initialize and set internal view entry */ 601 bzero(&iViewEntry, sizeof (iViewEntry)); 602 603 if (!viewEntry->allHosts) { 604 bcopy(viewEntry->hostGroup, iViewEntry.hostGroup, 605 sizeof (iViewEntry.hostGroup)); 606 } else { 607 iViewEntry.allHosts = B_TRUE; 608 } 609 610 if (!viewEntry->allTargets) { 611 bcopy(viewEntry->targetGroup, iViewEntry.targetGroup, 612 sizeof (iViewEntry.targetGroup)); 613 } else { 614 iViewEntry.allTargets = B_TRUE; 615 } 616 617 if (viewEntry->luNbrValid) { 618 iViewEntry.luNbrValid = B_TRUE; 619 bcopy(viewEntry->luNbr, iViewEntry.luNbr, 620 sizeof (iViewEntry.luNbr)); 621 } 622 623 /* 624 * set users return view entry index valid flag to false 625 * in case of failure 626 */ 627 viewEntry->veIndexValid = B_FALSE; 628 629 /* Check to ensure service exists */ 630 if (psCheckService() != STMF_STATUS_SUCCESS) { 631 return (STMF_ERROR_SERVICE_NOT_FOUND); 632 } 633 634 /* call init */ 635 ret = initializeConfig(); 636 if (ret != STMF_STATUS_SUCCESS) { 637 return (ret); 638 } 639 640 /* 641 * Open control node for stmf 642 */ 643 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 644 return (ret); 645 646 /* 647 * First add the view entry to the driver 648 */ 649 ret = addViewEntryIoctl(fd, lu, &iViewEntry); 650 if (ret != STMF_STATUS_SUCCESS) { 651 goto done; 652 } 653 654 /* 655 * If the add to driver was successful, add it to the persistent 656 * store. 657 */ 658 ret = psAddViewEntry(lu, &iViewEntry); 659 switch (ret) { 660 case STMF_PS_SUCCESS: 661 ret = STMF_STATUS_SUCCESS; 662 break; 663 case STMF_PS_ERROR_NOT_FOUND: 664 ret = STMF_ERROR_NOT_FOUND; 665 break; 666 case STMF_PS_ERROR_BUSY: 667 ret = STMF_ERROR_BUSY; 668 break; 669 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 670 ret = STMF_ERROR_SERVICE_NOT_FOUND; 671 break; 672 case STMF_PS_ERROR_VERSION_MISMATCH: 673 ret = STMF_ERROR_SERVICE_DATA_VERSION; 674 break; 675 default: 676 syslog(LOG_DEBUG, 677 "stmfAddViewEntry:psAddViewEntry:error(%d)", ret); 678 ret = STMF_STATUS_ERROR; 679 break; 680 } 681 682 done: 683 (void) close(fd); 684 685 if (ret == STMF_STATUS_SUCCESS) { 686 /* set caller's view entry on success */ 687 viewEntry->veIndexValid = iViewEntry.veIndexValid; 688 viewEntry->veIndex = iViewEntry.veIndex; 689 viewEntry->luNbrValid = B_TRUE; 690 bcopy(iViewEntry.luNbr, viewEntry->luNbr, 691 sizeof (iViewEntry.luNbr)); 692 } 693 return (ret); 694 } 695 696 /* 697 * stmfClearProviderData 698 * 699 * Purpose: delete all provider data for specified provider 700 * 701 * providerName - name of provider for which data should be deleted 702 */ 703 int 704 stmfClearProviderData(char *providerName, int providerType) 705 { 706 int ret; 707 int fd; 708 int ioctlRet; 709 int savedErrno; 710 stmf_iocdata_t stmfIoctl; 711 stmf_ppioctl_data_t ppi; 712 713 /* call init */ 714 ret = initializeConfig(); 715 if (ret != STMF_STATUS_SUCCESS) { 716 return (ret); 717 } 718 719 if (providerName == NULL) { 720 return (STMF_ERROR_INVALID_ARG); 721 } 722 723 if (providerType != STMF_LU_PROVIDER_TYPE && 724 providerType != STMF_PORT_PROVIDER_TYPE) { 725 return (STMF_ERROR_INVALID_ARG); 726 } 727 728 /* 729 * Open control node for stmf 730 */ 731 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 732 return (ret); 733 734 bzero(&ppi, sizeof (ppi)); 735 736 (void) strncpy(ppi.ppi_name, providerName, sizeof (ppi.ppi_name)); 737 738 switch (providerType) { 739 case STMF_LU_PROVIDER_TYPE: 740 ppi.ppi_lu_provider = 1; 741 break; 742 case STMF_PORT_PROVIDER_TYPE: 743 ppi.ppi_port_provider = 1; 744 break; 745 default: 746 ret = STMF_ERROR_INVALID_ARG; 747 goto done; 748 } 749 750 bzero(&stmfIoctl, sizeof (stmfIoctl)); 751 752 stmfIoctl.stmf_version = STMF_VERSION_1; 753 stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t); 754 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi; 755 756 ioctlRet = ioctl(fd, STMF_IOCTL_CLEAR_PP_DATA, &stmfIoctl); 757 if (ioctlRet != 0) { 758 savedErrno = errno; 759 switch (savedErrno) { 760 case EBUSY: 761 ret = STMF_ERROR_BUSY; 762 break; 763 case EACCES: 764 ret = STMF_ERROR_PERM; 765 break; 766 default: 767 syslog(LOG_DEBUG, 768 "stmfClearProviderData:ioctl error(%d)", 769 ioctlRet); 770 ret = STMF_STATUS_ERROR; 771 break; 772 } 773 if (savedErrno != ENOENT) { 774 goto done; 775 } 776 } 777 778 ret = psClearProviderData(providerName, providerType); 779 switch (ret) { 780 case STMF_PS_SUCCESS: 781 ret = STMF_STATUS_SUCCESS; 782 break; 783 case STMF_PS_ERROR_NOT_FOUND: 784 ret = STMF_ERROR_NOT_FOUND; 785 break; 786 case STMF_PS_ERROR_BUSY: 787 ret = STMF_ERROR_BUSY; 788 break; 789 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 790 ret = STMF_ERROR_SERVICE_NOT_FOUND; 791 break; 792 case STMF_PS_ERROR_VERSION_MISMATCH: 793 ret = STMF_ERROR_SERVICE_DATA_VERSION; 794 break; 795 default: 796 syslog(LOG_DEBUG, 797 "stmfClearProviderData:psClearProviderData" 798 ":error(%d)", ret); 799 ret = STMF_STATUS_ERROR; 800 break; 801 } 802 803 done: 804 (void) close(fd); 805 return (ret); 806 } 807 808 /* 809 * stmfCreateHostGroup 810 * 811 * Purpose: Create a new initiator group 812 * 813 * hostGroupName - name of host group to create 814 */ 815 int 816 stmfCreateHostGroup(stmfGroupName *hostGroupName) 817 { 818 int ret; 819 int fd; 820 821 if (hostGroupName == NULL || 822 (strnlen((char *)hostGroupName, sizeof (stmfGroupName)) 823 == sizeof (stmfGroupName))) { 824 return (STMF_ERROR_INVALID_ARG); 825 } 826 827 /* Check to ensure service exists */ 828 if (psCheckService() != STMF_STATUS_SUCCESS) { 829 return (STMF_ERROR_SERVICE_NOT_FOUND); 830 } 831 832 /* call init */ 833 ret = initializeConfig(); 834 if (ret != STMF_STATUS_SUCCESS) { 835 return (ret); 836 } 837 838 /* 839 * Open control node for stmf 840 */ 841 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 842 return (ret); 843 844 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP, 845 hostGroupName)) != STMF_STATUS_SUCCESS) { 846 goto done; 847 } 848 849 ret = psCreateHostGroup((char *)hostGroupName); 850 switch (ret) { 851 case STMF_PS_SUCCESS: 852 ret = STMF_STATUS_SUCCESS; 853 break; 854 case STMF_PS_ERROR_EXISTS: 855 ret = STMF_ERROR_EXISTS; 856 break; 857 case STMF_PS_ERROR_BUSY: 858 ret = STMF_ERROR_BUSY; 859 break; 860 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 861 ret = STMF_ERROR_SERVICE_NOT_FOUND; 862 break; 863 case STMF_PS_ERROR_VERSION_MISMATCH: 864 ret = STMF_ERROR_SERVICE_DATA_VERSION; 865 break; 866 default: 867 syslog(LOG_DEBUG, 868 "stmfCreateHostGroup:psCreateHostGroup:error(%d)", 869 ret); 870 ret = STMF_STATUS_ERROR; 871 break; 872 } 873 874 done: 875 (void) close(fd); 876 return (ret); 877 } 878 879 /* 880 * stmfCreateTargetGroup 881 * 882 * Purpose: Create a local port group 883 * 884 * targetGroupName - name of local port group to create 885 */ 886 int 887 stmfCreateTargetGroup(stmfGroupName *targetGroupName) 888 { 889 int ret; 890 int fd; 891 892 if (targetGroupName == NULL || 893 (strnlen((char *)targetGroupName, sizeof (stmfGroupName)) 894 == sizeof (stmfGroupName))) { 895 return (STMF_ERROR_INVALID_ARG); 896 } 897 898 /* Check to ensure service exists */ 899 if (psCheckService() != STMF_STATUS_SUCCESS) { 900 return (STMF_ERROR_SERVICE_NOT_FOUND); 901 } 902 903 /* call init */ 904 ret = initializeConfig(); 905 if (ret != STMF_STATUS_SUCCESS) { 906 return (ret); 907 } 908 909 /* 910 * Open control node for stmf 911 */ 912 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 913 return (ret); 914 915 /* 916 * Add the group to the driver 917 */ 918 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP, 919 targetGroupName)) != STMF_STATUS_SUCCESS) { 920 goto done; 921 } 922 923 /* 924 * If the add to the driver was successful, add it to the persistent 925 * store. 926 */ 927 ret = psCreateTargetGroup((char *)targetGroupName); 928 switch (ret) { 929 case STMF_PS_SUCCESS: 930 ret = STMF_STATUS_SUCCESS; 931 break; 932 case STMF_PS_ERROR_EXISTS: 933 ret = STMF_ERROR_EXISTS; 934 break; 935 case STMF_PS_ERROR_BUSY: 936 ret = STMF_ERROR_BUSY; 937 break; 938 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 939 ret = STMF_ERROR_SERVICE_NOT_FOUND; 940 break; 941 case STMF_PS_ERROR_VERSION_MISMATCH: 942 ret = STMF_ERROR_SERVICE_DATA_VERSION; 943 break; 944 default: 945 syslog(LOG_DEBUG, 946 "stmfCreateTargetGroup:psCreateTargetGroup" 947 ":error(%d)", ret); 948 ret = STMF_STATUS_ERROR; 949 break; 950 } 951 952 done: 953 (void) close(fd); 954 return (ret); 955 } 956 957 /* 958 * stmfDeleteHostGroup 959 * 960 * Purpose: Delete an initiator or local port group 961 * 962 * hostGroupName - group to delete 963 */ 964 int 965 stmfDeleteHostGroup(stmfGroupName *hostGroupName) 966 { 967 int ret; 968 int fd; 969 970 if (hostGroupName == NULL) { 971 return (STMF_ERROR_INVALID_ARG); 972 } 973 974 /* Check to ensure service exists */ 975 if (psCheckService() != STMF_STATUS_SUCCESS) { 976 return (STMF_ERROR_SERVICE_NOT_FOUND); 977 } 978 979 /* call init */ 980 ret = initializeConfig(); 981 if (ret != STMF_STATUS_SUCCESS) { 982 return (ret); 983 } 984 985 /* 986 * Open control node for stmf 987 */ 988 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 989 return (ret); 990 991 /* 992 * Remove the group from the driver 993 */ 994 if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP, 995 hostGroupName)) != STMF_STATUS_SUCCESS) { 996 goto done; 997 } 998 999 /* 1000 * If the remove from the driver was successful, remove it from the 1001 * persistent store. 1002 */ 1003 ret = psDeleteHostGroup((char *)hostGroupName); 1004 switch (ret) { 1005 case STMF_PS_SUCCESS: 1006 ret = STMF_STATUS_SUCCESS; 1007 break; 1008 case STMF_PS_ERROR_NOT_FOUND: 1009 ret = STMF_ERROR_NOT_FOUND; 1010 break; 1011 case STMF_PS_ERROR_BUSY: 1012 ret = STMF_ERROR_BUSY; 1013 break; 1014 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 1015 ret = STMF_ERROR_SERVICE_NOT_FOUND; 1016 break; 1017 case STMF_PS_ERROR_VERSION_MISMATCH: 1018 ret = STMF_ERROR_SERVICE_DATA_VERSION; 1019 break; 1020 default: 1021 syslog(LOG_DEBUG, 1022 "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)", 1023 ret); 1024 ret = STMF_STATUS_ERROR; 1025 break; 1026 } 1027 1028 done: 1029 (void) close(fd); 1030 return (ret); 1031 } 1032 1033 /* 1034 * stmfDeleteTargetGroup 1035 * 1036 * Purpose: Delete an initiator or local port group 1037 * 1038 * targetGroupName - group to delete 1039 */ 1040 int 1041 stmfDeleteTargetGroup(stmfGroupName *targetGroupName) 1042 { 1043 int ret = STMF_STATUS_SUCCESS; 1044 int fd; 1045 1046 if (targetGroupName == NULL) { 1047 return (STMF_ERROR_INVALID_ARG); 1048 } 1049 1050 /* Check to ensure service exists */ 1051 if (psCheckService() != STMF_STATUS_SUCCESS) { 1052 return (STMF_ERROR_SERVICE_NOT_FOUND); 1053 } 1054 1055 /* call init */ 1056 ret = initializeConfig(); 1057 if (ret != STMF_STATUS_SUCCESS) { 1058 return (ret); 1059 } 1060 1061 /* 1062 * Open control node for stmf 1063 */ 1064 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 1065 return (ret); 1066 1067 /* 1068 * Remove the group from the driver 1069 */ 1070 if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP, 1071 targetGroupName)) != STMF_STATUS_SUCCESS) { 1072 goto done; 1073 } 1074 1075 /* 1076 * If the remove from the driver was successful, remove it from the 1077 * persistent store. 1078 */ 1079 ret = psDeleteTargetGroup((char *)targetGroupName); 1080 switch (ret) { 1081 case STMF_PS_SUCCESS: 1082 ret = STMF_STATUS_SUCCESS; 1083 break; 1084 case STMF_PS_ERROR_NOT_FOUND: 1085 ret = STMF_ERROR_NOT_FOUND; 1086 break; 1087 case STMF_PS_ERROR_BUSY: 1088 ret = STMF_ERROR_BUSY; 1089 break; 1090 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 1091 ret = STMF_ERROR_SERVICE_NOT_FOUND; 1092 break; 1093 case STMF_PS_ERROR_VERSION_MISMATCH: 1094 ret = STMF_ERROR_SERVICE_DATA_VERSION; 1095 break; 1096 default: 1097 syslog(LOG_DEBUG, 1098 "stmfDeleteTargetGroup:psDeleteTargetGroup" 1099 ":error(%d)", ret); 1100 ret = STMF_STATUS_ERROR; 1101 break; 1102 } 1103 1104 done: 1105 (void) close(fd); 1106 return (ret); 1107 } 1108 1109 /* 1110 * stmfDevidFromIscsiName 1111 * 1112 * Purpose: convert an iSCSI name to an stmf devid 1113 * 1114 * iscsiName - unicode nul terminated utf-8 encoded iSCSI name 1115 * devid - on success, contains the converted iscsi name 1116 */ 1117 int 1118 stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid) 1119 { 1120 if (devid == NULL || iscsiName == NULL) 1121 return (STMF_ERROR_INVALID_ARG); 1122 1123 bzero(devid, sizeof (stmfDevid)); 1124 1125 /* Validate size of target */ 1126 if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME || 1127 devid->identLength < strlen(EUI) || 1128 devid->identLength < strlen(IQN)) { 1129 return (STMF_ERROR_INVALID_ARG); 1130 } 1131 1132 if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) && 1133 strncmp(iscsiName, IQN, strlen(IQN)) != 0) { 1134 return (STMF_ERROR_INVALID_ARG); 1135 } 1136 1137 /* copy UTF-8 bytes to ident */ 1138 bcopy(iscsiName, devid->ident, devid->identLength); 1139 1140 return (STMF_STATUS_SUCCESS); 1141 } 1142 1143 /* 1144 * stmfDevidFromWwn 1145 * 1146 * Purpose: convert a WWN to an stmf devid 1147 * 1148 * wwn - 8-byte wwn identifier 1149 * devid - on success, contains the converted wwn 1150 */ 1151 int 1152 stmfDevidFromWwn(uchar_t *wwn, stmfDevid *devid) 1153 { 1154 if (wwn == NULL || devid == NULL) 1155 return (STMF_ERROR_INVALID_ARG); 1156 1157 bzero(devid, sizeof (stmfDevid)); 1158 1159 /* Copy eui prefix */ 1160 (void) bcopy(WWN, devid->ident, strlen(WWN)); 1161 1162 /* Convert to ASCII uppercase hexadecimal string */ 1163 (void) snprintf((char *)&devid->ident[strlen(WWN)], 1164 sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X", 1165 wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 1166 1167 devid->identLength = strlen((char *)devid->ident); 1168 1169 return (STMF_STATUS_SUCCESS); 1170 } 1171 1172 /* 1173 * stmfFreeMemory 1174 * 1175 * Purpose: Free memory allocated by this library 1176 * 1177 * memory - previously allocated pointer of memory managed by library 1178 */ 1179 void 1180 stmfFreeMemory(void *memory) 1181 { 1182 free(memory); 1183 } 1184 1185 /* 1186 * stmfGetHostGroupList 1187 * 1188 * Purpose: Retrieves the list of initiator group oids 1189 * 1190 * hostGroupList - pointer to pointer to hostGroupList structure 1191 * on success, this contains the host group list. 1192 */ 1193 int 1194 stmfGetHostGroupList(stmfGroupList **hostGroupList) 1195 { 1196 int ret; 1197 1198 if (hostGroupList == NULL) { 1199 return (STMF_ERROR_INVALID_ARG); 1200 } 1201 1202 ret = psGetHostGroupList(hostGroupList); 1203 switch (ret) { 1204 case STMF_PS_SUCCESS: 1205 ret = STMF_STATUS_SUCCESS; 1206 break; 1207 case STMF_PS_ERROR_NOT_FOUND: 1208 ret = STMF_ERROR_NOT_FOUND; 1209 break; 1210 case STMF_PS_ERROR_BUSY: 1211 ret = STMF_ERROR_BUSY; 1212 break; 1213 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 1214 ret = STMF_ERROR_SERVICE_NOT_FOUND; 1215 break; 1216 case STMF_PS_ERROR_VERSION_MISMATCH: 1217 ret = STMF_ERROR_SERVICE_DATA_VERSION; 1218 break; 1219 default: 1220 syslog(LOG_DEBUG, 1221 "stmfGetHostGroupList:psGetHostGroupList:error(%d)", 1222 ret); 1223 ret = STMF_STATUS_ERROR; 1224 break; 1225 } 1226 1227 return (ret); 1228 } 1229 1230 /* 1231 * stmfGetHostGroupMembers 1232 * 1233 * Purpose: Retrieves the group properties for a host group 1234 * 1235 * groupName - name of group for which to retrieve host group members. 1236 * groupProp - pointer to pointer to stmfGroupProperties structure 1237 * on success, this contains the list of group members. 1238 */ 1239 int 1240 stmfGetHostGroupMembers(stmfGroupName *groupName, 1241 stmfGroupProperties **groupProp) 1242 { 1243 int ret; 1244 1245 if (groupName == NULL || groupProp == NULL) { 1246 return (STMF_ERROR_INVALID_ARG); 1247 } 1248 1249 ret = psGetHostGroupMemberList((char *)groupName, groupProp); 1250 switch (ret) { 1251 case STMF_PS_SUCCESS: 1252 ret = STMF_STATUS_SUCCESS; 1253 break; 1254 case STMF_PS_ERROR_NOT_FOUND: 1255 ret = STMF_ERROR_NOT_FOUND; 1256 break; 1257 case STMF_PS_ERROR_BUSY: 1258 ret = STMF_ERROR_BUSY; 1259 break; 1260 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 1261 ret = STMF_ERROR_SERVICE_NOT_FOUND; 1262 break; 1263 case STMF_PS_ERROR_VERSION_MISMATCH: 1264 ret = STMF_ERROR_SERVICE_DATA_VERSION; 1265 break; 1266 default: 1267 syslog(LOG_DEBUG, 1268 "stmfGetHostGroupMembers:psGetHostGroupMembers" 1269 ":error(%d)", ret); 1270 ret = STMF_STATUS_ERROR; 1271 break; 1272 } 1273 1274 return (ret); 1275 } 1276 1277 /* 1278 * stmfGetProviderData 1279 * 1280 * Purpose: Get provider data list 1281 * 1282 * providerName - name of provider for which to retrieve the data 1283 * nvl - pointer to nvlist_t pointer which will contain the nvlist data 1284 * retrieved. 1285 * providerType - type of provider for which to retrieve data. 1286 * STMF_LU_PROVIDER_TYPE 1287 * STMF_PORT_PROVIDER_TYPE 1288 */ 1289 int 1290 stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType) 1291 { 1292 return (stmfGetProviderDataProt(providerName, nvl, providerType, 1293 NULL)); 1294 } 1295 1296 /* 1297 * stmfGetProviderDataProt 1298 * 1299 * Purpose: Get provider data list with token 1300 * 1301 * providerName - name of provider for which to retrieve the data 1302 * nvl - pointer to nvlist_t pointer which will contain the nvlist data 1303 * retrieved. 1304 * providerType - type of provider for which to retrieve data. 1305 * STMF_LU_PROVIDER_TYPE 1306 * STMF_PORT_PROVIDER_TYPE 1307 * setToken - Returns the stale data token 1308 */ 1309 int 1310 stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType, 1311 uint64_t *setToken) 1312 { 1313 int ret; 1314 1315 if (providerName == NULL || nvl == NULL) { 1316 return (STMF_ERROR_INVALID_ARG); 1317 } 1318 1319 if (providerType != STMF_LU_PROVIDER_TYPE && 1320 providerType != STMF_PORT_PROVIDER_TYPE) { 1321 return (STMF_ERROR_INVALID_ARG); 1322 } 1323 1324 /* call init */ 1325 ret = initializeConfig(); 1326 if (ret != STMF_STATUS_SUCCESS) { 1327 return (ret); 1328 } 1329 1330 ret = psGetProviderData(providerName, nvl, providerType, setToken); 1331 switch (ret) { 1332 case STMF_PS_SUCCESS: 1333 ret = STMF_STATUS_SUCCESS; 1334 break; 1335 case STMF_PS_ERROR_BUSY: 1336 ret = STMF_ERROR_BUSY; 1337 break; 1338 case STMF_PS_ERROR_NOT_FOUND: 1339 ret = STMF_ERROR_NOT_FOUND; 1340 break; 1341 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 1342 ret = STMF_ERROR_SERVICE_NOT_FOUND; 1343 break; 1344 case STMF_PS_ERROR_VERSION_MISMATCH: 1345 ret = STMF_ERROR_SERVICE_DATA_VERSION; 1346 break; 1347 default: 1348 syslog(LOG_DEBUG, 1349 "stmfGetProviderData:psGetProviderData:error(%d)", 1350 ret); 1351 ret = STMF_STATUS_ERROR; 1352 break; 1353 } 1354 1355 return (ret); 1356 } 1357 1358 /* 1359 * stmfGetProviderDataList 1360 * 1361 * Purpose: Get the list of providers currently persisting data 1362 * 1363 * providerList - pointer to pointer to an stmfProviderList structure allocated 1364 * by the caller. Will contain the list of providers on success. 1365 */ 1366 int 1367 stmfGetProviderDataList(stmfProviderList **providerList) 1368 { 1369 int ret; 1370 1371 ret = psGetProviderDataList(providerList); 1372 switch (ret) { 1373 case STMF_PS_SUCCESS: 1374 ret = STMF_STATUS_SUCCESS; 1375 break; 1376 case STMF_PS_ERROR_BUSY: 1377 ret = STMF_ERROR_BUSY; 1378 break; 1379 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 1380 ret = STMF_ERROR_SERVICE_NOT_FOUND; 1381 break; 1382 case STMF_PS_ERROR_VERSION_MISMATCH: 1383 ret = STMF_ERROR_SERVICE_DATA_VERSION; 1384 break; 1385 default: 1386 syslog(LOG_DEBUG, 1387 "stmfGetProviderDataList:psGetProviderDataList" 1388 ":error(%d)", ret); 1389 ret = STMF_STATUS_ERROR; 1390 break; 1391 } 1392 1393 return (ret); 1394 } 1395 1396 1397 /* 1398 * stmfGetSessionList 1399 * 1400 * Purpose: Retrieves the session list for a target (devid) 1401 * 1402 * devid - devid of target for which to retrieve session information. 1403 * sessionList - pointer to pointer to stmfSessionList structure 1404 * on success, this contains the list of initiator sessions. 1405 */ 1406 int 1407 stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList) 1408 { 1409 int ret = STMF_STATUS_SUCCESS; 1410 int fd; 1411 int ioctlRet; 1412 int cmd = STMF_IOCTL_SESSION_LIST; 1413 int i; 1414 stmf_iocdata_t stmfIoctl; 1415 slist_scsi_session_t *fSessionList; 1416 uint8_t ident[260]; 1417 uint32_t fSessionListSize; 1418 1419 if (sessionList == NULL || devid == NULL) { 1420 ret = STMF_ERROR_INVALID_ARG; 1421 } 1422 1423 /* call init */ 1424 ret = initializeConfig(); 1425 if (ret != STMF_STATUS_SUCCESS) { 1426 return (ret); 1427 } 1428 1429 /* 1430 * Open control node for stmf 1431 */ 1432 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 1433 return (ret); 1434 1435 /* 1436 * Allocate ioctl input buffer 1437 */ 1438 fSessionListSize = MAX_SESSION; 1439 fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t)); 1440 fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize); 1441 if (fSessionList == NULL) { 1442 return (STMF_ERROR_NOMEM); 1443 } 1444 1445 ident[IDENT_LENGTH_BYTE] = devid->identLength; 1446 bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1], 1447 devid->identLength); 1448 1449 bzero(&stmfIoctl, sizeof (stmfIoctl)); 1450 /* 1451 * Issue ioctl to get the session list 1452 */ 1453 stmfIoctl.stmf_version = STMF_VERSION_1; 1454 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident; 1455 stmfIoctl.stmf_ibuf_size = sizeof (ident); 1456 stmfIoctl.stmf_obuf_size = fSessionListSize; 1457 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList; 1458 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 1459 if (ioctlRet != 0) { 1460 switch (errno) { 1461 case EBUSY: 1462 ret = STMF_ERROR_BUSY; 1463 break; 1464 case EACCES: 1465 ret = STMF_ERROR_PERM; 1466 break; 1467 default: 1468 syslog(LOG_DEBUG, 1469 "stmfGetSessionList:ioctl errno(%d)", 1470 errno); 1471 ret = STMF_STATUS_ERROR; 1472 break; 1473 } 1474 goto done; 1475 } 1476 /* 1477 * Check whether input buffer was large enough 1478 */ 1479 if (stmfIoctl.stmf_obuf_max_nentries > MAX_SESSION) { 1480 fSessionListSize = stmfIoctl.stmf_obuf_max_nentries * 1481 sizeof (slist_scsi_session_t); 1482 fSessionList = realloc(fSessionList, fSessionListSize); 1483 if (fSessionList == NULL) { 1484 return (STMF_ERROR_NOMEM); 1485 } 1486 stmfIoctl.stmf_obuf_size = fSessionListSize; 1487 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList; 1488 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 1489 if (ioctlRet != 0) { 1490 switch (errno) { 1491 case EBUSY: 1492 ret = STMF_ERROR_BUSY; 1493 break; 1494 case EACCES: 1495 ret = STMF_ERROR_PERM; 1496 break; 1497 default: 1498 syslog(LOG_DEBUG, 1499 "stmfGetSessionList:ioctl " 1500 "errno(%d)", errno); 1501 ret = STMF_STATUS_ERROR; 1502 break; 1503 } 1504 goto done; 1505 } 1506 } 1507 1508 /* 1509 * allocate caller's buffer with the final size 1510 */ 1511 *sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) + 1512 stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession)); 1513 if (*sessionList == NULL) { 1514 ret = STMF_ERROR_NOMEM; 1515 free(sessionList); 1516 goto done; 1517 } 1518 1519 (*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries; 1520 1521 /* 1522 * copy session info to caller's buffer 1523 */ 1524 for (i = 0; i < (*sessionList)->cnt; i++) { 1525 (*sessionList)->session[i].initiator.identLength = 1526 fSessionList->initiator[IDENT_LENGTH_BYTE]; 1527 bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]), 1528 (*sessionList)->session[i].initiator.ident, 1529 STMF_IDENT_LENGTH); 1530 bcopy(&(fSessionList->alias), 1531 &((*sessionList)->session[i].alias), 1532 sizeof ((*sessionList)->session[i].alias)); 1533 bcopy(&(fSessionList++->creation_time), 1534 &((*sessionList)->session[i].creationTime), 1535 sizeof (time_t)); 1536 } 1537 done: 1538 (void) close(fd); 1539 return (ret); 1540 } 1541 1542 /* 1543 * stmfGetTargetGroupList 1544 * 1545 * Purpose: Retrieves the list of target groups 1546 * 1547 * targetGroupList - pointer to a pointer to an stmfGroupList structure. On 1548 * success, it contains the list of target groups. 1549 */ 1550 int 1551 stmfGetTargetGroupList(stmfGroupList **targetGroupList) 1552 { 1553 int ret; 1554 1555 if (targetGroupList == NULL) { 1556 return (STMF_ERROR_INVALID_ARG); 1557 } 1558 1559 ret = psGetTargetGroupList(targetGroupList); 1560 switch (ret) { 1561 case STMF_PS_SUCCESS: 1562 ret = STMF_STATUS_SUCCESS; 1563 break; 1564 case STMF_PS_ERROR_NOT_FOUND: 1565 ret = STMF_ERROR_NOT_FOUND; 1566 break; 1567 case STMF_PS_ERROR_BUSY: 1568 ret = STMF_ERROR_BUSY; 1569 break; 1570 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 1571 ret = STMF_ERROR_SERVICE_NOT_FOUND; 1572 break; 1573 case STMF_PS_ERROR_VERSION_MISMATCH: 1574 ret = STMF_ERROR_SERVICE_DATA_VERSION; 1575 break; 1576 default: 1577 syslog(LOG_DEBUG, 1578 "stmfGetTargetGroupList:psGetTargetGroupList:" 1579 "error(%d)", ret); 1580 ret = STMF_STATUS_ERROR; 1581 break; 1582 } 1583 1584 return (ret); 1585 } 1586 1587 /* 1588 * stmfGetTargetGroupMembers 1589 * 1590 * Purpose: Retrieves the group members for a target group 1591 * 1592 * groupName - name of target group for which to retrieve members. 1593 * groupProp - pointer to pointer to stmfGroupProperties structure 1594 * on success, this contains the list of group members. 1595 */ 1596 int 1597 stmfGetTargetGroupMembers(stmfGroupName *groupName, 1598 stmfGroupProperties **groupProp) 1599 { 1600 int ret; 1601 1602 if (groupName == NULL || groupProp == NULL) { 1603 return (STMF_ERROR_INVALID_ARG); 1604 } 1605 1606 ret = psGetTargetGroupMemberList((char *)groupName, groupProp); 1607 switch (ret) { 1608 case STMF_PS_SUCCESS: 1609 ret = STMF_STATUS_SUCCESS; 1610 break; 1611 case STMF_PS_ERROR_NOT_FOUND: 1612 ret = STMF_ERROR_NOT_FOUND; 1613 break; 1614 case STMF_PS_ERROR_BUSY: 1615 ret = STMF_ERROR_BUSY; 1616 break; 1617 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 1618 ret = STMF_ERROR_SERVICE_NOT_FOUND; 1619 break; 1620 case STMF_PS_ERROR_VERSION_MISMATCH: 1621 ret = STMF_ERROR_SERVICE_DATA_VERSION; 1622 break; 1623 default: 1624 syslog(LOG_DEBUG, 1625 "stmfGetTargetGroupMembers:psGetTargetGroupMembers:" 1626 "error(%d)", ret); 1627 ret = STMF_STATUS_ERROR; 1628 break; 1629 } 1630 1631 return (ret); 1632 } 1633 1634 /* 1635 * stmfGetTargetList 1636 * 1637 * Purpose: Retrieves the list of target ports 1638 * 1639 * targetList - pointer to a pointer to an stmfDevidList structure. 1640 * On success, it contains the list of local ports (target). 1641 */ 1642 int 1643 stmfGetTargetList(stmfDevidList **targetList) 1644 { 1645 int ret; 1646 int fd; 1647 int ioctlRet; 1648 int i; 1649 stmf_iocdata_t stmfIoctl; 1650 /* framework target port list */ 1651 slist_target_port_t *fTargetList, *fTargetListP; 1652 uint32_t fTargetListSize; 1653 1654 if (targetList == NULL) { 1655 return (STMF_ERROR_INVALID_ARG); 1656 } 1657 1658 /* call init */ 1659 ret = initializeConfig(); 1660 if (ret != STMF_STATUS_SUCCESS) { 1661 return (ret); 1662 } 1663 1664 /* 1665 * Open control node for stmf 1666 */ 1667 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 1668 return (ret); 1669 1670 /* 1671 * Allocate ioctl input buffer 1672 */ 1673 fTargetListSize = MAX_TARGET_PORT * sizeof (slist_target_port_t); 1674 fTargetListP = fTargetList = 1675 (slist_target_port_t *)calloc(1, fTargetListSize); 1676 if (fTargetList == NULL) { 1677 goto done; 1678 } 1679 1680 bzero(&stmfIoctl, sizeof (stmfIoctl)); 1681 /* 1682 * Issue ioctl to retrieve target list 1683 */ 1684 stmfIoctl.stmf_version = STMF_VERSION_1; 1685 stmfIoctl.stmf_obuf_size = fTargetListSize; 1686 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList; 1687 ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl); 1688 if (ioctlRet != 0) { 1689 switch (errno) { 1690 case EBUSY: 1691 ret = STMF_ERROR_BUSY; 1692 break; 1693 case EACCES: 1694 ret = STMF_ERROR_PERM; 1695 break; 1696 default: 1697 syslog(LOG_DEBUG, 1698 "stmfGetTargetList:ioctl errno(%d)", errno); 1699 ret = STMF_STATUS_ERROR; 1700 break; 1701 } 1702 goto done; 1703 } 1704 /* 1705 * Check whether input buffer was large enough 1706 */ 1707 if (stmfIoctl.stmf_obuf_max_nentries > MAX_TARGET_PORT) { 1708 fTargetListSize = stmfIoctl.stmf_obuf_max_nentries * 1709 sizeof (slist_target_port_t); 1710 fTargetListP = fTargetList = 1711 realloc(fTargetList, fTargetListSize); 1712 if (fTargetList == NULL) { 1713 return (STMF_ERROR_NOMEM); 1714 } 1715 stmfIoctl.stmf_obuf_size = fTargetListSize; 1716 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList; 1717 ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, 1718 &stmfIoctl); 1719 if (ioctlRet != 0) { 1720 switch (errno) { 1721 case EBUSY: 1722 ret = STMF_ERROR_BUSY; 1723 break; 1724 case EACCES: 1725 ret = STMF_ERROR_PERM; 1726 break; 1727 default: 1728 syslog(LOG_DEBUG, 1729 "stmfGetTargetList:ioctl errno(%d)", 1730 errno); 1731 ret = STMF_STATUS_ERROR; 1732 break; 1733 } 1734 goto done; 1735 } 1736 } 1737 1738 *targetList = (stmfDevidList *)calloc(1, 1739 stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) + 1740 sizeof (stmfDevidList)); 1741 1742 (*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries; 1743 for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) { 1744 (*targetList)->devid[i].identLength = 1745 fTargetList->target[IDENT_LENGTH_BYTE]; 1746 bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1], 1747 &(*targetList)->devid[i].ident, 1748 fTargetList->target[IDENT_LENGTH_BYTE]); 1749 } 1750 1751 done: 1752 (void) close(fd); 1753 free(fTargetListP); 1754 return (ret); 1755 } 1756 1757 /* 1758 * stmfGetTargetProperties 1759 * 1760 * Purpose: Retrieves the properties for a logical unit 1761 * 1762 * devid - devid of the target for which to retrieve properties 1763 * targetProps - pointer to an stmfTargetProperties structure. 1764 * On success, it contains the target properties for 1765 * the specified devid. 1766 */ 1767 int 1768 stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps) 1769 { 1770 int ret = STMF_STATUS_SUCCESS; 1771 int fd; 1772 int ioctlRet; 1773 stmf_iocdata_t stmfIoctl; 1774 sioc_target_port_props_t targetProperties; 1775 1776 if (devid == NULL || targetProps == NULL) { 1777 return (STMF_ERROR_INVALID_ARG); 1778 } 1779 1780 /* call init */ 1781 ret = initializeConfig(); 1782 if (ret != STMF_STATUS_SUCCESS) { 1783 return (ret); 1784 } 1785 1786 /* 1787 * Open control node for stmf 1788 */ 1789 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 1790 return (ret); 1791 1792 targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength; 1793 bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1], 1794 devid->identLength); 1795 1796 bzero(&stmfIoctl, sizeof (stmfIoctl)); 1797 /* 1798 * Issue ioctl to add to the host group 1799 */ 1800 stmfIoctl.stmf_version = STMF_VERSION_1; 1801 stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id); 1802 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id; 1803 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties; 1804 stmfIoctl.stmf_obuf_size = sizeof (targetProperties); 1805 ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES, 1806 &stmfIoctl); 1807 if (ioctlRet != 0) { 1808 switch (errno) { 1809 case EBUSY: 1810 ret = STMF_ERROR_BUSY; 1811 break; 1812 case EACCES: 1813 ret = STMF_ERROR_PERM; 1814 break; 1815 case ENOENT: 1816 ret = STMF_ERROR_NOT_FOUND; 1817 break; 1818 default: 1819 syslog(LOG_DEBUG, 1820 "stmfGetTargetProperties:ioctl errno(%d)", 1821 errno); 1822 ret = STMF_STATUS_ERROR; 1823 break; 1824 } 1825 goto done; 1826 } 1827 1828 bcopy(targetProperties.tgt_provider_name, targetProps->providerName, 1829 sizeof (targetProperties.tgt_provider_name)); 1830 if (targetProperties.tgt_state == STMF_STATE_ONLINE) { 1831 targetProps->status = STMF_TARGET_PORT_ONLINE; 1832 } else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) { 1833 targetProps->status = STMF_TARGET_PORT_OFFLINE; 1834 } else if (targetProperties.tgt_state == STMF_STATE_ONLINING) { 1835 targetProps->status = STMF_TARGET_PORT_ONLINING; 1836 } else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) { 1837 targetProps->status = STMF_TARGET_PORT_OFFLINING; 1838 } 1839 bcopy(targetProperties.tgt_alias, targetProps->alias, 1840 sizeof (targetProps->alias)); 1841 done: 1842 (void) close(fd); 1843 return (ret); 1844 } 1845 1846 /* 1847 * stmfGetLogicalUnitList 1848 * 1849 * Purpose: Retrieves list of logical unit Object IDs 1850 * 1851 * luList - pointer to a pointer to a stmfGuidList structure. On success, 1852 * it contains the list of logical unit guids. 1853 * 1854 */ 1855 int 1856 stmfGetLogicalUnitList(stmfGuidList **luList) 1857 { 1858 int ret; 1859 int fd; 1860 int ioctlRet; 1861 int cmd = STMF_IOCTL_LU_LIST; 1862 int i, k; 1863 stmf_iocdata_t stmfIoctl; 1864 /* framework lu list */ 1865 slist_lu_t *fLuList; 1866 /* persistent store lu list */ 1867 stmfGuidList *sLuList = NULL; 1868 int finalListSize = 0; 1869 int newAllocSize; 1870 uint32_t fLuListSize; 1871 uint32_t endList; 1872 1873 if (luList == NULL) { 1874 return (STMF_ERROR_INVALID_ARG); 1875 } 1876 1877 /* call init */ 1878 ret = initializeConfig(); 1879 if (ret != STMF_STATUS_SUCCESS) { 1880 return (ret); 1881 } 1882 1883 /* 1884 * Open control node for stmf 1885 */ 1886 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 1887 return (ret); 1888 1889 /* 1890 * Allocate ioctl input buffer 1891 */ 1892 fLuListSize = MAX_LU; 1893 fLuListSize = fLuListSize * (sizeof (slist_lu_t)); 1894 fLuList = (slist_lu_t *)calloc(1, fLuListSize); 1895 if (fLuList == NULL) { 1896 return (STMF_ERROR_NOMEM); 1897 } 1898 1899 bzero(&stmfIoctl, sizeof (stmfIoctl)); 1900 /* 1901 * Issue ioctl to get the LU list 1902 */ 1903 stmfIoctl.stmf_version = STMF_VERSION_1; 1904 stmfIoctl.stmf_obuf_size = fLuListSize; 1905 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList; 1906 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 1907 if (ioctlRet != 0) { 1908 switch (errno) { 1909 case EBUSY: 1910 ret = STMF_ERROR_BUSY; 1911 break; 1912 case EACCES: 1913 ret = STMF_ERROR_PERM; 1914 break; 1915 default: 1916 syslog(LOG_DEBUG, 1917 "stmfGetLogicalUnitList:ioctl errno(%d)", 1918 errno); 1919 ret = STMF_STATUS_ERROR; 1920 break; 1921 } 1922 goto done; 1923 } 1924 /* 1925 * Check whether input buffer was large enough 1926 */ 1927 if (stmfIoctl.stmf_obuf_max_nentries > MAX_LU) { 1928 fLuListSize = stmfIoctl.stmf_obuf_max_nentries * 1929 sizeof (slist_lu_t); 1930 fLuList = realloc(fLuList, fLuListSize); 1931 if (fLuList == NULL) { 1932 return (STMF_ERROR_NOMEM); 1933 } 1934 stmfIoctl.stmf_obuf_size = fLuListSize; 1935 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList; 1936 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 1937 if (ioctlRet != 0) { 1938 switch (errno) { 1939 case EBUSY: 1940 ret = STMF_ERROR_BUSY; 1941 break; 1942 case EACCES: 1943 ret = STMF_ERROR_PERM; 1944 break; 1945 default: 1946 syslog(LOG_DEBUG, 1947 "stmfGetLogicalUnitList:" 1948 "ioctl errno(%d)", errno); 1949 ret = STMF_STATUS_ERROR; 1950 break; 1951 } 1952 goto done; 1953 } 1954 } 1955 1956 ret = psGetLogicalUnitList(&sLuList); 1957 switch (ret) { 1958 case STMF_PS_SUCCESS: 1959 ret = STMF_STATUS_SUCCESS; 1960 break; 1961 case STMF_PS_ERROR_BUSY: 1962 ret = STMF_ERROR_BUSY; 1963 break; 1964 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 1965 ret = STMF_ERROR_SERVICE_NOT_FOUND; 1966 break; 1967 case STMF_PS_ERROR_VERSION_MISMATCH: 1968 ret = STMF_ERROR_SERVICE_DATA_VERSION; 1969 break; 1970 default: 1971 syslog(LOG_DEBUG, 1972 "stmfGetLogicalUnitList:psGetLogicalUnitList" 1973 ":error(%d)", ret); 1974 ret = STMF_STATUS_ERROR; 1975 break; 1976 } 1977 if (ret != STMF_STATUS_SUCCESS) { 1978 goto done; 1979 } 1980 1981 /* 1982 * 2 lists must be merged 1983 * reallocate the store list to add the list from the 1984 * framework 1985 */ 1986 newAllocSize = sLuList->cnt * sizeof (stmfGuid) + sizeof (stmfGuidList) 1987 + stmfIoctl.stmf_obuf_nentries * sizeof (stmfGuid); 1988 1989 sLuList = realloc(sLuList, newAllocSize); 1990 if (sLuList == NULL) { 1991 ret = STMF_ERROR_NOMEM; 1992 goto done; 1993 } 1994 1995 /* 1996 * add list from ioctl. Start from end of list retrieved from store. 1997 */ 1998 endList = sLuList->cnt + stmfIoctl.stmf_obuf_nentries; 1999 for (k = 0, i = sLuList->cnt; i < endList; i++, k++) { 2000 bcopy(&fLuList[k].lu_guid, sLuList->guid[i].guid, 2001 sizeof (stmfGuid)); 2002 } 2003 sLuList->cnt = endList; 2004 2005 /* 2006 * sort the list for merging 2007 */ 2008 qsort((void *)&(sLuList->guid[0]), sLuList->cnt, 2009 sizeof (stmfGuid), guidCompare); 2010 2011 /* 2012 * get final list count 2013 */ 2014 for (i = 0; i < sLuList->cnt; i++) { 2015 if ((i + 1) <= sLuList->cnt) { 2016 if (bcmp(sLuList->guid[i].guid, sLuList->guid[i+1].guid, 2017 sizeof (stmfGuid)) == 0) { 2018 continue; 2019 } 2020 } 2021 finalListSize++; 2022 } 2023 2024 /* 2025 * allocate caller's buffer with the final size 2026 */ 2027 *luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) + 2028 finalListSize * sizeof (stmfGuid)); 2029 if (*luList == NULL) { 2030 ret = STMF_ERROR_NOMEM; 2031 goto done; 2032 } 2033 2034 /* 2035 * copy guids to caller's buffer 2036 */ 2037 for (k = 0, i = 0; i < sLuList->cnt; i++) { 2038 if ((i + 1) <= sLuList->cnt) { 2039 if (bcmp(sLuList->guid[i].guid, sLuList->guid[i+1].guid, 2040 sizeof (stmfGuid)) == 0) { 2041 continue; 2042 } 2043 } 2044 bcopy(&(sLuList->guid[i].guid), (*luList)->guid[k++].guid, 2045 sizeof (stmfGuid)); 2046 } 2047 2048 (*luList)->cnt = finalListSize; 2049 2050 done: 2051 (void) close(fd); 2052 /* 2053 * free internal buffers 2054 */ 2055 free(fLuList); 2056 free(sLuList); 2057 return (ret); 2058 } 2059 2060 /* 2061 * stmfGetLogicalUnitProperties 2062 * 2063 * Purpose: Retrieves the properties for a logical unit 2064 * 2065 * lu - guid of the logical unit for which to retrieve properties 2066 * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success, 2067 * it contains the logical unit properties for the specified guid. 2068 */ 2069 int 2070 stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps) 2071 { 2072 int ret = STMF_STATUS_SUCCESS; 2073 int stmfRet; 2074 int fd; 2075 int ioctlRet; 2076 int cmd = STMF_IOCTL_GET_LU_PROPERTIES; 2077 stmfViewEntryList *viewEntryList = NULL; 2078 stmf_iocdata_t stmfIoctl; 2079 sioc_lu_props_t fLuProps; 2080 2081 if (luProps == NULL || luProps == NULL) { 2082 ret = STMF_ERROR_INVALID_ARG; 2083 } 2084 2085 bzero(luProps, sizeof (stmfLogicalUnitProperties)); 2086 2087 /* call init */ 2088 ret = initializeConfig(); 2089 if (ret != STMF_STATUS_SUCCESS) { 2090 return (ret); 2091 } 2092 2093 /* 2094 * Open control node for stmf 2095 */ 2096 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 2097 return (ret); 2098 2099 bzero(&stmfIoctl, sizeof (stmfIoctl)); 2100 /* 2101 * Issue ioctl to add to the host group 2102 */ 2103 stmfIoctl.stmf_version = STMF_VERSION_1; 2104 stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid); 2105 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu; 2106 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps; 2107 stmfIoctl.stmf_obuf_size = sizeof (fLuProps); 2108 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 2109 if (ioctlRet != 0) { 2110 switch (errno) { 2111 case EBUSY: 2112 ret = STMF_ERROR_BUSY; 2113 break; 2114 case EACCES: 2115 ret = STMF_ERROR_PERM; 2116 break; 2117 case ENOENT: 2118 stmfRet = stmfGetViewEntryList(lu, 2119 &viewEntryList); 2120 if (stmfRet == STMF_STATUS_SUCCESS) { 2121 luProps->status = 2122 STMF_LOGICAL_UNIT_UNREGISTERED; 2123 if (viewEntryList->cnt > 0) { 2124 ret = STMF_STATUS_SUCCESS; 2125 } else { 2126 ret = STMF_ERROR_NOT_FOUND; 2127 } 2128 } else { 2129 ret = STMF_ERROR_NOT_FOUND; 2130 } 2131 stmfFreeMemory(viewEntryList); 2132 break; 2133 default: 2134 syslog(LOG_DEBUG, 2135 "stmfGetLogicalUnit:ioctl errno(%d)", 2136 errno); 2137 ret = STMF_STATUS_ERROR; 2138 break; 2139 } 2140 goto done; 2141 } 2142 2143 bcopy(fLuProps.lu_provider_name, luProps->providerName, 2144 sizeof (fLuProps.lu_provider_name)); 2145 if (fLuProps.lu_state == STMF_STATE_ONLINE) { 2146 luProps->status = STMF_LOGICAL_UNIT_ONLINE; 2147 } else if (fLuProps.lu_state == STMF_STATE_OFFLINE) { 2148 luProps->status = STMF_LOGICAL_UNIT_OFFLINE; 2149 } else if (fLuProps.lu_state == STMF_STATE_ONLINING) { 2150 luProps->status = STMF_LOGICAL_UNIT_ONLINING; 2151 } else if (fLuProps.lu_state == STMF_STATE_OFFLINING) { 2152 luProps->status = STMF_LOGICAL_UNIT_OFFLINING; 2153 } 2154 bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias)); 2155 done: 2156 (void) close(fd); 2157 return (ret); 2158 } 2159 2160 /* 2161 * stmfGetState 2162 * 2163 * Purpose: retrieve the current state of the stmf module 2164 * 2165 * state - pointer to stmfState structure allocated by the caller 2166 * On success, contains the state of stmf 2167 */ 2168 int 2169 stmfGetState(stmfState *state) 2170 { 2171 int ret; 2172 stmf_state_desc_t iState; 2173 2174 if (state == NULL) { 2175 return (STMF_ERROR_INVALID_ARG); 2176 } 2177 2178 ret = getStmfState(&iState); 2179 if (ret != STMF_STATUS_SUCCESS) { 2180 return (ret); 2181 } 2182 switch (iState.state) { 2183 case STMF_STATE_ONLINE: 2184 state->operationalState = 2185 STMF_SERVICE_STATE_ONLINE; 2186 break; 2187 case STMF_STATE_OFFLINE: 2188 state->operationalState = 2189 STMF_SERVICE_STATE_OFFLINE; 2190 break; 2191 case STMF_STATE_ONLINING: 2192 state->operationalState = 2193 STMF_SERVICE_STATE_ONLINING; 2194 break; 2195 case STMF_STATE_OFFLINING: 2196 state->operationalState = 2197 STMF_SERVICE_STATE_OFFLINING; 2198 break; 2199 default: 2200 state->operationalState = 2201 STMF_SERVICE_STATE_UNKNOWN; 2202 break; 2203 } 2204 switch (iState.config_state) { 2205 case STMF_CONFIG_NONE: 2206 state->configState = STMF_CONFIG_STATE_NONE; 2207 break; 2208 case STMF_CONFIG_INIT: 2209 state->configState = STMF_CONFIG_STATE_INIT; 2210 break; 2211 case STMF_CONFIG_INIT_DONE: 2212 state->configState = 2213 STMF_CONFIG_STATE_INIT_DONE; 2214 break; 2215 default: 2216 state->configState = 2217 STMF_CONFIG_STATE_UNKNOWN; 2218 break; 2219 } 2220 return (STMF_STATUS_SUCCESS); 2221 } 2222 2223 /* 2224 * stmfGetViewEntryList 2225 * 2226 * Purpose: Retrieves the list of view entries for the specified 2227 * logical unit. 2228 * 2229 * lu - the guid of the logical unit for which to retrieve the view entry list 2230 * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On 2231 * success, contains the list of view entries. 2232 */ 2233 int 2234 stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList) 2235 { 2236 int ret; 2237 2238 if (lu == NULL || viewEntryList == NULL) { 2239 return (STMF_ERROR_INVALID_ARG); 2240 } 2241 2242 ret = psGetViewEntryList(lu, viewEntryList); 2243 switch (ret) { 2244 case STMF_PS_SUCCESS: 2245 ret = STMF_STATUS_SUCCESS; 2246 break; 2247 case STMF_PS_ERROR_NOT_FOUND: 2248 ret = STMF_ERROR_NOT_FOUND; 2249 break; 2250 case STMF_PS_ERROR_BUSY: 2251 ret = STMF_ERROR_BUSY; 2252 break; 2253 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2254 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2255 break; 2256 case STMF_PS_ERROR_VERSION_MISMATCH: 2257 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2258 break; 2259 default: 2260 syslog(LOG_DEBUG, 2261 "stmfGetViewEntryList:error(%d)", ret); 2262 ret = STMF_STATUS_ERROR; 2263 break; 2264 } 2265 2266 return (ret); 2267 } 2268 2269 /* 2270 * loadHostGroups 2271 * 2272 * Purpose - issues the ioctl to load the host groups into stmf 2273 * 2274 * fd - file descriptor for the control node of stmf. 2275 * groupList - populated host group list 2276 */ 2277 static int 2278 loadHostGroups(int fd, stmfGroupList *groupList) 2279 { 2280 int i, j; 2281 int ret = STMF_STATUS_SUCCESS; 2282 stmfGroupProperties *groupProps = NULL; 2283 2284 for (i = 0; i < groupList->cnt; i++) { 2285 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP, 2286 &(groupList->name[i]))) != STMF_STATUS_SUCCESS) { 2287 goto out; 2288 } 2289 ret = stmfGetHostGroupMembers(&(groupList->name[i]), 2290 &groupProps); 2291 for (j = 0; j < groupProps->cnt; j++) { 2292 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, 2293 &(groupList->name[i]), &(groupProps->name[j]))) 2294 != STMF_STATUS_SUCCESS) { 2295 goto out; 2296 } 2297 } 2298 } 2299 2300 2301 out: 2302 stmfFreeMemory(groupProps); 2303 return (ret); 2304 } 2305 2306 /* 2307 * loadTargetGroups 2308 * 2309 * Purpose - issues the ioctl to load the target groups into stmf 2310 * 2311 * fd - file descriptor for the control node of stmf. 2312 * groupList - populated target group list. 2313 */ 2314 static int 2315 loadTargetGroups(int fd, stmfGroupList *groupList) 2316 { 2317 int i, j; 2318 int ret = STMF_STATUS_SUCCESS; 2319 stmfGroupProperties *groupProps = NULL; 2320 2321 for (i = 0; i < groupList->cnt; i++) { 2322 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP, 2323 &(groupList->name[i]))) != STMF_STATUS_SUCCESS) { 2324 goto out; 2325 } 2326 ret = stmfGetTargetGroupMembers(&(groupList->name[i]), 2327 &groupProps); 2328 for (j = 0; j < groupProps->cnt; j++) { 2329 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY, 2330 &(groupList->name[i]), &(groupProps->name[j]))) 2331 != STMF_STATUS_SUCCESS) { 2332 goto out; 2333 } 2334 } 2335 } 2336 2337 2338 out: 2339 stmfFreeMemory(groupProps); 2340 return (ret); 2341 } 2342 2343 2344 /* 2345 * loadStore 2346 * 2347 * Purpose: Load the configuration data from the store 2348 * 2349 * First load the host groups and target groups, then the view entries 2350 * and finally the provider data 2351 * 2352 * fd - file descriptor of control node for stmf. 2353 */ 2354 static int 2355 loadStore(int fd) 2356 { 2357 int ret; 2358 int i, j; 2359 stmfGroupList *groupList = NULL; 2360 stmfGuidList *guidList = NULL; 2361 stmfViewEntryList *viewEntryList = NULL; 2362 stmfProviderList *providerList = NULL; 2363 int providerType; 2364 nvlist_t *nvl = NULL; 2365 2366 2367 2368 /* load host groups */ 2369 ret = stmfGetHostGroupList(&groupList); 2370 if (ret != STMF_STATUS_SUCCESS) { 2371 return (ret); 2372 } 2373 ret = loadHostGroups(fd, groupList); 2374 if (ret != STMF_STATUS_SUCCESS) { 2375 goto out; 2376 } 2377 2378 stmfFreeMemory(groupList); 2379 groupList = NULL; 2380 2381 /* load target groups */ 2382 ret = stmfGetTargetGroupList(&groupList); 2383 if (ret != STMF_STATUS_SUCCESS) { 2384 goto out; 2385 } 2386 ret = loadTargetGroups(fd, groupList); 2387 if (ret != STMF_STATUS_SUCCESS) { 2388 goto out; 2389 } 2390 2391 stmfFreeMemory(groupList); 2392 groupList = NULL; 2393 2394 /* Get the guid list */ 2395 ret = psGetLogicalUnitList(&guidList); 2396 switch (ret) { 2397 case STMF_PS_SUCCESS: 2398 ret = STMF_STATUS_SUCCESS; 2399 break; 2400 case STMF_PS_ERROR_NOT_FOUND: 2401 ret = STMF_ERROR_NOT_FOUND; 2402 break; 2403 case STMF_PS_ERROR_BUSY: 2404 ret = STMF_ERROR_BUSY; 2405 break; 2406 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2407 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2408 break; 2409 case STMF_PS_ERROR_VERSION_MISMATCH: 2410 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2411 break; 2412 default: 2413 ret = STMF_STATUS_ERROR; 2414 break; 2415 } 2416 2417 if (ret != STMF_STATUS_SUCCESS) { 2418 goto out; 2419 } 2420 2421 /* 2422 * We have the guid list, now get the corresponding 2423 * view entries for each guid 2424 */ 2425 for (i = 0; i < guidList->cnt; i++) { 2426 ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList); 2427 switch (ret) { 2428 case STMF_PS_SUCCESS: 2429 ret = STMF_STATUS_SUCCESS; 2430 break; 2431 case STMF_PS_ERROR_NOT_FOUND: 2432 ret = STMF_ERROR_NOT_FOUND; 2433 break; 2434 case STMF_PS_ERROR_BUSY: 2435 ret = STMF_ERROR_BUSY; 2436 break; 2437 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2438 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2439 break; 2440 case STMF_PS_ERROR_VERSION_MISMATCH: 2441 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2442 break; 2443 default: 2444 ret = STMF_STATUS_ERROR; 2445 break; 2446 } 2447 if (ret != STMF_STATUS_SUCCESS) { 2448 goto out; 2449 } 2450 for (j = 0; j < viewEntryList->cnt; j++) { 2451 ret = addViewEntryIoctl(fd, &guidList->guid[i], 2452 &viewEntryList->ve[j]); 2453 if (ret != STMF_STATUS_SUCCESS) { 2454 goto out; 2455 } 2456 } 2457 } 2458 2459 /* get the list of providers that have data */ 2460 ret = psGetProviderDataList(&providerList); 2461 switch (ret) { 2462 case STMF_PS_SUCCESS: 2463 ret = STMF_STATUS_SUCCESS; 2464 break; 2465 case STMF_PS_ERROR_NOT_FOUND: 2466 ret = STMF_ERROR_NOT_FOUND; 2467 break; 2468 case STMF_PS_ERROR_BUSY: 2469 ret = STMF_ERROR_BUSY; 2470 break; 2471 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2472 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2473 break; 2474 case STMF_PS_ERROR_VERSION_MISMATCH: 2475 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2476 break; 2477 default: 2478 ret = STMF_STATUS_ERROR; 2479 break; 2480 } 2481 if (ret != STMF_STATUS_SUCCESS) { 2482 goto out; 2483 } 2484 2485 for (i = 0; i < providerList->cnt; i++) { 2486 providerType = providerList->provider[i].providerType; 2487 ret = psGetProviderData(providerList->provider[i].name, 2488 &nvl, providerType, NULL); 2489 switch (ret) { 2490 case STMF_PS_SUCCESS: 2491 ret = STMF_STATUS_SUCCESS; 2492 break; 2493 case STMF_PS_ERROR_NOT_FOUND: 2494 ret = STMF_ERROR_NOT_FOUND; 2495 break; 2496 case STMF_PS_ERROR_BUSY: 2497 ret = STMF_ERROR_BUSY; 2498 break; 2499 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2500 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2501 break; 2502 case STMF_PS_ERROR_VERSION_MISMATCH: 2503 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2504 break; 2505 default: 2506 ret = STMF_STATUS_ERROR; 2507 break; 2508 } 2509 if (ret != STMF_STATUS_SUCCESS) { 2510 goto out; 2511 } 2512 2513 /* call setProviderData */ 2514 ret = setProviderData(fd, providerList->provider[i].name, nvl, 2515 providerType); 2516 switch (ret) { 2517 case STMF_PS_SUCCESS: 2518 ret = STMF_STATUS_SUCCESS; 2519 break; 2520 case STMF_PS_ERROR_NOT_FOUND: 2521 ret = STMF_ERROR_NOT_FOUND; 2522 break; 2523 case STMF_PS_ERROR_BUSY: 2524 ret = STMF_ERROR_BUSY; 2525 break; 2526 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2527 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2528 break; 2529 case STMF_PS_ERROR_VERSION_MISMATCH: 2530 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2531 break; 2532 default: 2533 ret = STMF_STATUS_ERROR; 2534 break; 2535 } 2536 if (ret != STMF_STATUS_SUCCESS) { 2537 goto out; 2538 } 2539 2540 nvlist_free(nvl); 2541 nvl = NULL; 2542 } 2543 out: 2544 if (groupList != NULL) { 2545 free(groupList); 2546 } 2547 if (guidList != NULL) { 2548 free(guidList); 2549 } 2550 if (viewEntryList != NULL) { 2551 free(viewEntryList); 2552 } 2553 if (nvl != NULL) { 2554 nvlist_free(nvl); 2555 } 2556 return (ret); 2557 } 2558 2559 /* 2560 * stmfLoadConfig 2561 * 2562 * Purpose - load the configuration data from smf into stmf 2563 * 2564 */ 2565 int 2566 stmfLoadConfig(void) 2567 { 2568 int ret; 2569 int fd; 2570 stmf_state_desc_t stmfStateSet; 2571 stmfState state; 2572 2573 2574 /* Check to ensure service exists */ 2575 if (psCheckService() != STMF_STATUS_SUCCESS) { 2576 return (STMF_ERROR_SERVICE_NOT_FOUND); 2577 } 2578 2579 ret = stmfGetState(&state); 2580 if (ret == STMF_STATUS_SUCCESS) { 2581 if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) { 2582 return (STMF_ERROR_SERVICE_ONLINE); 2583 } 2584 } else { 2585 return (STMF_STATUS_ERROR); 2586 } 2587 2588 2589 stmfStateSet.state = STMF_STATE_OFFLINE; 2590 stmfStateSet.config_state = STMF_CONFIG_INIT; 2591 2592 /* 2593 * Open control node for stmf 2594 */ 2595 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2596 return (ret); 2597 2598 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE); 2599 if (ret != STMF_STATUS_SUCCESS) { 2600 goto done; 2601 } 2602 2603 /* Load the persistent configuration data */ 2604 ret = loadStore(fd); 2605 if (ret != 0) { 2606 goto done; 2607 } 2608 2609 stmfStateSet.state = STMF_STATE_OFFLINE; 2610 stmfStateSet.config_state = STMF_CONFIG_INIT_DONE; 2611 2612 done: 2613 if (ret == STMF_STATUS_SUCCESS) { 2614 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE); 2615 } 2616 (void) close(fd); 2617 return (ret); 2618 } 2619 2620 /* 2621 * getStmfState 2622 * 2623 * stmfState - pointer to stmf_state_desc_t structure. Will contain the state 2624 * information of the stmf service on success. 2625 */ 2626 static int 2627 getStmfState(stmf_state_desc_t *stmfState) 2628 { 2629 int ret = STMF_STATUS_SUCCESS; 2630 int fd; 2631 int ioctlRet; 2632 stmf_iocdata_t stmfIoctl; 2633 2634 /* 2635 * Open control node for stmf 2636 */ 2637 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 2638 return (ret); 2639 2640 bzero(&stmfIoctl, sizeof (stmfIoctl)); 2641 /* 2642 * Issue ioctl to get the stmf state 2643 */ 2644 stmfIoctl.stmf_version = STMF_VERSION_1; 2645 stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t); 2646 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState; 2647 stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t); 2648 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState; 2649 ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl); 2650 2651 (void) close(fd); 2652 2653 if (ioctlRet != 0) { 2654 switch (errno) { 2655 case EBUSY: 2656 ret = STMF_ERROR_BUSY; 2657 break; 2658 case EPERM: 2659 case EACCES: 2660 ret = STMF_ERROR_PERM; 2661 break; 2662 default: 2663 syslog(LOG_DEBUG, 2664 "getStmfState:ioctl errno(%d)", errno); 2665 ret = STMF_STATUS_ERROR; 2666 break; 2667 } 2668 } 2669 return (ret); 2670 } 2671 2672 2673 /* 2674 * setStmfState 2675 * 2676 * stmfState - pointer to caller set state structure 2677 * objectType - one of: 2678 * LOGICAL_UNIT_TYPE 2679 * TARGET_TYPE 2680 * STMF_SERVICE_TYPE 2681 */ 2682 static int 2683 setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType) 2684 { 2685 int ret = STMF_STATUS_SUCCESS; 2686 int ioctlRet; 2687 int cmd; 2688 stmf_iocdata_t stmfIoctl; 2689 2690 switch (objectType) { 2691 case LOGICAL_UNIT_TYPE: 2692 cmd = STMF_IOCTL_SET_LU_STATE; 2693 break; 2694 case TARGET_TYPE: 2695 cmd = STMF_IOCTL_SET_TARGET_PORT_STATE; 2696 break; 2697 case STMF_SERVICE_TYPE: 2698 cmd = STMF_IOCTL_SET_STMF_STATE; 2699 break; 2700 default: 2701 ret = STMF_STATUS_ERROR; 2702 goto done; 2703 } 2704 2705 bzero(&stmfIoctl, sizeof (stmfIoctl)); 2706 /* 2707 * Issue ioctl to set the stmf state 2708 */ 2709 stmfIoctl.stmf_version = STMF_VERSION_1; 2710 stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t); 2711 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState; 2712 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 2713 if (ioctlRet != 0) { 2714 switch (errno) { 2715 case EBUSY: 2716 ret = STMF_ERROR_BUSY; 2717 break; 2718 case EACCES: 2719 ret = STMF_ERROR_PERM; 2720 break; 2721 case ENOENT: 2722 ret = STMF_ERROR_NOT_FOUND; 2723 break; 2724 default: 2725 syslog(LOG_DEBUG, 2726 "setStmfState:ioctl errno(%d)", errno); 2727 ret = STMF_STATUS_ERROR; 2728 break; 2729 } 2730 } 2731 done: 2732 return (ret); 2733 } 2734 2735 /* 2736 * stmfOnline 2737 * 2738 * Purpose: Online stmf service 2739 * 2740 */ 2741 int 2742 stmfOnline(void) 2743 { 2744 int ret; 2745 int fd; 2746 stmfState state; 2747 stmf_state_desc_t iState; 2748 2749 ret = stmfGetState(&state); 2750 if (ret == STMF_STATUS_SUCCESS) { 2751 if (state.operationalState == STMF_SERVICE_STATE_ONLINE) { 2752 return (STMF_ERROR_SERVICE_ONLINE); 2753 } 2754 } else { 2755 return (STMF_STATUS_ERROR); 2756 } 2757 iState.state = STMF_STATE_ONLINE; 2758 iState.config_state = STMF_CONFIG_NONE; 2759 /* 2760 * Open control node for stmf 2761 * to make call to setStmfState() 2762 */ 2763 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2764 return (ret); 2765 ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE); 2766 (void) close(fd); 2767 return (ret); 2768 } 2769 2770 /* 2771 * stmfOffline 2772 * 2773 * Purpose: Offline stmf service 2774 * 2775 */ 2776 int 2777 stmfOffline(void) 2778 { 2779 int ret; 2780 int fd; 2781 stmfState state; 2782 stmf_state_desc_t iState; 2783 2784 ret = stmfGetState(&state); 2785 if (ret == STMF_STATUS_SUCCESS) { 2786 if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) { 2787 return (STMF_ERROR_SERVICE_OFFLINE); 2788 } 2789 } else { 2790 return (STMF_STATUS_ERROR); 2791 } 2792 iState.state = STMF_STATE_OFFLINE; 2793 iState.config_state = STMF_CONFIG_NONE; 2794 2795 /* 2796 * Open control node for stmf 2797 * to make call to setStmfState() 2798 */ 2799 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2800 return (ret); 2801 ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE); 2802 (void) close(fd); 2803 return (ret); 2804 } 2805 2806 2807 /* 2808 * stmfOfflineTarget 2809 * 2810 * Purpose: Change state of target to offline 2811 * 2812 * devid - devid of the target to offline 2813 */ 2814 int 2815 stmfOfflineTarget(stmfDevid *devid) 2816 { 2817 stmf_state_desc_t targetState; 2818 int ret = STMF_STATUS_SUCCESS; 2819 int fd; 2820 2821 if (devid == NULL) { 2822 return (STMF_ERROR_INVALID_ARG); 2823 } 2824 bzero(&targetState, sizeof (targetState)); 2825 2826 targetState.state = STMF_STATE_OFFLINE; 2827 targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength; 2828 bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1], 2829 devid->identLength); 2830 /* 2831 * Open control node for stmf 2832 * to make call to setStmfState() 2833 */ 2834 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2835 return (ret); 2836 ret = setStmfState(fd, &targetState, TARGET_TYPE); 2837 (void) close(fd); 2838 return (ret); 2839 } 2840 2841 /* 2842 * stmfOfflineLogicalUnit 2843 * 2844 * Purpose: Change state of logical unit to offline 2845 * 2846 * lu - guid of the logical unit to offline 2847 */ 2848 int 2849 stmfOfflineLogicalUnit(stmfGuid *lu) 2850 { 2851 stmf_state_desc_t luState; 2852 int ret = STMF_STATUS_SUCCESS; 2853 int fd; 2854 2855 if (lu == NULL) { 2856 return (STMF_ERROR_INVALID_ARG); 2857 } 2858 2859 bzero(&luState, sizeof (luState)); 2860 2861 luState.state = STMF_STATE_OFFLINE; 2862 bcopy(lu, &luState.ident, sizeof (stmfGuid)); 2863 /* 2864 * Open control node for stmf 2865 * to make call to setStmfState() 2866 */ 2867 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2868 return (ret); 2869 ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE); 2870 (void) close(fd); 2871 return (ret); 2872 } 2873 2874 /* 2875 * stmfOnlineTarget 2876 * 2877 * Purpose: Change state of target to online 2878 * 2879 * devid - devid of the target to online 2880 */ 2881 int 2882 stmfOnlineTarget(stmfDevid *devid) 2883 { 2884 stmf_state_desc_t targetState; 2885 int ret = STMF_STATUS_SUCCESS; 2886 int fd; 2887 2888 if (devid == NULL) { 2889 return (STMF_ERROR_INVALID_ARG); 2890 } 2891 bzero(&targetState, sizeof (targetState)); 2892 2893 targetState.state = STMF_STATE_ONLINE; 2894 targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength; 2895 bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1], 2896 devid->identLength); 2897 /* 2898 * Open control node for stmf 2899 * to make call to setStmfState() 2900 */ 2901 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2902 return (ret); 2903 ret = setStmfState(fd, &targetState, TARGET_TYPE); 2904 (void) close(fd); 2905 return (ret); 2906 } 2907 2908 /* 2909 * stmfOnlineLogicalUnit 2910 * 2911 * Purpose: Change state of logical unit to online 2912 * 2913 * lu - guid of the logical unit to online 2914 */ 2915 int 2916 stmfOnlineLogicalUnit(stmfGuid *lu) 2917 { 2918 stmf_state_desc_t luState; 2919 int ret = STMF_STATUS_SUCCESS; 2920 int fd; 2921 2922 if (lu == NULL) { 2923 return (STMF_ERROR_INVALID_ARG); 2924 } 2925 2926 bzero(&luState, sizeof (luState)); 2927 2928 luState.state = STMF_STATE_ONLINE; 2929 bcopy(lu, &luState.ident, sizeof (stmfGuid)); 2930 /* 2931 * Open control node for stmf 2932 * to make call to setStmfState() 2933 */ 2934 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2935 return (ret); 2936 ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE); 2937 (void) close(fd); 2938 return (ret); 2939 } 2940 2941 /* 2942 * stmfRemoveFromHostGroup 2943 * 2944 * Purpose: Removes an initiator from an initiator group 2945 * 2946 * hostGroupName - name of an initiator group 2947 * hostName - name of host group member to remove 2948 */ 2949 int 2950 stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName) 2951 { 2952 int ret; 2953 int fd; 2954 2955 if (hostGroupName == NULL || 2956 (strnlen((char *)hostGroupName, sizeof (stmfGroupName)) 2957 == sizeof (stmfGroupName)) || hostName == NULL) { 2958 return (STMF_ERROR_INVALID_ARG); 2959 } 2960 2961 /* call init */ 2962 ret = initializeConfig(); 2963 if (ret != STMF_STATUS_SUCCESS) { 2964 return (ret); 2965 } 2966 2967 /* 2968 * Open control node for stmf 2969 */ 2970 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 2971 return (ret); 2972 2973 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY, 2974 hostGroupName, hostName)) != STMF_STATUS_SUCCESS) { 2975 goto done; 2976 } 2977 2978 ret = psRemoveHostGroupMember((char *)hostGroupName, 2979 (char *)hostName->ident); 2980 switch (ret) { 2981 case STMF_PS_SUCCESS: 2982 ret = STMF_STATUS_SUCCESS; 2983 break; 2984 case STMF_PS_ERROR_MEMBER_NOT_FOUND: 2985 ret = STMF_ERROR_MEMBER_NOT_FOUND; 2986 break; 2987 case STMF_PS_ERROR_GROUP_NOT_FOUND: 2988 ret = STMF_ERROR_GROUP_NOT_FOUND; 2989 break; 2990 case STMF_PS_ERROR_BUSY: 2991 ret = STMF_ERROR_BUSY; 2992 break; 2993 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2994 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2995 break; 2996 case STMF_PS_ERROR_VERSION_MISMATCH: 2997 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2998 break; 2999 default: 3000 syslog(LOG_DEBUG, 3001 "stmfRemoveFromHostGroup" 3002 "psRemoveHostGroupMember:error(%d)", ret); 3003 ret = STMF_STATUS_ERROR; 3004 break; 3005 } 3006 3007 done: 3008 (void) close(fd); 3009 return (ret); 3010 } 3011 3012 /* 3013 * stmfRemoveFromTargetGroup 3014 * 3015 * Purpose: Removes a local port from a local port group 3016 * 3017 * targetGroupName - name of a target group 3018 * targetName - name of target to remove 3019 */ 3020 int 3021 stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName) 3022 { 3023 int ret; 3024 int fd; 3025 3026 if (targetGroupName == NULL || 3027 (strnlen((char *)targetGroupName, sizeof (stmfGroupName)) 3028 == sizeof (stmfGroupName)) || targetName == NULL) { 3029 return (STMF_ERROR_INVALID_ARG); 3030 } 3031 3032 /* call init */ 3033 ret = initializeConfig(); 3034 if (ret != STMF_STATUS_SUCCESS) { 3035 return (ret); 3036 } 3037 3038 /* 3039 * Open control node for stmf 3040 */ 3041 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3042 return (ret); 3043 3044 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY, 3045 targetGroupName, targetName)) != STMF_STATUS_SUCCESS) { 3046 goto done; 3047 } 3048 3049 ret = psRemoveTargetGroupMember((char *)targetGroupName, 3050 (char *)targetName->ident); 3051 switch (ret) { 3052 case STMF_PS_SUCCESS: 3053 ret = STMF_STATUS_SUCCESS; 3054 break; 3055 case STMF_PS_ERROR_MEMBER_NOT_FOUND: 3056 ret = STMF_ERROR_MEMBER_NOT_FOUND; 3057 break; 3058 case STMF_PS_ERROR_GROUP_NOT_FOUND: 3059 ret = STMF_ERROR_GROUP_NOT_FOUND; 3060 break; 3061 case STMF_PS_ERROR_BUSY: 3062 ret = STMF_ERROR_BUSY; 3063 break; 3064 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3065 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3066 break; 3067 case STMF_PS_ERROR_VERSION_MISMATCH: 3068 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3069 break; 3070 default: 3071 syslog(LOG_DEBUG, 3072 "stmfRemoveFromTargetGroup" 3073 "psRemoveTargetGroupMember:error(%d)", ret); 3074 ret = STMF_STATUS_ERROR; 3075 break; 3076 } 3077 3078 done: 3079 (void) close(fd); 3080 return (ret); 3081 } 3082 3083 /* 3084 * stmfRemoveViewEntry 3085 * 3086 * Purpose: Removes a view entry from a logical unit 3087 * 3088 * lu - guid of lu for which view entry is being removed 3089 * viewEntryIndex - index of view entry to remove 3090 * 3091 */ 3092 int 3093 stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex) 3094 { 3095 int ret = STMF_STATUS_SUCCESS; 3096 int fd; 3097 int ioctlRet; 3098 stmf_iocdata_t stmfIoctl; 3099 stmf_view_op_entry_t ioctlViewEntry; 3100 3101 if (lu == NULL) { 3102 return (STMF_ERROR_INVALID_ARG); 3103 } 3104 3105 /* call init */ 3106 ret = initializeConfig(); 3107 if (ret != STMF_STATUS_SUCCESS) { 3108 return (ret); 3109 } 3110 3111 /* 3112 * Open control node for stmf 3113 */ 3114 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3115 return (ret); 3116 3117 bzero(&ioctlViewEntry, sizeof (ioctlViewEntry)); 3118 ioctlViewEntry.ve_ndx_valid = B_TRUE; 3119 ioctlViewEntry.ve_ndx = viewEntryIndex; 3120 bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid)); 3121 3122 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3123 /* 3124 * Issue ioctl to add to the view entry 3125 */ 3126 stmfIoctl.stmf_version = STMF_VERSION_1; 3127 stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry); 3128 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry; 3129 ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl); 3130 if (ioctlRet != 0) { 3131 switch (errno) { 3132 case EBUSY: 3133 ret = STMF_ERROR_BUSY; 3134 break; 3135 case EACCES: 3136 switch (stmfIoctl.stmf_error) { 3137 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 3138 ret = STMF_ERROR_CONFIG_NONE; 3139 break; 3140 default: 3141 ret = STMF_ERROR_PERM; 3142 break; 3143 } 3144 break; 3145 case ENODEV: 3146 case ENOENT: 3147 ret = STMF_ERROR_NOT_FOUND; 3148 break; 3149 default: 3150 syslog(LOG_DEBUG, 3151 "stmfRemoveViewEntry:ioctl errno(%d)", 3152 errno); 3153 ret = STMF_STATUS_ERROR; 3154 break; 3155 } 3156 goto done; 3157 } 3158 3159 ret = psRemoveViewEntry(lu, viewEntryIndex); 3160 switch (ret) { 3161 case STMF_PS_SUCCESS: 3162 ret = STMF_STATUS_SUCCESS; 3163 break; 3164 case STMF_PS_ERROR_NOT_FOUND: 3165 ret = STMF_ERROR_NOT_FOUND; 3166 break; 3167 case STMF_PS_ERROR_BUSY: 3168 ret = STMF_ERROR_BUSY; 3169 break; 3170 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3171 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3172 break; 3173 case STMF_PS_ERROR_VERSION_MISMATCH: 3174 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3175 break; 3176 default: 3177 syslog(LOG_DEBUG, 3178 "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)", 3179 ret); 3180 ret = STMF_STATUS_ERROR; 3181 break; 3182 } 3183 3184 done: 3185 (void) close(fd); 3186 return (ret); 3187 } 3188 3189 /* 3190 * stmfSetProviderData 3191 * 3192 * Purpose: set the provider data 3193 * 3194 * providerName - unique name of provider 3195 * nvl - nvlist to set 3196 * providerType - type of provider for which to set data 3197 * STMF_LU_PROVIDER_TYPE 3198 * STMF_PORT_PROVIDER_TYPE 3199 */ 3200 int 3201 stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType) 3202 { 3203 return (stmfSetProviderDataProt(providerName, nvl, providerType, 3204 NULL)); 3205 } 3206 3207 /* 3208 * stmfSetProviderDataProt 3209 * 3210 * Purpose: set the provider data 3211 * 3212 * providerName - unique name of provider 3213 * nvl - nvlist to set 3214 * providerType - type of provider for which to set data 3215 * STMF_LU_PROVIDER_TYPE 3216 * STMF_PORT_PROVIDER_TYPE 3217 * setToken - Stale data token returned in the stmfGetProviderDataProt() 3218 * call or NULL. 3219 */ 3220 int 3221 stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType, 3222 uint64_t *setToken) 3223 { 3224 int ret; 3225 int fd; 3226 3227 if (providerName == NULL || nvl == NULL) { 3228 return (STMF_ERROR_INVALID_ARG); 3229 } 3230 3231 if (providerType != STMF_LU_PROVIDER_TYPE && 3232 providerType != STMF_PORT_PROVIDER_TYPE) { 3233 return (STMF_ERROR_INVALID_ARG); 3234 } 3235 3236 /* call init */ 3237 ret = initializeConfig(); 3238 if (ret != STMF_STATUS_SUCCESS) { 3239 return (ret); 3240 } 3241 3242 /* 3243 * Open control node for stmf 3244 */ 3245 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3246 return (ret); 3247 3248 ret = setProviderData(fd, providerName, nvl, providerType); 3249 3250 (void) close(fd); 3251 3252 if (ret != STMF_STATUS_SUCCESS) { 3253 goto done; 3254 } 3255 3256 /* setting driver provider data successful. Now persist it */ 3257 ret = psSetProviderData(providerName, nvl, providerType, setToken); 3258 switch (ret) { 3259 case STMF_PS_SUCCESS: 3260 ret = STMF_STATUS_SUCCESS; 3261 break; 3262 case STMF_PS_ERROR_EXISTS: 3263 ret = STMF_ERROR_EXISTS; 3264 break; 3265 case STMF_PS_ERROR_BUSY: 3266 ret = STMF_ERROR_BUSY; 3267 break; 3268 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3269 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3270 break; 3271 case STMF_PS_ERROR_VERSION_MISMATCH: 3272 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3273 break; 3274 case STMF_PS_ERROR_PROV_DATA_STALE: 3275 ret = STMF_ERROR_PROV_DATA_STALE; 3276 break; 3277 default: 3278 syslog(LOG_DEBUG, 3279 "stmfSetProviderData" 3280 "psSetProviderData:error(%d)", ret); 3281 ret = STMF_STATUS_ERROR; 3282 break; 3283 } 3284 3285 done: 3286 return (ret); 3287 } 3288 3289 /* 3290 * setProviderData 3291 * 3292 * Purpose: set the provider data 3293 * 3294 * providerName - unique name of provider 3295 * nvl - nvlist to set 3296 * providerType - logical unit or port provider 3297 */ 3298 static int 3299 setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType) 3300 { 3301 int ret = STMF_STATUS_SUCCESS; 3302 int ioctlRet; 3303 size_t nvlistEncodedSize; 3304 stmf_ppioctl_data_t *ppi = NULL; 3305 char *allocatedNvBuffer; 3306 stmf_iocdata_t stmfIoctl; 3307 3308 if (providerName == NULL) { 3309 return (STMF_ERROR_INVALID_ARG); 3310 } 3311 3312 /* get size of encoded nvlist */ 3313 if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) { 3314 return (STMF_STATUS_ERROR); 3315 } 3316 3317 /* allocate memory for ioctl */ 3318 ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize + 3319 sizeof (stmf_ppioctl_data_t)); 3320 if (ppi == NULL) { 3321 return (STMF_ERROR_NOMEM); 3322 } 3323 3324 allocatedNvBuffer = (char *)&ppi->ppi_data; 3325 if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize, 3326 NV_ENCODE_XDR, 0) != 0) { 3327 return (STMF_STATUS_ERROR); 3328 } 3329 3330 /* set provider name and provider type */ 3331 (void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name)); 3332 switch (providerType) { 3333 case STMF_LU_PROVIDER_TYPE: 3334 ppi->ppi_lu_provider = 1; 3335 break; 3336 case STMF_PORT_PROVIDER_TYPE: 3337 ppi->ppi_port_provider = 1; 3338 break; 3339 default: 3340 return (STMF_ERROR_INVALID_ARG); 3341 } 3342 3343 /* set the size of the ioctl data to packed data size */ 3344 ppi->ppi_data_size = nvlistEncodedSize; 3345 3346 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3347 3348 stmfIoctl.stmf_version = STMF_VERSION_1; 3349 /* 3350 * Subtracting 8 from the size as that is the size of the last member 3351 * of the structure where the packed data resides 3352 */ 3353 stmfIoctl.stmf_ibuf_size = nvlistEncodedSize + 3354 sizeof (stmf_ppioctl_data_t) - 8; 3355 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi; 3356 ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl); 3357 if (ioctlRet != 0) { 3358 switch (errno) { 3359 case EBUSY: 3360 ret = STMF_ERROR_BUSY; 3361 break; 3362 case EACCES: 3363 ret = STMF_ERROR_PERM; 3364 break; 3365 default: 3366 syslog(LOG_DEBUG, 3367 "setProviderData:ioctl errno(%d)", errno); 3368 ret = STMF_STATUS_ERROR; 3369 break; 3370 } 3371 if (ret != STMF_STATUS_SUCCESS) 3372 goto done; 3373 } 3374 3375 done: 3376 free(ppi); 3377 return (ret); 3378 } 3379