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 2009 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 <math.h> 47 #include <libstmf_impl.h> 48 #include <sys/stmf_ioctl.h> 49 #include <sys/stmf_sbd_ioctl.h> 50 #include <sys/pppt_ioctl.h> 51 52 #define STMF_PATH "/devices/pseudo/stmf@0:admin" 53 #define SBD_PATH "/devices/pseudo/stmf_sbd@0:admin" 54 #define PPPT_PATH "/devices/pseudo/pppt@0:pppt" 55 56 #define EUI "eui." 57 #define WWN "wwn." 58 #define IQN "iqn." 59 #define LU_ASCII_GUID_SIZE 32 60 #define LU_GUID_SIZE 16 61 #define OUI_ASCII_SIZE 6 62 #define OUI_SIZE 3 63 #define IDENT_LENGTH_BYTE 3 64 65 /* various initial allocation values */ 66 #define ALLOC_LU 8192 67 #define ALLOC_TARGET_PORT 2048 68 #define ALLOC_PROVIDER 64 69 #define ALLOC_GROUP 2048 70 #define ALLOC_SESSION 2048 71 #define ALLOC_VE 256 72 #define ALLOC_PP_DATA_SIZE 128*1024 73 #define ALLOC_GRP_MEMBER 256 74 75 #define MAX_ISCSI_NAME 223 76 #define MAX_SERIAL_SIZE 252 + 1 77 #define MAX_LU_ALIAS_SIZE 256 78 #define MAX_SBD_PROPS MAXPATHLEN + MAX_SERIAL_SIZE + MAX_LU_ALIAS_SIZE 79 80 #define OPEN_STMF 0 81 #define OPEN_EXCL_STMF O_EXCL 82 83 #define OPEN_SBD 0 84 #define OPEN_EXCL_SBD O_EXCL 85 86 #define OPEN_PPPT 0 87 #define OPEN_EXCL_PPPT O_EXCL 88 89 #define LOGICAL_UNIT_TYPE 0 90 #define TARGET_TYPE 1 91 #define STMF_SERVICE_TYPE 2 92 93 #define HOST_GROUP 1 94 #define TARGET_GROUP 2 95 96 /* set default persistence here */ 97 #define STMF_DEFAULT_PERSIST STMF_PERSIST_SMF 98 99 #define MAX_PROVIDER_RETRY 30 100 101 static int openStmf(int, int *fd); 102 static int openSbd(int, int *fd); 103 static int openPppt(int, int *fd); 104 static int groupIoctl(int fd, int cmd, stmfGroupName *); 105 static int loadStore(int fd); 106 static int initializeConfig(); 107 static int groupMemberIoctl(int fd, int cmd, stmfGroupName *, stmfDevid *); 108 static int guidCompare(const void *, const void *); 109 static int addViewEntryIoctl(int fd, stmfGuid *, stmfViewEntry *); 110 static int loadHostGroups(int fd, stmfGroupList *); 111 static int loadTargetGroups(int fd, stmfGroupList *); 112 static int getStmfState(stmf_state_desc_t *); 113 static int setStmfState(int fd, stmf_state_desc_t *, int); 114 static int setProviderData(int fd, char *, nvlist_t *, int, uint64_t *); 115 static int createDiskResource(luResourceImpl *); 116 static int createDiskLu(diskResource *, stmfGuid *); 117 static int deleteDiskLu(stmfGuid *luGuid); 118 static int getDiskProp(luResourceImpl *, uint32_t, char *, size_t *); 119 static int getDiskAllProps(stmfGuid *luGuid, luResource *hdl); 120 static int loadDiskPropsFromDriver(luResourceImpl *, sbd_lu_props_t *); 121 static int removeGuidFromDiskStore(stmfGuid *); 122 static int addGuidToDiskStore(stmfGuid *, char *); 123 static int persistDiskGuid(stmfGuid *, char *, boolean_t); 124 static int setDiskProp(luResourceImpl *, uint32_t, const char *); 125 static int checkHexUpper(char *); 126 static int strToShift(const char *); 127 static int niceStrToNum(const char *, uint64_t *); 128 static void diskError(uint32_t, int *); 129 static int importDiskLu(char *fname, stmfGuid *); 130 static int modifyDiskLu(diskResource *, stmfGuid *, const char *); 131 static int modifyDiskLuProp(stmfGuid *, const char *, uint32_t, const char *); 132 static int validateModifyDiskProp(uint32_t); 133 static uint8_t iGetPersistMethod(); 134 static int groupListIoctl(stmfGroupList **, int); 135 static int iLoadGroupFromPs(stmfGroupList **, int); 136 static int groupMemberListIoctl(stmfGroupName *, stmfGroupProperties **, int); 137 static int getProviderData(char *, nvlist_t **, int, uint64_t *); 138 static int setDiskStandby(stmfGuid *luGuid); 139 static int viewEntryCompare(const void *, const void *); 140 static void deleteNonActiveLus(); 141 142 static pthread_mutex_t persistenceTypeLock = PTHREAD_MUTEX_INITIALIZER; 143 static int iPersistType = 0; 144 /* when B_TRUE, no need to access SMF anymore. Just use iPersistType */ 145 static boolean_t iLibSetPersist = B_FALSE; 146 147 /* 148 * Open for stmf module 149 * 150 * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF) 151 * fd - pointer to integer. On success, contains the stmf file descriptor 152 */ 153 static int 154 openStmf(int flag, int *fd) 155 { 156 int ret = STMF_STATUS_ERROR; 157 158 if ((*fd = open(STMF_PATH, O_NDELAY | O_RDONLY | flag)) != -1) { 159 ret = STMF_STATUS_SUCCESS; 160 } else { 161 if (errno == EBUSY) { 162 ret = STMF_ERROR_BUSY; 163 } else if (errno == EACCES) { 164 ret = STMF_ERROR_PERM; 165 } else { 166 ret = STMF_STATUS_ERROR; 167 } 168 syslog(LOG_DEBUG, "openStmf:open failure:%s:errno(%d)", 169 STMF_PATH, errno); 170 } 171 172 return (ret); 173 } 174 175 /* 176 * Open for sbd module 177 * 178 * flag - open flag (OPEN_SBD, OPEN_EXCL_SBD) 179 * fd - pointer to integer. On success, contains the stmf file descriptor 180 */ 181 static int 182 openSbd(int flag, int *fd) 183 { 184 int ret = STMF_STATUS_ERROR; 185 186 if ((*fd = open(SBD_PATH, O_NDELAY | O_RDONLY | flag)) != -1) { 187 ret = STMF_STATUS_SUCCESS; 188 } else { 189 if (errno == EBUSY) { 190 ret = STMF_ERROR_BUSY; 191 } else if (errno == EACCES) { 192 ret = STMF_ERROR_PERM; 193 } else { 194 ret = STMF_STATUS_ERROR; 195 } 196 syslog(LOG_DEBUG, "openSbd:open failure:%s:errno(%d)", 197 SBD_PATH, errno); 198 } 199 200 return (ret); 201 } 202 203 /* 204 * Open for pppt module 205 * 206 * flag - open flag (OPEN_PPPT, OPEN_EXCL_PPPT) 207 * fd - pointer to integer. On success, contains the stmf file descriptor 208 */ 209 static int 210 openPppt(int flag, int *fd) 211 { 212 int ret = STMF_STATUS_ERROR; 213 214 if ((*fd = open(PPPT_PATH, O_RDONLY | flag)) != -1) { 215 ret = STMF_STATUS_SUCCESS; 216 } else { 217 if (errno == EBUSY) { 218 ret = STMF_ERROR_BUSY; 219 } else if (errno == EACCES) { 220 ret = STMF_ERROR_PERM; 221 } else { 222 ret = STMF_STATUS_ERROR; 223 } 224 syslog(LOG_DEBUG, "openPppt:open failure:%s:errno(%d)", 225 PPPT_PATH, errno); 226 } 227 228 return (ret); 229 } 230 231 /* 232 * initializeConfig 233 * 234 * This routine should be called before any ioctl requiring initialization 235 * which is basically everything except stmfGetState(), setStmfState() and 236 * stmfLoadConfig(). 237 */ 238 static int 239 initializeConfig() 240 { 241 int ret; 242 stmfState state; 243 244 245 ret = stmfGetState(&state); 246 if (ret != STMF_STATUS_SUCCESS) { 247 return (ret); 248 } 249 250 /* if we've already initialized or in the process, return success */ 251 if (state.configState == STMF_CONFIG_STATE_INIT_DONE || 252 state.configState == STMF_CONFIG_STATE_INIT) { 253 return (STMF_STATUS_SUCCESS); 254 } 255 256 ret = stmfLoadConfig(); 257 if (ret != STMF_STATUS_SUCCESS) { 258 syslog(LOG_DEBUG, 259 "initializeConfig:stmfLoadConfig:error(%d)", ret); 260 return (ret); 261 } 262 263 ret = stmfGetState(&state); 264 if (ret != STMF_STATUS_SUCCESS) { 265 syslog(LOG_DEBUG, 266 "initializeConfig:stmfGetState:error(%d)", ret); 267 return (ret); 268 } 269 270 if (state.configState != STMF_CONFIG_STATE_INIT_DONE) { 271 syslog(LOG_DEBUG, "initializeConfig:state.configState(%d)", 272 state.configState); 273 ret = STMF_STATUS_ERROR; 274 } 275 276 return (ret); 277 } 278 279 280 /* 281 * groupIoctl 282 * 283 * Purpose: issue ioctl for create/delete on group 284 * 285 * cmd - valid STMF ioctl group cmd 286 * groupName - groupName to create or delete 287 */ 288 static int 289 groupIoctl(int fd, int cmd, stmfGroupName *groupName) 290 { 291 int ret = STMF_STATUS_SUCCESS; 292 int ioctlRet; 293 stmf_iocdata_t stmfIoctl; 294 stmf_group_name_t iGroupName; 295 296 bzero(&iGroupName, sizeof (iGroupName)); 297 298 bcopy(groupName, &iGroupName.name, strlen((char *)groupName)); 299 300 iGroupName.name_size = strlen((char *)groupName); 301 302 bzero(&stmfIoctl, sizeof (stmfIoctl)); 303 /* 304 * Issue ioctl to create the host group 305 */ 306 stmfIoctl.stmf_version = STMF_VERSION_1; 307 stmfIoctl.stmf_ibuf_size = sizeof (iGroupName); 308 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName; 309 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 310 if (ioctlRet != 0) { 311 switch (errno) { 312 case EPERM: 313 case EACCES: 314 ret = STMF_ERROR_PERM; 315 break; 316 default: 317 switch (stmfIoctl.stmf_error) { 318 case STMF_IOCERR_TG_EXISTS: 319 case STMF_IOCERR_HG_EXISTS: 320 ret = STMF_ERROR_EXISTS; 321 break; 322 case STMF_IOCERR_TG_IN_USE: 323 case STMF_IOCERR_HG_IN_USE: 324 ret = STMF_ERROR_GROUP_IN_USE; 325 break; 326 case STMF_IOCERR_INVALID_HG: 327 case STMF_IOCERR_INVALID_TG: 328 ret = STMF_ERROR_NOT_FOUND; 329 break; 330 default: 331 syslog(LOG_DEBUG, 332 "groupIoctl:error(%d)", 333 stmfIoctl.stmf_error); 334 ret = STMF_STATUS_ERROR; 335 break; 336 } 337 break; 338 } 339 } 340 done: 341 return (ret); 342 } 343 344 /* 345 * groupMemberIoctl 346 * 347 * Purpose: issue ioctl for add/remove member on group 348 * 349 * cmd - valid STMF ioctl group member cmd 350 * groupName - groupName to add to or remove from 351 * devid - group member to add or remove 352 */ 353 static int 354 groupMemberIoctl(int fd, int cmd, stmfGroupName *groupName, stmfDevid *devid) 355 { 356 int ret = STMF_STATUS_SUCCESS; 357 int ioctlRet; 358 stmf_iocdata_t stmfIoctl; 359 stmf_group_op_data_t stmfGroupData; 360 361 bzero(&stmfGroupData, sizeof (stmfGroupData)); 362 363 bcopy(groupName, &stmfGroupData.group.name, strlen((char *)groupName)); 364 365 stmfGroupData.group.name_size = strlen((char *)groupName); 366 stmfGroupData.ident[IDENT_LENGTH_BYTE] = devid->identLength; 367 bcopy(&(devid->ident), &stmfGroupData.ident[IDENT_LENGTH_BYTE + 1], 368 devid->identLength); 369 370 bzero(&stmfIoctl, sizeof (stmfIoctl)); 371 /* 372 * Issue ioctl to add to the host group 373 */ 374 stmfIoctl.stmf_version = STMF_VERSION_1; 375 stmfIoctl.stmf_ibuf_size = sizeof (stmfGroupData); 376 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&stmfGroupData; 377 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 378 if (ioctlRet != 0) { 379 switch (errno) { 380 case EBUSY: 381 switch (stmfIoctl.stmf_error) { 382 case STMF_IOCERR_TG_NEED_TG_OFFLINE: 383 ret = STMF_ERROR_TG_ONLINE; 384 break; 385 default: 386 ret = STMF_ERROR_BUSY; 387 break; 388 } 389 break; 390 case EPERM: 391 case EACCES: 392 ret = STMF_ERROR_PERM; 393 break; 394 default: 395 switch (stmfIoctl.stmf_error) { 396 case STMF_IOCERR_TG_ENTRY_EXISTS: 397 case STMF_IOCERR_HG_ENTRY_EXISTS: 398 ret = STMF_ERROR_EXISTS; 399 break; 400 case STMF_IOCERR_INVALID_TG_ENTRY: 401 case STMF_IOCERR_INVALID_HG_ENTRY: 402 ret = 403 STMF_ERROR_MEMBER_NOT_FOUND; 404 break; 405 case STMF_IOCERR_INVALID_TG: 406 case STMF_IOCERR_INVALID_HG: 407 ret = 408 STMF_ERROR_GROUP_NOT_FOUND; 409 break; 410 default: 411 syslog(LOG_DEBUG, 412 "groupMemberIoctl:error" 413 "(%d)", 414 stmfIoctl.stmf_error); 415 ret = STMF_STATUS_ERROR; 416 break; 417 } 418 break; 419 } 420 } 421 done: 422 return (ret); 423 } 424 425 /* 426 * qsort function 427 * sort on veIndex 428 */ 429 static int 430 viewEntryCompare(const void *p1, const void *p2) 431 { 432 433 stmfViewEntry *v1 = (stmfViewEntry *)p1, *v2 = (stmfViewEntry *)p2; 434 if (v1->veIndex > v2->veIndex) 435 return (1); 436 if (v1->veIndex < v2->veIndex) 437 return (-1); 438 return (0); 439 } 440 441 /* 442 * guidCompare 443 * 444 * qsort function 445 * sort on guid 446 */ 447 static int 448 guidCompare(const void *p1, const void *p2) 449 { 450 451 stmfGuid *g1 = (stmfGuid *)p1, *g2 = (stmfGuid *)p2; 452 int i; 453 454 for (i = 0; i < sizeof (stmfGuid); i++) { 455 if (g1->guid[i] > g2->guid[i]) 456 return (1); 457 if (g1->guid[i] < g2->guid[i]) 458 return (-1); 459 } 460 461 return (0); 462 } 463 464 /* 465 * stmfAddToHostGroup 466 * 467 * Purpose: Adds an initiator to an existing host group 468 * 469 * hostGroupName - name of an existing host group 470 * hostName - name of initiator to add 471 */ 472 int 473 stmfAddToHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName) 474 { 475 int ret; 476 int fd; 477 478 if (hostGroupName == NULL || 479 (strnlen((char *)hostGroupName, sizeof (stmfGroupName)) 480 == sizeof (stmfGroupName)) || hostName == NULL) { 481 return (STMF_ERROR_INVALID_ARG); 482 } 483 484 /* call init */ 485 ret = initializeConfig(); 486 if (ret != STMF_STATUS_SUCCESS) { 487 return (ret); 488 } 489 490 /* 491 * Open control node for stmf 492 */ 493 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 494 return (ret); 495 496 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, hostGroupName, 497 hostName)) != STMF_STATUS_SUCCESS) { 498 goto done; 499 } 500 501 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 502 goto done; 503 } 504 505 ret = psAddHostGroupMember((char *)hostGroupName, 506 (char *)hostName->ident); 507 switch (ret) { 508 case STMF_PS_SUCCESS: 509 ret = STMF_STATUS_SUCCESS; 510 break; 511 case STMF_PS_ERROR_EXISTS: 512 ret = STMF_ERROR_EXISTS; 513 break; 514 case STMF_PS_ERROR_GROUP_NOT_FOUND: 515 ret = STMF_ERROR_GROUP_NOT_FOUND; 516 break; 517 case STMF_PS_ERROR_BUSY: 518 ret = STMF_ERROR_BUSY; 519 break; 520 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 521 ret = STMF_ERROR_SERVICE_NOT_FOUND; 522 break; 523 case STMF_PS_ERROR_VERSION_MISMATCH: 524 ret = STMF_ERROR_SERVICE_DATA_VERSION; 525 break; 526 default: 527 syslog(LOG_DEBUG, 528 "stmfAddToHostGroup:psAddHostGroupMember:error(%d)", 529 ret); 530 ret = STMF_STATUS_ERROR; 531 break; 532 } 533 534 done: 535 (void) close(fd); 536 return (ret); 537 } 538 539 /* 540 * stmfAddToTargetGroup 541 * 542 * Purpose: Adds a local port to an existing target group 543 * 544 * targetGroupName - name of an existing target group 545 * targetName - name of target to add 546 */ 547 int 548 stmfAddToTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName) 549 { 550 int ret; 551 int fd; 552 553 if (targetGroupName == NULL || 554 (strnlen((char *)targetGroupName, sizeof (stmfGroupName)) 555 == sizeof (stmfGroupName)) || targetName == NULL) { 556 return (STMF_ERROR_INVALID_ARG); 557 } 558 559 /* call init */ 560 ret = initializeConfig(); 561 if (ret != STMF_STATUS_SUCCESS) { 562 return (ret); 563 } 564 565 /* 566 * Open control node for stmf 567 */ 568 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 569 return (ret); 570 571 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY, 572 targetGroupName, targetName)) != STMF_STATUS_SUCCESS) { 573 goto done; 574 } 575 576 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 577 goto done; 578 } 579 580 ret = psAddTargetGroupMember((char *)targetGroupName, 581 (char *)targetName->ident); 582 switch (ret) { 583 case STMF_PS_SUCCESS: 584 ret = STMF_STATUS_SUCCESS; 585 break; 586 case STMF_PS_ERROR_EXISTS: 587 ret = STMF_ERROR_EXISTS; 588 break; 589 case STMF_PS_ERROR_GROUP_NOT_FOUND: 590 ret = STMF_ERROR_GROUP_NOT_FOUND; 591 break; 592 case STMF_PS_ERROR_BUSY: 593 ret = STMF_ERROR_BUSY; 594 break; 595 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 596 ret = STMF_ERROR_SERVICE_NOT_FOUND; 597 break; 598 case STMF_PS_ERROR_VERSION_MISMATCH: 599 ret = STMF_ERROR_SERVICE_DATA_VERSION; 600 break; 601 default: 602 syslog(LOG_DEBUG, 603 "stmfAddToTargetGroup:psAddTargetGroupMember:" 604 "error(%d)", ret); 605 ret = STMF_STATUS_ERROR; 606 break; 607 } 608 609 done: 610 (void) close(fd); 611 return (ret); 612 } 613 614 /* 615 * addViewEntryIoctl 616 * 617 * Purpose: Issues ioctl to add a view entry 618 * 619 * lu - Logical Unit identifier to which the view entry is added 620 * viewEntry - view entry to add 621 * init - When set to B_TRUE, we are in the init state, i.e. don't call open 622 */ 623 static int 624 addViewEntryIoctl(int fd, stmfGuid *lu, stmfViewEntry *viewEntry) 625 { 626 int ret = STMF_STATUS_SUCCESS; 627 int ioctlRet; 628 stmf_iocdata_t stmfIoctl; 629 stmf_view_op_entry_t ioctlViewEntry; 630 631 bzero(&ioctlViewEntry, sizeof (ioctlViewEntry)); 632 /* 633 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be 634 * false on input 635 */ 636 ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid; 637 ioctlViewEntry.ve_all_hosts = viewEntry->allHosts; 638 ioctlViewEntry.ve_all_targets = viewEntry->allTargets; 639 640 if (viewEntry->allHosts == B_FALSE) { 641 bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name, 642 sizeof (stmfGroupName)); 643 ioctlViewEntry.ve_host_group.name_size = 644 strlen((char *)viewEntry->hostGroup); 645 } 646 if (viewEntry->allTargets == B_FALSE) { 647 bcopy(viewEntry->targetGroup, 648 &ioctlViewEntry.ve_target_group.name, 649 sizeof (stmfGroupName)); 650 ioctlViewEntry.ve_target_group.name_size = 651 strlen((char *)viewEntry->targetGroup); 652 } 653 if (viewEntry->luNbrValid) { 654 bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr, 655 sizeof (ioctlViewEntry.ve_lu_nbr)); 656 } 657 bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid)); 658 659 bzero(&stmfIoctl, sizeof (stmfIoctl)); 660 /* 661 * Issue ioctl to add to the view entry 662 */ 663 stmfIoctl.stmf_version = STMF_VERSION_1; 664 stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry); 665 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry; 666 stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry); 667 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry; 668 ioctlRet = ioctl(fd, STMF_IOCTL_ADD_VIEW_ENTRY, &stmfIoctl); 669 if (ioctlRet != 0) { 670 switch (errno) { 671 case EBUSY: 672 ret = STMF_ERROR_BUSY; 673 break; 674 case EPERM: 675 ret = STMF_ERROR_PERM; 676 break; 677 case EACCES: 678 switch (stmfIoctl.stmf_error) { 679 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 680 ret = STMF_ERROR_CONFIG_NONE; 681 break; 682 default: 683 ret = STMF_ERROR_PERM; 684 break; 685 } 686 break; 687 default: 688 switch (stmfIoctl.stmf_error) { 689 case STMF_IOCERR_LU_NUMBER_IN_USE: 690 ret = STMF_ERROR_LUN_IN_USE; 691 break; 692 case STMF_IOCERR_VIEW_ENTRY_CONFLICT: 693 ret = STMF_ERROR_VE_CONFLICT; 694 break; 695 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 696 ret = STMF_ERROR_CONFIG_NONE; 697 break; 698 case STMF_IOCERR_INVALID_HG: 699 ret = STMF_ERROR_INVALID_HG; 700 break; 701 case STMF_IOCERR_INVALID_TG: 702 ret = STMF_ERROR_INVALID_TG; 703 break; 704 default: 705 syslog(LOG_DEBUG, 706 "addViewEntryIoctl" 707 ":error(%d)", 708 stmfIoctl.stmf_error); 709 ret = STMF_STATUS_ERROR; 710 break; 711 } 712 break; 713 } 714 goto done; 715 } 716 717 /* copy lu nbr back to caller's view entry on success */ 718 viewEntry->veIndex = ioctlViewEntry.ve_ndx; 719 if (ioctlViewEntry.ve_lu_number_valid) { 720 bcopy(&ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr, 721 sizeof (ioctlViewEntry.ve_lu_nbr)); 722 } 723 viewEntry->luNbrValid = B_TRUE; 724 725 done: 726 return (ret); 727 } 728 729 /* 730 * stmfAddViewEntry 731 * 732 * Purpose: Adds a view entry to a logical unit 733 * 734 * lu - guid of the logical unit to which the view entry is added 735 * viewEntry - view entry structure to add 736 */ 737 int 738 stmfAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry) 739 { 740 int ret; 741 int fd; 742 stmfViewEntry iViewEntry; 743 744 if (lu == NULL || viewEntry == NULL) { 745 return (STMF_ERROR_INVALID_ARG); 746 } 747 748 /* initialize and set internal view entry */ 749 bzero(&iViewEntry, sizeof (iViewEntry)); 750 751 if (!viewEntry->allHosts) { 752 bcopy(viewEntry->hostGroup, iViewEntry.hostGroup, 753 sizeof (iViewEntry.hostGroup)); 754 } else { 755 iViewEntry.allHosts = B_TRUE; 756 } 757 758 if (!viewEntry->allTargets) { 759 bcopy(viewEntry->targetGroup, iViewEntry.targetGroup, 760 sizeof (iViewEntry.targetGroup)); 761 } else { 762 iViewEntry.allTargets = B_TRUE; 763 } 764 765 if (viewEntry->luNbrValid) { 766 iViewEntry.luNbrValid = B_TRUE; 767 bcopy(viewEntry->luNbr, iViewEntry.luNbr, 768 sizeof (iViewEntry.luNbr)); 769 } 770 771 /* 772 * set users return view entry index valid flag to false 773 * in case of failure 774 */ 775 viewEntry->veIndexValid = B_FALSE; 776 777 /* Check to ensure service exists */ 778 if (psCheckService() != STMF_STATUS_SUCCESS) { 779 return (STMF_ERROR_SERVICE_NOT_FOUND); 780 } 781 782 /* call init */ 783 ret = initializeConfig(); 784 if (ret != STMF_STATUS_SUCCESS) { 785 return (ret); 786 } 787 788 /* 789 * Open control node for stmf 790 */ 791 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 792 return (ret); 793 794 /* 795 * First add the view entry to the driver 796 */ 797 ret = addViewEntryIoctl(fd, lu, &iViewEntry); 798 if (ret != STMF_STATUS_SUCCESS) { 799 goto done; 800 } 801 802 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 803 goto done; 804 } 805 806 /* 807 * If the add to driver was successful, add it to the persistent 808 * store. 809 */ 810 ret = psAddViewEntry(lu, &iViewEntry); 811 switch (ret) { 812 case STMF_PS_SUCCESS: 813 ret = STMF_STATUS_SUCCESS; 814 break; 815 case STMF_PS_ERROR_NOT_FOUND: 816 ret = STMF_ERROR_NOT_FOUND; 817 break; 818 case STMF_PS_ERROR_BUSY: 819 ret = STMF_ERROR_BUSY; 820 break; 821 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 822 ret = STMF_ERROR_SERVICE_NOT_FOUND; 823 break; 824 case STMF_PS_ERROR_VERSION_MISMATCH: 825 ret = STMF_ERROR_SERVICE_DATA_VERSION; 826 break; 827 default: 828 syslog(LOG_DEBUG, 829 "stmfAddViewEntry:psAddViewEntry:error(%d)", ret); 830 ret = STMF_STATUS_ERROR; 831 break; 832 } 833 834 done: 835 (void) close(fd); 836 837 if (ret == STMF_STATUS_SUCCESS) { 838 /* set caller's view entry on success */ 839 viewEntry->veIndexValid = iViewEntry.veIndexValid; 840 viewEntry->veIndex = iViewEntry.veIndex; 841 viewEntry->luNbrValid = B_TRUE; 842 bcopy(iViewEntry.luNbr, viewEntry->luNbr, 843 sizeof (iViewEntry.luNbr)); 844 } 845 return (ret); 846 } 847 848 /* 849 * stmfClearProviderData 850 * 851 * Purpose: delete all provider data for specified provider 852 * 853 * providerName - name of provider for which data should be deleted 854 */ 855 int 856 stmfClearProviderData(char *providerName, int providerType) 857 { 858 int ret; 859 int fd; 860 int ioctlRet; 861 int savedErrno; 862 stmf_iocdata_t stmfIoctl; 863 stmf_ppioctl_data_t ppi; 864 865 /* call init */ 866 ret = initializeConfig(); 867 if (ret != STMF_STATUS_SUCCESS) { 868 return (ret); 869 } 870 871 if (providerName == NULL) { 872 return (STMF_ERROR_INVALID_ARG); 873 } 874 875 if (providerType != STMF_LU_PROVIDER_TYPE && 876 providerType != STMF_PORT_PROVIDER_TYPE) { 877 return (STMF_ERROR_INVALID_ARG); 878 } 879 880 /* 881 * Open control node for stmf 882 */ 883 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 884 return (ret); 885 886 bzero(&ppi, sizeof (ppi)); 887 888 (void) strncpy(ppi.ppi_name, providerName, sizeof (ppi.ppi_name)); 889 890 switch (providerType) { 891 case STMF_LU_PROVIDER_TYPE: 892 ppi.ppi_lu_provider = 1; 893 break; 894 case STMF_PORT_PROVIDER_TYPE: 895 ppi.ppi_port_provider = 1; 896 break; 897 default: 898 ret = STMF_ERROR_INVALID_ARG; 899 goto done; 900 } 901 902 bzero(&stmfIoctl, sizeof (stmfIoctl)); 903 904 stmfIoctl.stmf_version = STMF_VERSION_1; 905 stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t); 906 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi; 907 908 ioctlRet = ioctl(fd, STMF_IOCTL_CLEAR_PP_DATA, &stmfIoctl); 909 if (ioctlRet != 0) { 910 savedErrno = errno; 911 switch (savedErrno) { 912 case EBUSY: 913 ret = STMF_ERROR_BUSY; 914 break; 915 case EPERM: 916 case EACCES: 917 ret = STMF_ERROR_PERM; 918 break; 919 default: 920 syslog(LOG_DEBUG, 921 "stmfClearProviderData:ioctl error(%d)", 922 ioctlRet); 923 ret = STMF_STATUS_ERROR; 924 break; 925 } 926 if (savedErrno != ENOENT) { 927 goto done; 928 } 929 } 930 931 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 932 goto done; 933 } 934 935 ret = psClearProviderData(providerName, providerType); 936 switch (ret) { 937 case STMF_PS_SUCCESS: 938 ret = STMF_STATUS_SUCCESS; 939 break; 940 case STMF_PS_ERROR_NOT_FOUND: 941 ret = STMF_ERROR_NOT_FOUND; 942 break; 943 case STMF_PS_ERROR_BUSY: 944 ret = STMF_ERROR_BUSY; 945 break; 946 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 947 ret = STMF_ERROR_SERVICE_NOT_FOUND; 948 break; 949 case STMF_PS_ERROR_VERSION_MISMATCH: 950 ret = STMF_ERROR_SERVICE_DATA_VERSION; 951 break; 952 default: 953 syslog(LOG_DEBUG, 954 "stmfClearProviderData:psClearProviderData" 955 ":error(%d)", ret); 956 ret = STMF_STATUS_ERROR; 957 break; 958 } 959 960 done: 961 (void) close(fd); 962 return (ret); 963 } 964 965 /* 966 * stmfCreateHostGroup 967 * 968 * Purpose: Create a new initiator group 969 * 970 * hostGroupName - name of host group to create 971 */ 972 int 973 stmfCreateHostGroup(stmfGroupName *hostGroupName) 974 { 975 int ret; 976 int fd; 977 978 if (hostGroupName == NULL || 979 (strnlen((char *)hostGroupName, sizeof (stmfGroupName)) 980 == sizeof (stmfGroupName))) { 981 return (STMF_ERROR_INVALID_ARG); 982 } 983 984 /* Check to ensure service exists */ 985 if (psCheckService() != STMF_STATUS_SUCCESS) { 986 return (STMF_ERROR_SERVICE_NOT_FOUND); 987 } 988 989 /* call init */ 990 ret = initializeConfig(); 991 if (ret != STMF_STATUS_SUCCESS) { 992 return (ret); 993 } 994 995 /* 996 * Open control node for stmf 997 */ 998 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 999 return (ret); 1000 1001 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP, 1002 hostGroupName)) != STMF_STATUS_SUCCESS) { 1003 goto done; 1004 } 1005 1006 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 1007 goto done; 1008 } 1009 1010 ret = psCreateHostGroup((char *)hostGroupName); 1011 switch (ret) { 1012 case STMF_PS_SUCCESS: 1013 ret = STMF_STATUS_SUCCESS; 1014 break; 1015 case STMF_PS_ERROR_EXISTS: 1016 ret = STMF_ERROR_EXISTS; 1017 break; 1018 case STMF_PS_ERROR_BUSY: 1019 ret = STMF_ERROR_BUSY; 1020 break; 1021 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 1022 ret = STMF_ERROR_SERVICE_NOT_FOUND; 1023 break; 1024 case STMF_PS_ERROR_VERSION_MISMATCH: 1025 ret = STMF_ERROR_SERVICE_DATA_VERSION; 1026 break; 1027 default: 1028 syslog(LOG_DEBUG, 1029 "stmfCreateHostGroup:psCreateHostGroup:error(%d)", 1030 ret); 1031 ret = STMF_STATUS_ERROR; 1032 break; 1033 } 1034 1035 done: 1036 (void) close(fd); 1037 return (ret); 1038 } 1039 1040 /* 1041 * stmfCreateLu 1042 * 1043 * Purpose: Create a logical unit 1044 * 1045 * hdl - handle to logical unit resource created via stmfCreateLuResource 1046 * 1047 * luGuid - If non-NULL, on success, contains the guid of the created logical 1048 * unit 1049 */ 1050 int 1051 stmfCreateLu(luResource hdl, stmfGuid *luGuid) 1052 { 1053 int ret = STMF_STATUS_SUCCESS; 1054 luResourceImpl *luPropsHdl = hdl; 1055 1056 if (hdl == NULL) { 1057 return (STMF_ERROR_INVALID_ARG); 1058 } 1059 1060 if (luPropsHdl->type == STMF_DISK) { 1061 ret = createDiskLu((diskResource *)luPropsHdl->resource, 1062 luGuid); 1063 } else { 1064 return (STMF_ERROR_INVALID_ARG); 1065 } 1066 1067 return (ret); 1068 } 1069 1070 /* 1071 * stmfCreateLuResource 1072 * 1073 * Purpose: Create resource handle for a logical unit 1074 * 1075 * dType - Type of logical unit resource to create 1076 * Can be: STMF_DISK 1077 * 1078 * hdl - pointer to luResource 1079 */ 1080 int 1081 stmfCreateLuResource(uint16_t dType, luResource *hdl) 1082 { 1083 int ret = STMF_STATUS_SUCCESS; 1084 1085 if (dType != STMF_DISK || hdl == NULL) { 1086 return (STMF_ERROR_INVALID_ARG); 1087 } 1088 1089 *hdl = calloc(1, sizeof (luResourceImpl)); 1090 if (*hdl == NULL) { 1091 return (STMF_ERROR_NOMEM); 1092 } 1093 1094 ret = createDiskResource((luResourceImpl *)*hdl); 1095 if (ret != STMF_STATUS_SUCCESS) { 1096 free(*hdl); 1097 return (ret); 1098 } 1099 1100 return (STMF_STATUS_SUCCESS); 1101 } 1102 1103 /* 1104 * Creates a disk logical unit 1105 * 1106 * disk - pointer to diskResource structure that represents the properties 1107 * for the disk logical unit to be created. 1108 */ 1109 static int 1110 createDiskLu(diskResource *disk, stmfGuid *createdGuid) 1111 { 1112 int ret = STMF_STATUS_SUCCESS; 1113 int dataFileNameLen = 0; 1114 int metaFileNameLen = 0; 1115 int serialNumLen = 0; 1116 int luAliasLen = 0; 1117 int luMgmtUrlLen = 0; 1118 int sluBufSize = 0; 1119 int bufOffset = 0; 1120 int fd = 0; 1121 int ioctlRet; 1122 int savedErrno; 1123 stmfGuid guid; 1124 stmf_iocdata_t sbdIoctl = {0}; 1125 1126 sbd_create_and_reg_lu_t *sbdLu = NULL; 1127 1128 /* 1129 * Open control node for sbd 1130 */ 1131 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS) 1132 return (ret); 1133 1134 /* data file name must be specified */ 1135 if (disk->luDataFileNameValid) { 1136 dataFileNameLen = strlen(disk->luDataFileName); 1137 } else { 1138 (void) close(fd); 1139 return (STMF_ERROR_MISSING_PROP_VAL); 1140 } 1141 1142 sluBufSize += dataFileNameLen + 1; 1143 1144 if (disk->luMetaFileNameValid) { 1145 metaFileNameLen = strlen(disk->luMetaFileName); 1146 sluBufSize += metaFileNameLen + 1; 1147 } 1148 1149 serialNumLen = strlen(disk->serialNum); 1150 sluBufSize += serialNumLen; 1151 1152 if (disk->luAliasValid) { 1153 luAliasLen = strlen(disk->luAlias); 1154 sluBufSize += luAliasLen + 1; 1155 } 1156 1157 if (disk->luMgmtUrlValid) { 1158 luMgmtUrlLen = strlen(disk->luMgmtUrl); 1159 sluBufSize += luMgmtUrlLen + 1; 1160 } 1161 1162 /* 1163 * 8 is the size of the buffer set aside for 1164 * concatenation of variable length fields 1165 */ 1166 sbdLu = (sbd_create_and_reg_lu_t *)calloc(1, 1167 sizeof (sbd_create_and_reg_lu_t) + sluBufSize - 8); 1168 if (sbdLu == NULL) { 1169 return (STMF_ERROR_NOMEM); 1170 } 1171 1172 sbdLu->slu_struct_size = sizeof (sbd_create_and_reg_lu_t) + 1173 sluBufSize - 8; 1174 1175 if (metaFileNameLen) { 1176 sbdLu->slu_meta_fname_valid = 1; 1177 sbdLu->slu_meta_fname_off = bufOffset; 1178 bcopy(disk->luMetaFileName, &(sbdLu->slu_buf[bufOffset]), 1179 metaFileNameLen + 1); 1180 bufOffset += metaFileNameLen + 1; 1181 } 1182 1183 bcopy(disk->luDataFileName, &(sbdLu->slu_buf[bufOffset]), 1184 dataFileNameLen + 1); 1185 sbdLu->slu_data_fname_off = bufOffset; 1186 bufOffset += dataFileNameLen + 1; 1187 1188 /* currently, serial # is not passed null terminated to the driver */ 1189 if (disk->serialNumValid) { 1190 sbdLu->slu_serial_valid = 1; 1191 sbdLu->slu_serial_off = bufOffset; 1192 sbdLu->slu_serial_size = serialNumLen; 1193 bcopy(disk->serialNum, &(sbdLu->slu_buf[bufOffset]), 1194 serialNumLen); 1195 bufOffset += serialNumLen; 1196 } 1197 1198 if (disk->luAliasValid) { 1199 sbdLu->slu_alias_valid = 1; 1200 sbdLu->slu_alias_off = bufOffset; 1201 bcopy(disk->luAlias, &(sbdLu->slu_buf[bufOffset]), 1202 luAliasLen + 1); 1203 bufOffset += luAliasLen + 1; 1204 } 1205 1206 if (disk->luMgmtUrlValid) { 1207 sbdLu->slu_mgmt_url_valid = 1; 1208 sbdLu->slu_mgmt_url_off = bufOffset; 1209 bcopy(disk->luMgmtUrl, &(sbdLu->slu_buf[bufOffset]), 1210 luMgmtUrlLen + 1); 1211 bufOffset += luMgmtUrlLen + 1; 1212 } 1213 1214 if (disk->luSizeValid) { 1215 sbdLu->slu_lu_size_valid = 1; 1216 sbdLu->slu_lu_size = disk->luSize; 1217 } 1218 1219 if (disk->luGuidValid) { 1220 sbdLu->slu_guid_valid = 1; 1221 bcopy(disk->luGuid, sbdLu->slu_guid, sizeof (disk->luGuid)); 1222 } 1223 1224 if (disk->vidValid) { 1225 sbdLu->slu_vid_valid = 1; 1226 bcopy(disk->vid, sbdLu->slu_vid, sizeof (disk->vid)); 1227 } 1228 1229 if (disk->pidValid) { 1230 sbdLu->slu_pid_valid = 1; 1231 bcopy(disk->pid, sbdLu->slu_pid, sizeof (disk->pid)); 1232 } 1233 1234 if (disk->revValid) { 1235 sbdLu->slu_rev_valid = 1; 1236 bcopy(disk->rev, sbdLu->slu_rev, sizeof (disk->rev)); 1237 } 1238 1239 if (disk->companyIdValid) { 1240 sbdLu->slu_company_id_valid = 1; 1241 sbdLu->slu_company_id = disk->companyId; 1242 } 1243 1244 if (disk->blkSizeValid) { 1245 sbdLu->slu_blksize_valid = 1; 1246 sbdLu->slu_blksize = disk->blkSize; 1247 } 1248 1249 if (disk->writeProtectEnableValid) { 1250 if (disk->writeProtectEnable) { 1251 sbdLu->slu_write_protected = 1; 1252 } 1253 } 1254 1255 if (disk->writebackCacheDisableValid) { 1256 sbdLu->slu_writeback_cache_disable_valid = 1; 1257 if (disk->writebackCacheDisable) { 1258 sbdLu->slu_writeback_cache_disable = 1; 1259 } 1260 } 1261 1262 sbdIoctl.stmf_version = STMF_VERSION_1; 1263 sbdIoctl.stmf_ibuf_size = sbdLu->slu_struct_size; 1264 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu; 1265 sbdIoctl.stmf_obuf_size = sbdLu->slu_struct_size; 1266 sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu; 1267 1268 ioctlRet = ioctl(fd, SBD_IOCTL_CREATE_AND_REGISTER_LU, &sbdIoctl); 1269 if (ioctlRet != 0) { 1270 savedErrno = errno; 1271 switch (savedErrno) { 1272 case EBUSY: 1273 ret = STMF_ERROR_BUSY; 1274 break; 1275 case EPERM: 1276 case EACCES: 1277 ret = STMF_ERROR_PERM; 1278 break; 1279 default: 1280 diskError(sbdIoctl.stmf_error, &ret); 1281 if (ret == STMF_STATUS_ERROR) { 1282 syslog(LOG_DEBUG, 1283 "createDiskLu:ioctl " 1284 "error(%d) (%d) (%d)", ioctlRet, 1285 sbdIoctl.stmf_error, savedErrno); 1286 } 1287 break; 1288 } 1289 } 1290 1291 if (ret != STMF_STATUS_SUCCESS) { 1292 goto done; 1293 } 1294 1295 /* 1296 * on success, copy the resulting guid into the caller's guid if not 1297 * NULL 1298 */ 1299 if (createdGuid) { 1300 bcopy(sbdLu->slu_guid, createdGuid->guid, 1301 sizeof (sbdLu->slu_guid)); 1302 } 1303 1304 bcopy(sbdLu->slu_guid, guid.guid, sizeof (sbdLu->slu_guid)); 1305 if (disk->luMetaFileNameValid) { 1306 ret = addGuidToDiskStore(&guid, disk->luMetaFileName); 1307 } else { 1308 ret = addGuidToDiskStore(&guid, disk->luDataFileName); 1309 } 1310 done: 1311 free(sbdLu); 1312 (void) close(fd); 1313 return (ret); 1314 } 1315 1316 1317 /* 1318 * stmfImportLu 1319 * 1320 * Purpose: Import a previously created logical unit 1321 * 1322 * dType - Type of logical unit 1323 * Can be: STMF_DISK 1324 * 1325 * luGuid - If non-NULL, on success, contains the guid of the imported logical 1326 * unit 1327 * 1328 * fname - A file name where the metadata resides 1329 * 1330 */ 1331 int 1332 stmfImportLu(uint16_t dType, char *fname, stmfGuid *luGuid) 1333 { 1334 int ret = STMF_STATUS_SUCCESS; 1335 1336 if (dType == STMF_DISK) { 1337 ret = importDiskLu(fname, luGuid); 1338 } else { 1339 return (STMF_ERROR_INVALID_ARG); 1340 } 1341 1342 return (ret); 1343 } 1344 1345 /* 1346 * importDiskLu 1347 * 1348 * filename - filename to import 1349 * createdGuid - if not NULL, on success contains the imported guid 1350 * 1351 */ 1352 static int 1353 importDiskLu(char *fname, stmfGuid *createdGuid) 1354 { 1355 int ret = STMF_STATUS_SUCCESS; 1356 int fd = 0; 1357 int ioctlRet; 1358 int savedErrno; 1359 int metaFileNameLen; 1360 stmfGuid iGuid; 1361 int iluBufSize = 0; 1362 sbd_import_lu_t *sbdLu = NULL; 1363 stmf_iocdata_t sbdIoctl = {0}; 1364 1365 if (fname == NULL) { 1366 return (STMF_ERROR_INVALID_ARG); 1367 } 1368 1369 /* 1370 * Open control node for sbd 1371 */ 1372 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS) 1373 return (ret); 1374 1375 metaFileNameLen = strlen(fname); 1376 iluBufSize += metaFileNameLen + 1; 1377 1378 /* 1379 * 8 is the size of the buffer set aside for 1380 * concatenation of variable length fields 1381 */ 1382 sbdLu = (sbd_import_lu_t *)calloc(1, 1383 sizeof (sbd_import_lu_t) + iluBufSize - 8); 1384 if (sbdLu == NULL) { 1385 (void) close(fd); 1386 return (STMF_ERROR_NOMEM); 1387 } 1388 1389 /* 1390 * Accept either a data file or meta data file. 1391 * sbd will do the right thing here either way. 1392 * i.e. if it's a data file, it assumes that the 1393 * meta data is shared with the data. 1394 */ 1395 (void) strncpy(sbdLu->ilu_meta_fname, fname, metaFileNameLen); 1396 1397 sbdLu->ilu_struct_size = sizeof (sbd_import_lu_t) + iluBufSize - 8; 1398 1399 sbdIoctl.stmf_version = STMF_VERSION_1; 1400 sbdIoctl.stmf_ibuf_size = sbdLu->ilu_struct_size; 1401 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu; 1402 sbdIoctl.stmf_obuf_size = sbdLu->ilu_struct_size; 1403 sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu; 1404 1405 ioctlRet = ioctl(fd, SBD_IOCTL_IMPORT_LU, &sbdIoctl); 1406 if (ioctlRet != 0) { 1407 savedErrno = errno; 1408 switch (savedErrno) { 1409 case EBUSY: 1410 ret = STMF_ERROR_BUSY; 1411 break; 1412 case EPERM: 1413 case EACCES: 1414 ret = STMF_ERROR_PERM; 1415 break; 1416 default: 1417 diskError(sbdIoctl.stmf_error, &ret); 1418 if (ret == STMF_STATUS_ERROR) { 1419 syslog(LOG_DEBUG, 1420 "importDiskLu:ioctl " 1421 "error(%d) (%d) (%d)", ioctlRet, 1422 sbdIoctl.stmf_error, savedErrno); 1423 } 1424 break; 1425 } 1426 } 1427 1428 if (ret != STMF_STATUS_SUCCESS) { 1429 goto done; 1430 } 1431 1432 /* 1433 * on success, copy the resulting guid into the caller's guid if not 1434 * NULL and add it to the persistent store for sbd 1435 */ 1436 if (createdGuid) { 1437 bcopy(sbdLu->ilu_ret_guid, createdGuid->guid, 1438 sizeof (sbdLu->ilu_ret_guid)); 1439 ret = addGuidToDiskStore(createdGuid, fname); 1440 } else { 1441 bcopy(sbdLu->ilu_ret_guid, iGuid.guid, 1442 sizeof (sbdLu->ilu_ret_guid)); 1443 ret = addGuidToDiskStore(&iGuid, fname); 1444 } 1445 done: 1446 free(sbdLu); 1447 (void) close(fd); 1448 return (ret); 1449 } 1450 1451 /* 1452 * diskError 1453 * 1454 * Purpose: Translate sbd driver error 1455 */ 1456 static void 1457 diskError(uint32_t stmfError, int *ret) 1458 { 1459 switch (stmfError) { 1460 case SBD_RET_META_CREATION_FAILED: 1461 case SBD_RET_ZFS_META_CREATE_FAILED: 1462 *ret = STMF_ERROR_META_CREATION; 1463 break; 1464 case SBD_RET_INVALID_BLKSIZE: 1465 *ret = STMF_ERROR_INVALID_BLKSIZE; 1466 break; 1467 case SBD_RET_FILE_ALREADY_REGISTERED: 1468 *ret = STMF_ERROR_FILE_IN_USE; 1469 break; 1470 case SBD_RET_GUID_ALREADY_REGISTERED: 1471 *ret = STMF_ERROR_GUID_IN_USE; 1472 break; 1473 case SBD_RET_META_PATH_NOT_ABSOLUTE: 1474 case SBD_RET_META_FILE_LOOKUP_FAILED: 1475 case SBD_RET_META_FILE_OPEN_FAILED: 1476 case SBD_RET_META_FILE_GETATTR_FAILED: 1477 case SBD_RET_NO_META: 1478 *ret = STMF_ERROR_META_FILE_NAME; 1479 break; 1480 case SBD_RET_DATA_PATH_NOT_ABSOLUTE: 1481 case SBD_RET_DATA_FILE_LOOKUP_FAILED: 1482 case SBD_RET_DATA_FILE_OPEN_FAILED: 1483 case SBD_RET_DATA_FILE_GETATTR_FAILED: 1484 *ret = STMF_ERROR_DATA_FILE_NAME; 1485 break; 1486 case SBD_RET_FILE_SIZE_ERROR: 1487 *ret = STMF_ERROR_FILE_SIZE_INVALID; 1488 break; 1489 case SBD_RET_SIZE_OUT_OF_RANGE: 1490 *ret = STMF_ERROR_SIZE_OUT_OF_RANGE; 1491 break; 1492 case SBD_RET_LU_BUSY: 1493 *ret = STMF_ERROR_LU_BUSY; 1494 break; 1495 case SBD_RET_WRITE_CACHE_SET_FAILED: 1496 *ret = STMF_ERROR_WRITE_CACHE_SET; 1497 break; 1498 case SBD_RET_ACCESS_STATE_FAILED: 1499 *ret = STMF_ERROR_ACCESS_STATE_SET; 1500 break; 1501 default: 1502 *ret = STMF_STATUS_ERROR; 1503 break; 1504 } 1505 } 1506 1507 /* 1508 * Creates a logical unit resource of type STMF_DISK. 1509 * 1510 * No defaults should be set here as all defaults are derived from the 1511 * driver's default settings. 1512 */ 1513 static int 1514 createDiskResource(luResourceImpl *hdl) 1515 { 1516 hdl->type = STMF_DISK; 1517 1518 hdl->resource = calloc(1, sizeof (diskResource)); 1519 if (hdl->resource == NULL) { 1520 return (STMF_ERROR_NOMEM); 1521 } 1522 1523 return (STMF_STATUS_SUCCESS); 1524 } 1525 1526 /* 1527 * stmfDeleteLu 1528 * 1529 * Purpose: Delete a logical unit 1530 * 1531 * hdl - handle to logical unit resource created via stmfCreateLuResource 1532 * 1533 * luGuid - If non-NULL, on success, contains the guid of the created logical 1534 * unit 1535 */ 1536 int 1537 stmfDeleteLu(stmfGuid *luGuid) 1538 { 1539 int ret = STMF_STATUS_SUCCESS; 1540 stmfLogicalUnitProperties luProps; 1541 1542 if (luGuid == NULL) { 1543 return (STMF_ERROR_INVALID_ARG); 1544 } 1545 1546 /* Check logical unit provider name to call correct dtype function */ 1547 if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps)) 1548 != STMF_STATUS_SUCCESS) { 1549 return (ret); 1550 } else { 1551 if (strcmp(luProps.providerName, "sbd") == 0) { 1552 ret = deleteDiskLu(luGuid); 1553 } else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) { 1554 return (STMF_ERROR_NOT_FOUND); 1555 } else { 1556 return (STMF_ERROR_INVALID_ARG); 1557 } 1558 } 1559 1560 return (ret); 1561 } 1562 1563 static int 1564 deleteDiskLu(stmfGuid *luGuid) 1565 { 1566 int ret = STMF_STATUS_SUCCESS; 1567 int fd; 1568 int savedErrno; 1569 int ioctlRet; 1570 sbd_delete_lu_t deleteLu = {0}; 1571 1572 stmf_iocdata_t sbdIoctl = {0}; 1573 1574 /* 1575 * Open control node for sbd 1576 */ 1577 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS) 1578 return (ret); 1579 1580 ret = removeGuidFromDiskStore(luGuid); 1581 if (ret != STMF_STATUS_SUCCESS) { 1582 goto done; 1583 } 1584 1585 bcopy(luGuid, deleteLu.dlu_guid, sizeof (deleteLu.dlu_guid)); 1586 deleteLu.dlu_by_guid = 1; 1587 1588 sbdIoctl.stmf_version = STMF_VERSION_1; 1589 sbdIoctl.stmf_ibuf_size = sizeof (deleteLu); 1590 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&deleteLu; 1591 ioctlRet = ioctl(fd, SBD_IOCTL_DELETE_LU, &sbdIoctl); 1592 if (ioctlRet != 0) { 1593 savedErrno = errno; 1594 switch (savedErrno) { 1595 case EBUSY: 1596 ret = STMF_ERROR_BUSY; 1597 break; 1598 case EPERM: 1599 case EACCES: 1600 ret = STMF_ERROR_PERM; 1601 break; 1602 case ENOENT: 1603 ret = STMF_ERROR_NOT_FOUND; 1604 break; 1605 default: 1606 syslog(LOG_DEBUG, 1607 "deleteDiskLu:ioctl error(%d) (%d) (%d)", 1608 ioctlRet, sbdIoctl.stmf_error, savedErrno); 1609 ret = STMF_STATUS_ERROR; 1610 break; 1611 } 1612 } 1613 1614 done: 1615 (void) close(fd); 1616 return (ret); 1617 } 1618 1619 /* 1620 * stmfLuStandby 1621 * 1622 * Purpose: Sets access state to standby 1623 * 1624 * luGuid - guid of registered logical unit 1625 * 1626 */ 1627 int 1628 stmfLuStandby(stmfGuid *luGuid) 1629 { 1630 int ret = STMF_STATUS_SUCCESS; 1631 stmfLogicalUnitProperties luProps; 1632 1633 if (luGuid == NULL) { 1634 return (STMF_ERROR_INVALID_ARG); 1635 } 1636 1637 /* Check logical unit provider name to call correct dtype function */ 1638 if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps)) 1639 != STMF_STATUS_SUCCESS) { 1640 return (ret); 1641 } else { 1642 if (strcmp(luProps.providerName, "sbd") == 0) { 1643 ret = setDiskStandby(luGuid); 1644 } else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) { 1645 return (STMF_ERROR_NOT_FOUND); 1646 } else { 1647 return (STMF_ERROR_INVALID_ARG); 1648 } 1649 } 1650 1651 return (ret); 1652 } 1653 1654 static int 1655 setDiskStandby(stmfGuid *luGuid) 1656 { 1657 int ret = STMF_STATUS_SUCCESS; 1658 stmf_iocdata_t sbdIoctl = {0}; 1659 sbd_set_lu_standby_t sbdLu = {0}; 1660 int ioctlRet; 1661 int savedErrno; 1662 int fd = 0; 1663 1664 /* 1665 * Open control node for sbd 1666 */ 1667 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS) 1668 return (ret); 1669 1670 bcopy(luGuid, &sbdLu.stlu_guid, sizeof (stmfGuid)); 1671 1672 sbdIoctl.stmf_version = STMF_VERSION_1; 1673 sbdIoctl.stmf_ibuf_size = sizeof (sbd_set_lu_standby_t); 1674 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&sbdLu; 1675 1676 ioctlRet = ioctl(fd, SBD_IOCTL_SET_LU_STANDBY, &sbdIoctl); 1677 if (ioctlRet != 0) { 1678 savedErrno = errno; 1679 switch (savedErrno) { 1680 case EBUSY: 1681 ret = STMF_ERROR_BUSY; 1682 break; 1683 case EPERM: 1684 case EACCES: 1685 ret = STMF_ERROR_PERM; 1686 break; 1687 default: 1688 diskError(sbdIoctl.stmf_error, &ret); 1689 if (ret == STMF_STATUS_ERROR) { 1690 syslog(LOG_DEBUG, 1691 "setDiskStandby:ioctl " 1692 "error(%d) (%d) (%d)", ioctlRet, 1693 sbdIoctl.stmf_error, savedErrno); 1694 } 1695 break; 1696 } 1697 } 1698 return (ret); 1699 } 1700 1701 /* 1702 * stmfModifyLu 1703 * 1704 * Purpose: Modify properties of a logical unit 1705 * 1706 * luGuid - guid of registered logical unit 1707 * prop - property to modify 1708 * propVal - property value to set 1709 * 1710 */ 1711 int 1712 stmfModifyLu(stmfGuid *luGuid, uint32_t prop, const char *propVal) 1713 { 1714 int ret = STMF_STATUS_SUCCESS; 1715 stmfLogicalUnitProperties luProps; 1716 1717 if (luGuid == NULL) { 1718 return (STMF_ERROR_INVALID_ARG); 1719 } 1720 1721 /* Check logical unit provider name to call correct dtype function */ 1722 if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps)) 1723 != STMF_STATUS_SUCCESS) { 1724 return (ret); 1725 } else { 1726 if (strcmp(luProps.providerName, "sbd") == 0) { 1727 ret = modifyDiskLuProp(luGuid, NULL, prop, propVal); 1728 } else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) { 1729 return (STMF_ERROR_NOT_FOUND); 1730 } else { 1731 return (STMF_ERROR_INVALID_ARG); 1732 } 1733 } 1734 1735 return (ret); 1736 } 1737 1738 /* 1739 * stmfModifyLuByFname 1740 * 1741 * Purpose: Modify a device by filename. Device does not need to be registered. 1742 * 1743 * dType - type of device to modify 1744 * STMF_DISK 1745 * 1746 * fname - filename or meta filename 1747 * prop - valid property identifier 1748 * propVal - property value 1749 * 1750 */ 1751 int 1752 stmfModifyLuByFname(uint16_t dType, const char *fname, uint32_t prop, 1753 const char *propVal) 1754 { 1755 int ret = STMF_STATUS_SUCCESS; 1756 if (fname == NULL) { 1757 return (STMF_ERROR_INVALID_ARG); 1758 } 1759 1760 if (dType == STMF_DISK) { 1761 ret = modifyDiskLuProp(NULL, fname, prop, propVal); 1762 } else { 1763 return (STMF_ERROR_INVALID_ARG); 1764 } 1765 1766 return (ret); 1767 } 1768 1769 static int 1770 modifyDiskLuProp(stmfGuid *luGuid, const char *fname, uint32_t prop, 1771 const char *propVal) 1772 { 1773 int ret = STMF_STATUS_SUCCESS; 1774 luResource hdl = NULL; 1775 luResourceImpl *luPropsHdl; 1776 1777 ret = stmfCreateLuResource(STMF_DISK, &hdl); 1778 if (ret != STMF_STATUS_SUCCESS) { 1779 return (ret); 1780 } 1781 ret = validateModifyDiskProp(prop); 1782 if (ret != STMF_STATUS_SUCCESS) { 1783 (void) stmfFreeLuResource(hdl); 1784 return (STMF_ERROR_INVALID_PROP); 1785 } 1786 ret = stmfSetLuProp(hdl, prop, propVal); 1787 if (ret != STMF_STATUS_SUCCESS) { 1788 (void) stmfFreeLuResource(hdl); 1789 return (ret); 1790 } 1791 luPropsHdl = hdl; 1792 ret = modifyDiskLu((diskResource *)luPropsHdl->resource, luGuid, fname); 1793 (void) stmfFreeLuResource(hdl); 1794 return (ret); 1795 } 1796 1797 static int 1798 validateModifyDiskProp(uint32_t prop) 1799 { 1800 switch (prop) { 1801 case STMF_LU_PROP_ALIAS: 1802 case STMF_LU_PROP_SIZE: 1803 case STMF_LU_PROP_MGMT_URL: 1804 case STMF_LU_PROP_WRITE_PROTECT: 1805 case STMF_LU_PROP_WRITE_CACHE_DISABLE: 1806 return (STMF_STATUS_SUCCESS); 1807 break; 1808 default: 1809 return (STMF_STATUS_ERROR); 1810 break; 1811 } 1812 } 1813 1814 static int 1815 modifyDiskLu(diskResource *disk, stmfGuid *luGuid, const char *fname) 1816 { 1817 int ret = STMF_STATUS_SUCCESS; 1818 int luAliasLen = 0; 1819 int luMgmtUrlLen = 0; 1820 int mluBufSize = 0; 1821 int bufOffset = 0; 1822 int fd = 0; 1823 int ioctlRet; 1824 int savedErrno; 1825 int fnameSize = 0; 1826 stmf_iocdata_t sbdIoctl = {0}; 1827 1828 sbd_modify_lu_t *sbdLu = NULL; 1829 1830 if (luGuid == NULL && fname == NULL) { 1831 return (STMF_ERROR_INVALID_ARG); 1832 } 1833 1834 if (fname) { 1835 fnameSize = strlen(fname) + 1; 1836 mluBufSize += fnameSize; 1837 } 1838 1839 /* 1840 * Open control node for sbd 1841 */ 1842 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS) 1843 return (ret); 1844 1845 if (disk->luAliasValid) { 1846 luAliasLen = strlen(disk->luAlias); 1847 mluBufSize += luAliasLen + 1; 1848 } 1849 1850 if (disk->luMgmtUrlValid) { 1851 luMgmtUrlLen = strlen(disk->luMgmtUrl); 1852 mluBufSize += luMgmtUrlLen + 1; 1853 } 1854 1855 /* 1856 * 8 is the size of the buffer set aside for 1857 * concatenation of variable length fields 1858 */ 1859 sbdLu = (sbd_modify_lu_t *)calloc(1, 1860 sizeof (sbd_modify_lu_t) + mluBufSize - 8 + fnameSize); 1861 if (sbdLu == NULL) { 1862 (void) close(fd); 1863 return (STMF_ERROR_NOMEM); 1864 } 1865 1866 sbdLu->mlu_struct_size = sizeof (sbd_modify_lu_t) + 1867 mluBufSize - 8 + fnameSize; 1868 1869 if (disk->luAliasValid) { 1870 sbdLu->mlu_alias_valid = 1; 1871 sbdLu->mlu_alias_off = bufOffset; 1872 bcopy(disk->luAlias, &(sbdLu->mlu_buf[bufOffset]), 1873 luAliasLen + 1); 1874 bufOffset += luAliasLen + 1; 1875 } 1876 1877 if (disk->luMgmtUrlValid) { 1878 sbdLu->mlu_mgmt_url_valid = 1; 1879 sbdLu->mlu_mgmt_url_off = bufOffset; 1880 bcopy(disk->luMgmtUrl, &(sbdLu->mlu_buf[bufOffset]), 1881 luMgmtUrlLen + 1); 1882 bufOffset += luMgmtUrlLen + 1; 1883 } 1884 1885 if (disk->luSizeValid) { 1886 sbdLu->mlu_lu_size_valid = 1; 1887 sbdLu->mlu_lu_size = disk->luSize; 1888 } 1889 1890 if (disk->writeProtectEnableValid) { 1891 sbdLu->mlu_write_protected_valid = 1; 1892 if (disk->writeProtectEnable) { 1893 sbdLu->mlu_write_protected = 1; 1894 } 1895 } 1896 1897 if (disk->writebackCacheDisableValid) { 1898 sbdLu->mlu_writeback_cache_disable_valid = 1; 1899 if (disk->writebackCacheDisable) { 1900 sbdLu->mlu_writeback_cache_disable = 1; 1901 } 1902 } 1903 1904 if (luGuid) { 1905 bcopy(luGuid, sbdLu->mlu_input_guid, sizeof (stmfGuid)); 1906 sbdLu->mlu_by_guid = 1; 1907 } else { 1908 sbdLu->mlu_fname_off = bufOffset; 1909 bcopy(fname, &(sbdLu->mlu_buf[bufOffset]), fnameSize + 1); 1910 sbdLu->mlu_by_fname = 1; 1911 } 1912 1913 sbdIoctl.stmf_version = STMF_VERSION_1; 1914 sbdIoctl.stmf_ibuf_size = sbdLu->mlu_struct_size; 1915 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu; 1916 1917 ioctlRet = ioctl(fd, SBD_IOCTL_MODIFY_LU, &sbdIoctl); 1918 if (ioctlRet != 0) { 1919 savedErrno = errno; 1920 switch (savedErrno) { 1921 case EBUSY: 1922 ret = STMF_ERROR_BUSY; 1923 break; 1924 case EPERM: 1925 case EACCES: 1926 ret = STMF_ERROR_PERM; 1927 break; 1928 default: 1929 diskError(sbdIoctl.stmf_error, &ret); 1930 if (ret == STMF_STATUS_ERROR) { 1931 syslog(LOG_DEBUG, 1932 "modifyDiskLu:ioctl " 1933 "error(%d) (%d) (%d)", ioctlRet, 1934 sbdIoctl.stmf_error, savedErrno); 1935 } 1936 break; 1937 } 1938 } 1939 1940 if (ret != STMF_STATUS_SUCCESS) { 1941 goto done; 1942 } 1943 1944 done: 1945 free(sbdLu); 1946 (void) close(fd); 1947 return (ret); 1948 } 1949 1950 /* 1951 * removeGuidFromDiskStore 1952 * 1953 * Purpose: delete a logical unit from the sbd provider data 1954 */ 1955 static int 1956 removeGuidFromDiskStore(stmfGuid *guid) 1957 { 1958 return (persistDiskGuid(guid, NULL, B_FALSE)); 1959 } 1960 1961 1962 /* 1963 * addGuidToDiskStore 1964 * 1965 * Purpose: add a logical unit to the sbd provider data 1966 */ 1967 static int 1968 addGuidToDiskStore(stmfGuid *guid, char *filename) 1969 { 1970 return (persistDiskGuid(guid, filename, B_TRUE)); 1971 } 1972 1973 1974 /* 1975 * persistDiskGuid 1976 * 1977 * Purpose: Persist or unpersist a guid for the sbd provider data 1978 * 1979 */ 1980 static int 1981 persistDiskGuid(stmfGuid *guid, char *filename, boolean_t persist) 1982 { 1983 char guidAsciiBuf[LU_ASCII_GUID_SIZE + 1] = {0}; 1984 nvlist_t *nvl = NULL; 1985 1986 uint64_t setToken; 1987 boolean_t retryGetProviderData = B_FALSE; 1988 boolean_t newData = B_FALSE; 1989 int ret = STMF_STATUS_SUCCESS; 1990 int retryCnt = 0; 1991 int stmfRet; 1992 1993 /* if we're persisting a guid, there must be a filename */ 1994 if (persist && !filename) { 1995 return (1); 1996 } 1997 1998 /* guid is stored in lowercase ascii hex */ 1999 (void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf), 2000 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" 2001 "%02x%02x%02x%02x%02x%02x", 2002 guid->guid[0], guid->guid[1], guid->guid[2], guid->guid[3], 2003 guid->guid[4], guid->guid[5], guid->guid[6], guid->guid[7], 2004 guid->guid[8], guid->guid[9], guid->guid[10], guid->guid[11], 2005 guid->guid[12], guid->guid[13], guid->guid[14], guid->guid[15]); 2006 2007 2008 do { 2009 retryGetProviderData = B_FALSE; 2010 stmfRet = stmfGetProviderDataProt("sbd", &nvl, 2011 STMF_LU_PROVIDER_TYPE, &setToken); 2012 if (stmfRet != STMF_STATUS_SUCCESS) { 2013 if (persist && stmfRet == STMF_ERROR_NOT_FOUND) { 2014 ret = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0); 2015 if (ret != 0) { 2016 syslog(LOG_DEBUG, 2017 "unpersistGuid:nvlist_alloc(%d)", 2018 ret); 2019 ret = STMF_STATUS_ERROR; 2020 goto done; 2021 } 2022 newData = B_TRUE; 2023 } else { 2024 /* 2025 * if we're persisting the data, it's 2026 * an error. Otherwise, just return 2027 */ 2028 if (persist) { 2029 ret = stmfRet; 2030 } 2031 goto done; 2032 } 2033 } 2034 if (persist) { 2035 ret = nvlist_add_string(nvl, guidAsciiBuf, filename); 2036 } else { 2037 ret = nvlist_remove(nvl, guidAsciiBuf, 2038 DATA_TYPE_STRING); 2039 if (ret == ENOENT) { 2040 ret = 0; 2041 } 2042 } 2043 if (ret == 0) { 2044 if (newData) { 2045 stmfRet = stmfSetProviderDataProt("sbd", nvl, 2046 STMF_LU_PROVIDER_TYPE, NULL); 2047 } else { 2048 stmfRet = stmfSetProviderDataProt("sbd", nvl, 2049 STMF_LU_PROVIDER_TYPE, &setToken); 2050 } 2051 if (stmfRet != STMF_STATUS_SUCCESS) { 2052 if (stmfRet == STMF_ERROR_BUSY) { 2053 /* get/set failed, try again */ 2054 retryGetProviderData = B_TRUE; 2055 if (retryCnt++ > MAX_PROVIDER_RETRY) { 2056 ret = stmfRet; 2057 break; 2058 } 2059 continue; 2060 } else if (stmfRet == 2061 STMF_ERROR_PROV_DATA_STALE) { 2062 /* update failed, try again */ 2063 nvlist_free(nvl); 2064 nvl = NULL; 2065 retryGetProviderData = B_TRUE; 2066 if (retryCnt++ > MAX_PROVIDER_RETRY) { 2067 ret = stmfRet; 2068 break; 2069 } 2070 continue; 2071 } else { 2072 syslog(LOG_DEBUG, 2073 "unpersistGuid:error(%x)", stmfRet); 2074 ret = stmfRet; 2075 } 2076 break; 2077 } 2078 } else { 2079 syslog(LOG_DEBUG, 2080 "unpersistGuid:error nvlist_add/remove(%d)", 2081 ret); 2082 ret = STMF_STATUS_ERROR; 2083 } 2084 } while (retryGetProviderData); 2085 2086 done: 2087 nvlist_free(nvl); 2088 return (ret); 2089 } 2090 2091 2092 /* 2093 * stmfGetLuProp 2094 * 2095 * Purpose: Get current value for a resource property 2096 * 2097 * hdl - luResource from a previous call to stmfCreateLuResource 2098 * 2099 * resourceProp - a valid resource property type 2100 * 2101 * propVal - void pointer to a pointer of the value to be retrieved 2102 */ 2103 int 2104 stmfGetLuProp(luResource hdl, uint32_t prop, char *propVal, size_t *propLen) 2105 { 2106 int ret = STMF_STATUS_SUCCESS; 2107 luResourceImpl *luPropsHdl = hdl; 2108 if (hdl == NULL || propLen == NULL || propVal == NULL) { 2109 return (STMF_ERROR_INVALID_ARG); 2110 } 2111 2112 if (luPropsHdl->type == STMF_DISK) { 2113 ret = getDiskProp(luPropsHdl, prop, propVal, propLen); 2114 } else { 2115 return (STMF_ERROR_INVALID_ARG); 2116 } 2117 2118 return (ret); 2119 } 2120 2121 /* 2122 * stmfGetLuResource 2123 * 2124 * Purpose: Get a logical unit resource handle for a given logical unit. 2125 * 2126 * hdl - pointer to luResource 2127 */ 2128 int 2129 stmfGetLuResource(stmfGuid *luGuid, luResource *hdl) 2130 { 2131 int ret = STMF_STATUS_SUCCESS; 2132 stmfLogicalUnitProperties luProps; 2133 2134 2135 /* Check logical unit provider name to call correct dtype function */ 2136 if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps)) 2137 != STMF_STATUS_SUCCESS) { 2138 return (ret); 2139 } else { 2140 if (strcmp(luProps.providerName, "sbd") == 0) { 2141 ret = getDiskAllProps(luGuid, hdl); 2142 } else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) { 2143 return (STMF_ERROR_NOT_FOUND); 2144 } else { 2145 return (STMF_ERROR_INVALID_ARG); 2146 } 2147 } 2148 2149 return (ret); 2150 } 2151 2152 /* 2153 * getDiskAllProps 2154 * 2155 * Purpose: load all disk properties from sbd driver 2156 * 2157 * luGuid - guid of disk device for which properties are to be retrieved 2158 * hdl - allocated luResource into which properties are to be copied 2159 * 2160 */ 2161 static int 2162 getDiskAllProps(stmfGuid *luGuid, luResource *hdl) 2163 { 2164 int ret = STMF_STATUS_SUCCESS; 2165 int fd; 2166 sbd_lu_props_t *sbdProps; 2167 int ioctlRet; 2168 int savedErrno; 2169 int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS; 2170 stmf_iocdata_t sbdIoctl = {0}; 2171 2172 /* 2173 * Open control node for sbd 2174 */ 2175 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS) 2176 return (ret); 2177 2178 2179 *hdl = calloc(1, sizeof (luResourceImpl)); 2180 if (*hdl == NULL) { 2181 (void) close(fd); 2182 return (STMF_ERROR_NOMEM); 2183 } 2184 2185 sbdProps = calloc(1, sbdPropsSize); 2186 if (sbdProps == NULL) { 2187 free(*hdl); 2188 (void) close(fd); 2189 return (STMF_ERROR_NOMEM); 2190 } 2191 2192 ret = createDiskResource((luResourceImpl *)*hdl); 2193 if (ret != STMF_STATUS_SUCCESS) { 2194 free(*hdl); 2195 free(sbdProps); 2196 (void) close(fd); 2197 return (ret); 2198 } 2199 2200 sbdProps->slp_input_guid = 1; 2201 bcopy(luGuid, sbdProps->slp_guid, sizeof (sbdProps->slp_guid)); 2202 2203 sbdIoctl.stmf_version = STMF_VERSION_1; 2204 sbdIoctl.stmf_ibuf_size = sbdPropsSize; 2205 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdProps; 2206 sbdIoctl.stmf_obuf_size = sbdPropsSize; 2207 sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps; 2208 ioctlRet = ioctl(fd, SBD_IOCTL_GET_LU_PROPS, &sbdIoctl); 2209 if (ioctlRet != 0) { 2210 savedErrno = errno; 2211 switch (savedErrno) { 2212 case EBUSY: 2213 ret = STMF_ERROR_BUSY; 2214 break; 2215 case EPERM: 2216 case EACCES: 2217 ret = STMF_ERROR_PERM; 2218 break; 2219 case ENOENT: 2220 ret = STMF_ERROR_NOT_FOUND; 2221 break; 2222 default: 2223 syslog(LOG_DEBUG, 2224 "getDiskAllProps:ioctl error(%d) (%d) (%d)", 2225 ioctlRet, sbdIoctl.stmf_error, savedErrno); 2226 ret = STMF_STATUS_ERROR; 2227 break; 2228 } 2229 } 2230 2231 if (ret == STMF_STATUS_SUCCESS) { 2232 ret = loadDiskPropsFromDriver((luResourceImpl *)*hdl, sbdProps); 2233 } 2234 2235 free(sbdProps); 2236 (void) close(fd); 2237 return (ret); 2238 } 2239 2240 /* 2241 * loadDiskPropsFromDriver 2242 * 2243 * Purpose: Retrieve all disk type properties from sbd driver 2244 * 2245 * hdl - Allocated luResourceImpl 2246 * sbdProps - sbd_lu_props_t structure returned from sbd driver 2247 * 2248 */ 2249 static int 2250 loadDiskPropsFromDriver(luResourceImpl *hdl, sbd_lu_props_t *sbdProps) 2251 { 2252 int ret = STMF_STATUS_SUCCESS; 2253 diskResource *diskLu = hdl->resource; 2254 /* copy guid */ 2255 diskLu->luGuidValid = B_TRUE; 2256 bcopy(sbdProps->slp_guid, diskLu->luGuid, sizeof (sbdProps->slp_guid)); 2257 2258 if (sbdProps->slp_separate_meta && sbdProps->slp_meta_fname_valid) { 2259 diskLu->luMetaFileNameValid = B_TRUE; 2260 if (strlcpy(diskLu->luMetaFileName, 2261 (char *)&(sbdProps->slp_buf[sbdProps->slp_meta_fname_off]), 2262 sizeof (diskLu->luMetaFileName)) >= 2263 sizeof (diskLu->luMetaFileName)) { 2264 return (STMF_STATUS_ERROR); 2265 } 2266 } 2267 2268 if (sbdProps->slp_data_fname_valid) { 2269 diskLu->luDataFileNameValid = B_TRUE; 2270 if (strlcpy(diskLu->luDataFileName, 2271 (char *)&(sbdProps->slp_buf[sbdProps->slp_data_fname_off]), 2272 sizeof (diskLu->luDataFileName)) >= 2273 sizeof (diskLu->luDataFileName)) { 2274 return (STMF_STATUS_ERROR); 2275 } 2276 } 2277 2278 if (sbdProps->slp_serial_valid) { 2279 diskLu->serialNumValid = B_TRUE; 2280 bcopy(&(sbdProps->slp_buf[sbdProps->slp_serial_off]), 2281 diskLu->serialNum, sbdProps->slp_serial_size); 2282 } 2283 2284 if (sbdProps->slp_mgmt_url_valid) { 2285 diskLu->luMgmtUrlValid = B_TRUE; 2286 if (strlcpy(diskLu->luMgmtUrl, 2287 (char *)&(sbdProps->slp_buf[sbdProps->slp_mgmt_url_off]), 2288 sizeof (diskLu->luMgmtUrl)) >= 2289 sizeof (diskLu->luMgmtUrl)) { 2290 return (STMF_STATUS_ERROR); 2291 } 2292 } 2293 2294 if (sbdProps->slp_alias_valid) { 2295 diskLu->luAliasValid = B_TRUE; 2296 if (strlcpy(diskLu->luAlias, 2297 (char *)&(sbdProps->slp_buf[sbdProps->slp_alias_off]), 2298 sizeof (diskLu->luAlias)) >= 2299 sizeof (diskLu->luAlias)) { 2300 return (STMF_STATUS_ERROR); 2301 } 2302 } else { /* set alias to data filename if not set */ 2303 if (sbdProps->slp_data_fname_valid) { 2304 diskLu->luAliasValid = B_TRUE; 2305 if (strlcpy(diskLu->luAlias, 2306 (char *)&(sbdProps->slp_buf[ 2307 sbdProps->slp_data_fname_off]), 2308 sizeof (diskLu->luAlias)) >= 2309 sizeof (diskLu->luAlias)) { 2310 return (STMF_STATUS_ERROR); 2311 } 2312 } 2313 } 2314 2315 diskLu->vidValid = B_TRUE; 2316 bcopy(sbdProps->slp_vid, diskLu->vid, sizeof (diskLu->vid)); 2317 2318 diskLu->pidValid = B_TRUE; 2319 bcopy(sbdProps->slp_pid, diskLu->pid, sizeof (diskLu->pid)); 2320 2321 diskLu->revValid = B_TRUE; 2322 bcopy(sbdProps->slp_rev, diskLu->rev, sizeof (diskLu->rev)); 2323 2324 diskLu->writeProtectEnableValid = B_TRUE; 2325 if (sbdProps->slp_write_protected) { 2326 diskLu->writeProtectEnable = B_TRUE; 2327 } 2328 2329 diskLu->writebackCacheDisableValid = B_TRUE; 2330 if (sbdProps->slp_writeback_cache_disable_cur) { 2331 diskLu->writebackCacheDisable = B_TRUE; 2332 } 2333 2334 diskLu->blkSizeValid = B_TRUE; 2335 diskLu->blkSize = sbdProps->slp_blksize; 2336 2337 diskLu->luSizeValid = B_TRUE; 2338 diskLu->luSize = sbdProps->slp_lu_size; 2339 2340 diskLu->accessState = sbdProps->slp_access_state; 2341 2342 return (ret); 2343 } 2344 2345 2346 /* 2347 * stmfSetLuProp 2348 * 2349 * Purpose: set a property on an luResource 2350 * 2351 * hdl - allocated luResource 2352 * prop - property identifier 2353 * propVal - property value to be set 2354 */ 2355 int 2356 stmfSetLuProp(luResource hdl, uint32_t prop, const char *propVal) 2357 { 2358 int ret = STMF_STATUS_SUCCESS; 2359 luResourceImpl *luPropsHdl = hdl; 2360 if (hdl == NULL) { 2361 return (STMF_ERROR_INVALID_ARG); 2362 } 2363 2364 if (luPropsHdl->type == STMF_DISK) { 2365 ret = setDiskProp(luPropsHdl, prop, propVal); 2366 } else { 2367 return (STMF_ERROR_INVALID_ARG); 2368 } 2369 2370 return (ret); 2371 } 2372 2373 /* 2374 * getDiskProp 2375 * 2376 * Purpose: retrieve a given property from a logical unit resource of type disk 2377 * 2378 * hdl - allocated luResourceImpl 2379 * prop - property identifier 2380 * propVal - pointer to character to contain the retrieved property value 2381 * propLen - On input this is the length of propVal. On failure, it contains the 2382 * number of bytes required for propVal 2383 */ 2384 static int 2385 getDiskProp(luResourceImpl *hdl, uint32_t prop, char *propVal, size_t *propLen) 2386 { 2387 int ret = STMF_STATUS_SUCCESS; 2388 diskResource *diskLu = hdl->resource; 2389 char accessState[20]; 2390 size_t reqLen; 2391 2392 if (prop == STMF_LU_PROP_ACCESS_STATE) { 2393 if (diskLu->accessState == SBD_LU_ACTIVE) { 2394 (void) strlcpy(accessState, STMF_ACCESS_ACTIVE, 2395 sizeof (accessState)); 2396 } else if (diskLu->accessState == SBD_LU_TRANSITION_TO_ACTIVE) { 2397 (void) strlcpy(accessState, 2398 STMF_ACCESS_STANDBY_TO_ACTIVE, 2399 sizeof (accessState)); 2400 } else if (diskLu->accessState == SBD_LU_STANDBY) { 2401 (void) strlcpy(accessState, STMF_ACCESS_STANDBY, 2402 sizeof (accessState)); 2403 } else if (diskLu->accessState == 2404 SBD_LU_TRANSITION_TO_STANDBY) { 2405 (void) strlcpy(accessState, 2406 STMF_ACCESS_ACTIVE_TO_STANDBY, 2407 sizeof (accessState)); 2408 } 2409 if ((reqLen = strlcpy(propVal, accessState, 2410 *propLen)) >= *propLen) { 2411 *propLen = reqLen + 1; 2412 return (STMF_ERROR_INVALID_ARG); 2413 } 2414 return (0); 2415 } 2416 2417 if (diskLu->accessState != SBD_LU_ACTIVE) { 2418 return (STMF_ERROR_NO_PROP_STANDBY); 2419 } 2420 2421 switch (prop) { 2422 case STMF_LU_PROP_BLOCK_SIZE: 2423 if (diskLu->blkSizeValid == B_FALSE) { 2424 return (STMF_ERROR_NO_PROP); 2425 } 2426 reqLen = snprintf(propVal, *propLen, "%llu", 2427 (u_longlong_t)diskLu->blkSize); 2428 if (reqLen >= *propLen) { 2429 *propLen = reqLen + 1; 2430 return (STMF_ERROR_INVALID_ARG); 2431 } 2432 break; 2433 case STMF_LU_PROP_FILENAME: 2434 if (diskLu->luDataFileNameValid == B_FALSE) { 2435 return (STMF_ERROR_NO_PROP); 2436 } 2437 if ((reqLen = strlcpy(propVal, diskLu->luDataFileName, 2438 *propLen)) >= *propLen) { 2439 *propLen = reqLen + 1; 2440 return (STMF_ERROR_INVALID_ARG); 2441 } 2442 break; 2443 case STMF_LU_PROP_META_FILENAME: 2444 if (diskLu->luMetaFileNameValid == B_FALSE) { 2445 return (STMF_ERROR_NO_PROP); 2446 } 2447 if ((reqLen = strlcpy(propVal, diskLu->luMetaFileName, 2448 *propLen)) >= *propLen) { 2449 *propLen = reqLen + 1; 2450 return (STMF_ERROR_INVALID_ARG); 2451 } 2452 break; 2453 case STMF_LU_PROP_MGMT_URL: 2454 if (diskLu->luMgmtUrlValid == B_FALSE) { 2455 return (STMF_ERROR_NO_PROP); 2456 } 2457 if ((reqLen = strlcpy(propVal, diskLu->luMgmtUrl, 2458 *propLen)) >= *propLen) { 2459 *propLen = reqLen + 1; 2460 return (STMF_ERROR_INVALID_ARG); 2461 } 2462 break; 2463 case STMF_LU_PROP_GUID: 2464 if (diskLu->luGuidValid == B_FALSE) { 2465 return (STMF_ERROR_NO_PROP); 2466 } 2467 reqLen = snprintf(propVal, *propLen, 2468 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X" 2469 "%02X%02X%02X%02X", 2470 diskLu->luGuid[0], diskLu->luGuid[1], 2471 diskLu->luGuid[2], diskLu->luGuid[3], 2472 diskLu->luGuid[4], diskLu->luGuid[5], 2473 diskLu->luGuid[6], diskLu->luGuid[7], 2474 diskLu->luGuid[8], diskLu->luGuid[9], 2475 diskLu->luGuid[10], diskLu->luGuid[11], 2476 diskLu->luGuid[12], diskLu->luGuid[13], 2477 diskLu->luGuid[14], diskLu->luGuid[15]); 2478 if (reqLen >= *propLen) { 2479 *propLen = reqLen + 1; 2480 return (STMF_ERROR_INVALID_ARG); 2481 } 2482 break; 2483 case STMF_LU_PROP_SERIAL_NUM: 2484 if (diskLu->serialNumValid == B_FALSE) { 2485 return (STMF_ERROR_NO_PROP); 2486 } 2487 if ((reqLen = strlcpy(propVal, diskLu->serialNum, 2488 *propLen)) >= *propLen) { 2489 *propLen = reqLen + 1; 2490 return (STMF_ERROR_INVALID_ARG); 2491 } 2492 break; 2493 case STMF_LU_PROP_SIZE: 2494 if (diskLu->luSizeValid == B_FALSE) { 2495 return (STMF_ERROR_NO_PROP); 2496 } 2497 (void) snprintf(propVal, *propLen, "%llu", 2498 (u_longlong_t)diskLu->luSize); 2499 break; 2500 case STMF_LU_PROP_ALIAS: 2501 if (diskLu->luAliasValid == B_FALSE) { 2502 return (STMF_ERROR_NO_PROP); 2503 } 2504 if ((reqLen = strlcpy(propVal, diskLu->luAlias, 2505 *propLen)) >= *propLen) { 2506 *propLen = reqLen + 1; 2507 return (STMF_ERROR_INVALID_ARG); 2508 } 2509 break; 2510 case STMF_LU_PROP_VID: 2511 if (diskLu->vidValid == B_FALSE) { 2512 return (STMF_ERROR_NO_PROP); 2513 } 2514 if (*propLen <= sizeof (diskLu->vid)) { 2515 return (STMF_ERROR_INVALID_ARG); 2516 } 2517 bcopy(diskLu->vid, propVal, sizeof (diskLu->vid)); 2518 propVal[sizeof (diskLu->vid)] = 0; 2519 break; 2520 case STMF_LU_PROP_PID: 2521 if (diskLu->pidValid == B_FALSE) { 2522 return (STMF_ERROR_NO_PROP); 2523 } 2524 if (*propLen <= sizeof (diskLu->pid)) { 2525 return (STMF_ERROR_INVALID_ARG); 2526 } 2527 bcopy(diskLu->pid, propVal, sizeof (diskLu->pid)); 2528 propVal[sizeof (diskLu->pid)] = 0; 2529 break; 2530 case STMF_LU_PROP_WRITE_PROTECT: 2531 if (diskLu->writeProtectEnableValid == B_FALSE) { 2532 return (STMF_ERROR_NO_PROP); 2533 } 2534 if (diskLu->writeProtectEnable) { 2535 if ((reqLen = strlcpy(propVal, "true", 2536 *propLen)) >= *propLen) { 2537 *propLen = reqLen + 1; 2538 return (STMF_ERROR_INVALID_ARG); 2539 } 2540 } else { 2541 if ((reqLen = strlcpy(propVal, "false", 2542 *propLen)) >= *propLen) { 2543 *propLen = reqLen + 1; 2544 return (STMF_ERROR_INVALID_ARG); 2545 } 2546 } 2547 break; 2548 case STMF_LU_PROP_WRITE_CACHE_DISABLE: 2549 if (diskLu->writebackCacheDisableValid == B_FALSE) { 2550 return (STMF_ERROR_NO_PROP); 2551 } 2552 if (diskLu->writebackCacheDisable) { 2553 if ((reqLen = strlcpy(propVal, "true", 2554 *propLen)) >= *propLen) { 2555 *propLen = reqLen + 1; 2556 return (STMF_ERROR_INVALID_ARG); 2557 } 2558 } else { 2559 if ((reqLen = strlcpy(propVal, "false", 2560 *propLen)) >= *propLen) { 2561 *propLen = reqLen + 1; 2562 return (STMF_ERROR_INVALID_ARG); 2563 } 2564 } 2565 break; 2566 default: 2567 ret = STMF_ERROR_NO_PROP; 2568 break; 2569 } 2570 2571 return (ret); 2572 } 2573 2574 /* 2575 * setDiskProp 2576 * 2577 * Purpose: set properties for resource of type disk 2578 * 2579 * hdl - allocated luResourceImpl 2580 * resourceProp - valid resource identifier 2581 * propVal - valid resource value 2582 */ 2583 static int 2584 setDiskProp(luResourceImpl *hdl, uint32_t resourceProp, const char *propVal) 2585 { 2586 int ret = STMF_STATUS_SUCCESS; 2587 int i; 2588 diskResource *diskLu = hdl->resource; 2589 unsigned long long numericProp = 0; 2590 char guidProp[LU_ASCII_GUID_SIZE + 1]; 2591 char ouiProp[OUI_ASCII_SIZE + 1]; 2592 unsigned int oui[OUI_SIZE]; 2593 unsigned int guid[LU_GUID_SIZE]; 2594 int propSize; 2595 2596 2597 if (propVal == NULL) { 2598 return (STMF_ERROR_INVALID_ARG); 2599 } 2600 2601 switch (resourceProp) { 2602 case STMF_LU_PROP_ALIAS: 2603 if (strlcpy(diskLu->luAlias, propVal, 2604 sizeof (diskLu->luAlias)) >= 2605 sizeof (diskLu->luAlias)) { 2606 return (STMF_ERROR_INVALID_PROPSIZE); 2607 } 2608 diskLu->luAliasValid = B_TRUE; 2609 break; 2610 case STMF_LU_PROP_BLOCK_SIZE: 2611 (void) sscanf(propVal, "%llu", &numericProp); 2612 if (numericProp > UINT16_MAX) { 2613 return (STMF_ERROR_INVALID_PROPSIZE); 2614 } 2615 diskLu->blkSize = numericProp; 2616 diskLu->blkSizeValid = B_TRUE; 2617 break; 2618 case STMF_LU_PROP_COMPANY_ID: 2619 if ((strlcpy(ouiProp, propVal, sizeof (ouiProp))) >= 2620 sizeof (ouiProp)) { 2621 return (STMF_ERROR_INVALID_ARG); 2622 } 2623 if (checkHexUpper(ouiProp) != 0) { 2624 return (STMF_ERROR_INVALID_ARG); 2625 } 2626 (void) sscanf(ouiProp, "%2X%2X%2X", 2627 &oui[0], &oui[1], &oui[2]); 2628 2629 diskLu->companyId = 0; 2630 diskLu->companyId += oui[0] << 16; 2631 diskLu->companyId += oui[1] << 8; 2632 diskLu->companyId += oui[2]; 2633 diskLu->companyIdValid = B_TRUE; 2634 break; 2635 case STMF_LU_PROP_GUID: 2636 if (strlen(propVal) != LU_ASCII_GUID_SIZE) { 2637 return (STMF_ERROR_INVALID_PROPSIZE); 2638 } 2639 2640 if ((strlcpy(guidProp, propVal, sizeof (guidProp))) >= 2641 sizeof (guidProp)) { 2642 return (STMF_ERROR_INVALID_ARG); 2643 } 2644 2645 if (checkHexUpper(guidProp) != 0) { 2646 return (STMF_ERROR_INVALID_ARG); 2647 } 2648 2649 (void) sscanf(guidProp, 2650 "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X", 2651 &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], 2652 &guid[5], &guid[6], &guid[7], &guid[8], &guid[9], 2653 &guid[10], &guid[11], &guid[12], &guid[13], 2654 &guid[14], &guid[15]); 2655 for (i = 0; i < sizeof (diskLu->luGuid); i++) { 2656 diskLu->luGuid[i] = guid[i]; 2657 } 2658 diskLu->luGuidValid = B_TRUE; 2659 break; 2660 case STMF_LU_PROP_FILENAME: 2661 if ((strlcpy(diskLu->luDataFileName, propVal, 2662 sizeof (diskLu->luDataFileName))) >= 2663 sizeof (diskLu->luDataFileName)) { 2664 return (STMF_ERROR_INVALID_PROPSIZE); 2665 } 2666 diskLu->luDataFileNameValid = B_TRUE; 2667 break; 2668 case STMF_LU_PROP_META_FILENAME: 2669 if ((strlcpy(diskLu->luMetaFileName, propVal, 2670 sizeof (diskLu->luMetaFileName))) >= 2671 sizeof (diskLu->luMetaFileName)) { 2672 return (STMF_ERROR_INVALID_PROPSIZE); 2673 } 2674 diskLu->luMetaFileNameValid = B_TRUE; 2675 break; 2676 case STMF_LU_PROP_MGMT_URL: 2677 if ((strlcpy(diskLu->luMgmtUrl, propVal, 2678 sizeof (diskLu->luMgmtUrl))) >= 2679 sizeof (diskLu->luMgmtUrl)) { 2680 return (STMF_ERROR_INVALID_PROPSIZE); 2681 } 2682 diskLu->luMgmtUrlValid = B_TRUE; 2683 break; 2684 case STMF_LU_PROP_PID: 2685 if ((propSize = strlen(propVal)) > 2686 sizeof (diskLu->pid)) { 2687 return (STMF_ERROR_INVALID_PROPSIZE); 2688 } 2689 (void) strncpy(diskLu->pid, propVal, propSize); 2690 diskLu->pidValid = B_TRUE; 2691 break; 2692 case STMF_LU_PROP_SERIAL_NUM: 2693 if ((propSize = strlen(propVal)) > 2694 (sizeof (diskLu->serialNum) - 1)) { 2695 return (STMF_ERROR_INVALID_PROPSIZE); 2696 } 2697 (void) strncpy(diskLu->serialNum, propVal, propSize); 2698 diskLu->serialNumValid = B_TRUE; 2699 break; 2700 case STMF_LU_PROP_SIZE: 2701 if ((niceStrToNum(propVal, &diskLu->luSize) != 0)) { 2702 return (STMF_ERROR_INVALID_ARG); 2703 } 2704 diskLu->luSizeValid = B_TRUE; 2705 break; 2706 case STMF_LU_PROP_VID: 2707 if ((propSize = strlen(propVal)) > 2708 sizeof (diskLu->vid)) { 2709 return (STMF_ERROR_INVALID_PROPSIZE); 2710 } 2711 (void) strncpy(diskLu->vid, propVal, propSize); 2712 diskLu->vidValid = B_TRUE; 2713 break; 2714 case STMF_LU_PROP_WRITE_PROTECT: 2715 if (strcasecmp(propVal, "TRUE") == 0) { 2716 diskLu->writeProtectEnable = B_TRUE; 2717 } else if (strcasecmp(propVal, "FALSE") == 0) { 2718 diskLu->writeProtectEnable = B_FALSE; 2719 } else { 2720 return (STMF_ERROR_INVALID_ARG); 2721 } 2722 diskLu->writeProtectEnableValid = B_TRUE; 2723 break; 2724 case STMF_LU_PROP_WRITE_CACHE_DISABLE: 2725 if (strcasecmp(propVal, "TRUE") == 0) { 2726 diskLu->writebackCacheDisable = B_TRUE; 2727 } else if (strcasecmp(propVal, "FALSE") == 0) { 2728 diskLu->writebackCacheDisable = B_FALSE; 2729 } else { 2730 return (STMF_ERROR_INVALID_ARG); 2731 } 2732 diskLu->writebackCacheDisableValid = B_TRUE; 2733 break; 2734 case STMF_LU_PROP_ACCESS_STATE: 2735 ret = STMF_ERROR_INVALID_PROP; 2736 break; 2737 default: 2738 ret = STMF_ERROR_NO_PROP; 2739 break; 2740 } 2741 return (ret); 2742 } 2743 2744 static int 2745 checkHexUpper(char *buf) 2746 { 2747 int i; 2748 2749 for (i = 0; i < strlen(buf); i++) { 2750 if (isxdigit(buf[i])) { 2751 buf[i] = toupper(buf[i]); 2752 continue; 2753 } 2754 return (-1); 2755 } 2756 2757 return (0); 2758 } 2759 2760 /* 2761 * Given a numeric suffix, convert the value into a number of bits that the 2762 * resulting value must be shifted. 2763 * Code lifted from libzfs_util.c 2764 */ 2765 static int 2766 strToShift(const char *buf) 2767 { 2768 const char *ends = "BKMGTPE"; 2769 int i; 2770 2771 if (buf[0] == '\0') 2772 return (0); 2773 2774 for (i = 0; i < strlen(ends); i++) { 2775 if (toupper(buf[0]) == ends[i]) 2776 return (10*i); 2777 } 2778 2779 return (-1); 2780 } 2781 2782 int 2783 stmfFreeLuResource(luResource hdl) 2784 { 2785 int ret = STMF_STATUS_SUCCESS; 2786 if (hdl == NULL) { 2787 return (STMF_ERROR_INVALID_ARG); 2788 } 2789 2790 luResourceImpl *hdlImpl = hdl; 2791 free(hdlImpl->resource); 2792 free(hdlImpl); 2793 return (ret); 2794 } 2795 2796 /* 2797 * Convert a string of the form '100G' into a real number. Used when setting 2798 * the size of a logical unit. 2799 * Code lifted from libzfs_util.c 2800 */ 2801 static int 2802 niceStrToNum(const char *value, uint64_t *num) 2803 { 2804 char *end; 2805 int shift; 2806 2807 *num = 0; 2808 2809 /* Check to see if this looks like a number. */ 2810 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 2811 return (-1); 2812 } 2813 2814 /* Rely on stroull() to process the numeric portion. */ 2815 errno = 0; 2816 *num = strtoull(value, &end, 10); 2817 2818 /* 2819 * Check for ERANGE, which indicates that the value is too large to fit 2820 * in a 64-bit value. 2821 */ 2822 if (errno == ERANGE) { 2823 return (-1); 2824 } 2825 2826 /* 2827 * If we have a decimal value, then do the computation with floating 2828 * point arithmetic. Otherwise, use standard arithmetic. 2829 */ 2830 if (*end == '.') { 2831 double fval = strtod(value, &end); 2832 2833 if ((shift = strToShift(end)) == -1) { 2834 return (-1); 2835 } 2836 2837 fval *= pow(2, shift); 2838 2839 if (fval > UINT64_MAX) { 2840 return (-1); 2841 } 2842 2843 *num = (uint64_t)fval; 2844 } else { 2845 if ((shift = strToShift(end)) == -1) { 2846 return (-1); 2847 } 2848 2849 /* Check for overflow */ 2850 if (shift >= 64 || (*num << shift) >> shift != *num) { 2851 return (-1); 2852 } 2853 2854 *num <<= shift; 2855 } 2856 2857 return (0); 2858 } 2859 2860 /* 2861 * stmfCreateTargetGroup 2862 * 2863 * Purpose: Create a local port group 2864 * 2865 * targetGroupName - name of local port group to create 2866 */ 2867 int 2868 stmfCreateTargetGroup(stmfGroupName *targetGroupName) 2869 { 2870 int ret; 2871 int fd; 2872 2873 if (targetGroupName == NULL || 2874 (strnlen((char *)targetGroupName, sizeof (stmfGroupName)) 2875 == sizeof (stmfGroupName))) { 2876 return (STMF_ERROR_INVALID_ARG); 2877 } 2878 2879 /* Check to ensure service exists */ 2880 if (psCheckService() != STMF_STATUS_SUCCESS) { 2881 return (STMF_ERROR_SERVICE_NOT_FOUND); 2882 } 2883 2884 /* call init */ 2885 ret = initializeConfig(); 2886 if (ret != STMF_STATUS_SUCCESS) { 2887 return (ret); 2888 } 2889 2890 /* 2891 * Open control node for stmf 2892 */ 2893 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 2894 return (ret); 2895 2896 /* 2897 * Add the group to the driver 2898 */ 2899 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP, 2900 targetGroupName)) != STMF_STATUS_SUCCESS) { 2901 goto done; 2902 } 2903 2904 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 2905 goto done; 2906 } 2907 2908 /* 2909 * If the add to the driver was successful, add it to the persistent 2910 * store. 2911 */ 2912 ret = psCreateTargetGroup((char *)targetGroupName); 2913 switch (ret) { 2914 case STMF_PS_SUCCESS: 2915 ret = STMF_STATUS_SUCCESS; 2916 break; 2917 case STMF_PS_ERROR_EXISTS: 2918 ret = STMF_ERROR_EXISTS; 2919 break; 2920 case STMF_PS_ERROR_BUSY: 2921 ret = STMF_ERROR_BUSY; 2922 break; 2923 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 2924 ret = STMF_ERROR_SERVICE_NOT_FOUND; 2925 break; 2926 case STMF_PS_ERROR_VERSION_MISMATCH: 2927 ret = STMF_ERROR_SERVICE_DATA_VERSION; 2928 break; 2929 default: 2930 syslog(LOG_DEBUG, 2931 "stmfCreateTargetGroup:psCreateTargetGroup" 2932 ":error(%d)", ret); 2933 ret = STMF_STATUS_ERROR; 2934 break; 2935 } 2936 2937 done: 2938 (void) close(fd); 2939 return (ret); 2940 } 2941 2942 /* 2943 * stmfDeleteHostGroup 2944 * 2945 * Purpose: Delete an initiator or local port group 2946 * 2947 * hostGroupName - group to delete 2948 */ 2949 int 2950 stmfDeleteHostGroup(stmfGroupName *hostGroupName) 2951 { 2952 int ret; 2953 int fd; 2954 2955 if (hostGroupName == NULL) { 2956 return (STMF_ERROR_INVALID_ARG); 2957 } 2958 2959 /* Check to ensure service exists */ 2960 if (psCheckService() != STMF_STATUS_SUCCESS) { 2961 return (STMF_ERROR_SERVICE_NOT_FOUND); 2962 } 2963 2964 /* call init */ 2965 ret = initializeConfig(); 2966 if (ret != STMF_STATUS_SUCCESS) { 2967 return (ret); 2968 } 2969 2970 /* 2971 * Open control node for stmf 2972 */ 2973 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 2974 return (ret); 2975 2976 /* 2977 * Remove the group from the driver 2978 */ 2979 if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP, 2980 hostGroupName)) != STMF_STATUS_SUCCESS) { 2981 goto done; 2982 } 2983 2984 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 2985 goto done; 2986 } 2987 2988 /* 2989 * If the remove from the driver was successful, remove it from the 2990 * persistent store. 2991 */ 2992 ret = psDeleteHostGroup((char *)hostGroupName); 2993 switch (ret) { 2994 case STMF_PS_SUCCESS: 2995 ret = STMF_STATUS_SUCCESS; 2996 break; 2997 case STMF_PS_ERROR_NOT_FOUND: 2998 ret = STMF_ERROR_NOT_FOUND; 2999 break; 3000 case STMF_PS_ERROR_BUSY: 3001 ret = STMF_ERROR_BUSY; 3002 break; 3003 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3004 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3005 break; 3006 case STMF_PS_ERROR_VERSION_MISMATCH: 3007 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3008 break; 3009 default: 3010 syslog(LOG_DEBUG, 3011 "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)", 3012 ret); 3013 ret = STMF_STATUS_ERROR; 3014 break; 3015 } 3016 3017 done: 3018 (void) close(fd); 3019 return (ret); 3020 } 3021 3022 /* 3023 * stmfDeleteTargetGroup 3024 * 3025 * Purpose: Delete an initiator or local port group 3026 * 3027 * targetGroupName - group to delete 3028 */ 3029 int 3030 stmfDeleteTargetGroup(stmfGroupName *targetGroupName) 3031 { 3032 int ret = STMF_STATUS_SUCCESS; 3033 int fd; 3034 3035 if (targetGroupName == NULL) { 3036 return (STMF_ERROR_INVALID_ARG); 3037 } 3038 3039 /* Check to ensure service exists */ 3040 if (psCheckService() != STMF_STATUS_SUCCESS) { 3041 return (STMF_ERROR_SERVICE_NOT_FOUND); 3042 } 3043 3044 /* call init */ 3045 ret = initializeConfig(); 3046 if (ret != STMF_STATUS_SUCCESS) { 3047 return (ret); 3048 } 3049 3050 /* 3051 * Open control node for stmf 3052 */ 3053 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3054 return (ret); 3055 3056 /* 3057 * Remove the group from the driver 3058 */ 3059 if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP, 3060 targetGroupName)) != STMF_STATUS_SUCCESS) { 3061 goto done; 3062 } 3063 3064 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 3065 goto done; 3066 } 3067 3068 /* 3069 * If the remove from the driver was successful, remove it from the 3070 * persistent store. 3071 */ 3072 ret = psDeleteTargetGroup((char *)targetGroupName); 3073 switch (ret) { 3074 case STMF_PS_SUCCESS: 3075 ret = STMF_STATUS_SUCCESS; 3076 break; 3077 case STMF_PS_ERROR_NOT_FOUND: 3078 ret = STMF_ERROR_NOT_FOUND; 3079 break; 3080 case STMF_PS_ERROR_BUSY: 3081 ret = STMF_ERROR_BUSY; 3082 break; 3083 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3084 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3085 break; 3086 case STMF_PS_ERROR_VERSION_MISMATCH: 3087 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3088 break; 3089 default: 3090 syslog(LOG_DEBUG, 3091 "stmfDeleteTargetGroup:psDeleteTargetGroup" 3092 ":error(%d)", ret); 3093 ret = STMF_STATUS_ERROR; 3094 break; 3095 } 3096 3097 done: 3098 (void) close(fd); 3099 return (ret); 3100 } 3101 3102 /* 3103 * stmfDevidFromIscsiName 3104 * 3105 * Purpose: convert an iSCSI name to an stmf devid 3106 * 3107 * iscsiName - unicode nul terminated utf-8 encoded iSCSI name 3108 * devid - on success, contains the converted iscsi name 3109 */ 3110 int 3111 stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid) 3112 { 3113 if (devid == NULL || iscsiName == NULL) 3114 return (STMF_ERROR_INVALID_ARG); 3115 3116 bzero(devid, sizeof (stmfDevid)); 3117 3118 /* Validate size of target */ 3119 if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME || 3120 devid->identLength < strlen(EUI) || 3121 devid->identLength < strlen(IQN)) { 3122 return (STMF_ERROR_INVALID_ARG); 3123 } 3124 3125 if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) && 3126 strncmp(iscsiName, IQN, strlen(IQN)) != 0) { 3127 return (STMF_ERROR_INVALID_ARG); 3128 } 3129 3130 /* copy UTF-8 bytes to ident */ 3131 bcopy(iscsiName, devid->ident, devid->identLength); 3132 3133 return (STMF_STATUS_SUCCESS); 3134 } 3135 3136 /* 3137 * stmfDevidFromWwn 3138 * 3139 * Purpose: convert a WWN to an stmf devid 3140 * 3141 * wwn - 8-byte wwn identifier 3142 * devid - on success, contains the converted wwn 3143 */ 3144 int 3145 stmfDevidFromWwn(uchar_t *wwn, stmfDevid *devid) 3146 { 3147 if (wwn == NULL || devid == NULL) 3148 return (STMF_ERROR_INVALID_ARG); 3149 3150 bzero(devid, sizeof (stmfDevid)); 3151 3152 /* Copy eui prefix */ 3153 (void) bcopy(WWN, devid->ident, strlen(WWN)); 3154 3155 /* Convert to ASCII uppercase hexadecimal string */ 3156 (void) snprintf((char *)&devid->ident[strlen(WWN)], 3157 sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X", 3158 wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 3159 3160 devid->identLength = strlen((char *)devid->ident); 3161 3162 return (STMF_STATUS_SUCCESS); 3163 } 3164 3165 /* 3166 * stmfFreeMemory 3167 * 3168 * Purpose: Free memory allocated by this library 3169 * 3170 * memory - previously allocated pointer of memory managed by library 3171 */ 3172 void 3173 stmfFreeMemory(void *memory) 3174 { 3175 free(memory); 3176 } 3177 3178 /* 3179 * get host group, target group list from stmf 3180 * 3181 * groupType - HOST_GROUP, TARGET_GROUP 3182 */ 3183 static int 3184 groupListIoctl(stmfGroupList **groupList, int groupType) 3185 { 3186 int ret; 3187 int fd; 3188 int ioctlRet; 3189 int i; 3190 int cmd; 3191 stmf_iocdata_t stmfIoctl; 3192 /* framework group list */ 3193 stmf_group_name_t *iGroupList = NULL; 3194 uint32_t groupListSize; 3195 3196 if (groupList == NULL) { 3197 return (STMF_ERROR_INVALID_ARG); 3198 } 3199 3200 if (groupType == HOST_GROUP) { 3201 cmd = STMF_IOCTL_GET_HG_LIST; 3202 } else if (groupType == TARGET_GROUP) { 3203 cmd = STMF_IOCTL_GET_TG_LIST; 3204 } else { 3205 return (STMF_ERROR_INVALID_ARG); 3206 } 3207 3208 /* call init */ 3209 ret = initializeConfig(); 3210 if (ret != STMF_STATUS_SUCCESS) { 3211 return (ret); 3212 } 3213 3214 /* 3215 * Open control node for stmf 3216 */ 3217 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3218 return (ret); 3219 3220 /* 3221 * Allocate ioctl input buffer 3222 */ 3223 groupListSize = ALLOC_GROUP; 3224 groupListSize = groupListSize * (sizeof (stmf_group_name_t)); 3225 iGroupList = (stmf_group_name_t *)calloc(1, groupListSize); 3226 if (iGroupList == NULL) { 3227 ret = STMF_ERROR_NOMEM; 3228 goto done; 3229 } 3230 3231 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3232 /* 3233 * Issue ioctl to get the group list 3234 */ 3235 stmfIoctl.stmf_version = STMF_VERSION_1; 3236 stmfIoctl.stmf_obuf_size = groupListSize; 3237 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList; 3238 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3239 if (ioctlRet != 0) { 3240 switch (errno) { 3241 case EBUSY: 3242 ret = STMF_ERROR_BUSY; 3243 break; 3244 case EPERM: 3245 case EACCES: 3246 ret = STMF_ERROR_PERM; 3247 break; 3248 default: 3249 syslog(LOG_DEBUG, 3250 "groupListIoctl:ioctl errno(%d)", 3251 errno); 3252 ret = STMF_STATUS_ERROR; 3253 break; 3254 } 3255 goto done; 3256 } 3257 /* 3258 * Check whether input buffer was large enough 3259 */ 3260 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GROUP) { 3261 groupListSize = stmfIoctl.stmf_obuf_max_nentries * 3262 sizeof (stmf_group_name_t); 3263 iGroupList = realloc(iGroupList, groupListSize); 3264 if (iGroupList == NULL) { 3265 ret = STMF_ERROR_NOMEM; 3266 goto done; 3267 } 3268 stmfIoctl.stmf_obuf_size = groupListSize; 3269 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList; 3270 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3271 if (ioctlRet != 0) { 3272 switch (errno) { 3273 case EBUSY: 3274 ret = STMF_ERROR_BUSY; 3275 break; 3276 case EPERM: 3277 case EACCES: 3278 ret = STMF_ERROR_PERM; 3279 break; 3280 default: 3281 syslog(LOG_DEBUG, 3282 "groupListIoctl:ioctl errno(%d)", 3283 errno); 3284 ret = STMF_STATUS_ERROR; 3285 break; 3286 } 3287 goto done; 3288 } 3289 } 3290 3291 /* allocate and copy to caller's buffer */ 3292 *groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) + 3293 sizeof (stmfGroupName) * stmfIoctl.stmf_obuf_nentries); 3294 if (*groupList == NULL) { 3295 ret = STMF_ERROR_NOMEM; 3296 goto done; 3297 } 3298 (*groupList)->cnt = stmfIoctl.stmf_obuf_nentries; 3299 for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) { 3300 bcopy(iGroupList[i].name, (*groupList)->name[i], 3301 sizeof (stmfGroupName)); 3302 } 3303 3304 done: 3305 free(iGroupList); 3306 (void) close(fd); 3307 return (ret); 3308 } 3309 3310 /* 3311 * get host group members, target group members from stmf 3312 * 3313 * groupProps - allocated on success 3314 * 3315 * groupType - HOST_GROUP, TARGET_GROUP 3316 */ 3317 static int 3318 groupMemberListIoctl(stmfGroupName *groupName, stmfGroupProperties **groupProps, 3319 int groupType) 3320 { 3321 int ret; 3322 int fd; 3323 int ioctlRet; 3324 int i; 3325 int cmd; 3326 stmf_iocdata_t stmfIoctl; 3327 /* framework group list */ 3328 stmf_group_name_t iGroupName; 3329 stmf_ge_ident_t *iGroupMembers; 3330 uint32_t groupListSize; 3331 3332 if (groupName == NULL) { 3333 return (STMF_ERROR_INVALID_ARG); 3334 } 3335 3336 if (groupType == HOST_GROUP) { 3337 cmd = STMF_IOCTL_GET_HG_ENTRIES; 3338 } else if (groupType == TARGET_GROUP) { 3339 cmd = STMF_IOCTL_GET_TG_ENTRIES; 3340 } else { 3341 return (STMF_ERROR_INVALID_ARG); 3342 } 3343 3344 /* call init */ 3345 ret = initializeConfig(); 3346 if (ret != STMF_STATUS_SUCCESS) { 3347 return (ret); 3348 } 3349 3350 /* 3351 * Open control node for stmf 3352 */ 3353 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3354 return (ret); 3355 3356 bzero(&iGroupName, sizeof (iGroupName)); 3357 3358 bcopy(groupName, &iGroupName.name, strlen((char *)groupName)); 3359 3360 iGroupName.name_size = strlen((char *)groupName); 3361 3362 /* 3363 * Allocate ioctl input buffer 3364 */ 3365 groupListSize = ALLOC_GRP_MEMBER; 3366 groupListSize = groupListSize * (sizeof (stmf_ge_ident_t)); 3367 iGroupMembers = (stmf_ge_ident_t *)calloc(1, groupListSize); 3368 if (iGroupMembers == NULL) { 3369 ret = STMF_ERROR_NOMEM; 3370 goto done; 3371 } 3372 3373 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3374 /* 3375 * Issue ioctl to get the group list 3376 */ 3377 stmfIoctl.stmf_version = STMF_VERSION_1; 3378 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName; 3379 stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t); 3380 stmfIoctl.stmf_obuf_size = groupListSize; 3381 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers; 3382 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3383 if (ioctlRet != 0) { 3384 switch (errno) { 3385 case EBUSY: 3386 ret = STMF_ERROR_BUSY; 3387 break; 3388 case EPERM: 3389 case EACCES: 3390 ret = STMF_ERROR_PERM; 3391 break; 3392 default: 3393 syslog(LOG_DEBUG, 3394 "groupListIoctl:ioctl errno(%d)", 3395 errno); 3396 ret = STMF_STATUS_ERROR; 3397 break; 3398 } 3399 goto done; 3400 } 3401 /* 3402 * Check whether input buffer was large enough 3403 */ 3404 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GRP_MEMBER) { 3405 groupListSize = stmfIoctl.stmf_obuf_max_nentries * 3406 sizeof (stmf_ge_ident_t); 3407 iGroupMembers = realloc(iGroupMembers, groupListSize); 3408 if (iGroupMembers == NULL) { 3409 ret = STMF_ERROR_NOMEM; 3410 goto done; 3411 } 3412 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName; 3413 stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t); 3414 stmfIoctl.stmf_obuf_size = groupListSize; 3415 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers; 3416 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3417 if (ioctlRet != 0) { 3418 switch (errno) { 3419 case EBUSY: 3420 ret = STMF_ERROR_BUSY; 3421 break; 3422 case EPERM: 3423 case EACCES: 3424 ret = STMF_ERROR_PERM; 3425 break; 3426 default: 3427 syslog(LOG_DEBUG, 3428 "groupListIoctl:ioctl errno(%d)", 3429 errno); 3430 ret = STMF_STATUS_ERROR; 3431 break; 3432 } 3433 goto done; 3434 } 3435 } 3436 3437 /* allocate and copy to caller's buffer */ 3438 *groupProps = (stmfGroupProperties *)calloc(1, 3439 sizeof (stmfGroupProperties) + 3440 sizeof (stmfDevid) * stmfIoctl.stmf_obuf_nentries); 3441 if (*groupProps == NULL) { 3442 ret = STMF_ERROR_NOMEM; 3443 goto done; 3444 } 3445 (*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries; 3446 for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) { 3447 (*groupProps)->name[i].identLength = 3448 iGroupMembers[i].ident_size; 3449 bcopy(iGroupMembers[i].ident, (*groupProps)->name[i].ident, 3450 iGroupMembers[i].ident_size); 3451 } 3452 3453 done: 3454 free(iGroupMembers); 3455 (void) close(fd); 3456 return (ret); 3457 } 3458 3459 /* 3460 * Purpose: access persistent config data for host groups and target groups 3461 */ 3462 static int 3463 iLoadGroupFromPs(stmfGroupList **groupList, int type) 3464 { 3465 int ret; 3466 3467 if (groupList == NULL) { 3468 return (STMF_ERROR_INVALID_ARG); 3469 } 3470 3471 if (type == HOST_GROUP) { 3472 ret = psGetHostGroupList(groupList); 3473 } else if (type == TARGET_GROUP) { 3474 ret = psGetTargetGroupList(groupList); 3475 } else { 3476 return (STMF_ERROR_INVALID_ARG); 3477 } 3478 switch (ret) { 3479 case STMF_PS_SUCCESS: 3480 ret = STMF_STATUS_SUCCESS; 3481 break; 3482 case STMF_PS_ERROR_NOT_FOUND: 3483 ret = STMF_ERROR_NOT_FOUND; 3484 break; 3485 case STMF_PS_ERROR_BUSY: 3486 ret = STMF_ERROR_BUSY; 3487 break; 3488 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3489 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3490 break; 3491 case STMF_PS_ERROR_VERSION_MISMATCH: 3492 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3493 break; 3494 default: 3495 syslog(LOG_DEBUG, 3496 "stmfGetHostGroupList:psGetHostGroupList:error(%d)", 3497 ret); 3498 ret = STMF_STATUS_ERROR; 3499 break; 3500 } 3501 3502 return (ret); 3503 } 3504 3505 /* 3506 * stmfGetHostGroupList 3507 * 3508 * Purpose: Retrieves the list of initiator group oids 3509 * 3510 * hostGroupList - pointer to pointer to hostGroupList structure 3511 * on success, this contains the host group list. 3512 */ 3513 int 3514 stmfGetHostGroupList(stmfGroupList **hostGroupList) 3515 { 3516 int ret = STMF_STATUS_ERROR; 3517 3518 if (hostGroupList == NULL) { 3519 return (STMF_ERROR_INVALID_ARG); 3520 } 3521 3522 ret = groupListIoctl(hostGroupList, HOST_GROUP); 3523 return (ret); 3524 } 3525 3526 3527 /* 3528 * Purpose: access persistent config data for host groups and target groups 3529 */ 3530 static int 3531 iLoadGroupMembersFromPs(stmfGroupName *groupName, 3532 stmfGroupProperties **groupProp, int type) 3533 { 3534 int ret; 3535 3536 if (groupName == NULL) { 3537 return (STMF_ERROR_INVALID_ARG); 3538 } 3539 3540 if (type == HOST_GROUP) { 3541 ret = psGetHostGroupMemberList((char *)groupName, groupProp); 3542 } else if (type == TARGET_GROUP) { 3543 ret = psGetTargetGroupMemberList((char *)groupName, groupProp); 3544 } else { 3545 return (STMF_ERROR_INVALID_ARG); 3546 } 3547 switch (ret) { 3548 case STMF_PS_SUCCESS: 3549 ret = STMF_STATUS_SUCCESS; 3550 break; 3551 case STMF_PS_ERROR_NOT_FOUND: 3552 ret = STMF_ERROR_NOT_FOUND; 3553 break; 3554 case STMF_PS_ERROR_BUSY: 3555 ret = STMF_ERROR_BUSY; 3556 break; 3557 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3558 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3559 break; 3560 case STMF_PS_ERROR_VERSION_MISMATCH: 3561 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3562 break; 3563 default: 3564 syslog(LOG_DEBUG, 3565 "iLoadGroupMembersFromPs:psGetHostGroupList:" 3566 "error(%d)", ret); 3567 ret = STMF_STATUS_ERROR; 3568 break; 3569 } 3570 3571 return (ret); 3572 } 3573 3574 /* 3575 * stmfGetHostGroupMembers 3576 * 3577 * Purpose: Retrieves the group properties for a host group 3578 * 3579 * groupName - name of group for which to retrieve host group members. 3580 * groupProp - pointer to pointer to stmfGroupProperties structure 3581 * on success, this contains the list of group members. 3582 */ 3583 int 3584 stmfGetHostGroupMembers(stmfGroupName *groupName, 3585 stmfGroupProperties **groupProp) 3586 { 3587 int ret; 3588 3589 if (groupName == NULL || groupProp == NULL) { 3590 return (STMF_ERROR_INVALID_ARG); 3591 } 3592 3593 ret = groupMemberListIoctl(groupName, groupProp, HOST_GROUP); 3594 3595 return (ret); 3596 } 3597 3598 /* 3599 * stmfGetProviderData 3600 * 3601 * Purpose: Get provider data list 3602 * 3603 * providerName - name of provider for which to retrieve the data 3604 * nvl - pointer to nvlist_t pointer which will contain the nvlist data 3605 * retrieved. 3606 * providerType - type of provider for which to retrieve data. 3607 * STMF_LU_PROVIDER_TYPE 3608 * STMF_PORT_PROVIDER_TYPE 3609 */ 3610 int 3611 stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType) 3612 { 3613 return (stmfGetProviderDataProt(providerName, nvl, providerType, 3614 NULL)); 3615 } 3616 3617 /* 3618 * stmfGetProviderDataProt 3619 * 3620 * Purpose: Get provider data list with token 3621 * 3622 * providerName - name of provider for which to retrieve the data 3623 * nvl - pointer to nvlist_t pointer which will contain the nvlist data 3624 * retrieved. 3625 * providerType - type of provider for which to retrieve data. 3626 * STMF_LU_PROVIDER_TYPE 3627 * STMF_PORT_PROVIDER_TYPE 3628 * setToken - Returns the stale data token 3629 */ 3630 int 3631 stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType, 3632 uint64_t *setToken) 3633 { 3634 int ret; 3635 3636 if (providerName == NULL || nvl == NULL) { 3637 return (STMF_ERROR_INVALID_ARG); 3638 } 3639 if (providerType != STMF_LU_PROVIDER_TYPE && 3640 providerType != STMF_PORT_PROVIDER_TYPE) { 3641 return (STMF_ERROR_INVALID_ARG); 3642 } 3643 /* call init */ 3644 ret = initializeConfig(); 3645 if (ret != STMF_STATUS_SUCCESS) { 3646 return (ret); 3647 } 3648 return (getProviderData(providerName, nvl, providerType, setToken)); 3649 } 3650 3651 /* 3652 * stmfGetProviderDataList 3653 * 3654 * Purpose: Get the list of providers currently persisting data 3655 * 3656 * providerList - pointer to pointer to an stmfProviderList structure allocated 3657 * by the caller. Will contain the list of providers on success. 3658 */ 3659 int 3660 stmfGetProviderDataList(stmfProviderList **providerList) 3661 { 3662 int ret; 3663 3664 ret = psGetProviderDataList(providerList); 3665 switch (ret) { 3666 case STMF_PS_SUCCESS: 3667 ret = STMF_STATUS_SUCCESS; 3668 break; 3669 case STMF_PS_ERROR_BUSY: 3670 ret = STMF_ERROR_BUSY; 3671 break; 3672 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3673 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3674 break; 3675 case STMF_PS_ERROR_VERSION_MISMATCH: 3676 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3677 break; 3678 default: 3679 syslog(LOG_DEBUG, 3680 "stmfGetProviderDataList:psGetProviderDataList" 3681 ":error(%d)", ret); 3682 ret = STMF_STATUS_ERROR; 3683 break; 3684 } 3685 3686 return (ret); 3687 } 3688 3689 3690 /* 3691 * stmfGetSessionList 3692 * 3693 * Purpose: Retrieves the session list for a target (devid) 3694 * 3695 * devid - devid of target for which to retrieve session information. 3696 * sessionList - pointer to pointer to stmfSessionList structure 3697 * on success, this contains the list of initiator sessions. 3698 */ 3699 int 3700 stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList) 3701 { 3702 int ret = STMF_STATUS_SUCCESS; 3703 int fd; 3704 int ioctlRet; 3705 int cmd = STMF_IOCTL_SESSION_LIST; 3706 int i; 3707 stmf_iocdata_t stmfIoctl; 3708 slist_scsi_session_t *fSessionList, *fSessionListP = NULL; 3709 uint8_t ident[260]; 3710 uint32_t fSessionListSize; 3711 3712 if (sessionList == NULL || devid == NULL) { 3713 ret = STMF_ERROR_INVALID_ARG; 3714 } 3715 3716 /* call init */ 3717 ret = initializeConfig(); 3718 if (ret != STMF_STATUS_SUCCESS) { 3719 return (ret); 3720 } 3721 3722 /* 3723 * Open control node for stmf 3724 */ 3725 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3726 return (ret); 3727 3728 /* 3729 * Allocate ioctl input buffer 3730 */ 3731 fSessionListSize = ALLOC_SESSION; 3732 fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t)); 3733 fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize); 3734 fSessionListP = fSessionList; 3735 if (fSessionList == NULL) { 3736 ret = STMF_ERROR_NOMEM; 3737 goto done; 3738 } 3739 3740 ident[IDENT_LENGTH_BYTE] = devid->identLength; 3741 bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1], 3742 devid->identLength); 3743 3744 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3745 /* 3746 * Issue ioctl to get the session list 3747 */ 3748 stmfIoctl.stmf_version = STMF_VERSION_1; 3749 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident; 3750 stmfIoctl.stmf_ibuf_size = sizeof (ident); 3751 stmfIoctl.stmf_obuf_size = fSessionListSize; 3752 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList; 3753 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3754 if (ioctlRet != 0) { 3755 switch (errno) { 3756 case EBUSY: 3757 ret = STMF_ERROR_BUSY; 3758 break; 3759 case EPERM: 3760 case EACCES: 3761 ret = STMF_ERROR_PERM; 3762 break; 3763 default: 3764 syslog(LOG_DEBUG, 3765 "stmfGetSessionList:ioctl errno(%d)", 3766 errno); 3767 ret = STMF_STATUS_ERROR; 3768 break; 3769 } 3770 goto done; 3771 } 3772 /* 3773 * Check whether input buffer was large enough 3774 */ 3775 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_SESSION) { 3776 fSessionListSize = stmfIoctl.stmf_obuf_max_nentries * 3777 sizeof (slist_scsi_session_t); 3778 fSessionList = realloc(fSessionList, fSessionListSize); 3779 if (fSessionList == NULL) { 3780 ret = STMF_ERROR_NOMEM; 3781 goto done; 3782 } 3783 fSessionListP = fSessionList; 3784 stmfIoctl.stmf_obuf_size = fSessionListSize; 3785 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList; 3786 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3787 if (ioctlRet != 0) { 3788 switch (errno) { 3789 case EBUSY: 3790 ret = STMF_ERROR_BUSY; 3791 break; 3792 case EPERM: 3793 case EACCES: 3794 ret = STMF_ERROR_PERM; 3795 break; 3796 default: 3797 syslog(LOG_DEBUG, 3798 "stmfGetSessionList:ioctl " 3799 "errno(%d)", errno); 3800 ret = STMF_STATUS_ERROR; 3801 break; 3802 } 3803 goto done; 3804 } 3805 } 3806 3807 /* 3808 * allocate caller's buffer with the final size 3809 */ 3810 *sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) + 3811 stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession)); 3812 if (*sessionList == NULL) { 3813 ret = STMF_ERROR_NOMEM; 3814 free(sessionList); 3815 goto done; 3816 } 3817 3818 (*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries; 3819 3820 /* 3821 * copy session info to caller's buffer 3822 */ 3823 for (i = 0; i < (*sessionList)->cnt; i++) { 3824 (*sessionList)->session[i].initiator.identLength = 3825 fSessionList->initiator[IDENT_LENGTH_BYTE]; 3826 bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]), 3827 (*sessionList)->session[i].initiator.ident, 3828 STMF_IDENT_LENGTH); 3829 bcopy(&(fSessionList->alias), 3830 &((*sessionList)->session[i].alias), 3831 sizeof ((*sessionList)->session[i].alias)); 3832 bcopy(&(fSessionList++->creation_time), 3833 &((*sessionList)->session[i].creationTime), 3834 sizeof (time_t)); 3835 } 3836 done: 3837 (void) close(fd); 3838 free(fSessionListP); 3839 return (ret); 3840 } 3841 3842 /* 3843 * stmfGetTargetGroupList 3844 * 3845 * Purpose: Retrieves the list of target groups 3846 * 3847 * targetGroupList - pointer to a pointer to an stmfGroupList structure. On 3848 * success, it contains the list of target groups. 3849 */ 3850 int 3851 stmfGetTargetGroupList(stmfGroupList **targetGroupList) 3852 { 3853 int ret; 3854 3855 if (targetGroupList == NULL) { 3856 return (STMF_ERROR_INVALID_ARG); 3857 } 3858 3859 ret = groupListIoctl(targetGroupList, TARGET_GROUP); 3860 return (ret); 3861 } 3862 3863 /* 3864 * stmfGetTargetGroupMembers 3865 * 3866 * Purpose: Retrieves the group members for a target group 3867 * 3868 * groupName - name of target group for which to retrieve members. 3869 * groupProp - pointer to pointer to stmfGroupProperties structure 3870 * on success, this contains the list of group members. 3871 */ 3872 int 3873 stmfGetTargetGroupMembers(stmfGroupName *groupName, 3874 stmfGroupProperties **groupProp) 3875 { 3876 int ret; 3877 3878 if (groupName == NULL || groupProp == NULL) { 3879 return (STMF_ERROR_INVALID_ARG); 3880 } 3881 3882 ret = groupMemberListIoctl(groupName, groupProp, TARGET_GROUP); 3883 3884 return (ret); 3885 } 3886 3887 /* 3888 * stmfGetTargetList 3889 * 3890 * Purpose: Retrieves the list of target ports 3891 * 3892 * targetList - pointer to a pointer to an stmfDevidList structure. 3893 * On success, it contains the list of local ports (target). 3894 */ 3895 int 3896 stmfGetTargetList(stmfDevidList **targetList) 3897 { 3898 int ret; 3899 int fd; 3900 int ioctlRet; 3901 int i; 3902 stmf_iocdata_t stmfIoctl; 3903 /* framework target port list */ 3904 slist_target_port_t *fTargetList, *fTargetListP = NULL; 3905 uint32_t fTargetListSize; 3906 3907 if (targetList == NULL) { 3908 return (STMF_ERROR_INVALID_ARG); 3909 } 3910 3911 /* call init */ 3912 ret = initializeConfig(); 3913 if (ret != STMF_STATUS_SUCCESS) { 3914 return (ret); 3915 } 3916 3917 /* 3918 * Open control node for stmf 3919 */ 3920 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3921 return (ret); 3922 3923 /* 3924 * Allocate ioctl input buffer 3925 */ 3926 fTargetListSize = ALLOC_TARGET_PORT * sizeof (slist_target_port_t); 3927 fTargetListP = fTargetList = 3928 (slist_target_port_t *)calloc(1, fTargetListSize); 3929 if (fTargetList == NULL) { 3930 ret = STMF_ERROR_NOMEM; 3931 goto done; 3932 } 3933 3934 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3935 /* 3936 * Issue ioctl to retrieve target list 3937 */ 3938 stmfIoctl.stmf_version = STMF_VERSION_1; 3939 stmfIoctl.stmf_obuf_size = fTargetListSize; 3940 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList; 3941 ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl); 3942 if (ioctlRet != 0) { 3943 switch (errno) { 3944 case EBUSY: 3945 ret = STMF_ERROR_BUSY; 3946 break; 3947 case EPERM: 3948 case EACCES: 3949 ret = STMF_ERROR_PERM; 3950 break; 3951 default: 3952 syslog(LOG_DEBUG, 3953 "stmfGetTargetList:ioctl errno(%d)", errno); 3954 ret = STMF_STATUS_ERROR; 3955 break; 3956 } 3957 goto done; 3958 } 3959 /* 3960 * Check whether input buffer was large enough 3961 */ 3962 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_TARGET_PORT) { 3963 fTargetListSize = stmfIoctl.stmf_obuf_max_nentries * 3964 sizeof (slist_target_port_t); 3965 fTargetListP = fTargetList = 3966 realloc(fTargetList, fTargetListSize); 3967 if (fTargetList == NULL) { 3968 ret = STMF_ERROR_NOMEM; 3969 goto done; 3970 } 3971 stmfIoctl.stmf_obuf_size = fTargetListSize; 3972 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList; 3973 ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, 3974 &stmfIoctl); 3975 if (ioctlRet != 0) { 3976 switch (errno) { 3977 case EBUSY: 3978 ret = STMF_ERROR_BUSY; 3979 break; 3980 case EPERM: 3981 case EACCES: 3982 ret = STMF_ERROR_PERM; 3983 break; 3984 default: 3985 syslog(LOG_DEBUG, 3986 "stmfGetTargetList:ioctl errno(%d)", 3987 errno); 3988 ret = STMF_STATUS_ERROR; 3989 break; 3990 } 3991 goto done; 3992 } 3993 } 3994 3995 *targetList = (stmfDevidList *)calloc(1, 3996 stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) + 3997 sizeof (stmfDevidList)); 3998 if (*targetList == NULL) { 3999 ret = STMF_ERROR_NOMEM; 4000 goto done; 4001 } 4002 4003 (*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries; 4004 for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) { 4005 (*targetList)->devid[i].identLength = 4006 fTargetList->target[IDENT_LENGTH_BYTE]; 4007 bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1], 4008 &(*targetList)->devid[i].ident, 4009 fTargetList->target[IDENT_LENGTH_BYTE]); 4010 } 4011 4012 done: 4013 (void) close(fd); 4014 free(fTargetListP); 4015 return (ret); 4016 } 4017 4018 /* 4019 * stmfGetTargetProperties 4020 * 4021 * Purpose: Retrieves the properties for a logical unit 4022 * 4023 * devid - devid of the target for which to retrieve properties 4024 * targetProps - pointer to an stmfTargetProperties structure. 4025 * On success, it contains the target properties for 4026 * the specified devid. 4027 */ 4028 int 4029 stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps) 4030 { 4031 int ret = STMF_STATUS_SUCCESS; 4032 int fd; 4033 int ioctlRet; 4034 stmf_iocdata_t stmfIoctl; 4035 sioc_target_port_props_t targetProperties; 4036 scsi_devid_desc_t *scsiDevid; 4037 4038 if (devid == NULL || targetProps == NULL) { 4039 return (STMF_ERROR_INVALID_ARG); 4040 } 4041 4042 /* call init */ 4043 ret = initializeConfig(); 4044 if (ret != STMF_STATUS_SUCCESS) { 4045 return (ret); 4046 } 4047 4048 /* 4049 * Open control node for stmf 4050 */ 4051 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4052 return (ret); 4053 4054 targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength; 4055 bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1], 4056 devid->identLength); 4057 4058 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4059 /* 4060 * Issue ioctl to add to the host group 4061 */ 4062 stmfIoctl.stmf_version = STMF_VERSION_1; 4063 stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id); 4064 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id; 4065 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties; 4066 stmfIoctl.stmf_obuf_size = sizeof (targetProperties); 4067 ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES, 4068 &stmfIoctl); 4069 if (ioctlRet != 0) { 4070 switch (errno) { 4071 case EBUSY: 4072 ret = STMF_ERROR_BUSY; 4073 break; 4074 case EPERM: 4075 case EACCES: 4076 ret = STMF_ERROR_PERM; 4077 break; 4078 case ENOENT: 4079 ret = STMF_ERROR_NOT_FOUND; 4080 break; 4081 default: 4082 syslog(LOG_DEBUG, 4083 "stmfGetTargetProperties:ioctl errno(%d)", 4084 errno); 4085 ret = STMF_STATUS_ERROR; 4086 break; 4087 } 4088 goto done; 4089 } 4090 4091 bcopy(targetProperties.tgt_provider_name, targetProps->providerName, 4092 sizeof (targetProperties.tgt_provider_name)); 4093 if (targetProperties.tgt_state == STMF_STATE_ONLINE) { 4094 targetProps->status = STMF_TARGET_PORT_ONLINE; 4095 } else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) { 4096 targetProps->status = STMF_TARGET_PORT_OFFLINE; 4097 } else if (targetProperties.tgt_state == STMF_STATE_ONLINING) { 4098 targetProps->status = STMF_TARGET_PORT_ONLINING; 4099 } else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) { 4100 targetProps->status = STMF_TARGET_PORT_OFFLINING; 4101 } 4102 bcopy(targetProperties.tgt_alias, targetProps->alias, 4103 sizeof (targetProps->alias)); 4104 4105 scsiDevid = (scsi_devid_desc_t *)&targetProperties.tgt_id; 4106 targetProps->protocol = scsiDevid->protocol_id; 4107 4108 done: 4109 (void) close(fd); 4110 return (ret); 4111 } 4112 4113 /* 4114 * stmfGetLogicalUnitList 4115 * 4116 * Purpose: Retrieves list of logical unit Object IDs 4117 * 4118 * luList - pointer to a pointer to a stmfGuidList structure. On success, 4119 * it contains the list of logical unit guids. 4120 * 4121 */ 4122 int 4123 stmfGetLogicalUnitList(stmfGuidList **luList) 4124 { 4125 int ret; 4126 int fd; 4127 int ioctlRet; 4128 int cmd = STMF_IOCTL_LU_LIST; 4129 int i; 4130 stmf_iocdata_t stmfIoctl; 4131 slist_lu_t *fLuList; 4132 uint32_t fLuListSize; 4133 uint32_t listCnt; 4134 4135 if (luList == NULL) { 4136 return (STMF_ERROR_INVALID_ARG); 4137 } 4138 4139 /* call init */ 4140 ret = initializeConfig(); 4141 if (ret != STMF_STATUS_SUCCESS) { 4142 return (ret); 4143 } 4144 4145 /* 4146 * Open control node for stmf 4147 */ 4148 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4149 return (ret); 4150 4151 /* 4152 * Allocate ioctl input buffer 4153 */ 4154 fLuListSize = ALLOC_LU; 4155 fLuListSize = fLuListSize * (sizeof (slist_lu_t)); 4156 fLuList = (slist_lu_t *)calloc(1, fLuListSize); 4157 if (fLuList == NULL) { 4158 ret = STMF_ERROR_NOMEM; 4159 goto done; 4160 } 4161 4162 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4163 /* 4164 * Issue ioctl to get the LU list 4165 */ 4166 stmfIoctl.stmf_version = STMF_VERSION_1; 4167 stmfIoctl.stmf_obuf_size = fLuListSize; 4168 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList; 4169 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4170 if (ioctlRet != 0) { 4171 switch (errno) { 4172 case EBUSY: 4173 ret = STMF_ERROR_BUSY; 4174 break; 4175 case EPERM: 4176 case EACCES: 4177 ret = STMF_ERROR_PERM; 4178 break; 4179 default: 4180 syslog(LOG_DEBUG, 4181 "stmfGetLogicalUnitList:ioctl errno(%d)", 4182 errno); 4183 ret = STMF_STATUS_ERROR; 4184 break; 4185 } 4186 goto done; 4187 } 4188 /* 4189 * Check whether input buffer was large enough 4190 */ 4191 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_LU) { 4192 fLuListSize = stmfIoctl.stmf_obuf_max_nentries * 4193 sizeof (slist_lu_t); 4194 free(fLuList); 4195 fLuList = (slist_lu_t *)calloc(1, fLuListSize); 4196 if (fLuList == NULL) { 4197 ret = STMF_ERROR_NOMEM; 4198 goto done; 4199 } 4200 stmfIoctl.stmf_obuf_size = fLuListSize; 4201 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList; 4202 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4203 if (ioctlRet != 0) { 4204 switch (errno) { 4205 case EBUSY: 4206 ret = STMF_ERROR_BUSY; 4207 break; 4208 case EPERM: 4209 case EACCES: 4210 ret = STMF_ERROR_PERM; 4211 break; 4212 default: 4213 syslog(LOG_DEBUG, 4214 "stmfGetLogicalUnitList:" 4215 "ioctl errno(%d)", errno); 4216 ret = STMF_STATUS_ERROR; 4217 break; 4218 } 4219 goto done; 4220 } 4221 } 4222 4223 if (ret != STMF_STATUS_SUCCESS) { 4224 goto done; 4225 } 4226 4227 listCnt = stmfIoctl.stmf_obuf_nentries; 4228 4229 /* 4230 * allocate caller's buffer with the final size 4231 */ 4232 *luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) + 4233 listCnt * sizeof (stmfGuid)); 4234 if (*luList == NULL) { 4235 ret = STMF_ERROR_NOMEM; 4236 goto done; 4237 } 4238 4239 (*luList)->cnt = listCnt; 4240 4241 /* copy to caller's buffer */ 4242 for (i = 0; i < listCnt; i++) { 4243 bcopy(&fLuList[i].lu_guid, (*luList)->guid[i].guid, 4244 sizeof (stmfGuid)); 4245 } 4246 4247 /* 4248 * sort the list. This gives a consistent view across gets 4249 */ 4250 qsort((void *)&((*luList)->guid[0]), (*luList)->cnt, 4251 sizeof (stmfGuid), guidCompare); 4252 4253 done: 4254 (void) close(fd); 4255 /* 4256 * free internal buffers 4257 */ 4258 free(fLuList); 4259 return (ret); 4260 } 4261 4262 /* 4263 * stmfGetLogicalUnitProperties 4264 * 4265 * Purpose: Retrieves the properties for a logical unit 4266 * 4267 * lu - guid of the logical unit for which to retrieve properties 4268 * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success, 4269 * it contains the logical unit properties for the specified guid. 4270 */ 4271 int 4272 stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps) 4273 { 4274 int ret = STMF_STATUS_SUCCESS; 4275 int stmfRet; 4276 int fd; 4277 int ioctlRet; 4278 int cmd = STMF_IOCTL_GET_LU_PROPERTIES; 4279 stmfViewEntryList *viewEntryList = NULL; 4280 stmf_iocdata_t stmfIoctl; 4281 sioc_lu_props_t fLuProps; 4282 4283 if (lu == NULL || luProps == NULL) { 4284 return (STMF_ERROR_INVALID_ARG); 4285 } 4286 4287 bzero(luProps, sizeof (stmfLogicalUnitProperties)); 4288 4289 /* call init */ 4290 ret = initializeConfig(); 4291 if (ret != STMF_STATUS_SUCCESS) { 4292 return (ret); 4293 } 4294 4295 /* 4296 * Open control node for stmf 4297 */ 4298 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4299 return (ret); 4300 4301 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4302 /* 4303 * Issue ioctl to add to the host group 4304 */ 4305 stmfIoctl.stmf_version = STMF_VERSION_1; 4306 stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid); 4307 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu; 4308 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps; 4309 stmfIoctl.stmf_obuf_size = sizeof (fLuProps); 4310 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4311 if (ioctlRet != 0) { 4312 switch (errno) { 4313 case EBUSY: 4314 ret = STMF_ERROR_BUSY; 4315 break; 4316 case EPERM: 4317 case EACCES: 4318 ret = STMF_ERROR_PERM; 4319 break; 4320 case ENOENT: 4321 stmfRet = stmfGetViewEntryList(lu, 4322 &viewEntryList); 4323 if (stmfRet == STMF_STATUS_SUCCESS) { 4324 luProps->status = 4325 STMF_LOGICAL_UNIT_UNREGISTERED; 4326 if (viewEntryList->cnt > 0) { 4327 ret = STMF_STATUS_SUCCESS; 4328 } else { 4329 ret = STMF_ERROR_NOT_FOUND; 4330 } 4331 } else { 4332 ret = STMF_ERROR_NOT_FOUND; 4333 } 4334 stmfFreeMemory(viewEntryList); 4335 break; 4336 default: 4337 syslog(LOG_DEBUG, 4338 "stmfGetLogicalUnit:ioctl errno(%d)", 4339 errno); 4340 ret = STMF_STATUS_ERROR; 4341 break; 4342 } 4343 goto done; 4344 } 4345 4346 bcopy(fLuProps.lu_provider_name, luProps->providerName, 4347 sizeof (fLuProps.lu_provider_name)); 4348 if (fLuProps.lu_state == STMF_STATE_ONLINE) { 4349 luProps->status = STMF_LOGICAL_UNIT_ONLINE; 4350 } else if (fLuProps.lu_state == STMF_STATE_OFFLINE) { 4351 luProps->status = STMF_LOGICAL_UNIT_OFFLINE; 4352 } else if (fLuProps.lu_state == STMF_STATE_ONLINING) { 4353 luProps->status = STMF_LOGICAL_UNIT_ONLINING; 4354 } else if (fLuProps.lu_state == STMF_STATE_OFFLINING) { 4355 luProps->status = STMF_LOGICAL_UNIT_OFFLINING; 4356 } 4357 bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias)); 4358 done: 4359 (void) close(fd); 4360 return (ret); 4361 } 4362 4363 /* 4364 * stmfGetState 4365 * 4366 * Purpose: retrieve the current state of the stmf module 4367 * 4368 * state - pointer to stmfState structure allocated by the caller 4369 * On success, contains the state of stmf 4370 */ 4371 int 4372 stmfGetState(stmfState *state) 4373 { 4374 int ret; 4375 stmf_state_desc_t iState; 4376 4377 if (state == NULL) { 4378 return (STMF_ERROR_INVALID_ARG); 4379 } 4380 4381 ret = getStmfState(&iState); 4382 if (ret != STMF_STATUS_SUCCESS) { 4383 return (ret); 4384 } 4385 switch (iState.state) { 4386 case STMF_STATE_ONLINE: 4387 state->operationalState = 4388 STMF_SERVICE_STATE_ONLINE; 4389 break; 4390 case STMF_STATE_OFFLINE: 4391 state->operationalState = 4392 STMF_SERVICE_STATE_OFFLINE; 4393 break; 4394 case STMF_STATE_ONLINING: 4395 state->operationalState = 4396 STMF_SERVICE_STATE_ONLINING; 4397 break; 4398 case STMF_STATE_OFFLINING: 4399 state->operationalState = 4400 STMF_SERVICE_STATE_OFFLINING; 4401 break; 4402 default: 4403 state->operationalState = 4404 STMF_SERVICE_STATE_UNKNOWN; 4405 break; 4406 } 4407 switch (iState.config_state) { 4408 case STMF_CONFIG_NONE: 4409 state->configState = STMF_CONFIG_STATE_NONE; 4410 break; 4411 case STMF_CONFIG_INIT: 4412 state->configState = STMF_CONFIG_STATE_INIT; 4413 break; 4414 case STMF_CONFIG_INIT_DONE: 4415 state->configState = 4416 STMF_CONFIG_STATE_INIT_DONE; 4417 break; 4418 default: 4419 state->configState = 4420 STMF_CONFIG_STATE_UNKNOWN; 4421 break; 4422 } 4423 return (STMF_STATUS_SUCCESS); 4424 } 4425 4426 /* 4427 * stmfGetViewEntryList 4428 * 4429 * Purpose: Retrieves the list of view entries for the specified 4430 * logical unit. 4431 * 4432 * lu - the guid of the logical unit for which to retrieve the view entry list 4433 * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On 4434 * success, contains the list of view entries. 4435 */ 4436 int 4437 stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList) 4438 { 4439 int ret; 4440 int fd; 4441 int ioctlRet; 4442 int cmd = STMF_IOCTL_LU_VE_LIST; 4443 int i; 4444 stmf_iocdata_t stmfIoctl; 4445 stmf_view_op_entry_t *fVeList; 4446 uint32_t fVeListSize; 4447 uint32_t listCnt; 4448 4449 if (lu == NULL || viewEntryList == NULL) { 4450 return (STMF_ERROR_INVALID_ARG); 4451 } 4452 4453 /* call init */ 4454 ret = initializeConfig(); 4455 if (ret != STMF_STATUS_SUCCESS) { 4456 return (ret); 4457 } 4458 4459 /* 4460 * Open control node for stmf 4461 */ 4462 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4463 return (ret); 4464 4465 /* 4466 * Allocate ioctl input buffer 4467 */ 4468 fVeListSize = ALLOC_VE; 4469 fVeListSize = fVeListSize * (sizeof (stmf_view_op_entry_t)); 4470 fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize); 4471 if (fVeList == NULL) { 4472 ret = STMF_ERROR_NOMEM; 4473 goto done; 4474 } 4475 4476 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4477 /* 4478 * Issue ioctl to get the LU list 4479 */ 4480 stmfIoctl.stmf_version = STMF_VERSION_1; 4481 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu; 4482 stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid); 4483 stmfIoctl.stmf_obuf_size = fVeListSize; 4484 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList; 4485 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4486 if (ioctlRet != 0) { 4487 switch (errno) { 4488 case EBUSY: 4489 ret = STMF_ERROR_BUSY; 4490 break; 4491 case EPERM: 4492 case EACCES: 4493 ret = STMF_ERROR_PERM; 4494 break; 4495 default: 4496 syslog(LOG_DEBUG, 4497 "stmfGetViewEntryList:ioctl errno(%d)", 4498 errno); 4499 ret = STMF_STATUS_ERROR; 4500 break; 4501 } 4502 goto done; 4503 } 4504 /* 4505 * Check whether input buffer was large enough 4506 */ 4507 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_VE) { 4508 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4509 fVeListSize = stmfIoctl.stmf_obuf_max_nentries * 4510 sizeof (stmf_view_op_entry_t); 4511 free(fVeList); 4512 fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize); 4513 if (fVeList == NULL) { 4514 return (STMF_ERROR_NOMEM); 4515 } 4516 stmfIoctl.stmf_obuf_size = fVeListSize; 4517 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList; 4518 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4519 if (ioctlRet != 0) { 4520 switch (errno) { 4521 case EBUSY: 4522 ret = STMF_ERROR_BUSY; 4523 break; 4524 case EPERM: 4525 case EACCES: 4526 ret = STMF_ERROR_PERM; 4527 break; 4528 default: 4529 syslog(LOG_DEBUG, 4530 "stmfGetLogicalUnitList:" 4531 "ioctl errno(%d)", errno); 4532 ret = STMF_STATUS_ERROR; 4533 break; 4534 } 4535 goto done; 4536 } 4537 } 4538 4539 if (ret != STMF_STATUS_SUCCESS) { 4540 goto done; 4541 } 4542 4543 if (stmfIoctl.stmf_obuf_nentries == 0) { 4544 ret = STMF_ERROR_NOT_FOUND; 4545 goto done; 4546 } 4547 4548 listCnt = stmfIoctl.stmf_obuf_nentries; 4549 4550 /* 4551 * allocate caller's buffer with the final size 4552 */ 4553 *viewEntryList = (stmfViewEntryList *)calloc(1, 4554 sizeof (stmfViewEntryList) + listCnt * sizeof (stmfViewEntry)); 4555 if (*viewEntryList == NULL) { 4556 ret = STMF_ERROR_NOMEM; 4557 goto done; 4558 } 4559 4560 (*viewEntryList)->cnt = listCnt; 4561 4562 /* copy to caller's buffer */ 4563 for (i = 0; i < listCnt; i++) { 4564 (*viewEntryList)->ve[i].veIndexValid = B_TRUE; 4565 (*viewEntryList)->ve[i].veIndex = fVeList[i].ve_ndx; 4566 if (fVeList[i].ve_all_hosts == 1) { 4567 (*viewEntryList)->ve[i].allHosts = B_TRUE; 4568 } else { 4569 bcopy(fVeList[i].ve_host_group.name, 4570 (*viewEntryList)->ve[i].hostGroup, 4571 fVeList[i].ve_host_group.name_size); 4572 } 4573 if (fVeList[i].ve_all_targets == 1) { 4574 (*viewEntryList)->ve[i].allTargets = B_TRUE; 4575 } else { 4576 bcopy(fVeList[i].ve_target_group.name, 4577 (*viewEntryList)->ve[i].targetGroup, 4578 fVeList[i].ve_target_group.name_size); 4579 } 4580 bcopy(fVeList[i].ve_lu_nbr, (*viewEntryList)->ve[i].luNbr, 4581 sizeof ((*viewEntryList)->ve[i].luNbr)); 4582 (*viewEntryList)->ve[i].luNbrValid = B_TRUE; 4583 } 4584 4585 /* 4586 * sort the list. This gives a consistent view across gets 4587 */ 4588 qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt, 4589 sizeof (stmfViewEntry), viewEntryCompare); 4590 4591 done: 4592 (void) close(fd); 4593 /* 4594 * free internal buffers 4595 */ 4596 free(fVeList); 4597 return (ret); 4598 } 4599 4600 4601 /* 4602 * loadHostGroups 4603 * 4604 * Purpose - issues the ioctl to load the host groups into stmf 4605 * 4606 * fd - file descriptor for the control node of stmf. 4607 * groupList - populated host group list 4608 */ 4609 static int 4610 loadHostGroups(int fd, stmfGroupList *groupList) 4611 { 4612 int i, j; 4613 int ret = STMF_STATUS_SUCCESS; 4614 stmfGroupProperties *groupProps = NULL; 4615 4616 for (i = 0; i < groupList->cnt; i++) { 4617 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP, 4618 &(groupList->name[i]))) != STMF_STATUS_SUCCESS) { 4619 goto out; 4620 } 4621 ret = iLoadGroupMembersFromPs(&(groupList->name[i]), 4622 &groupProps, HOST_GROUP); 4623 for (j = 0; j < groupProps->cnt; j++) { 4624 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, 4625 &(groupList->name[i]), &(groupProps->name[j]))) 4626 != STMF_STATUS_SUCCESS) { 4627 goto out; 4628 } 4629 } 4630 } 4631 4632 4633 out: 4634 stmfFreeMemory(groupProps); 4635 return (ret); 4636 } 4637 4638 /* 4639 * loadTargetGroups 4640 * 4641 * Purpose - issues the ioctl to load the target groups into stmf 4642 * 4643 * fd - file descriptor for the control node of stmf. 4644 * groupList - populated target group list. 4645 */ 4646 static int 4647 loadTargetGroups(int fd, stmfGroupList *groupList) 4648 { 4649 int i, j; 4650 int ret = STMF_STATUS_SUCCESS; 4651 stmfGroupProperties *groupProps = NULL; 4652 4653 for (i = 0; i < groupList->cnt; i++) { 4654 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP, 4655 &(groupList->name[i]))) != STMF_STATUS_SUCCESS) { 4656 goto out; 4657 } 4658 ret = iLoadGroupMembersFromPs(&(groupList->name[i]), 4659 &groupProps, TARGET_GROUP); 4660 for (j = 0; j < groupProps->cnt; j++) { 4661 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY, 4662 &(groupList->name[i]), &(groupProps->name[j]))) 4663 != STMF_STATUS_SUCCESS) { 4664 goto out; 4665 } 4666 } 4667 } 4668 4669 4670 out: 4671 stmfFreeMemory(groupProps); 4672 return (ret); 4673 } 4674 4675 4676 /* 4677 * loadStore 4678 * 4679 * Purpose: Load the configuration data from the store 4680 * 4681 * First load the host groups and target groups, then the view entries 4682 * and finally the provider data 4683 * 4684 * fd - file descriptor of control node for stmf. 4685 */ 4686 static int 4687 loadStore(int fd) 4688 { 4689 int ret; 4690 int i, j; 4691 stmfGroupList *groupList = NULL; 4692 stmfGuidList *guidList = NULL; 4693 stmfViewEntryList *viewEntryList = NULL; 4694 stmfProviderList *providerList = NULL; 4695 int providerType; 4696 nvlist_t *nvl = NULL; 4697 4698 4699 4700 /* load host groups */ 4701 ret = iLoadGroupFromPs(&groupList, HOST_GROUP); 4702 if (ret != STMF_STATUS_SUCCESS) { 4703 return (ret); 4704 } 4705 ret = loadHostGroups(fd, groupList); 4706 if (ret != STMF_STATUS_SUCCESS) { 4707 goto out; 4708 } 4709 4710 stmfFreeMemory(groupList); 4711 groupList = NULL; 4712 4713 /* load target groups */ 4714 ret = iLoadGroupFromPs(&groupList, TARGET_GROUP); 4715 if (ret != STMF_STATUS_SUCCESS) { 4716 goto out; 4717 } 4718 ret = loadTargetGroups(fd, groupList); 4719 if (ret != STMF_STATUS_SUCCESS) { 4720 goto out; 4721 } 4722 4723 stmfFreeMemory(groupList); 4724 groupList = NULL; 4725 4726 /* Get the guid list */ 4727 ret = psGetLogicalUnitList(&guidList); 4728 switch (ret) { 4729 case STMF_PS_SUCCESS: 4730 ret = STMF_STATUS_SUCCESS; 4731 break; 4732 case STMF_PS_ERROR_NOT_FOUND: 4733 ret = STMF_ERROR_NOT_FOUND; 4734 break; 4735 case STMF_PS_ERROR_BUSY: 4736 ret = STMF_ERROR_BUSY; 4737 break; 4738 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 4739 ret = STMF_ERROR_SERVICE_NOT_FOUND; 4740 break; 4741 case STMF_PS_ERROR_VERSION_MISMATCH: 4742 ret = STMF_ERROR_SERVICE_DATA_VERSION; 4743 break; 4744 default: 4745 ret = STMF_STATUS_ERROR; 4746 break; 4747 } 4748 4749 if (ret != STMF_STATUS_SUCCESS) { 4750 goto out; 4751 } 4752 4753 /* 4754 * We have the guid list, now get the corresponding 4755 * view entries for each guid 4756 */ 4757 for (i = 0; i < guidList->cnt; i++) { 4758 ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList); 4759 switch (ret) { 4760 case STMF_PS_SUCCESS: 4761 ret = STMF_STATUS_SUCCESS; 4762 break; 4763 case STMF_PS_ERROR_NOT_FOUND: 4764 ret = STMF_ERROR_NOT_FOUND; 4765 break; 4766 case STMF_PS_ERROR_BUSY: 4767 ret = STMF_ERROR_BUSY; 4768 break; 4769 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 4770 ret = STMF_ERROR_SERVICE_NOT_FOUND; 4771 break; 4772 case STMF_PS_ERROR_VERSION_MISMATCH: 4773 ret = STMF_ERROR_SERVICE_DATA_VERSION; 4774 break; 4775 default: 4776 ret = STMF_STATUS_ERROR; 4777 break; 4778 } 4779 if (ret != STMF_STATUS_SUCCESS) { 4780 goto out; 4781 } 4782 for (j = 0; j < viewEntryList->cnt; j++) { 4783 ret = addViewEntryIoctl(fd, &guidList->guid[i], 4784 &viewEntryList->ve[j]); 4785 if (ret != STMF_STATUS_SUCCESS) { 4786 goto out; 4787 } 4788 } 4789 } 4790 4791 /* get the list of providers that have data */ 4792 ret = psGetProviderDataList(&providerList); 4793 switch (ret) { 4794 case STMF_PS_SUCCESS: 4795 ret = STMF_STATUS_SUCCESS; 4796 break; 4797 case STMF_PS_ERROR_NOT_FOUND: 4798 ret = STMF_ERROR_NOT_FOUND; 4799 break; 4800 case STMF_PS_ERROR_BUSY: 4801 ret = STMF_ERROR_BUSY; 4802 break; 4803 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 4804 ret = STMF_ERROR_SERVICE_NOT_FOUND; 4805 break; 4806 case STMF_PS_ERROR_VERSION_MISMATCH: 4807 ret = STMF_ERROR_SERVICE_DATA_VERSION; 4808 break; 4809 default: 4810 ret = STMF_STATUS_ERROR; 4811 break; 4812 } 4813 if (ret != STMF_STATUS_SUCCESS) { 4814 goto out; 4815 } 4816 4817 for (i = 0; i < providerList->cnt; i++) { 4818 providerType = providerList->provider[i].providerType; 4819 ret = psGetProviderData(providerList->provider[i].name, 4820 &nvl, providerType, NULL); 4821 switch (ret) { 4822 case STMF_PS_SUCCESS: 4823 ret = STMF_STATUS_SUCCESS; 4824 break; 4825 case STMF_PS_ERROR_NOT_FOUND: 4826 ret = STMF_ERROR_NOT_FOUND; 4827 break; 4828 case STMF_PS_ERROR_BUSY: 4829 ret = STMF_ERROR_BUSY; 4830 break; 4831 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 4832 ret = STMF_ERROR_SERVICE_NOT_FOUND; 4833 break; 4834 case STMF_PS_ERROR_VERSION_MISMATCH: 4835 ret = STMF_ERROR_SERVICE_DATA_VERSION; 4836 break; 4837 default: 4838 ret = STMF_STATUS_ERROR; 4839 break; 4840 } 4841 if (ret != STMF_STATUS_SUCCESS) { 4842 goto out; 4843 } 4844 4845 /* call setProviderData */ 4846 ret = setProviderData(fd, providerList->provider[i].name, nvl, 4847 providerType, NULL); 4848 switch (ret) { 4849 case STMF_PS_SUCCESS: 4850 ret = STMF_STATUS_SUCCESS; 4851 break; 4852 case STMF_PS_ERROR_NOT_FOUND: 4853 ret = STMF_ERROR_NOT_FOUND; 4854 break; 4855 case STMF_PS_ERROR_BUSY: 4856 ret = STMF_ERROR_BUSY; 4857 break; 4858 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 4859 ret = STMF_ERROR_SERVICE_NOT_FOUND; 4860 break; 4861 case STMF_PS_ERROR_VERSION_MISMATCH: 4862 ret = STMF_ERROR_SERVICE_DATA_VERSION; 4863 break; 4864 default: 4865 ret = STMF_STATUS_ERROR; 4866 break; 4867 } 4868 if (ret != STMF_STATUS_SUCCESS) { 4869 goto out; 4870 } 4871 4872 nvlist_free(nvl); 4873 nvl = NULL; 4874 } 4875 out: 4876 if (groupList != NULL) { 4877 free(groupList); 4878 } 4879 if (guidList != NULL) { 4880 free(guidList); 4881 } 4882 if (viewEntryList != NULL) { 4883 free(viewEntryList); 4884 } 4885 if (nvl != NULL) { 4886 nvlist_free(nvl); 4887 } 4888 return (ret); 4889 } 4890 4891 /* 4892 * stmfGetAluaState 4893 * 4894 * Purpose - Get the alua state 4895 * 4896 */ 4897 int 4898 stmfGetAluaState(boolean_t *enabled, uint32_t *node) 4899 { 4900 int ret = STMF_STATUS_SUCCESS; 4901 int fd; 4902 stmf_iocdata_t stmfIoctl = {0}; 4903 stmf_alua_state_desc_t alua_state = {0}; 4904 int ioctlRet; 4905 4906 if (enabled == NULL || node == NULL) { 4907 return (STMF_ERROR_INVALID_ARG); 4908 } 4909 4910 /* 4911 * Open control node for stmf 4912 */ 4913 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4914 return (ret); 4915 4916 /* 4917 * Issue ioctl to get the stmf state 4918 */ 4919 stmfIoctl.stmf_version = STMF_VERSION_1; 4920 stmfIoctl.stmf_obuf_size = sizeof (alua_state); 4921 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&alua_state; 4922 ioctlRet = ioctl(fd, STMF_IOCTL_GET_ALUA_STATE, &stmfIoctl); 4923 4924 (void) close(fd); 4925 4926 if (ioctlRet != 0) { 4927 switch (errno) { 4928 case EBUSY: 4929 ret = STMF_ERROR_BUSY; 4930 break; 4931 case EPERM: 4932 case EACCES: 4933 ret = STMF_ERROR_PERM; 4934 break; 4935 default: 4936 syslog(LOG_DEBUG, 4937 "getStmfState:ioctl errno(%d)", errno); 4938 ret = STMF_STATUS_ERROR; 4939 break; 4940 } 4941 } else { 4942 if (alua_state.alua_state == 1) { 4943 *enabled = B_TRUE; 4944 } else { 4945 *enabled = B_FALSE; 4946 } 4947 *node = alua_state.alua_node; 4948 } 4949 4950 return (ret); 4951 } 4952 4953 /* 4954 * stmfSetAluaState 4955 * 4956 * Purpose - set the alua state to enabled/disabled 4957 * 4958 */ 4959 int 4960 stmfSetAluaState(boolean_t enabled, uint32_t node) 4961 { 4962 int ret = STMF_STATUS_SUCCESS; 4963 int fd; 4964 stmf_iocdata_t stmfIoctl = {0}; 4965 stmf_alua_state_desc_t alua_state = {0}; 4966 int ioctlRet; 4967 4968 if ((enabled != B_TRUE && enabled != B_FALSE) || (node > 1)) { 4969 return (STMF_ERROR_INVALID_ARG); 4970 } 4971 4972 if (enabled) { 4973 alua_state.alua_state = 1; 4974 } 4975 4976 alua_state.alua_node = node; 4977 4978 /* 4979 * Open control node for stmf 4980 */ 4981 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4982 return (ret); 4983 4984 /* 4985 * Issue ioctl to get the stmf state 4986 */ 4987 stmfIoctl.stmf_version = STMF_VERSION_1; 4988 stmfIoctl.stmf_ibuf_size = sizeof (alua_state); 4989 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&alua_state; 4990 ioctlRet = ioctl(fd, STMF_IOCTL_SET_ALUA_STATE, &stmfIoctl); 4991 4992 (void) close(fd); 4993 4994 if (ioctlRet != 0) { 4995 switch (errno) { 4996 case EBUSY: 4997 ret = STMF_ERROR_BUSY; 4998 break; 4999 case EPERM: 5000 case EACCES: 5001 ret = STMF_ERROR_PERM; 5002 break; 5003 default: 5004 syslog(LOG_DEBUG, 5005 "getStmfState:ioctl errno(%d)", errno); 5006 ret = STMF_STATUS_ERROR; 5007 break; 5008 } 5009 } 5010 if (ret == STMF_STATUS_SUCCESS) { 5011 deleteNonActiveLus(); 5012 } 5013 5014 return (ret); 5015 } 5016 5017 static void 5018 deleteNonActiveLus() 5019 { 5020 int stmfRet; 5021 int i; 5022 stmfGuidList *luList; 5023 luResource hdl = NULL; 5024 char propVal[10]; 5025 size_t propValSize = sizeof (propVal); 5026 5027 stmfRet = stmfGetLogicalUnitList(&luList); 5028 if (stmfRet != STMF_STATUS_SUCCESS) { 5029 return; 5030 } 5031 5032 for (i = 0; i < luList->cnt; i++) { 5033 stmfRet = stmfGetLuResource(&luList->guid[i], &hdl); 5034 if (stmfRet != STMF_STATUS_SUCCESS) { 5035 goto err; 5036 } 5037 stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_ACCESS_STATE, propVal, 5038 &propValSize); 5039 if (stmfRet != STMF_STATUS_SUCCESS) { 5040 goto err; 5041 } 5042 if (propVal[0] == '0') { 5043 (void) stmfFreeLuResource(hdl); 5044 hdl = NULL; 5045 continue; 5046 } 5047 (void) stmfDeleteLu(&luList->guid[i]); 5048 (void) stmfFreeLuResource(hdl); 5049 hdl = NULL; 5050 } 5051 5052 err: 5053 stmfFreeMemory(luList); 5054 (void) stmfFreeLuResource(hdl); 5055 } 5056 5057 /* 5058 * stmfLoadConfig 5059 * 5060 * Purpose - load the configuration data from smf into stmf 5061 * 5062 */ 5063 int 5064 stmfLoadConfig(void) 5065 { 5066 int ret = STMF_STATUS_SUCCESS; 5067 int fd; 5068 stmf_state_desc_t stmfStateSet; 5069 stmfState state; 5070 5071 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5072 stmfStateSet.state = STMF_STATE_OFFLINE; 5073 5074 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) 5075 != STMF_STATUS_SUCCESS) { 5076 return (ret); 5077 } 5078 /* 5079 * Configuration not stored persistently; nothing to 5080 * initialize so do not set to STMF_CONFIG_INIT. 5081 */ 5082 stmfStateSet.config_state = STMF_CONFIG_INIT_DONE; 5083 goto done; 5084 } 5085 5086 /* Check to ensure service exists */ 5087 if (psCheckService() != STMF_STATUS_SUCCESS) { 5088 return (STMF_ERROR_SERVICE_NOT_FOUND); 5089 } 5090 5091 ret = stmfGetState(&state); 5092 if (ret == STMF_STATUS_SUCCESS) { 5093 if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) { 5094 return (STMF_ERROR_SERVICE_ONLINE); 5095 } 5096 } else { 5097 return (STMF_STATUS_ERROR); 5098 } 5099 5100 5101 stmfStateSet.state = STMF_STATE_OFFLINE; 5102 stmfStateSet.config_state = STMF_CONFIG_INIT; 5103 5104 /* 5105 * Open control node for stmf 5106 */ 5107 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5108 return (ret); 5109 5110 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE); 5111 if (ret != STMF_STATUS_SUCCESS) { 5112 goto done; 5113 } 5114 5115 /* Load the persistent configuration data */ 5116 ret = loadStore(fd); 5117 if (ret != 0) { 5118 goto done; 5119 } 5120 5121 stmfStateSet.state = STMF_STATE_OFFLINE; 5122 stmfStateSet.config_state = STMF_CONFIG_INIT_DONE; 5123 5124 done: 5125 if (ret == STMF_STATUS_SUCCESS) { 5126 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE); 5127 } 5128 (void) close(fd); 5129 return (ret); 5130 } 5131 5132 5133 /* 5134 * getStmfState 5135 * 5136 * stmfState - pointer to stmf_state_desc_t structure. Will contain the state 5137 * information of the stmf service on success. 5138 */ 5139 static int 5140 getStmfState(stmf_state_desc_t *stmfState) 5141 { 5142 int ret = STMF_STATUS_SUCCESS; 5143 int fd; 5144 int ioctlRet; 5145 stmf_iocdata_t stmfIoctl; 5146 5147 /* 5148 * Open control node for stmf 5149 */ 5150 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5151 return (ret); 5152 5153 bzero(&stmfIoctl, sizeof (stmfIoctl)); 5154 /* 5155 * Issue ioctl to get the stmf state 5156 */ 5157 stmfIoctl.stmf_version = STMF_VERSION_1; 5158 stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t); 5159 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState; 5160 stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t); 5161 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState; 5162 ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl); 5163 5164 (void) close(fd); 5165 5166 if (ioctlRet != 0) { 5167 switch (errno) { 5168 case EBUSY: 5169 ret = STMF_ERROR_BUSY; 5170 break; 5171 case EPERM: 5172 case EACCES: 5173 ret = STMF_ERROR_PERM; 5174 break; 5175 default: 5176 syslog(LOG_DEBUG, 5177 "getStmfState:ioctl errno(%d)", errno); 5178 ret = STMF_STATUS_ERROR; 5179 break; 5180 } 5181 } 5182 return (ret); 5183 } 5184 5185 5186 /* 5187 * setStmfState 5188 * 5189 * stmfState - pointer to caller set state structure 5190 * objectType - one of: 5191 * LOGICAL_UNIT_TYPE 5192 * TARGET_TYPE 5193 * STMF_SERVICE_TYPE 5194 */ 5195 static int 5196 setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType) 5197 { 5198 int ret = STMF_STATUS_SUCCESS; 5199 int ioctlRet; 5200 int cmd; 5201 stmf_iocdata_t stmfIoctl; 5202 5203 switch (objectType) { 5204 case LOGICAL_UNIT_TYPE: 5205 cmd = STMF_IOCTL_SET_LU_STATE; 5206 break; 5207 case TARGET_TYPE: 5208 cmd = STMF_IOCTL_SET_TARGET_PORT_STATE; 5209 break; 5210 case STMF_SERVICE_TYPE: 5211 cmd = STMF_IOCTL_SET_STMF_STATE; 5212 break; 5213 default: 5214 ret = STMF_STATUS_ERROR; 5215 goto done; 5216 } 5217 5218 bzero(&stmfIoctl, sizeof (stmfIoctl)); 5219 /* 5220 * Issue ioctl to set the stmf state 5221 */ 5222 stmfIoctl.stmf_version = STMF_VERSION_1; 5223 stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t); 5224 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState; 5225 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 5226 if (ioctlRet != 0) { 5227 switch (errno) { 5228 case EBUSY: 5229 ret = STMF_ERROR_BUSY; 5230 break; 5231 case EPERM: 5232 case EACCES: 5233 ret = STMF_ERROR_PERM; 5234 break; 5235 case ENOENT: 5236 ret = STMF_ERROR_NOT_FOUND; 5237 break; 5238 default: 5239 syslog(LOG_DEBUG, 5240 "setStmfState:ioctl errno(%d)", errno); 5241 ret = STMF_STATUS_ERROR; 5242 break; 5243 } 5244 } 5245 done: 5246 return (ret); 5247 } 5248 5249 /* 5250 * stmfOnline 5251 * 5252 * Purpose: Online stmf service 5253 * 5254 */ 5255 int 5256 stmfOnline(void) 5257 { 5258 int ret; 5259 int fd; 5260 stmfState state; 5261 stmf_state_desc_t iState; 5262 5263 ret = stmfGetState(&state); 5264 if (ret == STMF_STATUS_SUCCESS) { 5265 if (state.operationalState == STMF_SERVICE_STATE_ONLINE) { 5266 return (STMF_ERROR_SERVICE_ONLINE); 5267 } 5268 } else { 5269 return (STMF_STATUS_ERROR); 5270 } 5271 iState.state = STMF_STATE_ONLINE; 5272 iState.config_state = STMF_CONFIG_NONE; 5273 /* 5274 * Open control node for stmf 5275 * to make call to setStmfState() 5276 */ 5277 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5278 return (ret); 5279 ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE); 5280 (void) close(fd); 5281 return (ret); 5282 } 5283 5284 /* 5285 * stmfOffline 5286 * 5287 * Purpose: Offline stmf service 5288 * 5289 */ 5290 int 5291 stmfOffline(void) 5292 { 5293 int ret; 5294 int fd; 5295 stmfState state; 5296 stmf_state_desc_t iState; 5297 5298 ret = stmfGetState(&state); 5299 if (ret == STMF_STATUS_SUCCESS) { 5300 if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) { 5301 return (STMF_ERROR_SERVICE_OFFLINE); 5302 } 5303 } else { 5304 return (STMF_STATUS_ERROR); 5305 } 5306 iState.state = STMF_STATE_OFFLINE; 5307 iState.config_state = STMF_CONFIG_NONE; 5308 5309 /* 5310 * Open control node for stmf 5311 * to make call to setStmfState() 5312 */ 5313 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5314 return (ret); 5315 ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE); 5316 (void) close(fd); 5317 return (ret); 5318 } 5319 5320 5321 /* 5322 * stmfOfflineTarget 5323 * 5324 * Purpose: Change state of target to offline 5325 * 5326 * devid - devid of the target to offline 5327 */ 5328 int 5329 stmfOfflineTarget(stmfDevid *devid) 5330 { 5331 stmf_state_desc_t targetState; 5332 int ret = STMF_STATUS_SUCCESS; 5333 int fd; 5334 5335 if (devid == NULL) { 5336 return (STMF_ERROR_INVALID_ARG); 5337 } 5338 bzero(&targetState, sizeof (targetState)); 5339 5340 targetState.state = STMF_STATE_OFFLINE; 5341 targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength; 5342 bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1], 5343 devid->identLength); 5344 /* 5345 * Open control node for stmf 5346 * to make call to setStmfState() 5347 */ 5348 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5349 return (ret); 5350 ret = setStmfState(fd, &targetState, TARGET_TYPE); 5351 (void) close(fd); 5352 return (ret); 5353 } 5354 5355 /* 5356 * stmfOfflineLogicalUnit 5357 * 5358 * Purpose: Change state of logical unit to offline 5359 * 5360 * lu - guid of the logical unit to offline 5361 */ 5362 int 5363 stmfOfflineLogicalUnit(stmfGuid *lu) 5364 { 5365 stmf_state_desc_t luState; 5366 int ret = STMF_STATUS_SUCCESS; 5367 int fd; 5368 5369 if (lu == NULL) { 5370 return (STMF_ERROR_INVALID_ARG); 5371 } 5372 5373 bzero(&luState, sizeof (luState)); 5374 5375 luState.state = STMF_STATE_OFFLINE; 5376 bcopy(lu, &luState.ident, sizeof (stmfGuid)); 5377 /* 5378 * Open control node for stmf 5379 * to make call to setStmfState() 5380 */ 5381 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5382 return (ret); 5383 ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE); 5384 (void) close(fd); 5385 return (ret); 5386 } 5387 5388 /* 5389 * stmfOnlineTarget 5390 * 5391 * Purpose: Change state of target to online 5392 * 5393 * devid - devid of the target to online 5394 */ 5395 int 5396 stmfOnlineTarget(stmfDevid *devid) 5397 { 5398 stmf_state_desc_t targetState; 5399 int ret = STMF_STATUS_SUCCESS; 5400 int fd; 5401 5402 if (devid == NULL) { 5403 return (STMF_ERROR_INVALID_ARG); 5404 } 5405 bzero(&targetState, sizeof (targetState)); 5406 5407 targetState.state = STMF_STATE_ONLINE; 5408 targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength; 5409 bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1], 5410 devid->identLength); 5411 /* 5412 * Open control node for stmf 5413 * to make call to setStmfState() 5414 */ 5415 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5416 return (ret); 5417 ret = setStmfState(fd, &targetState, TARGET_TYPE); 5418 (void) close(fd); 5419 return (ret); 5420 } 5421 5422 /* 5423 * stmfOnlineLogicalUnit 5424 * 5425 * Purpose: Change state of logical unit to online 5426 * 5427 * lu - guid of the logical unit to online 5428 */ 5429 int 5430 stmfOnlineLogicalUnit(stmfGuid *lu) 5431 { 5432 stmf_state_desc_t luState; 5433 int ret = STMF_STATUS_SUCCESS; 5434 int fd; 5435 5436 if (lu == NULL) { 5437 return (STMF_ERROR_INVALID_ARG); 5438 } 5439 5440 bzero(&luState, sizeof (luState)); 5441 5442 luState.state = STMF_STATE_ONLINE; 5443 bcopy(lu, &luState.ident, sizeof (stmfGuid)); 5444 /* 5445 * Open control node for stmf 5446 * to make call to setStmfState() 5447 */ 5448 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5449 return (ret); 5450 ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE); 5451 (void) close(fd); 5452 return (ret); 5453 } 5454 5455 /* 5456 * stmfRemoveFromHostGroup 5457 * 5458 * Purpose: Removes an initiator from an initiator group 5459 * 5460 * hostGroupName - name of an initiator group 5461 * hostName - name of host group member to remove 5462 */ 5463 int 5464 stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName) 5465 { 5466 int ret; 5467 int fd; 5468 5469 if (hostGroupName == NULL || 5470 (strnlen((char *)hostGroupName, sizeof (stmfGroupName)) 5471 == sizeof (stmfGroupName)) || hostName == NULL) { 5472 return (STMF_ERROR_INVALID_ARG); 5473 } 5474 5475 /* call init */ 5476 ret = initializeConfig(); 5477 if (ret != STMF_STATUS_SUCCESS) { 5478 return (ret); 5479 } 5480 5481 /* 5482 * Open control node for stmf 5483 */ 5484 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5485 return (ret); 5486 5487 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY, 5488 hostGroupName, hostName)) != STMF_STATUS_SUCCESS) { 5489 goto done; 5490 } 5491 5492 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5493 goto done; 5494 } 5495 5496 ret = psRemoveHostGroupMember((char *)hostGroupName, 5497 (char *)hostName->ident); 5498 switch (ret) { 5499 case STMF_PS_SUCCESS: 5500 ret = STMF_STATUS_SUCCESS; 5501 break; 5502 case STMF_PS_ERROR_MEMBER_NOT_FOUND: 5503 ret = STMF_ERROR_MEMBER_NOT_FOUND; 5504 break; 5505 case STMF_PS_ERROR_GROUP_NOT_FOUND: 5506 ret = STMF_ERROR_GROUP_NOT_FOUND; 5507 break; 5508 case STMF_PS_ERROR_BUSY: 5509 ret = STMF_ERROR_BUSY; 5510 break; 5511 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5512 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5513 break; 5514 case STMF_PS_ERROR_VERSION_MISMATCH: 5515 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5516 break; 5517 default: 5518 syslog(LOG_DEBUG, 5519 "stmfRemoveFromHostGroup" 5520 "psRemoveHostGroupMember:error(%d)", ret); 5521 ret = STMF_STATUS_ERROR; 5522 break; 5523 } 5524 5525 done: 5526 (void) close(fd); 5527 return (ret); 5528 } 5529 5530 /* 5531 * stmfRemoveFromTargetGroup 5532 * 5533 * Purpose: Removes a local port from a local port group 5534 * 5535 * targetGroupName - name of a target group 5536 * targetName - name of target to remove 5537 */ 5538 int 5539 stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName) 5540 { 5541 int ret; 5542 int fd; 5543 5544 if (targetGroupName == NULL || 5545 (strnlen((char *)targetGroupName, sizeof (stmfGroupName)) 5546 == sizeof (stmfGroupName)) || targetName == NULL) { 5547 return (STMF_ERROR_INVALID_ARG); 5548 } 5549 5550 /* call init */ 5551 ret = initializeConfig(); 5552 if (ret != STMF_STATUS_SUCCESS) { 5553 return (ret); 5554 } 5555 5556 /* 5557 * Open control node for stmf 5558 */ 5559 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5560 return (ret); 5561 5562 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY, 5563 targetGroupName, targetName)) != STMF_STATUS_SUCCESS) { 5564 goto done; 5565 } 5566 5567 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5568 goto done; 5569 } 5570 5571 ret = psRemoveTargetGroupMember((char *)targetGroupName, 5572 (char *)targetName->ident); 5573 switch (ret) { 5574 case STMF_PS_SUCCESS: 5575 ret = STMF_STATUS_SUCCESS; 5576 break; 5577 case STMF_PS_ERROR_MEMBER_NOT_FOUND: 5578 ret = STMF_ERROR_MEMBER_NOT_FOUND; 5579 break; 5580 case STMF_PS_ERROR_GROUP_NOT_FOUND: 5581 ret = STMF_ERROR_GROUP_NOT_FOUND; 5582 break; 5583 case STMF_PS_ERROR_BUSY: 5584 ret = STMF_ERROR_BUSY; 5585 break; 5586 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5587 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5588 break; 5589 case STMF_PS_ERROR_VERSION_MISMATCH: 5590 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5591 break; 5592 default: 5593 syslog(LOG_DEBUG, 5594 "stmfRemoveFromTargetGroup" 5595 "psRemoveTargetGroupMember:error(%d)", ret); 5596 ret = STMF_STATUS_ERROR; 5597 break; 5598 } 5599 5600 done: 5601 (void) close(fd); 5602 return (ret); 5603 } 5604 5605 /* 5606 * stmfRemoveViewEntry 5607 * 5608 * Purpose: Removes a view entry from a logical unit 5609 * 5610 * lu - guid of lu for which view entry is being removed 5611 * viewEntryIndex - index of view entry to remove 5612 * 5613 */ 5614 int 5615 stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex) 5616 { 5617 int ret = STMF_STATUS_SUCCESS; 5618 int fd; 5619 int ioctlRet; 5620 stmf_iocdata_t stmfIoctl; 5621 stmf_view_op_entry_t ioctlViewEntry; 5622 5623 if (lu == NULL) { 5624 return (STMF_ERROR_INVALID_ARG); 5625 } 5626 5627 /* call init */ 5628 ret = initializeConfig(); 5629 if (ret != STMF_STATUS_SUCCESS) { 5630 return (ret); 5631 } 5632 5633 /* 5634 * Open control node for stmf 5635 */ 5636 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5637 return (ret); 5638 5639 bzero(&ioctlViewEntry, sizeof (ioctlViewEntry)); 5640 ioctlViewEntry.ve_ndx_valid = B_TRUE; 5641 ioctlViewEntry.ve_ndx = viewEntryIndex; 5642 bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid)); 5643 5644 bzero(&stmfIoctl, sizeof (stmfIoctl)); 5645 /* 5646 * Issue ioctl to add to the view entry 5647 */ 5648 stmfIoctl.stmf_version = STMF_VERSION_1; 5649 stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry); 5650 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry; 5651 ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl); 5652 if (ioctlRet != 0) { 5653 switch (errno) { 5654 case EBUSY: 5655 ret = STMF_ERROR_BUSY; 5656 break; 5657 case EPERM: 5658 ret = STMF_ERROR_PERM; 5659 break; 5660 case EACCES: 5661 switch (stmfIoctl.stmf_error) { 5662 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 5663 ret = STMF_ERROR_CONFIG_NONE; 5664 break; 5665 default: 5666 ret = STMF_ERROR_PERM; 5667 break; 5668 } 5669 break; 5670 case ENODEV: 5671 case ENOENT: 5672 ret = STMF_ERROR_NOT_FOUND; 5673 break; 5674 default: 5675 syslog(LOG_DEBUG, 5676 "stmfRemoveViewEntry:ioctl errno(%d)", 5677 errno); 5678 ret = STMF_STATUS_ERROR; 5679 break; 5680 } 5681 goto done; 5682 } 5683 5684 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5685 goto done; 5686 } 5687 5688 ret = psRemoveViewEntry(lu, viewEntryIndex); 5689 switch (ret) { 5690 case STMF_PS_SUCCESS: 5691 ret = STMF_STATUS_SUCCESS; 5692 break; 5693 case STMF_PS_ERROR_NOT_FOUND: 5694 ret = STMF_ERROR_NOT_FOUND; 5695 break; 5696 case STMF_PS_ERROR_BUSY: 5697 ret = STMF_ERROR_BUSY; 5698 break; 5699 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5700 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5701 break; 5702 case STMF_PS_ERROR_VERSION_MISMATCH: 5703 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5704 break; 5705 default: 5706 syslog(LOG_DEBUG, 5707 "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)", 5708 ret); 5709 ret = STMF_STATUS_ERROR; 5710 break; 5711 } 5712 5713 done: 5714 (void) close(fd); 5715 return (ret); 5716 } 5717 5718 /* 5719 * stmfSetProviderData 5720 * 5721 * Purpose: set the provider data 5722 * 5723 * providerName - unique name of provider 5724 * nvl - nvlist to set 5725 * providerType - type of provider for which to set data 5726 * STMF_LU_PROVIDER_TYPE 5727 * STMF_PORT_PROVIDER_TYPE 5728 */ 5729 int 5730 stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType) 5731 { 5732 return (stmfSetProviderDataProt(providerName, nvl, providerType, 5733 NULL)); 5734 } 5735 5736 /* 5737 * stmfSetProviderDataProt 5738 * 5739 * Purpose: set the provider data 5740 * 5741 * providerName - unique name of provider 5742 * nvl - nvlist to set 5743 * providerType - type of provider for which to set data 5744 * STMF_LU_PROVIDER_TYPE 5745 * STMF_PORT_PROVIDER_TYPE 5746 * setToken - Stale data token returned in the stmfGetProviderDataProt() 5747 * call or NULL. 5748 */ 5749 int 5750 stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType, 5751 uint64_t *setToken) 5752 { 5753 int ret; 5754 int fd; 5755 5756 if (providerName == NULL || nvl == NULL) { 5757 return (STMF_ERROR_INVALID_ARG); 5758 } 5759 5760 if (providerType != STMF_LU_PROVIDER_TYPE && 5761 providerType != STMF_PORT_PROVIDER_TYPE) { 5762 return (STMF_ERROR_INVALID_ARG); 5763 } 5764 5765 /* call init */ 5766 ret = initializeConfig(); 5767 if (ret != STMF_STATUS_SUCCESS) { 5768 return (ret); 5769 } 5770 5771 /* 5772 * Open control node for stmf 5773 */ 5774 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5775 return (ret); 5776 5777 ret = setProviderData(fd, providerName, nvl, providerType, setToken); 5778 5779 (void) close(fd); 5780 5781 if (ret != STMF_STATUS_SUCCESS) { 5782 goto done; 5783 } 5784 5785 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5786 goto done; 5787 } 5788 5789 /* setting driver provider data successful. Now persist it */ 5790 ret = psSetProviderData(providerName, nvl, providerType, NULL); 5791 switch (ret) { 5792 case STMF_PS_SUCCESS: 5793 ret = STMF_STATUS_SUCCESS; 5794 break; 5795 case STMF_PS_ERROR_EXISTS: 5796 ret = STMF_ERROR_EXISTS; 5797 break; 5798 case STMF_PS_ERROR_BUSY: 5799 ret = STMF_ERROR_BUSY; 5800 break; 5801 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5802 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5803 break; 5804 case STMF_PS_ERROR_VERSION_MISMATCH: 5805 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5806 break; 5807 case STMF_PS_ERROR_PROV_DATA_STALE: 5808 ret = STMF_ERROR_PROV_DATA_STALE; 5809 break; 5810 default: 5811 syslog(LOG_DEBUG, 5812 "stmfSetProviderData" 5813 "psSetProviderData:error(%d)", ret); 5814 ret = STMF_STATUS_ERROR; 5815 break; 5816 } 5817 5818 done: 5819 return (ret); 5820 } 5821 5822 /* 5823 * getProviderData 5824 * 5825 * Purpose: set the provider data from stmf 5826 * 5827 * providerName - unique name of provider 5828 * nvl - nvlist to load/retrieve 5829 * providerType - logical unit or port provider 5830 * setToken - returned stale data token 5831 */ 5832 int 5833 getProviderData(char *providerName, nvlist_t **nvl, int providerType, 5834 uint64_t *setToken) 5835 { 5836 int ret = STMF_STATUS_SUCCESS; 5837 int fd; 5838 int ioctlRet; 5839 size_t nvlistSize = ALLOC_PP_DATA_SIZE; 5840 int retryCnt = 0; 5841 int retryCntMax = MAX_PROVIDER_RETRY; 5842 stmf_ppioctl_data_t ppi = {0}, *ppi_out = NULL; 5843 boolean_t retry = B_TRUE; 5844 stmf_iocdata_t stmfIoctl; 5845 5846 if (providerName == NULL) { 5847 return (STMF_ERROR_INVALID_ARG); 5848 } 5849 5850 /* 5851 * Open control node for stmf 5852 */ 5853 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5854 return (ret); 5855 5856 /* set provider name and provider type */ 5857 if (strlcpy(ppi.ppi_name, providerName, 5858 sizeof (ppi.ppi_name)) >= 5859 sizeof (ppi.ppi_name)) { 5860 ret = STMF_ERROR_INVALID_ARG; 5861 goto done; 5862 } 5863 switch (providerType) { 5864 case STMF_LU_PROVIDER_TYPE: 5865 ppi.ppi_lu_provider = 1; 5866 break; 5867 case STMF_PORT_PROVIDER_TYPE: 5868 ppi.ppi_port_provider = 1; 5869 break; 5870 default: 5871 ret = STMF_ERROR_INVALID_ARG; 5872 goto done; 5873 } 5874 5875 do { 5876 /* allocate memory for ioctl */ 5877 ppi_out = (stmf_ppioctl_data_t *)calloc(1, nvlistSize + 5878 sizeof (stmf_ppioctl_data_t)); 5879 if (ppi_out == NULL) { 5880 ret = STMF_ERROR_NOMEM; 5881 goto done; 5882 5883 } 5884 5885 /* set the size of the ioctl data to allocated buffer */ 5886 ppi.ppi_data_size = nvlistSize; 5887 5888 bzero(&stmfIoctl, sizeof (stmfIoctl)); 5889 5890 stmfIoctl.stmf_version = STMF_VERSION_1; 5891 stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t); 5892 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi; 5893 stmfIoctl.stmf_obuf_size = sizeof (stmf_ppioctl_data_t) + 5894 nvlistSize; 5895 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)ppi_out; 5896 ioctlRet = ioctl(fd, STMF_IOCTL_GET_PP_DATA, &stmfIoctl); 5897 if (ioctlRet != 0) { 5898 switch (errno) { 5899 case EBUSY: 5900 ret = STMF_ERROR_BUSY; 5901 break; 5902 case EPERM: 5903 case EACCES: 5904 ret = STMF_ERROR_PERM; 5905 break; 5906 case EINVAL: 5907 if (stmfIoctl.stmf_error == 5908 STMF_IOCERR_INSUFFICIENT_BUF) { 5909 nvlistSize = 5910 ppi_out->ppi_data_size; 5911 free(ppi_out); 5912 ppi_out = NULL; 5913 if (retryCnt++ > retryCntMax) { 5914 retry = B_FALSE; 5915 ret = STMF_ERROR_BUSY; 5916 } else { 5917 ret = 5918 STMF_STATUS_SUCCESS; 5919 } 5920 } else { 5921 syslog(LOG_DEBUG, 5922 "getProviderData:ioctl" 5923 "unable to retrieve " 5924 "nvlist"); 5925 ret = STMF_STATUS_ERROR; 5926 } 5927 break; 5928 case ENOENT: 5929 ret = STMF_ERROR_NOT_FOUND; 5930 break; 5931 default: 5932 syslog(LOG_DEBUG, 5933 "getProviderData:ioctl errno(%d)", 5934 errno); 5935 ret = STMF_STATUS_ERROR; 5936 break; 5937 } 5938 if (ret != STMF_STATUS_SUCCESS) 5939 goto done; 5940 } 5941 } while (retry && stmfIoctl.stmf_error == STMF_IOCERR_INSUFFICIENT_BUF); 5942 5943 if ((ret = nvlist_unpack((char *)ppi_out->ppi_data, 5944 ppi_out->ppi_data_size, nvl, 0)) != 0) { 5945 ret = STMF_STATUS_ERROR; 5946 goto done; 5947 } 5948 5949 /* caller has asked for new token */ 5950 if (setToken) { 5951 *setToken = ppi_out->ppi_token; 5952 } 5953 done: 5954 free(ppi_out); 5955 (void) close(fd); 5956 return (ret); 5957 } 5958 5959 /* 5960 * setProviderData 5961 * 5962 * Purpose: set the provider data in stmf 5963 * 5964 * providerName - unique name of provider 5965 * nvl - nvlist to set 5966 * providerType - logical unit or port provider 5967 * setToken - stale data token to check if not NULL 5968 */ 5969 static int 5970 setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType, 5971 uint64_t *setToken) 5972 { 5973 int ret = STMF_STATUS_SUCCESS; 5974 int ioctlRet; 5975 size_t nvlistEncodedSize; 5976 stmf_ppioctl_data_t *ppi = NULL; 5977 uint64_t outToken; 5978 char *allocatedNvBuffer; 5979 stmf_iocdata_t stmfIoctl; 5980 5981 if (providerName == NULL) { 5982 return (STMF_ERROR_INVALID_ARG); 5983 } 5984 5985 /* get size of encoded nvlist */ 5986 if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) { 5987 return (STMF_STATUS_ERROR); 5988 } 5989 5990 /* allocate memory for ioctl */ 5991 ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize + 5992 sizeof (stmf_ppioctl_data_t)); 5993 if (ppi == NULL) { 5994 return (STMF_ERROR_NOMEM); 5995 } 5996 5997 if (setToken) { 5998 ppi->ppi_token_valid = 1; 5999 ppi->ppi_token = *setToken; 6000 } 6001 6002 allocatedNvBuffer = (char *)&ppi->ppi_data; 6003 if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize, 6004 NV_ENCODE_XDR, 0) != 0) { 6005 return (STMF_STATUS_ERROR); 6006 } 6007 6008 /* set provider name and provider type */ 6009 (void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name)); 6010 switch (providerType) { 6011 case STMF_LU_PROVIDER_TYPE: 6012 ppi->ppi_lu_provider = 1; 6013 break; 6014 case STMF_PORT_PROVIDER_TYPE: 6015 ppi->ppi_port_provider = 1; 6016 break; 6017 default: 6018 return (STMF_ERROR_INVALID_ARG); 6019 } 6020 6021 /* set the size of the ioctl data to packed data size */ 6022 ppi->ppi_data_size = nvlistEncodedSize; 6023 6024 bzero(&stmfIoctl, sizeof (stmfIoctl)); 6025 6026 stmfIoctl.stmf_version = STMF_VERSION_1; 6027 /* 6028 * Subtracting 8 from the size as that is the size of the last member 6029 * of the structure where the packed data resides 6030 */ 6031 stmfIoctl.stmf_ibuf_size = nvlistEncodedSize + 6032 sizeof (stmf_ppioctl_data_t) - 8; 6033 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi; 6034 stmfIoctl.stmf_obuf_size = sizeof (uint64_t); 6035 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&outToken; 6036 ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl); 6037 if (ioctlRet != 0) { 6038 switch (errno) { 6039 case EBUSY: 6040 ret = STMF_ERROR_BUSY; 6041 break; 6042 case EPERM: 6043 case EACCES: 6044 ret = STMF_ERROR_PERM; 6045 break; 6046 case EINVAL: 6047 if (stmfIoctl.stmf_error == 6048 STMF_IOCERR_PPD_UPDATED) { 6049 ret = STMF_ERROR_PROV_DATA_STALE; 6050 } else { 6051 ret = STMF_STATUS_ERROR; 6052 } 6053 break; 6054 default: 6055 syslog(LOG_DEBUG, 6056 "setProviderData:ioctl errno(%d)", errno); 6057 ret = STMF_STATUS_ERROR; 6058 break; 6059 } 6060 if (ret != STMF_STATUS_SUCCESS) 6061 goto done; 6062 } 6063 6064 /* caller has asked for new token */ 6065 if (setToken) { 6066 *setToken = outToken; 6067 } 6068 done: 6069 free(ppi); 6070 return (ret); 6071 } 6072 6073 /* 6074 * set the persistence method in the library only or library and service 6075 */ 6076 int 6077 stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet) 6078 { 6079 int ret = STMF_STATUS_SUCCESS; 6080 int oldPersist; 6081 6082 (void) pthread_mutex_lock(&persistenceTypeLock); 6083 oldPersist = iPersistType; 6084 if (persistType == STMF_PERSIST_NONE || 6085 persistType == STMF_PERSIST_SMF) { 6086 iLibSetPersist = B_TRUE; 6087 iPersistType = persistType; 6088 } else { 6089 (void) pthread_mutex_unlock(&persistenceTypeLock); 6090 return (STMF_ERROR_INVALID_ARG); 6091 } 6092 /* Is this for this library open or in SMF */ 6093 if (serviceSet == B_TRUE) { 6094 ret = psSetServicePersist(persistType); 6095 if (ret != STMF_PS_SUCCESS) { 6096 ret = STMF_ERROR_PERSIST_TYPE; 6097 /* Set to old value */ 6098 iPersistType = oldPersist; 6099 } 6100 } 6101 (void) pthread_mutex_unlock(&persistenceTypeLock); 6102 6103 return (ret); 6104 } 6105 6106 /* 6107 * Only returns internal state for persist. If unset, goes to ps. If that 6108 * fails, returns default setting 6109 */ 6110 static uint8_t 6111 iGetPersistMethod() 6112 { 6113 6114 uint8_t persistType = 0; 6115 6116 (void) pthread_mutex_lock(&persistenceTypeLock); 6117 if (iLibSetPersist) { 6118 persistType = iPersistType; 6119 } else { 6120 int ret; 6121 ret = psGetServicePersist(&persistType); 6122 if (ret != STMF_PS_SUCCESS) { 6123 /* set to default */ 6124 persistType = STMF_DEFAULT_PERSIST; 6125 } 6126 } 6127 (void) pthread_mutex_unlock(&persistenceTypeLock); 6128 return (persistType); 6129 } 6130 6131 /* 6132 * Returns either library state or persistent config state depending on 6133 * serviceState 6134 */ 6135 int 6136 stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState) 6137 { 6138 int ret = STMF_STATUS_SUCCESS; 6139 6140 if (persistType == NULL) { 6141 return (STMF_ERROR_INVALID_ARG); 6142 } 6143 if (serviceState) { 6144 ret = psGetServicePersist(persistType); 6145 if (ret != STMF_PS_SUCCESS) { 6146 ret = STMF_ERROR_PERSIST_TYPE; 6147 } 6148 } else { 6149 (void) pthread_mutex_lock(&persistenceTypeLock); 6150 if (iLibSetPersist) { 6151 *persistType = iPersistType; 6152 } else { 6153 *persistType = STMF_DEFAULT_PERSIST; 6154 } 6155 (void) pthread_mutex_unlock(&persistenceTypeLock); 6156 } 6157 6158 return (ret); 6159 } 6160 6161 /* 6162 * stmfPostProxyMsg 6163 * 6164 * Purpose: Post a message to the proxy port provider 6165 * 6166 * buf - buffer containing message to post 6167 * buflen - buffer length 6168 */ 6169 int 6170 stmfPostProxyMsg(int hdl, void *buf, uint32_t buflen) 6171 { 6172 int ret = STMF_STATUS_SUCCESS; 6173 int ioctlRet; 6174 pppt_iocdata_t ppptIoctl = {0}; 6175 6176 if (buf == NULL) { 6177 return (STMF_ERROR_INVALID_ARG); 6178 } 6179 6180 /* 6181 * Issue ioctl to post the message 6182 */ 6183 ppptIoctl.pppt_version = PPPT_VERSION_1; 6184 ppptIoctl.pppt_buf_size = buflen; 6185 ppptIoctl.pppt_buf = (uint64_t)(unsigned long)buf; 6186 ioctlRet = ioctl(hdl, PPPT_MESSAGE, &ppptIoctl); 6187 if (ioctlRet != 0) { 6188 switch (errno) { 6189 case EPERM: 6190 case EACCES: 6191 ret = STMF_ERROR_PERM; 6192 break; 6193 default: 6194 ret = STMF_ERROR_POST_MSG_FAILED; 6195 break; 6196 } 6197 } 6198 6199 return (ret); 6200 } 6201 6202 /* 6203 * stmfInitProxyDoor 6204 * 6205 * Purpose: Install door in proxy 6206 * 6207 * hdl - pointer to returned handle 6208 * fd - door from door_create() 6209 */ 6210 int 6211 stmfInitProxyDoor(int *hdl, int door) 6212 { 6213 int ret = STMF_STATUS_SUCCESS; 6214 int ioctlRet; 6215 int fd; 6216 pppt_iocdata_t ppptIoctl = {0}; 6217 6218 if (hdl == NULL) { 6219 return (STMF_ERROR_INVALID_ARG); 6220 } 6221 6222 /* 6223 * Open control node for pppt 6224 */ 6225 if ((ret = openPppt(OPEN_PPPT, &fd)) != STMF_STATUS_SUCCESS) { 6226 return (ret); 6227 } 6228 6229 /* 6230 * Issue ioctl to install the door 6231 */ 6232 ppptIoctl.pppt_version = PPPT_VERSION_1; 6233 ppptIoctl.pppt_door_fd = (uint32_t)door; 6234 ioctlRet = ioctl(fd, PPPT_INSTALL_DOOR, &ppptIoctl); 6235 if (ioctlRet != 0) { 6236 switch (errno) { 6237 case EPERM: 6238 case EACCES: 6239 ret = STMF_ERROR_PERM; 6240 break; 6241 case EINVAL: 6242 ret = STMF_ERROR_INVALID_ARG; 6243 break; 6244 case EBUSY: 6245 ret = STMF_ERROR_DOOR_INSTALLED; 6246 break; 6247 default: 6248 ret = STMF_STATUS_ERROR; 6249 break; 6250 } 6251 } 6252 6253 /* return driver fd to caller */ 6254 *hdl = fd; 6255 return (ret); 6256 } 6257 6258 void 6259 stmfDestroyProxyDoor(int hdl) 6260 { 6261 (void) close(hdl); 6262 } 6263 6264 /* 6265 * validateLunNumIoctl 6266 * 6267 * Purpose: Issues ioctl to check and get available lun# in view entry 6268 * 6269 * viewEntry - view entry to use 6270 */ 6271 static int 6272 validateLunNumIoctl(int fd, stmfViewEntry *viewEntry) 6273 { 6274 int ret = STMF_STATUS_SUCCESS; 6275 int ioctlRet; 6276 stmf_iocdata_t stmfIoctl; 6277 stmf_view_op_entry_t ioctlViewEntry; 6278 6279 bzero(&ioctlViewEntry, sizeof (ioctlViewEntry)); 6280 /* 6281 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be 6282 * false on input 6283 */ 6284 ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid; 6285 ioctlViewEntry.ve_all_hosts = viewEntry->allHosts; 6286 ioctlViewEntry.ve_all_targets = viewEntry->allTargets; 6287 6288 if (viewEntry->allHosts == B_FALSE) { 6289 bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name, 6290 sizeof (stmfGroupName)); 6291 ioctlViewEntry.ve_host_group.name_size = 6292 strlen((char *)viewEntry->hostGroup); 6293 } 6294 if (viewEntry->allTargets == B_FALSE) { 6295 bcopy(viewEntry->targetGroup, 6296 &ioctlViewEntry.ve_target_group.name, 6297 sizeof (stmfGroupName)); 6298 ioctlViewEntry.ve_target_group.name_size = 6299 strlen((char *)viewEntry->targetGroup); 6300 } 6301 /* Validating the lun number */ 6302 if (viewEntry->luNbrValid) { 6303 bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr, 6304 sizeof (ioctlViewEntry.ve_lu_nbr)); 6305 } 6306 6307 bzero(&stmfIoctl, sizeof (stmfIoctl)); 6308 /* 6309 * Issue ioctl to validate lun# in the view entry 6310 */ 6311 stmfIoctl.stmf_version = STMF_VERSION_1; 6312 stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry); 6313 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry; 6314 stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry); 6315 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry; 6316 ioctlRet = ioctl(fd, STMF_IOCTL_VALIDATE_VIEW, &stmfIoctl); 6317 6318 /* save available lun number */ 6319 if (!viewEntry->luNbrValid) { 6320 bcopy(ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr, 6321 sizeof (ioctlViewEntry.ve_lu_nbr)); 6322 } 6323 if (ioctlRet != 0) { 6324 switch (errno) { 6325 case EBUSY: 6326 ret = STMF_ERROR_BUSY; 6327 break; 6328 case EPERM: 6329 ret = STMF_ERROR_PERM; 6330 break; 6331 case EACCES: 6332 switch (stmfIoctl.stmf_error) { 6333 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 6334 ret = STMF_ERROR_CONFIG_NONE; 6335 break; 6336 default: 6337 ret = STMF_ERROR_PERM; 6338 break; 6339 } 6340 break; 6341 default: 6342 switch (stmfIoctl.stmf_error) { 6343 case STMF_IOCERR_LU_NUMBER_IN_USE: 6344 ret = STMF_ERROR_LUN_IN_USE; 6345 break; 6346 case STMF_IOCERR_VIEW_ENTRY_CONFLICT: 6347 ret = STMF_ERROR_VE_CONFLICT; 6348 break; 6349 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 6350 ret = STMF_ERROR_CONFIG_NONE; 6351 break; 6352 case STMF_IOCERR_INVALID_HG: 6353 ret = STMF_ERROR_INVALID_HG; 6354 break; 6355 case STMF_IOCERR_INVALID_TG: 6356 ret = STMF_ERROR_INVALID_TG; 6357 break; 6358 default: 6359 syslog(LOG_DEBUG, 6360 "addViewEntryIoctl" 6361 ":error(%d)", 6362 stmfIoctl.stmf_error); 6363 ret = STMF_STATUS_ERROR; 6364 break; 6365 } 6366 break; 6367 } 6368 } 6369 return (ret); 6370 } 6371 6372 /* 6373 * stmfValidateView 6374 * 6375 * Purpose: Validate or get lun # base on TG, HG of view entry 6376 * 6377 * viewEntry - view entry structure to use 6378 */ 6379 int 6380 stmfValidateView(stmfViewEntry *viewEntry) 6381 { 6382 int ret; 6383 int fd; 6384 stmfViewEntry iViewEntry; 6385 6386 if (viewEntry == NULL) { 6387 return (STMF_ERROR_INVALID_ARG); 6388 } 6389 6390 /* initialize and set internal view entry */ 6391 bzero(&iViewEntry, sizeof (iViewEntry)); 6392 6393 if (!viewEntry->allHosts) { 6394 bcopy(viewEntry->hostGroup, iViewEntry.hostGroup, 6395 sizeof (iViewEntry.hostGroup)); 6396 } else { 6397 iViewEntry.allHosts = B_TRUE; 6398 } 6399 6400 if (!viewEntry->allTargets) { 6401 bcopy(viewEntry->targetGroup, iViewEntry.targetGroup, 6402 sizeof (iViewEntry.targetGroup)); 6403 } else { 6404 iViewEntry.allTargets = B_TRUE; 6405 } 6406 6407 if (viewEntry->luNbrValid) { 6408 iViewEntry.luNbrValid = B_TRUE; 6409 bcopy(viewEntry->luNbr, iViewEntry.luNbr, 6410 sizeof (iViewEntry.luNbr)); 6411 } 6412 6413 /* 6414 * set users return view entry index valid flag to false 6415 * in case of failure 6416 */ 6417 viewEntry->veIndexValid = B_FALSE; 6418 6419 /* Check to ensure service exists */ 6420 if (psCheckService() != STMF_STATUS_SUCCESS) { 6421 return (STMF_ERROR_SERVICE_NOT_FOUND); 6422 } 6423 6424 /* call init */ 6425 ret = initializeConfig(); 6426 if (ret != STMF_STATUS_SUCCESS) { 6427 return (ret); 6428 } 6429 6430 /* 6431 * Open control node for stmf 6432 */ 6433 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 6434 return (ret); 6435 6436 /* 6437 * Validate lun# in the view entry from the driver 6438 */ 6439 ret = validateLunNumIoctl(fd, &iViewEntry); 6440 (void) close(fd); 6441 6442 /* save available lun number */ 6443 if (!viewEntry->luNbrValid) { 6444 bcopy(iViewEntry.luNbr, viewEntry->luNbr, 6445 sizeof (iViewEntry.luNbr)); 6446 } 6447 6448 return (ret); 6449 } 6450