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; 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 fTargetList = (slist_target_port_t *)calloc(1, fTargetListSize); 1675 if (fTargetList == NULL) { 1676 goto done; 1677 } 1678 1679 bzero(&stmfIoctl, sizeof (stmfIoctl)); 1680 /* 1681 * Issue ioctl to add to the host group 1682 */ 1683 stmfIoctl.stmf_version = STMF_VERSION_1; 1684 stmfIoctl.stmf_obuf_size = fTargetListSize; 1685 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList; 1686 ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl); 1687 if (ioctlRet != 0) { 1688 switch (errno) { 1689 case EBUSY: 1690 ret = STMF_ERROR_BUSY; 1691 break; 1692 case EACCES: 1693 ret = STMF_ERROR_PERM; 1694 break; 1695 default: 1696 syslog(LOG_DEBUG, 1697 "stmfGetTargetList:ioctl errno(%d)", errno); 1698 ret = STMF_STATUS_ERROR; 1699 break; 1700 } 1701 goto done; 1702 } 1703 /* 1704 * Check whether input buffer was large enough 1705 */ 1706 if (stmfIoctl.stmf_obuf_max_nentries > MAX_TARGET_PORT) { 1707 fTargetListSize = stmfIoctl.stmf_obuf_max_nentries * 1708 sizeof (slist_target_port_t); 1709 fTargetList = realloc(fTargetList, fTargetListSize); 1710 if (fTargetList == NULL) { 1711 return (STMF_ERROR_NOMEM); 1712 } 1713 stmfIoctl.stmf_obuf_size = fTargetListSize; 1714 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList; 1715 ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, 1716 &stmfIoctl); 1717 if (ioctlRet != 0) { 1718 switch (errno) { 1719 case EBUSY: 1720 ret = STMF_ERROR_BUSY; 1721 break; 1722 case EACCES: 1723 ret = STMF_ERROR_PERM; 1724 break; 1725 default: 1726 syslog(LOG_DEBUG, 1727 "stmfGetTargetList:ioctl errno(%d)", 1728 errno); 1729 ret = STMF_STATUS_ERROR; 1730 break; 1731 } 1732 goto done; 1733 } 1734 } 1735 1736 *targetList = (stmfDevidList *)calloc(1, 1737 stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) + 1738 sizeof (stmfDevidList)); 1739 1740 (*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries; 1741 for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) { 1742 (*targetList)->devid[i].identLength = 1743 fTargetList->target[IDENT_LENGTH_BYTE]; 1744 bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1], 1745 &(*targetList)->devid[i].ident, 1746 fTargetList->target[IDENT_LENGTH_BYTE]); 1747 } 1748 1749 done: 1750 (void) close(fd); 1751 free(fTargetList); 1752 return (ret); 1753 } 1754 1755 /* 1756 * stmfGetTargetProperties 1757 * 1758 * Purpose: Retrieves the properties for a logical unit 1759 * 1760 * devid - devid of the target for which to retrieve properties 1761 * targetProps - pointer to an stmfTargetProperties structure. 1762 * On success, it contains the target properties for 1763 * the specified devid. 1764 */ 1765 int 1766 stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps) 1767 { 1768 int ret = STMF_STATUS_SUCCESS; 1769 int fd; 1770 int ioctlRet; 1771 stmf_iocdata_t stmfIoctl; 1772 sioc_target_port_props_t targetProperties; 1773 1774 if (devid == NULL || targetProps == NULL) { 1775 return (STMF_ERROR_INVALID_ARG); 1776 } 1777 1778 /* call init */ 1779 ret = initializeConfig(); 1780 if (ret != STMF_STATUS_SUCCESS) { 1781 return (ret); 1782 } 1783 1784 /* 1785 * Open control node for stmf 1786 */ 1787 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 1788 return (ret); 1789 1790 targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength; 1791 bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1], 1792 devid->identLength); 1793 1794 bzero(&stmfIoctl, sizeof (stmfIoctl)); 1795 /* 1796 * Issue ioctl to add to the host group 1797 */ 1798 stmfIoctl.stmf_version = STMF_VERSION_1; 1799 stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id); 1800 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id; 1801 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties; 1802 stmfIoctl.stmf_obuf_size = sizeof (targetProperties); 1803 ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES, 1804 &stmfIoctl); 1805 if (ioctlRet != 0) { 1806 switch (errno) { 1807 case EBUSY: 1808 ret = STMF_ERROR_BUSY; 1809 break; 1810 case EACCES: 1811 ret = STMF_ERROR_PERM; 1812 break; 1813 case ENOENT: 1814 ret = STMF_ERROR_NOT_FOUND; 1815 break; 1816 default: 1817 syslog(LOG_DEBUG, 1818 "stmfGetTargetProperties:ioctl errno(%d)", 1819 errno); 1820 ret = STMF_STATUS_ERROR; 1821 break; 1822 } 1823 goto done; 1824 } 1825 1826 bcopy(targetProperties.tgt_provider_name, targetProps->providerName, 1827 sizeof (targetProperties.tgt_provider_name)); 1828 if (targetProperties.tgt_state == STMF_STATE_ONLINE) { 1829 targetProps->status = STMF_TARGET_PORT_ONLINE; 1830 } else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) { 1831 targetProps->status = STMF_TARGET_PORT_OFFLINE; 1832 } else if (targetProperties.tgt_state == STMF_STATE_ONLINING) { 1833 targetProps->status = STMF_TARGET_PORT_ONLINING; 1834 } else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) { 1835 targetProps->status = STMF_TARGET_PORT_OFFLINING; 1836 } 1837 bcopy(targetProperties.tgt_alias, targetProps->alias, 1838 sizeof (targetProps->alias)); 1839 done: 1840 (void) close(fd); 1841 return (ret); 1842 } 1843 1844 /* 1845 * stmfGetLogicalUnitList 1846 * 1847 * Purpose: Retrieves list of logical unit Object IDs 1848 * 1849 * luList - pointer to a pointer to a stmfGuidList structure. On success, 1850 * it contains the list of logical unit guids. 1851 * 1852 */ 1853 int 1854 stmfGetLogicalUnitList(stmfGuidList **luList) 1855 { 1856 int ret; 1857 int fd; 1858 int ioctlRet; 1859 int cmd = STMF_IOCTL_LU_LIST; 1860 int i, k; 1861 stmf_iocdata_t stmfIoctl; 1862 /* framework lu list */ 1863 slist_lu_t *fLuList; 1864 /* persistent store lu list */ 1865 stmfGuidList *sLuList = NULL; 1866 int finalListSize = 0; 1867 int newAllocSize; 1868 uint32_t fLuListSize; 1869 uint32_t endList; 1870 1871 if (luList == NULL) { 1872 return (STMF_ERROR_INVALID_ARG); 1873 } 1874 1875 /* call init */ 1876 ret = initializeConfig(); 1877 if (ret != STMF_STATUS_SUCCESS) { 1878 return (ret); 1879 } 1880 1881 /* 1882 * Open control node for stmf 1883 */ 1884 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 1885 return (ret); 1886 1887 /* 1888 * Allocate ioctl input buffer 1889 */ 1890 fLuListSize = MAX_LU; 1891 fLuListSize = fLuListSize * (sizeof (slist_lu_t)); 1892 fLuList = (slist_lu_t *)calloc(1, fLuListSize); 1893 if (fLuList == NULL) { 1894 return (STMF_ERROR_NOMEM); 1895 } 1896 1897 bzero(&stmfIoctl, sizeof (stmfIoctl)); 1898 /* 1899 * Issue ioctl to get the LU list 1900 */ 1901 stmfIoctl.stmf_version = STMF_VERSION_1; 1902 stmfIoctl.stmf_obuf_size = fLuListSize; 1903 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList; 1904 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 1905 if (ioctlRet != 0) { 1906 switch (errno) { 1907 case EBUSY: 1908 ret = STMF_ERROR_BUSY; 1909 break; 1910 case EACCES: 1911 ret = STMF_ERROR_PERM; 1912 break; 1913 default: 1914 syslog(LOG_DEBUG, 1915 "stmfGetLogicalUnitList:ioctl errno(%d)", 1916 errno); 1917 ret = STMF_STATUS_ERROR; 1918 break; 1919 } 1920 goto done; 1921 } 1922 /* 1923 * Check whether input buffer was large enough 1924 */ 1925 if (stmfIoctl.stmf_obuf_max_nentries > MAX_LU) { 1926 fLuListSize = stmfIoctl.stmf_obuf_max_nentries * 1927 sizeof (slist_lu_t); 1928 fLuList = realloc(fLuList, fLuListSize); 1929 if (fLuList == NULL) { 1930 return (STMF_ERROR_NOMEM); 1931 } 1932 stmfIoctl.stmf_obuf_size = fLuListSize; 1933 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList; 1934 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 1935 if (ioctlRet != 0) { 1936 switch (errno) { 1937 case EBUSY: 1938 ret = STMF_ERROR_BUSY; 1939 break; 1940 case EACCES: 1941 ret = STMF_ERROR_PERM; 1942 break; 1943 default: 1944 syslog(LOG_DEBUG, 1945 "stmfGetLogicalUnitList:" 1946 "ioctl errno(%d)", errno); 1947 ret = STMF_STATUS_ERROR; 1948 break; 1949 } 1950 goto done; 1951 } 1952 } 1953 1954 ret = psGetLogicalUnitList(&sLuList); 1955 switch (ret) { 1956 case STMF_PS_SUCCESS: 1957 ret = STMF_STATUS_SUCCESS; 1958 break; 1959 case STMF_PS_ERROR_BUSY: 1960 ret = STMF_ERROR_BUSY; 1961 break; 1962 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 1963 ret = STMF_ERROR_SERVICE_NOT_FOUND; 1964 break; 1965 case STMF_PS_ERROR_VERSION_MISMATCH: 1966 ret = STMF_ERROR_SERVICE_DATA_VERSION; 1967 break; 1968 default: 1969 syslog(LOG_DEBUG, 1970 "stmfGetLogicalUnitList:psGetLogicalUnitList" 1971 ":error(%d)", ret); 1972 ret = STMF_STATUS_ERROR; 1973 break; 1974 } 1975 if (ret != STMF_STATUS_SUCCESS) { 1976 goto done; 1977 } 1978 1979 /* 1980 * 2 lists must be merged 1981 * reallocate the store list to add the list from the 1982 * framework 1983 */ 1984 newAllocSize = sLuList->cnt * sizeof (stmfGuid) + sizeof (stmfGuidList) 1985 + stmfIoctl.stmf_obuf_nentries * sizeof (stmfGuid); 1986 1987 sLuList = realloc(sLuList, newAllocSize); 1988 if (sLuList == NULL) { 1989 ret = STMF_ERROR_NOMEM; 1990 goto done; 1991 } 1992 1993 /* 1994 * add list from ioctl. Start from end of list retrieved from store. 1995 */ 1996 endList = sLuList->cnt + stmfIoctl.stmf_obuf_nentries; 1997 for (k = 0, i = sLuList->cnt; i < endList; i++, k++) { 1998 bcopy(&fLuList[k].lu_guid, sLuList->guid[i].guid, 1999 sizeof (stmfGuid)); 2000 } 2001 sLuList->cnt = endList; 2002 2003 /* 2004 * sort the list for merging 2005 */ 2006 qsort((void *)&(sLuList->guid[0]), sLuList->cnt, 2007 sizeof (stmfGuid), guidCompare); 2008 2009 /* 2010 * get final list count 2011 */ 2012 for (i = 0; i < sLuList->cnt; i++) { 2013 if ((i + 1) <= sLuList->cnt) { 2014 if (bcmp(sLuList->guid[i].guid, sLuList->guid[i+1].guid, 2015 sizeof (stmfGuid)) == 0) { 2016 continue; 2017 } 2018 } 2019 finalListSize++; 2020 } 2021 2022 /* 2023 * allocate caller's buffer with the final size 2024 */ 2025 *luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) + 2026 finalListSize * sizeof (stmfGuid)); 2027 if (*luList == NULL) { 2028 ret = STMF_ERROR_NOMEM; 2029 goto done; 2030 } 2031 2032 /* 2033 * copy guids to caller's buffer 2034 */ 2035 for (k = 0, i = 0; i < sLuList->cnt; i++) { 2036 if ((i + 1) <= sLuList->cnt) { 2037 if (bcmp(sLuList->guid[i].guid, sLuList->guid[i+1].guid, 2038 sizeof (stmfGuid)) == 0) { 2039 continue; 2040 } 2041 } 2042 bcopy(&(sLuList->guid[i].guid), (*luList)->guid[k++].guid, 2043 sizeof (stmfGuid)); 2044 } 2045 2046 (*luList)->cnt = finalListSize; 2047 2048 done: 2049 (void) close(fd); 2050 /* 2051 * free internal buffers 2052 */ 2053 free(fLuList); 2054 free(sLuList); 2055 return (ret); 2056 } 2057 2058 /* 2059 * stmfGetLogicalUnitProperties 2060 * 2061 * Purpose: Retrieves the properties for a logical unit 2062 * 2063 * lu - guid of the logical unit for which to retrieve properties 2064 * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success, 2065 * it contains the logical unit properties for the specified guid. 2066 */ 2067 int 2068 stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps) 2069 { 2070 int ret = STMF_STATUS_SUCCESS; 2071 int stmfRet; 2072 int fd; 2073 int ioctlRet; 2074 int cmd = STMF_IOCTL_GET_LU_PROPERTIES; 2075 stmfViewEntryList *viewEntryList = NULL; 2076 stmf_iocdata_t stmfIoctl; 2077 sioc_lu_props_t fLuProps; 2078 2079 if (luProps == NULL || luProps == NULL) { 2080 ret = STMF_ERROR_INVALID_ARG; 2081 } 2082 2083 bzero(luProps, sizeof (stmfLogicalUnitProperties)); 2084 2085 /* call init */ 2086 ret = initializeConfig(); 2087 if (ret != STMF_STATUS_SUCCESS) { 2088 return (ret); 2089 } 2090 2091 /* 2092 * Open control node for stmf 2093 */ 2094 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 2095 return (ret); 2096 2097 bzero(&stmfIoctl, sizeof (stmfIoctl)); 2098 /* 2099 * Issue ioctl to add to the host group 2100 */ 2101 stmfIoctl.stmf_version = STMF_VERSION_1; 2102 stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid); 2103 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu; 2104 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps; 2105 stmfIoctl.stmf_obuf_size = sizeof (fLuProps); 2106 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 2107 if (ioctlRet != 0) { 2108 switch (errno) { 2109 case EBUSY: 2110 ret = STMF_ERROR_BUSY; 2111 break; 2112 case EACCES: 2113 ret = STMF_ERROR_PERM; 2114 break; 2115 case ENOENT: 2116 stmfRet = stmfGetViewEntryList(lu, 2117 &viewEntryList); 2118 if (stmfRet == STMF_STATUS_SUCCESS) { 2119 luProps->status = 2120 STMF_LOGICAL_UNIT_UNREGISTERED; 2121 if (viewEntryList->cnt > 0) { 2122 ret = STMF_STATUS_SUCCESS; 2123 } else { 2124 ret = STMF_ERROR_NOT_FOUND; 2125 } 2126 } else { 2127 ret = STMF_ERROR_NOT_FOUND; 2128 } 2129 stmfFreeMemory(viewEntryList); 2130 break; 2131 default: 2132 syslog(LOG_DEBUG, 2133 "stmfGetLogicalUnit:ioctl errno(%d)", 2134 errno); 2135 ret = STMF_STATUS_ERROR; 2136 break; 2137 } 2138 goto done; 2139 } 2140 2141 bcopy(fLuProps.lu_provider_name, luProps->providerName, 2142 sizeof (fLuProps.lu_provider_name)); 2143 if (fLuProps.lu_state == STMF_STATE_ONLINE) { 2144 luProps->status = STMF_LOGICAL_UNIT_ONLINE; 2145 } else if (fLuProps.lu_state == STMF_STATE_OFFLINE) { 2146 luProps->status = STMF_LOGICAL_UNIT_OFFLINE; 2147 } else if (fLuProps.lu_state == STMF_STATE_ONLINING) { 2148 luProps->status = STMF_LOGICAL_UNIT_ONLINING; 2149 } else if (fLuProps.lu_state == STMF_STATE_OFFLINING) { 2150 luProps->status = STMF_LOGICAL_UNIT_OFFLINING; 2151 } 2152 bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias)); 2153 done: 2154 (void) close(fd); 2155 return (ret); 2156 } 2157 2158 /* 2159 * stmfGetState 2160 * 2161 * Purpose: retrieve the current state of the stmf module 2162 * 2163 * state - pointer to stmfState structure allocated by the caller 2164 * On success, contains the state of stmf 2165 */ 2166 int 2167 stmfGetState(stmfState *state) 2168 { 2169 int ret; 2170 stmf_state_desc_t iState; 2171 2172 if (state == NULL) { 2173 return (STMF_ERROR_INVALID_ARG); 2174 } 2175 2176 ret = getStmfState(&iState); 2177 if (ret != STMF_STATUS_SUCCESS) { 2178 return (ret); 2179 } 2180 switch (iState.state) { 2181 case STMF_STATE_ONLINE: 2182 state->operationalState = 2183 STMF_SERVICE_STATE_ONLINE; 2184 break; 2185 case STMF_STATE_OFFLINE: 2186 state->operationalState = 2187 STMF_SERVICE_STATE_OFFLINE; 2188 break; 2189 case STMF_STATE_ONLINING: 2190 state->operationalState = 2191 STMF_SERVICE_STATE_ONLINING; 2192 break; 2193 case STMF_STATE_OFFLINING: 2194 state->operationalState = 2195 STMF_SERVICE_STATE_OFFLINING; 2196 break; 2197 default: 2198 state->operationalState = 2199 STMF_SERVICE_STATE_UNKNOWN; 2200 break; 2201 } 2202 switch (iState.config_state) { 2203 case STMF_CONFIG_NONE: 2204 state->configState = STMF_CONFIG_STATE_NONE; 2205 break; 2206 case STMF_CONFIG_INIT: 2207 state->configState = STMF_CONFIG_STATE_INIT; 2208 break; 2209 case STMF_CONFIG_INIT_DONE: 2210 state->configState = 2211 STMF_CONFIG_STATE_INIT_DONE; 2212 break; 2213 default: 2214 state->configState = 2215 STMF_CONFIG_STATE_UNKNOWN; 2216 break; 2217 } 2218 return (STMF_STATUS_SUCCESS); 2219 } 2220 2221 /* 2222 * stmfGetViewEntryList 2223 * 2224 * Purpose: Retrieves the list of view entries for the specified 2225 * logical unit. 2226 * 2227 * lu - the guid of the logical unit for which to retrieve the view entry list 2228 * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On 2229 * success, contains the list of view entries. 2230 */ 2231 int 2232 stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList) 2233 { 2234 int ret; 2235 2236 if (lu == NULL || viewEntryList == NULL) { 2237 return (STMF_ERROR_INVALID_ARG); 2238 } 2239 2240 ret = psGetViewEntryList(lu, viewEntryList); 2241 switch (ret) { 2242 case STMF_PS_SUCCESS: 2243 ret = STMF_STATUS_SUCCESS; 2244 break; 2245 case STMF_PS_ERROR_NOT_FOUND: 2246 ret = STMF_ERROR_NOT_FOUND; 2247 break; 2248 case STMF_PS_ERROR_BUSY: 2249 ret = STMF_ERROR_BUSY; 2250 break; 2251 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2252 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2253 break; 2254 case STMF_PS_ERROR_VERSION_MISMATCH: 2255 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2256 break; 2257 default: 2258 syslog(LOG_DEBUG, 2259 "stmfGetViewEntryList:error(%d)", ret); 2260 ret = STMF_STATUS_ERROR; 2261 break; 2262 } 2263 2264 return (ret); 2265 } 2266 2267 /* 2268 * loadHostGroups 2269 * 2270 * Purpose - issues the ioctl to load the host groups into stmf 2271 * 2272 * fd - file descriptor for the control node of stmf. 2273 * groupList - populated host group list 2274 */ 2275 static int 2276 loadHostGroups(int fd, stmfGroupList *groupList) 2277 { 2278 int i, j; 2279 int ret = STMF_STATUS_SUCCESS; 2280 stmfGroupProperties *groupProps = NULL; 2281 2282 for (i = 0; i < groupList->cnt; i++) { 2283 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP, 2284 &(groupList->name[i]))) != STMF_STATUS_SUCCESS) { 2285 goto out; 2286 } 2287 ret = stmfGetHostGroupMembers(&(groupList->name[i]), 2288 &groupProps); 2289 for (j = 0; j < groupProps->cnt; j++) { 2290 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, 2291 &(groupList->name[i]), &(groupProps->name[j]))) 2292 != STMF_STATUS_SUCCESS) { 2293 goto out; 2294 } 2295 } 2296 } 2297 2298 2299 out: 2300 stmfFreeMemory(groupProps); 2301 return (ret); 2302 } 2303 2304 /* 2305 * loadTargetGroups 2306 * 2307 * Purpose - issues the ioctl to load the target groups into stmf 2308 * 2309 * fd - file descriptor for the control node of stmf. 2310 * groupList - populated target group list. 2311 */ 2312 static int 2313 loadTargetGroups(int fd, stmfGroupList *groupList) 2314 { 2315 int i, j; 2316 int ret = STMF_STATUS_SUCCESS; 2317 stmfGroupProperties *groupProps = NULL; 2318 2319 for (i = 0; i < groupList->cnt; i++) { 2320 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP, 2321 &(groupList->name[i]))) != STMF_STATUS_SUCCESS) { 2322 goto out; 2323 } 2324 ret = stmfGetTargetGroupMembers(&(groupList->name[i]), 2325 &groupProps); 2326 for (j = 0; j < groupProps->cnt; j++) { 2327 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY, 2328 &(groupList->name[i]), &(groupProps->name[j]))) 2329 != STMF_STATUS_SUCCESS) { 2330 goto out; 2331 } 2332 } 2333 } 2334 2335 2336 out: 2337 stmfFreeMemory(groupProps); 2338 return (ret); 2339 } 2340 2341 2342 /* 2343 * loadStore 2344 * 2345 * Purpose: Load the configuration data from the store 2346 * 2347 * First load the host groups and target groups, then the view entries 2348 * and finally the provider data 2349 * 2350 * fd - file descriptor of control node for stmf. 2351 */ 2352 static int 2353 loadStore(int fd) 2354 { 2355 int ret; 2356 int i, j; 2357 stmfGroupList *groupList = NULL; 2358 stmfGuidList *guidList = NULL; 2359 stmfViewEntryList *viewEntryList = NULL; 2360 stmfProviderList *providerList = NULL; 2361 int providerType; 2362 nvlist_t *nvl = NULL; 2363 2364 2365 2366 /* load host groups */ 2367 ret = stmfGetHostGroupList(&groupList); 2368 if (ret != STMF_STATUS_SUCCESS) { 2369 return (ret); 2370 } 2371 ret = loadHostGroups(fd, groupList); 2372 if (ret != STMF_STATUS_SUCCESS) { 2373 goto out; 2374 } 2375 2376 stmfFreeMemory(groupList); 2377 groupList = NULL; 2378 2379 /* load target groups */ 2380 ret = stmfGetTargetGroupList(&groupList); 2381 if (ret != STMF_STATUS_SUCCESS) { 2382 goto out; 2383 } 2384 ret = loadTargetGroups(fd, groupList); 2385 if (ret != STMF_STATUS_SUCCESS) { 2386 goto out; 2387 } 2388 2389 stmfFreeMemory(groupList); 2390 groupList = NULL; 2391 2392 /* Get the guid list */ 2393 ret = psGetLogicalUnitList(&guidList); 2394 switch (ret) { 2395 case STMF_PS_SUCCESS: 2396 ret = STMF_STATUS_SUCCESS; 2397 break; 2398 case STMF_PS_ERROR_NOT_FOUND: 2399 ret = STMF_ERROR_NOT_FOUND; 2400 break; 2401 case STMF_PS_ERROR_BUSY: 2402 ret = STMF_ERROR_BUSY; 2403 break; 2404 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2405 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2406 break; 2407 case STMF_PS_ERROR_VERSION_MISMATCH: 2408 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2409 break; 2410 default: 2411 ret = STMF_STATUS_ERROR; 2412 break; 2413 } 2414 2415 if (ret != STMF_STATUS_SUCCESS) { 2416 goto out; 2417 } 2418 2419 /* 2420 * We have the guid list, now get the corresponding 2421 * view entries for each guid 2422 */ 2423 for (i = 0; i < guidList->cnt; i++) { 2424 ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList); 2425 switch (ret) { 2426 case STMF_PS_SUCCESS: 2427 ret = STMF_STATUS_SUCCESS; 2428 break; 2429 case STMF_PS_ERROR_NOT_FOUND: 2430 ret = STMF_ERROR_NOT_FOUND; 2431 break; 2432 case STMF_PS_ERROR_BUSY: 2433 ret = STMF_ERROR_BUSY; 2434 break; 2435 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2436 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2437 break; 2438 case STMF_PS_ERROR_VERSION_MISMATCH: 2439 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2440 break; 2441 default: 2442 ret = STMF_STATUS_ERROR; 2443 break; 2444 } 2445 if (ret != STMF_STATUS_SUCCESS) { 2446 goto out; 2447 } 2448 for (j = 0; j < viewEntryList->cnt; j++) { 2449 ret = addViewEntryIoctl(fd, &guidList->guid[i], 2450 &viewEntryList->ve[j]); 2451 if (ret != STMF_STATUS_SUCCESS) { 2452 goto out; 2453 } 2454 } 2455 } 2456 2457 /* get the list of providers that have data */ 2458 ret = psGetProviderDataList(&providerList); 2459 switch (ret) { 2460 case STMF_PS_SUCCESS: 2461 ret = STMF_STATUS_SUCCESS; 2462 break; 2463 case STMF_PS_ERROR_NOT_FOUND: 2464 ret = STMF_ERROR_NOT_FOUND; 2465 break; 2466 case STMF_PS_ERROR_BUSY: 2467 ret = STMF_ERROR_BUSY; 2468 break; 2469 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2470 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2471 break; 2472 case STMF_PS_ERROR_VERSION_MISMATCH: 2473 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2474 break; 2475 default: 2476 ret = STMF_STATUS_ERROR; 2477 break; 2478 } 2479 if (ret != STMF_STATUS_SUCCESS) { 2480 goto out; 2481 } 2482 2483 for (i = 0; i < providerList->cnt; i++) { 2484 providerType = providerList->provider[i].providerType; 2485 ret = psGetProviderData(providerList->provider[i].name, 2486 &nvl, providerType, NULL); 2487 switch (ret) { 2488 case STMF_PS_SUCCESS: 2489 ret = STMF_STATUS_SUCCESS; 2490 break; 2491 case STMF_PS_ERROR_NOT_FOUND: 2492 ret = STMF_ERROR_NOT_FOUND; 2493 break; 2494 case STMF_PS_ERROR_BUSY: 2495 ret = STMF_ERROR_BUSY; 2496 break; 2497 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2498 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2499 break; 2500 case STMF_PS_ERROR_VERSION_MISMATCH: 2501 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2502 break; 2503 default: 2504 ret = STMF_STATUS_ERROR; 2505 break; 2506 } 2507 if (ret != STMF_STATUS_SUCCESS) { 2508 goto out; 2509 } 2510 2511 /* call setProviderData */ 2512 ret = setProviderData(fd, providerList->provider[i].name, nvl, 2513 providerType); 2514 switch (ret) { 2515 case STMF_PS_SUCCESS: 2516 ret = STMF_STATUS_SUCCESS; 2517 break; 2518 case STMF_PS_ERROR_NOT_FOUND: 2519 ret = STMF_ERROR_NOT_FOUND; 2520 break; 2521 case STMF_PS_ERROR_BUSY: 2522 ret = STMF_ERROR_BUSY; 2523 break; 2524 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2525 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2526 break; 2527 case STMF_PS_ERROR_VERSION_MISMATCH: 2528 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2529 break; 2530 default: 2531 ret = STMF_STATUS_ERROR; 2532 break; 2533 } 2534 if (ret != STMF_STATUS_SUCCESS) { 2535 goto out; 2536 } 2537 2538 nvlist_free(nvl); 2539 nvl = NULL; 2540 } 2541 out: 2542 if (groupList != NULL) { 2543 free(groupList); 2544 } 2545 if (guidList != NULL) { 2546 free(guidList); 2547 } 2548 if (viewEntryList != NULL) { 2549 free(viewEntryList); 2550 } 2551 if (nvl != NULL) { 2552 nvlist_free(nvl); 2553 } 2554 return (ret); 2555 } 2556 2557 /* 2558 * stmfLoadConfig 2559 * 2560 * Purpose - load the configuration data from smf into stmf 2561 * 2562 */ 2563 int 2564 stmfLoadConfig(void) 2565 { 2566 int ret; 2567 int fd; 2568 stmf_state_desc_t stmfStateSet; 2569 stmfState state; 2570 2571 2572 /* Check to ensure service exists */ 2573 if (psCheckService() != STMF_STATUS_SUCCESS) { 2574 return (STMF_ERROR_SERVICE_NOT_FOUND); 2575 } 2576 2577 ret = stmfGetState(&state); 2578 if (ret == STMF_STATUS_SUCCESS) { 2579 if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) { 2580 return (STMF_ERROR_SERVICE_ONLINE); 2581 } 2582 } else { 2583 return (STMF_STATUS_ERROR); 2584 } 2585 2586 2587 stmfStateSet.state = STMF_STATE_OFFLINE; 2588 stmfStateSet.config_state = STMF_CONFIG_INIT; 2589 2590 /* 2591 * Open control node for stmf 2592 */ 2593 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2594 return (ret); 2595 2596 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE); 2597 if (ret != STMF_STATUS_SUCCESS) { 2598 goto done; 2599 } 2600 2601 /* Load the persistent configuration data */ 2602 ret = loadStore(fd); 2603 if (ret != 0) { 2604 goto done; 2605 } 2606 2607 stmfStateSet.state = STMF_STATE_OFFLINE; 2608 stmfStateSet.config_state = STMF_CONFIG_INIT_DONE; 2609 2610 done: 2611 if (ret == STMF_STATUS_SUCCESS) { 2612 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE); 2613 } 2614 (void) close(fd); 2615 return (ret); 2616 } 2617 2618 /* 2619 * getStmfState 2620 * 2621 * stmfState - pointer to stmf_state_desc_t structure. Will contain the state 2622 * information of the stmf service on success. 2623 */ 2624 static int 2625 getStmfState(stmf_state_desc_t *stmfState) 2626 { 2627 int ret = STMF_STATUS_SUCCESS; 2628 int fd; 2629 int ioctlRet; 2630 stmf_iocdata_t stmfIoctl; 2631 2632 /* 2633 * Open control node for stmf 2634 */ 2635 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 2636 return (ret); 2637 2638 bzero(&stmfIoctl, sizeof (stmfIoctl)); 2639 /* 2640 * Issue ioctl to get the stmf state 2641 */ 2642 stmfIoctl.stmf_version = STMF_VERSION_1; 2643 stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t); 2644 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState; 2645 stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t); 2646 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState; 2647 ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl); 2648 2649 (void) close(fd); 2650 2651 if (ioctlRet != 0) { 2652 switch (errno) { 2653 case EBUSY: 2654 ret = STMF_ERROR_BUSY; 2655 break; 2656 case EPERM: 2657 case EACCES: 2658 ret = STMF_ERROR_PERM; 2659 break; 2660 default: 2661 syslog(LOG_DEBUG, 2662 "getStmfState:ioctl errno(%d)", errno); 2663 ret = STMF_STATUS_ERROR; 2664 break; 2665 } 2666 } 2667 return (ret); 2668 } 2669 2670 2671 /* 2672 * setStmfState 2673 * 2674 * stmfState - pointer to caller set state structure 2675 * objectType - one of: 2676 * LOGICAL_UNIT_TYPE 2677 * TARGET_TYPE 2678 * STMF_SERVICE_TYPE 2679 */ 2680 static int 2681 setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType) 2682 { 2683 int ret = STMF_STATUS_SUCCESS; 2684 int ioctlRet; 2685 int cmd; 2686 stmf_iocdata_t stmfIoctl; 2687 2688 switch (objectType) { 2689 case LOGICAL_UNIT_TYPE: 2690 cmd = STMF_IOCTL_SET_LU_STATE; 2691 break; 2692 case TARGET_TYPE: 2693 cmd = STMF_IOCTL_SET_TARGET_PORT_STATE; 2694 break; 2695 case STMF_SERVICE_TYPE: 2696 cmd = STMF_IOCTL_SET_STMF_STATE; 2697 break; 2698 default: 2699 ret = STMF_STATUS_ERROR; 2700 goto done; 2701 } 2702 2703 bzero(&stmfIoctl, sizeof (stmfIoctl)); 2704 /* 2705 * Issue ioctl to set the stmf state 2706 */ 2707 stmfIoctl.stmf_version = STMF_VERSION_1; 2708 stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t); 2709 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState; 2710 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 2711 if (ioctlRet != 0) { 2712 switch (errno) { 2713 case EBUSY: 2714 ret = STMF_ERROR_BUSY; 2715 break; 2716 case EACCES: 2717 ret = STMF_ERROR_PERM; 2718 break; 2719 case ENOENT: 2720 ret = STMF_ERROR_NOT_FOUND; 2721 break; 2722 default: 2723 syslog(LOG_DEBUG, 2724 "setStmfState:ioctl errno(%d)", errno); 2725 ret = STMF_STATUS_ERROR; 2726 break; 2727 } 2728 } 2729 done: 2730 return (ret); 2731 } 2732 2733 /* 2734 * stmfOnline 2735 * 2736 * Purpose: Online stmf service 2737 * 2738 */ 2739 int 2740 stmfOnline(void) 2741 { 2742 int ret; 2743 int fd; 2744 stmfState state; 2745 stmf_state_desc_t iState; 2746 2747 ret = stmfGetState(&state); 2748 if (ret == STMF_STATUS_SUCCESS) { 2749 if (state.operationalState == STMF_SERVICE_STATE_ONLINE) { 2750 return (STMF_ERROR_SERVICE_ONLINE); 2751 } 2752 } else { 2753 return (STMF_STATUS_ERROR); 2754 } 2755 iState.state = STMF_STATE_ONLINE; 2756 iState.config_state = STMF_CONFIG_NONE; 2757 /* 2758 * Open control node for stmf 2759 * to make call to setStmfState() 2760 */ 2761 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2762 return (ret); 2763 ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE); 2764 (void) close(fd); 2765 return (ret); 2766 } 2767 2768 /* 2769 * stmfOffline 2770 * 2771 * Purpose: Offline stmf service 2772 * 2773 */ 2774 int 2775 stmfOffline(void) 2776 { 2777 int ret; 2778 int fd; 2779 stmfState state; 2780 stmf_state_desc_t iState; 2781 2782 ret = stmfGetState(&state); 2783 if (ret == STMF_STATUS_SUCCESS) { 2784 if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) { 2785 return (STMF_ERROR_SERVICE_OFFLINE); 2786 } 2787 } else { 2788 return (STMF_STATUS_ERROR); 2789 } 2790 iState.state = STMF_STATE_OFFLINE; 2791 iState.config_state = STMF_CONFIG_NONE; 2792 2793 /* 2794 * Open control node for stmf 2795 * to make call to setStmfState() 2796 */ 2797 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2798 return (ret); 2799 ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE); 2800 (void) close(fd); 2801 return (ret); 2802 } 2803 2804 2805 /* 2806 * stmfOfflineTarget 2807 * 2808 * Purpose: Change state of target to offline 2809 * 2810 * devid - devid of the target to offline 2811 */ 2812 int 2813 stmfOfflineTarget(stmfDevid *devid) 2814 { 2815 stmf_state_desc_t targetState; 2816 int ret = STMF_STATUS_SUCCESS; 2817 int fd; 2818 2819 if (devid == NULL) { 2820 return (STMF_ERROR_INVALID_ARG); 2821 } 2822 bzero(&targetState, sizeof (targetState)); 2823 2824 targetState.state = STMF_STATE_OFFLINE; 2825 targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength; 2826 bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1], 2827 devid->identLength); 2828 /* 2829 * Open control node for stmf 2830 * to make call to setStmfState() 2831 */ 2832 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2833 return (ret); 2834 ret = setStmfState(fd, &targetState, TARGET_TYPE); 2835 (void) close(fd); 2836 return (ret); 2837 } 2838 2839 /* 2840 * stmfOfflineLogicalUnit 2841 * 2842 * Purpose: Change state of logical unit to offline 2843 * 2844 * lu - guid of the logical unit to offline 2845 */ 2846 int 2847 stmfOfflineLogicalUnit(stmfGuid *lu) 2848 { 2849 stmf_state_desc_t luState; 2850 int ret = STMF_STATUS_SUCCESS; 2851 int fd; 2852 2853 if (lu == NULL) { 2854 return (STMF_ERROR_INVALID_ARG); 2855 } 2856 2857 bzero(&luState, sizeof (luState)); 2858 2859 luState.state = STMF_STATE_OFFLINE; 2860 bcopy(lu, &luState.ident, sizeof (stmfGuid)); 2861 /* 2862 * Open control node for stmf 2863 * to make call to setStmfState() 2864 */ 2865 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2866 return (ret); 2867 ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE); 2868 (void) close(fd); 2869 return (ret); 2870 } 2871 2872 /* 2873 * stmfOnlineTarget 2874 * 2875 * Purpose: Change state of target to online 2876 * 2877 * devid - devid of the target to online 2878 */ 2879 int 2880 stmfOnlineTarget(stmfDevid *devid) 2881 { 2882 stmf_state_desc_t targetState; 2883 int ret = STMF_STATUS_SUCCESS; 2884 int fd; 2885 2886 if (devid == NULL) { 2887 return (STMF_ERROR_INVALID_ARG); 2888 } 2889 bzero(&targetState, sizeof (targetState)); 2890 2891 targetState.state = STMF_STATE_ONLINE; 2892 targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength; 2893 bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1], 2894 devid->identLength); 2895 /* 2896 * Open control node for stmf 2897 * to make call to setStmfState() 2898 */ 2899 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2900 return (ret); 2901 ret = setStmfState(fd, &targetState, TARGET_TYPE); 2902 (void) close(fd); 2903 return (ret); 2904 } 2905 2906 /* 2907 * stmfOnlineLogicalUnit 2908 * 2909 * Purpose: Change state of logical unit to online 2910 * 2911 * lu - guid of the logical unit to online 2912 */ 2913 int 2914 stmfOnlineLogicalUnit(stmfGuid *lu) 2915 { 2916 stmf_state_desc_t luState; 2917 int ret = STMF_STATUS_SUCCESS; 2918 int fd; 2919 2920 if (lu == NULL) { 2921 return (STMF_ERROR_INVALID_ARG); 2922 } 2923 2924 bzero(&luState, sizeof (luState)); 2925 2926 luState.state = STMF_STATE_ONLINE; 2927 bcopy(lu, &luState.ident, sizeof (stmfGuid)); 2928 /* 2929 * Open control node for stmf 2930 * to make call to setStmfState() 2931 */ 2932 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 2933 return (ret); 2934 ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE); 2935 (void) close(fd); 2936 return (ret); 2937 } 2938 2939 /* 2940 * stmfRemoveFromHostGroup 2941 * 2942 * Purpose: Removes an initiator from an initiator group 2943 * 2944 * hostGroupName - name of an initiator group 2945 * hostName - name of host group member to remove 2946 */ 2947 int 2948 stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName) 2949 { 2950 int ret; 2951 int fd; 2952 2953 if (hostGroupName == NULL || 2954 (strnlen((char *)hostGroupName, sizeof (stmfGroupName)) 2955 == sizeof (stmfGroupName)) || hostName == NULL) { 2956 return (STMF_ERROR_INVALID_ARG); 2957 } 2958 2959 /* call init */ 2960 ret = initializeConfig(); 2961 if (ret != STMF_STATUS_SUCCESS) { 2962 return (ret); 2963 } 2964 2965 /* 2966 * Open control node for stmf 2967 */ 2968 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 2969 return (ret); 2970 2971 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY, 2972 hostGroupName, hostName)) != STMF_STATUS_SUCCESS) { 2973 goto done; 2974 } 2975 2976 ret = psRemoveHostGroupMember((char *)hostGroupName, 2977 (char *)hostName->ident); 2978 switch (ret) { 2979 case STMF_PS_SUCCESS: 2980 ret = STMF_STATUS_SUCCESS; 2981 break; 2982 case STMF_PS_ERROR_MEMBER_NOT_FOUND: 2983 ret = STMF_ERROR_MEMBER_NOT_FOUND; 2984 break; 2985 case STMF_PS_ERROR_GROUP_NOT_FOUND: 2986 ret = STMF_ERROR_GROUP_NOT_FOUND; 2987 break; 2988 case STMF_PS_ERROR_BUSY: 2989 ret = STMF_ERROR_BUSY; 2990 break; 2991 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2992 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2993 break; 2994 case STMF_PS_ERROR_VERSION_MISMATCH: 2995 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2996 break; 2997 default: 2998 syslog(LOG_DEBUG, 2999 "stmfRemoveFromHostGroup" 3000 "psRemoveHostGroupMember:error(%d)", ret); 3001 ret = STMF_STATUS_ERROR; 3002 break; 3003 } 3004 3005 done: 3006 (void) close(fd); 3007 return (ret); 3008 } 3009 3010 /* 3011 * stmfRemoveFromTargetGroup 3012 * 3013 * Purpose: Removes a local port from a local port group 3014 * 3015 * targetGroupName - name of a target group 3016 * targetName - name of target to remove 3017 */ 3018 int 3019 stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName) 3020 { 3021 int ret; 3022 int fd; 3023 3024 if (targetGroupName == NULL || 3025 (strnlen((char *)targetGroupName, sizeof (stmfGroupName)) 3026 == sizeof (stmfGroupName)) || targetName == NULL) { 3027 return (STMF_ERROR_INVALID_ARG); 3028 } 3029 3030 /* call init */ 3031 ret = initializeConfig(); 3032 if (ret != STMF_STATUS_SUCCESS) { 3033 return (ret); 3034 } 3035 3036 /* 3037 * Open control node for stmf 3038 */ 3039 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3040 return (ret); 3041 3042 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY, 3043 targetGroupName, targetName)) != STMF_STATUS_SUCCESS) { 3044 goto done; 3045 } 3046 3047 ret = psRemoveTargetGroupMember((char *)targetGroupName, 3048 (char *)targetName->ident); 3049 switch (ret) { 3050 case STMF_PS_SUCCESS: 3051 ret = STMF_STATUS_SUCCESS; 3052 break; 3053 case STMF_PS_ERROR_MEMBER_NOT_FOUND: 3054 ret = STMF_ERROR_MEMBER_NOT_FOUND; 3055 break; 3056 case STMF_PS_ERROR_GROUP_NOT_FOUND: 3057 ret = STMF_ERROR_GROUP_NOT_FOUND; 3058 break; 3059 case STMF_PS_ERROR_BUSY: 3060 ret = STMF_ERROR_BUSY; 3061 break; 3062 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3063 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3064 break; 3065 case STMF_PS_ERROR_VERSION_MISMATCH: 3066 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3067 break; 3068 default: 3069 syslog(LOG_DEBUG, 3070 "stmfRemoveFromTargetGroup" 3071 "psRemoveTargetGroupMember:error(%d)", ret); 3072 ret = STMF_STATUS_ERROR; 3073 break; 3074 } 3075 3076 done: 3077 (void) close(fd); 3078 return (ret); 3079 } 3080 3081 /* 3082 * stmfRemoveViewEntry 3083 * 3084 * Purpose: Removes a view entry from a logical unit 3085 * 3086 * lu - guid of lu for which view entry is being removed 3087 * viewEntryIndex - index of view entry to remove 3088 * 3089 */ 3090 int 3091 stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex) 3092 { 3093 int ret = STMF_STATUS_SUCCESS; 3094 int fd; 3095 int ioctlRet; 3096 stmf_iocdata_t stmfIoctl; 3097 stmf_view_op_entry_t ioctlViewEntry; 3098 3099 if (lu == NULL) { 3100 return (STMF_ERROR_INVALID_ARG); 3101 } 3102 3103 /* call init */ 3104 ret = initializeConfig(); 3105 if (ret != STMF_STATUS_SUCCESS) { 3106 return (ret); 3107 } 3108 3109 /* 3110 * Open control node for stmf 3111 */ 3112 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3113 return (ret); 3114 3115 bzero(&ioctlViewEntry, sizeof (ioctlViewEntry)); 3116 ioctlViewEntry.ve_ndx_valid = B_TRUE; 3117 ioctlViewEntry.ve_ndx = viewEntryIndex; 3118 bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid)); 3119 3120 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3121 /* 3122 * Issue ioctl to add to the view entry 3123 */ 3124 stmfIoctl.stmf_version = STMF_VERSION_1; 3125 stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry); 3126 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry; 3127 ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl); 3128 if (ioctlRet != 0) { 3129 switch (errno) { 3130 case EBUSY: 3131 ret = STMF_ERROR_BUSY; 3132 break; 3133 case EACCES: 3134 switch (stmfIoctl.stmf_error) { 3135 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 3136 ret = STMF_ERROR_CONFIG_NONE; 3137 break; 3138 default: 3139 ret = STMF_ERROR_PERM; 3140 break; 3141 } 3142 break; 3143 case ENODEV: 3144 case ENOENT: 3145 ret = STMF_ERROR_NOT_FOUND; 3146 break; 3147 default: 3148 syslog(LOG_DEBUG, 3149 "stmfRemoveViewEntry:ioctl errno(%d)", 3150 errno); 3151 ret = STMF_STATUS_ERROR; 3152 break; 3153 } 3154 goto done; 3155 } 3156 3157 ret = psRemoveViewEntry(lu, viewEntryIndex); 3158 switch (ret) { 3159 case STMF_PS_SUCCESS: 3160 ret = STMF_STATUS_SUCCESS; 3161 break; 3162 case STMF_PS_ERROR_NOT_FOUND: 3163 ret = STMF_ERROR_NOT_FOUND; 3164 break; 3165 case STMF_PS_ERROR_BUSY: 3166 ret = STMF_ERROR_BUSY; 3167 break; 3168 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3169 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3170 break; 3171 case STMF_PS_ERROR_VERSION_MISMATCH: 3172 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3173 break; 3174 default: 3175 syslog(LOG_DEBUG, 3176 "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)", 3177 ret); 3178 ret = STMF_STATUS_ERROR; 3179 break; 3180 } 3181 3182 done: 3183 (void) close(fd); 3184 return (ret); 3185 } 3186 3187 /* 3188 * stmfSetProviderData 3189 * 3190 * Purpose: set the provider data 3191 * 3192 * providerName - unique name of provider 3193 * nvl - nvlist to set 3194 * providerType - type of provider for which to set data 3195 * STMF_LU_PROVIDER_TYPE 3196 * STMF_PORT_PROVIDER_TYPE 3197 */ 3198 int 3199 stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType) 3200 { 3201 return (stmfSetProviderDataProt(providerName, nvl, providerType, 3202 NULL)); 3203 } 3204 3205 /* 3206 * stmfSetProviderDataProt 3207 * 3208 * Purpose: set the provider data 3209 * 3210 * providerName - unique name of provider 3211 * nvl - nvlist to set 3212 * providerType - type of provider for which to set data 3213 * STMF_LU_PROVIDER_TYPE 3214 * STMF_PORT_PROVIDER_TYPE 3215 * setToken - Stale data token returned in the stmfGetProviderDataProt() 3216 * call or NULL. 3217 */ 3218 int 3219 stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType, 3220 uint64_t *setToken) 3221 { 3222 int ret; 3223 int fd; 3224 3225 if (providerName == NULL || nvl == NULL) { 3226 return (STMF_ERROR_INVALID_ARG); 3227 } 3228 3229 if (providerType != STMF_LU_PROVIDER_TYPE && 3230 providerType != STMF_PORT_PROVIDER_TYPE) { 3231 return (STMF_ERROR_INVALID_ARG); 3232 } 3233 3234 /* call init */ 3235 ret = initializeConfig(); 3236 if (ret != STMF_STATUS_SUCCESS) { 3237 return (ret); 3238 } 3239 3240 /* 3241 * Open control node for stmf 3242 */ 3243 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3244 return (ret); 3245 3246 ret = setProviderData(fd, providerName, nvl, providerType); 3247 3248 (void) close(fd); 3249 3250 if (ret != STMF_STATUS_SUCCESS) { 3251 goto done; 3252 } 3253 3254 /* setting driver provider data successful. Now persist it */ 3255 ret = psSetProviderData(providerName, nvl, providerType, setToken); 3256 switch (ret) { 3257 case STMF_PS_SUCCESS: 3258 ret = STMF_STATUS_SUCCESS; 3259 break; 3260 case STMF_PS_ERROR_EXISTS: 3261 ret = STMF_ERROR_EXISTS; 3262 break; 3263 case STMF_PS_ERROR_BUSY: 3264 ret = STMF_ERROR_BUSY; 3265 break; 3266 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3267 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3268 break; 3269 case STMF_PS_ERROR_VERSION_MISMATCH: 3270 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3271 break; 3272 case STMF_PS_ERROR_PROV_DATA_STALE: 3273 ret = STMF_ERROR_PROV_DATA_STALE; 3274 break; 3275 default: 3276 syslog(LOG_DEBUG, 3277 "stmfSetProviderData" 3278 "psSetProviderData:error(%d)", ret); 3279 ret = STMF_STATUS_ERROR; 3280 break; 3281 } 3282 3283 done: 3284 return (ret); 3285 } 3286 3287 /* 3288 * setProviderData 3289 * 3290 * Purpose: set the provider data 3291 * 3292 * providerName - unique name of provider 3293 * nvl - nvlist to set 3294 * providerType - logical unit or port provider 3295 */ 3296 static int 3297 setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType) 3298 { 3299 int ret = STMF_STATUS_SUCCESS; 3300 int ioctlRet; 3301 size_t nvlistEncodedSize; 3302 stmf_ppioctl_data_t *ppi = NULL; 3303 char *allocatedNvBuffer; 3304 stmf_iocdata_t stmfIoctl; 3305 3306 if (providerName == NULL) { 3307 return (STMF_ERROR_INVALID_ARG); 3308 } 3309 3310 /* get size of encoded nvlist */ 3311 if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) { 3312 return (STMF_STATUS_ERROR); 3313 } 3314 3315 /* allocate memory for ioctl */ 3316 ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize + 3317 sizeof (stmf_ppioctl_data_t)); 3318 if (ppi == NULL) { 3319 return (STMF_ERROR_NOMEM); 3320 } 3321 3322 allocatedNvBuffer = (char *)&ppi->ppi_data; 3323 if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize, 3324 NV_ENCODE_XDR, 0) != 0) { 3325 return (STMF_STATUS_ERROR); 3326 } 3327 3328 /* set provider name and provider type */ 3329 (void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name)); 3330 switch (providerType) { 3331 case STMF_LU_PROVIDER_TYPE: 3332 ppi->ppi_lu_provider = 1; 3333 break; 3334 case STMF_PORT_PROVIDER_TYPE: 3335 ppi->ppi_port_provider = 1; 3336 break; 3337 default: 3338 return (STMF_ERROR_INVALID_ARG); 3339 } 3340 3341 /* set the size of the ioctl data to packed data size */ 3342 ppi->ppi_data_size = nvlistEncodedSize; 3343 3344 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3345 3346 stmfIoctl.stmf_version = STMF_VERSION_1; 3347 /* 3348 * Subtracting 8 from the size as that is the size of the last member 3349 * of the structure where the packed data resides 3350 */ 3351 stmfIoctl.stmf_ibuf_size = nvlistEncodedSize + 3352 sizeof (stmf_ppioctl_data_t) - 8; 3353 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi; 3354 ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl); 3355 if (ioctlRet != 0) { 3356 switch (errno) { 3357 case EBUSY: 3358 ret = STMF_ERROR_BUSY; 3359 break; 3360 case EACCES: 3361 ret = STMF_ERROR_PERM; 3362 break; 3363 default: 3364 syslog(LOG_DEBUG, 3365 "setProviderData:ioctl errno(%d)", errno); 3366 ret = STMF_STATUS_ERROR; 3367 break; 3368 } 3369 if (ret != STMF_STATUS_SUCCESS) 3370 goto done; 3371 } 3372 3373 done: 3374 free(ppi); 3375 return (ret); 3376 } 3377