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