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