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 2010 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 if (hdl == NULL) { 2145 return (STMF_ERROR_INVALID_ARG); 2146 } 2147 2148 /* Check logical unit provider name to call correct dtype function */ 2149 if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps)) 2150 != STMF_STATUS_SUCCESS) { 2151 return (ret); 2152 } else { 2153 if (strcmp(luProps.providerName, "sbd") == 0) { 2154 ret = getDiskAllProps(luGuid, hdl); 2155 } else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) { 2156 return (STMF_ERROR_NOT_FOUND); 2157 } else { 2158 return (STMF_ERROR_INVALID_ARG); 2159 } 2160 } 2161 2162 return (ret); 2163 } 2164 2165 /* 2166 * getDiskAllProps 2167 * 2168 * Purpose: load all disk properties from sbd driver 2169 * 2170 * luGuid - guid of disk device for which properties are to be retrieved 2171 * hdl - allocated luResource into which properties are to be copied 2172 * 2173 */ 2174 static int 2175 getDiskAllProps(stmfGuid *luGuid, luResource *hdl) 2176 { 2177 int ret = STMF_STATUS_SUCCESS; 2178 int fd; 2179 sbd_lu_props_t *sbdProps; 2180 int ioctlRet; 2181 int savedErrno; 2182 int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS; 2183 stmf_iocdata_t sbdIoctl = {0}; 2184 2185 /* 2186 * Open control node for sbd 2187 */ 2188 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS) 2189 return (ret); 2190 2191 2192 *hdl = calloc(1, sizeof (luResourceImpl)); 2193 if (*hdl == NULL) { 2194 (void) close(fd); 2195 return (STMF_ERROR_NOMEM); 2196 } 2197 2198 sbdProps = calloc(1, sbdPropsSize); 2199 if (sbdProps == NULL) { 2200 free(*hdl); 2201 (void) close(fd); 2202 return (STMF_ERROR_NOMEM); 2203 } 2204 2205 ret = createDiskResource((luResourceImpl *)*hdl); 2206 if (ret != STMF_STATUS_SUCCESS) { 2207 free(*hdl); 2208 free(sbdProps); 2209 (void) close(fd); 2210 return (ret); 2211 } 2212 2213 sbdProps->slp_input_guid = 1; 2214 bcopy(luGuid, sbdProps->slp_guid, sizeof (sbdProps->slp_guid)); 2215 2216 sbdIoctl.stmf_version = STMF_VERSION_1; 2217 sbdIoctl.stmf_ibuf_size = sbdPropsSize; 2218 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdProps; 2219 sbdIoctl.stmf_obuf_size = sbdPropsSize; 2220 sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps; 2221 ioctlRet = ioctl(fd, SBD_IOCTL_GET_LU_PROPS, &sbdIoctl); 2222 if (ioctlRet != 0) { 2223 savedErrno = errno; 2224 switch (savedErrno) { 2225 case EBUSY: 2226 ret = STMF_ERROR_BUSY; 2227 break; 2228 case EPERM: 2229 case EACCES: 2230 ret = STMF_ERROR_PERM; 2231 break; 2232 case ENOENT: 2233 ret = STMF_ERROR_NOT_FOUND; 2234 break; 2235 default: 2236 syslog(LOG_DEBUG, 2237 "getDiskAllProps:ioctl error(%d) (%d) (%d)", 2238 ioctlRet, sbdIoctl.stmf_error, savedErrno); 2239 ret = STMF_STATUS_ERROR; 2240 break; 2241 } 2242 } 2243 2244 if (ret == STMF_STATUS_SUCCESS) { 2245 ret = loadDiskPropsFromDriver((luResourceImpl *)*hdl, sbdProps); 2246 } 2247 2248 free(sbdProps); 2249 (void) close(fd); 2250 return (ret); 2251 } 2252 2253 /* 2254 * loadDiskPropsFromDriver 2255 * 2256 * Purpose: Retrieve all disk type properties from sbd driver 2257 * 2258 * hdl - Allocated luResourceImpl 2259 * sbdProps - sbd_lu_props_t structure returned from sbd driver 2260 * 2261 */ 2262 static int 2263 loadDiskPropsFromDriver(luResourceImpl *hdl, sbd_lu_props_t *sbdProps) 2264 { 2265 int ret = STMF_STATUS_SUCCESS; 2266 diskResource *diskLu = hdl->resource; 2267 /* copy guid */ 2268 diskLu->luGuidValid = B_TRUE; 2269 bcopy(sbdProps->slp_guid, diskLu->luGuid, sizeof (sbdProps->slp_guid)); 2270 2271 if (sbdProps->slp_separate_meta && sbdProps->slp_meta_fname_valid) { 2272 diskLu->luMetaFileNameValid = B_TRUE; 2273 if (strlcpy(diskLu->luMetaFileName, 2274 (char *)&(sbdProps->slp_buf[sbdProps->slp_meta_fname_off]), 2275 sizeof (diskLu->luMetaFileName)) >= 2276 sizeof (diskLu->luMetaFileName)) { 2277 return (STMF_STATUS_ERROR); 2278 } 2279 } 2280 2281 if (sbdProps->slp_data_fname_valid) { 2282 diskLu->luDataFileNameValid = B_TRUE; 2283 if (strlcpy(diskLu->luDataFileName, 2284 (char *)&(sbdProps->slp_buf[sbdProps->slp_data_fname_off]), 2285 sizeof (diskLu->luDataFileName)) >= 2286 sizeof (diskLu->luDataFileName)) { 2287 return (STMF_STATUS_ERROR); 2288 } 2289 } 2290 2291 if (sbdProps->slp_serial_valid) { 2292 diskLu->serialNumValid = B_TRUE; 2293 bcopy(&(sbdProps->slp_buf[sbdProps->slp_serial_off]), 2294 diskLu->serialNum, sbdProps->slp_serial_size); 2295 } 2296 2297 if (sbdProps->slp_mgmt_url_valid) { 2298 diskLu->luMgmtUrlValid = B_TRUE; 2299 if (strlcpy(diskLu->luMgmtUrl, 2300 (char *)&(sbdProps->slp_buf[sbdProps->slp_mgmt_url_off]), 2301 sizeof (diskLu->luMgmtUrl)) >= 2302 sizeof (diskLu->luMgmtUrl)) { 2303 return (STMF_STATUS_ERROR); 2304 } 2305 } 2306 2307 if (sbdProps->slp_alias_valid) { 2308 diskLu->luAliasValid = B_TRUE; 2309 if (strlcpy(diskLu->luAlias, 2310 (char *)&(sbdProps->slp_buf[sbdProps->slp_alias_off]), 2311 sizeof (diskLu->luAlias)) >= 2312 sizeof (diskLu->luAlias)) { 2313 return (STMF_STATUS_ERROR); 2314 } 2315 } else { /* set alias to data filename if not set */ 2316 if (sbdProps->slp_data_fname_valid) { 2317 diskLu->luAliasValid = B_TRUE; 2318 if (strlcpy(diskLu->luAlias, 2319 (char *)&(sbdProps->slp_buf[ 2320 sbdProps->slp_data_fname_off]), 2321 sizeof (diskLu->luAlias)) >= 2322 sizeof (diskLu->luAlias)) { 2323 return (STMF_STATUS_ERROR); 2324 } 2325 } 2326 } 2327 2328 diskLu->vidValid = B_TRUE; 2329 bcopy(sbdProps->slp_vid, diskLu->vid, sizeof (diskLu->vid)); 2330 2331 diskLu->pidValid = B_TRUE; 2332 bcopy(sbdProps->slp_pid, diskLu->pid, sizeof (diskLu->pid)); 2333 2334 diskLu->revValid = B_TRUE; 2335 bcopy(sbdProps->slp_rev, diskLu->rev, sizeof (diskLu->rev)); 2336 2337 diskLu->writeProtectEnableValid = B_TRUE; 2338 if (sbdProps->slp_write_protected) { 2339 diskLu->writeProtectEnable = B_TRUE; 2340 } 2341 2342 diskLu->writebackCacheDisableValid = B_TRUE; 2343 if (sbdProps->slp_writeback_cache_disable_cur) { 2344 diskLu->writebackCacheDisable = B_TRUE; 2345 } 2346 2347 diskLu->blkSizeValid = B_TRUE; 2348 diskLu->blkSize = sbdProps->slp_blksize; 2349 2350 diskLu->luSizeValid = B_TRUE; 2351 diskLu->luSize = sbdProps->slp_lu_size; 2352 2353 diskLu->accessState = sbdProps->slp_access_state; 2354 2355 return (ret); 2356 } 2357 2358 /* 2359 * stmfGetGlobalLuProp 2360 * 2361 * Purpose: get a global property for a device type 2362 * 2363 */ 2364 int 2365 stmfGetGlobalLuProp(uint16_t dType, uint32_t prop, char *propVal, 2366 size_t *propLen) 2367 { 2368 int ret = STMF_STATUS_SUCCESS; 2369 if (dType != STMF_DISK || propVal == NULL) { 2370 return (STMF_ERROR_INVALID_ARG); 2371 } 2372 2373 ret = getDiskGlobalProp(prop, propVal, propLen); 2374 2375 return (ret); 2376 } 2377 2378 /* 2379 * getDiskGlobalProp 2380 * 2381 * Purpose: get global property from sbd driver 2382 * 2383 */ 2384 static int 2385 getDiskGlobalProp(uint32_t prop, char *propVal, size_t *propLen) 2386 { 2387 int ret = STMF_STATUS_SUCCESS; 2388 int fd; 2389 sbd_global_props_t *sbdProps; 2390 void *sbd_realloc; 2391 int retryCnt = 0; 2392 boolean_t retry; 2393 int ioctlRet; 2394 int savedErrno; 2395 int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS; 2396 stmf_iocdata_t sbdIoctl = {0}; 2397 size_t reqLen; 2398 2399 switch (prop) { 2400 case STMF_LU_PROP_MGMT_URL: 2401 break; 2402 default: 2403 return (STMF_ERROR_INVALID_PROP); 2404 } 2405 2406 /* 2407 * Open control node for sbd 2408 */ 2409 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS) 2410 return (ret); 2411 2412 sbdProps = calloc(1, sbdPropsSize); 2413 if (sbdProps == NULL) { 2414 (void) close(fd); 2415 return (STMF_ERROR_NOMEM); 2416 } 2417 2418 do { 2419 retry = B_FALSE; 2420 sbdIoctl.stmf_version = STMF_VERSION_1; 2421 sbdIoctl.stmf_obuf_size = sbdPropsSize; 2422 sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps; 2423 ioctlRet = ioctl(fd, SBD_IOCTL_GET_GLOBAL_LU, &sbdIoctl); 2424 if (ioctlRet != 0) { 2425 savedErrno = errno; 2426 switch (savedErrno) { 2427 case EBUSY: 2428 ret = STMF_ERROR_BUSY; 2429 break; 2430 case EPERM: 2431 case EACCES: 2432 ret = STMF_ERROR_PERM; 2433 break; 2434 case ENOMEM: 2435 if (sbdIoctl.stmf_error == 2436 SBD_RET_INSUFFICIENT_BUF_SPACE && 2437 retryCnt++ < 3) { 2438 sbdPropsSize = 2439 sizeof (*sbdProps) + 2440 sbdProps-> 2441 mlu_buf_size_needed; 2442 2443 sbd_realloc = sbdProps; 2444 sbdProps = realloc(sbdProps, 2445 sbdPropsSize); 2446 if (sbdProps == NULL) { 2447 free(sbd_realloc); 2448 ret = STMF_ERROR_NOMEM; 2449 break; 2450 } 2451 retry = B_TRUE; 2452 } else { 2453 ret = STMF_ERROR_NOMEM; 2454 } 2455 break; 2456 default: 2457 syslog(LOG_DEBUG, 2458 "getDiskGlobalProp:ioctl error(%d)" 2459 "(%d)(%d)", ioctlRet, 2460 sbdIoctl.stmf_error, savedErrno); 2461 ret = STMF_STATUS_ERROR; 2462 break; 2463 } 2464 2465 } 2466 } while (retry); 2467 2468 if (ret != STMF_STATUS_SUCCESS) { 2469 goto done; 2470 } 2471 2472 switch (prop) { 2473 case STMF_LU_PROP_MGMT_URL: 2474 if (sbdProps->mlu_mgmt_url_valid == 0) { 2475 ret = STMF_ERROR_NO_PROP; 2476 goto done; 2477 } 2478 if ((reqLen = strlcpy(propVal, (char *)&( 2479 sbdProps->mlu_buf[sbdProps->mlu_mgmt_url_off]), 2480 *propLen)) >= *propLen) { 2481 *propLen = reqLen + 1; 2482 ret = STMF_ERROR_INVALID_ARG; 2483 goto done; 2484 } 2485 break; 2486 } 2487 2488 done: 2489 free(sbdProps); 2490 (void) close(fd); 2491 return (ret); 2492 } 2493 2494 /* 2495 * stmfSetGlobalLuProp 2496 * 2497 * Purpose: set a global property for a device type 2498 * 2499 */ 2500 int 2501 stmfSetGlobalLuProp(uint16_t dType, uint32_t prop, const char *propVal) 2502 { 2503 int ret = STMF_STATUS_SUCCESS; 2504 if (dType != STMF_DISK || propVal == NULL) { 2505 return (STMF_ERROR_INVALID_ARG); 2506 } 2507 2508 ret = setDiskGlobalProp(prop, propVal); 2509 2510 return (ret); 2511 } 2512 2513 /* 2514 * setDiskGlobalProp 2515 * 2516 * Purpose: set properties for resource of type disk 2517 * 2518 * resourceProp - valid resource identifier 2519 * propVal - valid resource value 2520 */ 2521 static int 2522 setDiskGlobalProp(uint32_t resourceProp, const char *propVal) 2523 { 2524 int ret = STMF_STATUS_SUCCESS; 2525 sbd_global_props_t *sbdGlobalProps = NULL; 2526 int sbdGlobalPropsSize = 0; 2527 int propLen; 2528 int mluBufSize = 0; 2529 int fd; 2530 int savedErrno; 2531 int ioctlRet; 2532 stmf_iocdata_t sbdIoctl = {0}; 2533 2534 switch (resourceProp) { 2535 case STMF_LU_PROP_MGMT_URL: 2536 break; 2537 default: 2538 return (STMF_ERROR_INVALID_PROP); 2539 break; 2540 } 2541 2542 /* 2543 * Open control node for sbd 2544 */ 2545 if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS) 2546 return (ret); 2547 2548 propLen = strlen(propVal); 2549 mluBufSize += propLen + 1; 2550 sbdGlobalPropsSize += sizeof (sbd_global_props_t) - 8 + 2551 max(8, mluBufSize); 2552 /* 2553 * 8 is the size of the buffer set aside for 2554 * concatenation of variable length fields 2555 */ 2556 sbdGlobalProps = (sbd_global_props_t *)calloc(1, sbdGlobalPropsSize); 2557 if (sbdGlobalProps == NULL) { 2558 (void) close(fd); 2559 return (STMF_ERROR_NOMEM); 2560 } 2561 2562 sbdGlobalProps->mlu_struct_size = sbdGlobalPropsSize; 2563 2564 switch (resourceProp) { 2565 case STMF_LU_PROP_MGMT_URL: 2566 sbdGlobalProps->mlu_mgmt_url_valid = 1; 2567 bcopy(propVal, &(sbdGlobalProps->mlu_buf), 2568 propLen + 1); 2569 break; 2570 default: 2571 ret = STMF_ERROR_NO_PROP; 2572 goto done; 2573 } 2574 2575 sbdIoctl.stmf_version = STMF_VERSION_1; 2576 sbdIoctl.stmf_ibuf_size = sbdGlobalProps->mlu_struct_size; 2577 sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdGlobalProps; 2578 2579 ioctlRet = ioctl(fd, SBD_IOCTL_SET_GLOBAL_LU, &sbdIoctl); 2580 if (ioctlRet != 0) { 2581 savedErrno = errno; 2582 switch (savedErrno) { 2583 case EBUSY: 2584 ret = STMF_ERROR_BUSY; 2585 break; 2586 case EPERM: 2587 case EACCES: 2588 ret = STMF_ERROR_PERM; 2589 break; 2590 default: 2591 diskError(sbdIoctl.stmf_error, &ret); 2592 if (ret == STMF_STATUS_ERROR) { 2593 syslog(LOG_DEBUG, 2594 "modifyDiskLu:ioctl " 2595 "error(%d) (%d) (%d)", ioctlRet, 2596 sbdIoctl.stmf_error, savedErrno); 2597 } 2598 break; 2599 } 2600 } 2601 2602 done: 2603 free(sbdGlobalProps); 2604 (void) close(fd); 2605 return (ret); 2606 } 2607 2608 2609 /* 2610 * stmfSetLuProp 2611 * 2612 * Purpose: set a property on an luResource 2613 * 2614 * hdl - allocated luResource 2615 * prop - property identifier 2616 * propVal - property value to be set 2617 */ 2618 int 2619 stmfSetLuProp(luResource hdl, uint32_t prop, const char *propVal) 2620 { 2621 int ret = STMF_STATUS_SUCCESS; 2622 luResourceImpl *luPropsHdl = hdl; 2623 if (hdl == NULL) { 2624 return (STMF_ERROR_INVALID_ARG); 2625 } 2626 2627 if (luPropsHdl->type == STMF_DISK) { 2628 ret = setDiskProp(luPropsHdl, prop, propVal); 2629 } else { 2630 return (STMF_ERROR_INVALID_ARG); 2631 } 2632 2633 return (ret); 2634 } 2635 2636 /* 2637 * getDiskProp 2638 * 2639 * Purpose: retrieve a given property from a logical unit resource of type disk 2640 * 2641 * hdl - allocated luResourceImpl 2642 * prop - property identifier 2643 * propVal - pointer to character to contain the retrieved property value 2644 * propLen - On input this is the length of propVal. On failure, it contains the 2645 * number of bytes required for propVal 2646 */ 2647 static int 2648 getDiskProp(luResourceImpl *hdl, uint32_t prop, char *propVal, size_t *propLen) 2649 { 2650 int ret = STMF_STATUS_SUCCESS; 2651 diskResource *diskLu = hdl->resource; 2652 char accessState[20]; 2653 size_t reqLen; 2654 2655 if (prop == STMF_LU_PROP_ACCESS_STATE) { 2656 if (diskLu->accessState == SBD_LU_ACTIVE) { 2657 (void) strlcpy(accessState, STMF_ACCESS_ACTIVE, 2658 sizeof (accessState)); 2659 } else if (diskLu->accessState == SBD_LU_TRANSITION_TO_ACTIVE) { 2660 (void) strlcpy(accessState, 2661 STMF_ACCESS_STANDBY_TO_ACTIVE, 2662 sizeof (accessState)); 2663 } else if (diskLu->accessState == SBD_LU_STANDBY) { 2664 (void) strlcpy(accessState, STMF_ACCESS_STANDBY, 2665 sizeof (accessState)); 2666 } else if (diskLu->accessState == 2667 SBD_LU_TRANSITION_TO_STANDBY) { 2668 (void) strlcpy(accessState, 2669 STMF_ACCESS_ACTIVE_TO_STANDBY, 2670 sizeof (accessState)); 2671 } 2672 if ((reqLen = strlcpy(propVal, accessState, 2673 *propLen)) >= *propLen) { 2674 *propLen = reqLen + 1; 2675 return (STMF_ERROR_INVALID_ARG); 2676 } 2677 return (0); 2678 } 2679 2680 if (diskLu->accessState != SBD_LU_ACTIVE) { 2681 return (STMF_ERROR_NO_PROP_STANDBY); 2682 } 2683 2684 switch (prop) { 2685 case STMF_LU_PROP_BLOCK_SIZE: 2686 if (diskLu->blkSizeValid == B_FALSE) { 2687 return (STMF_ERROR_NO_PROP); 2688 } 2689 reqLen = snprintf(propVal, *propLen, "%llu", 2690 (u_longlong_t)diskLu->blkSize); 2691 if (reqLen >= *propLen) { 2692 *propLen = reqLen + 1; 2693 return (STMF_ERROR_INVALID_ARG); 2694 } 2695 break; 2696 case STMF_LU_PROP_FILENAME: 2697 if (diskLu->luDataFileNameValid == B_FALSE) { 2698 return (STMF_ERROR_NO_PROP); 2699 } 2700 if ((reqLen = strlcpy(propVal, diskLu->luDataFileName, 2701 *propLen)) >= *propLen) { 2702 *propLen = reqLen + 1; 2703 return (STMF_ERROR_INVALID_ARG); 2704 } 2705 break; 2706 case STMF_LU_PROP_META_FILENAME: 2707 if (diskLu->luMetaFileNameValid == B_FALSE) { 2708 return (STMF_ERROR_NO_PROP); 2709 } 2710 if ((reqLen = strlcpy(propVal, diskLu->luMetaFileName, 2711 *propLen)) >= *propLen) { 2712 *propLen = reqLen + 1; 2713 return (STMF_ERROR_INVALID_ARG); 2714 } 2715 break; 2716 case STMF_LU_PROP_MGMT_URL: 2717 if (diskLu->luMgmtUrlValid == B_FALSE) { 2718 return (STMF_ERROR_NO_PROP); 2719 } 2720 if ((reqLen = strlcpy(propVal, diskLu->luMgmtUrl, 2721 *propLen)) >= *propLen) { 2722 *propLen = reqLen + 1; 2723 return (STMF_ERROR_INVALID_ARG); 2724 } 2725 break; 2726 case STMF_LU_PROP_GUID: 2727 if (diskLu->luGuidValid == B_FALSE) { 2728 return (STMF_ERROR_NO_PROP); 2729 } 2730 reqLen = snprintf(propVal, *propLen, 2731 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X" 2732 "%02X%02X%02X%02X", 2733 diskLu->luGuid[0], diskLu->luGuid[1], 2734 diskLu->luGuid[2], diskLu->luGuid[3], 2735 diskLu->luGuid[4], diskLu->luGuid[5], 2736 diskLu->luGuid[6], diskLu->luGuid[7], 2737 diskLu->luGuid[8], diskLu->luGuid[9], 2738 diskLu->luGuid[10], diskLu->luGuid[11], 2739 diskLu->luGuid[12], diskLu->luGuid[13], 2740 diskLu->luGuid[14], diskLu->luGuid[15]); 2741 if (reqLen >= *propLen) { 2742 *propLen = reqLen + 1; 2743 return (STMF_ERROR_INVALID_ARG); 2744 } 2745 break; 2746 case STMF_LU_PROP_SERIAL_NUM: 2747 if (diskLu->serialNumValid == B_FALSE) { 2748 return (STMF_ERROR_NO_PROP); 2749 } 2750 if ((reqLen = strlcpy(propVal, diskLu->serialNum, 2751 *propLen)) >= *propLen) { 2752 *propLen = reqLen + 1; 2753 return (STMF_ERROR_INVALID_ARG); 2754 } 2755 break; 2756 case STMF_LU_PROP_SIZE: 2757 if (diskLu->luSizeValid == B_FALSE) { 2758 return (STMF_ERROR_NO_PROP); 2759 } 2760 (void) snprintf(propVal, *propLen, "%llu", 2761 (u_longlong_t)diskLu->luSize); 2762 break; 2763 case STMF_LU_PROP_ALIAS: 2764 if (diskLu->luAliasValid == B_FALSE) { 2765 return (STMF_ERROR_NO_PROP); 2766 } 2767 if ((reqLen = strlcpy(propVal, diskLu->luAlias, 2768 *propLen)) >= *propLen) { 2769 *propLen = reqLen + 1; 2770 return (STMF_ERROR_INVALID_ARG); 2771 } 2772 break; 2773 case STMF_LU_PROP_VID: 2774 if (diskLu->vidValid == B_FALSE) { 2775 return (STMF_ERROR_NO_PROP); 2776 } 2777 if (*propLen <= sizeof (diskLu->vid)) { 2778 return (STMF_ERROR_INVALID_ARG); 2779 } 2780 bcopy(diskLu->vid, propVal, sizeof (diskLu->vid)); 2781 propVal[sizeof (diskLu->vid)] = 0; 2782 break; 2783 case STMF_LU_PROP_PID: 2784 if (diskLu->pidValid == B_FALSE) { 2785 return (STMF_ERROR_NO_PROP); 2786 } 2787 if (*propLen <= sizeof (diskLu->pid)) { 2788 return (STMF_ERROR_INVALID_ARG); 2789 } 2790 bcopy(diskLu->pid, propVal, sizeof (diskLu->pid)); 2791 propVal[sizeof (diskLu->pid)] = 0; 2792 break; 2793 case STMF_LU_PROP_WRITE_PROTECT: 2794 if (diskLu->writeProtectEnableValid == B_FALSE) { 2795 return (STMF_ERROR_NO_PROP); 2796 } 2797 if (diskLu->writeProtectEnable) { 2798 if ((reqLen = strlcpy(propVal, "true", 2799 *propLen)) >= *propLen) { 2800 *propLen = reqLen + 1; 2801 return (STMF_ERROR_INVALID_ARG); 2802 } 2803 } else { 2804 if ((reqLen = strlcpy(propVal, "false", 2805 *propLen)) >= *propLen) { 2806 *propLen = reqLen + 1; 2807 return (STMF_ERROR_INVALID_ARG); 2808 } 2809 } 2810 break; 2811 case STMF_LU_PROP_WRITE_CACHE_DISABLE: 2812 if (diskLu->writebackCacheDisableValid == B_FALSE) { 2813 return (STMF_ERROR_NO_PROP); 2814 } 2815 if (diskLu->writebackCacheDisable) { 2816 if ((reqLen = strlcpy(propVal, "true", 2817 *propLen)) >= *propLen) { 2818 *propLen = reqLen + 1; 2819 return (STMF_ERROR_INVALID_ARG); 2820 } 2821 } else { 2822 if ((reqLen = strlcpy(propVal, "false", 2823 *propLen)) >= *propLen) { 2824 *propLen = reqLen + 1; 2825 return (STMF_ERROR_INVALID_ARG); 2826 } 2827 } 2828 break; 2829 default: 2830 ret = STMF_ERROR_INVALID_PROP; 2831 break; 2832 } 2833 2834 return (ret); 2835 } 2836 2837 /* 2838 * setDiskProp 2839 * 2840 * Purpose: set properties for resource of type disk 2841 * 2842 * hdl - allocated luResourceImpl 2843 * resourceProp - valid resource identifier 2844 * propVal - valid resource value 2845 */ 2846 static int 2847 setDiskProp(luResourceImpl *hdl, uint32_t resourceProp, const char *propVal) 2848 { 2849 int ret = STMF_STATUS_SUCCESS; 2850 int i; 2851 diskResource *diskLu = hdl->resource; 2852 unsigned long long numericProp = 0; 2853 char guidProp[LU_ASCII_GUID_SIZE + 1]; 2854 char ouiProp[OUI_ASCII_SIZE + 1]; 2855 char hostIdProp[HOST_ID_ASCII_SIZE + 1]; 2856 unsigned int oui[OUI_SIZE]; 2857 unsigned int hostId[HOST_ID_SIZE]; 2858 unsigned int guid[LU_GUID_SIZE]; 2859 int propSize; 2860 2861 2862 if (propVal == NULL) { 2863 return (STMF_ERROR_INVALID_ARG); 2864 } 2865 2866 switch (resourceProp) { 2867 case STMF_LU_PROP_ALIAS: 2868 if (strlcpy(diskLu->luAlias, propVal, 2869 sizeof (diskLu->luAlias)) >= 2870 sizeof (diskLu->luAlias)) { 2871 return (STMF_ERROR_INVALID_PROPSIZE); 2872 } 2873 diskLu->luAliasValid = B_TRUE; 2874 break; 2875 case STMF_LU_PROP_BLOCK_SIZE: 2876 (void) sscanf(propVal, "%llu", &numericProp); 2877 if (numericProp > UINT16_MAX) { 2878 return (STMF_ERROR_INVALID_PROPSIZE); 2879 } 2880 diskLu->blkSize = numericProp; 2881 diskLu->blkSizeValid = B_TRUE; 2882 break; 2883 case STMF_LU_PROP_COMPANY_ID: 2884 if ((strlcpy(ouiProp, propVal, sizeof (ouiProp))) >= 2885 sizeof (ouiProp)) { 2886 return (STMF_ERROR_INVALID_ARG); 2887 } 2888 if (checkHexUpper(ouiProp) != 0) { 2889 return (STMF_ERROR_INVALID_ARG); 2890 } 2891 (void) sscanf(ouiProp, "%2X%2X%2X", 2892 &oui[0], &oui[1], &oui[2]); 2893 2894 diskLu->companyId = 0; 2895 diskLu->companyId += oui[0] << 16; 2896 diskLu->companyId += oui[1] << 8; 2897 diskLu->companyId += oui[2]; 2898 if (diskLu->companyId == 0) { 2899 return (STMF_ERROR_INVALID_ARG); 2900 } 2901 diskLu->companyIdValid = B_TRUE; 2902 break; 2903 case STMF_LU_PROP_HOST_ID: 2904 if ((strlcpy(hostIdProp, propVal, 2905 sizeof (hostIdProp))) >= sizeof (hostIdProp)) { 2906 return (STMF_ERROR_INVALID_ARG); 2907 } 2908 if (checkHexUpper(hostIdProp) != 0) { 2909 return (STMF_ERROR_INVALID_ARG); 2910 } 2911 (void) sscanf(hostIdProp, "%2X%2X%2X%2X", 2912 &hostId[0], &hostId[1], &hostId[2], &hostId[3]); 2913 2914 diskLu->hostId = 0; 2915 diskLu->hostId += hostId[0] << 24; 2916 diskLu->hostId += hostId[1] << 16; 2917 diskLu->hostId += hostId[2] << 8; 2918 diskLu->hostId += hostId[3]; 2919 if (diskLu->hostId == 0) { 2920 return (STMF_ERROR_INVALID_ARG); 2921 } 2922 diskLu->hostIdValid = B_TRUE; 2923 break; 2924 case STMF_LU_PROP_GUID: 2925 if (strlen(propVal) != LU_ASCII_GUID_SIZE) { 2926 return (STMF_ERROR_INVALID_PROPSIZE); 2927 } 2928 2929 if ((strlcpy(guidProp, propVal, sizeof (guidProp))) >= 2930 sizeof (guidProp)) { 2931 return (STMF_ERROR_INVALID_ARG); 2932 } 2933 2934 if (checkHexUpper(guidProp) != 0) { 2935 return (STMF_ERROR_INVALID_ARG); 2936 } 2937 2938 (void) sscanf(guidProp, 2939 "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X", 2940 &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], 2941 &guid[5], &guid[6], &guid[7], &guid[8], &guid[9], 2942 &guid[10], &guid[11], &guid[12], &guid[13], 2943 &guid[14], &guid[15]); 2944 for (i = 0; i < sizeof (diskLu->luGuid); i++) { 2945 diskLu->luGuid[i] = guid[i]; 2946 } 2947 diskLu->luGuidValid = B_TRUE; 2948 break; 2949 case STMF_LU_PROP_FILENAME: 2950 if ((strlcpy(diskLu->luDataFileName, propVal, 2951 sizeof (diskLu->luDataFileName))) >= 2952 sizeof (diskLu->luDataFileName)) { 2953 return (STMF_ERROR_INVALID_PROPSIZE); 2954 } 2955 diskLu->luDataFileNameValid = B_TRUE; 2956 break; 2957 case STMF_LU_PROP_META_FILENAME: 2958 if ((strlcpy(diskLu->luMetaFileName, propVal, 2959 sizeof (diskLu->luMetaFileName))) >= 2960 sizeof (diskLu->luMetaFileName)) { 2961 return (STMF_ERROR_INVALID_PROPSIZE); 2962 } 2963 diskLu->luMetaFileNameValid = B_TRUE; 2964 break; 2965 case STMF_LU_PROP_MGMT_URL: 2966 if ((strlcpy(diskLu->luMgmtUrl, propVal, 2967 sizeof (diskLu->luMgmtUrl))) >= 2968 sizeof (diskLu->luMgmtUrl)) { 2969 return (STMF_ERROR_INVALID_PROPSIZE); 2970 } 2971 diskLu->luMgmtUrlValid = B_TRUE; 2972 break; 2973 case STMF_LU_PROP_PID: 2974 if ((propSize = strlen(propVal)) > 2975 sizeof (diskLu->pid)) { 2976 return (STMF_ERROR_INVALID_PROPSIZE); 2977 } 2978 (void) strncpy(diskLu->pid, propVal, propSize); 2979 diskLu->pidValid = B_TRUE; 2980 break; 2981 case STMF_LU_PROP_SERIAL_NUM: 2982 if ((propSize = strlen(propVal)) > 2983 (sizeof (diskLu->serialNum) - 1)) { 2984 return (STMF_ERROR_INVALID_PROPSIZE); 2985 } 2986 (void) strncpy(diskLu->serialNum, propVal, propSize); 2987 diskLu->serialNumValid = B_TRUE; 2988 break; 2989 case STMF_LU_PROP_SIZE: 2990 if ((niceStrToNum(propVal, &diskLu->luSize) != 0)) { 2991 return (STMF_ERROR_INVALID_ARG); 2992 } 2993 diskLu->luSizeValid = B_TRUE; 2994 break; 2995 case STMF_LU_PROP_VID: 2996 if ((propSize = strlen(propVal)) > 2997 sizeof (diskLu->vid)) { 2998 return (STMF_ERROR_INVALID_PROPSIZE); 2999 } 3000 (void) strncpy(diskLu->vid, propVal, propSize); 3001 diskLu->vidValid = B_TRUE; 3002 break; 3003 case STMF_LU_PROP_WRITE_PROTECT: 3004 if (strcasecmp(propVal, "TRUE") == 0) { 3005 diskLu->writeProtectEnable = B_TRUE; 3006 } else if (strcasecmp(propVal, "FALSE") == 0) { 3007 diskLu->writeProtectEnable = B_FALSE; 3008 } else { 3009 return (STMF_ERROR_INVALID_ARG); 3010 } 3011 diskLu->writeProtectEnableValid = B_TRUE; 3012 break; 3013 case STMF_LU_PROP_WRITE_CACHE_DISABLE: 3014 if (strcasecmp(propVal, "TRUE") == 0) { 3015 diskLu->writebackCacheDisable = B_TRUE; 3016 } else if (strcasecmp(propVal, "FALSE") == 0) { 3017 diskLu->writebackCacheDisable = B_FALSE; 3018 } else { 3019 return (STMF_ERROR_INVALID_ARG); 3020 } 3021 diskLu->writebackCacheDisableValid = B_TRUE; 3022 break; 3023 case STMF_LU_PROP_ACCESS_STATE: 3024 ret = STMF_ERROR_INVALID_PROP; 3025 break; 3026 default: 3027 ret = STMF_ERROR_INVALID_PROP; 3028 break; 3029 } 3030 return (ret); 3031 } 3032 3033 static int 3034 checkHexUpper(char *buf) 3035 { 3036 int i; 3037 3038 for (i = 0; i < strlen(buf); i++) { 3039 if (isxdigit(buf[i])) { 3040 buf[i] = toupper(buf[i]); 3041 continue; 3042 } 3043 return (-1); 3044 } 3045 3046 return (0); 3047 } 3048 3049 /* 3050 * Given a numeric suffix, convert the value into a number of bits that the 3051 * resulting value must be shifted. 3052 * Code lifted from libzfs_util.c 3053 */ 3054 static int 3055 strToShift(const char *buf) 3056 { 3057 const char *ends = "BKMGTPE"; 3058 int i; 3059 3060 if (buf[0] == '\0') 3061 return (0); 3062 3063 for (i = 0; i < strlen(ends); i++) { 3064 if (toupper(buf[0]) == ends[i]) 3065 return (10*i); 3066 } 3067 3068 return (-1); 3069 } 3070 3071 int 3072 stmfFreeLuResource(luResource hdl) 3073 { 3074 int ret = STMF_STATUS_SUCCESS; 3075 if (hdl == NULL) { 3076 return (STMF_ERROR_INVALID_ARG); 3077 } 3078 3079 luResourceImpl *hdlImpl = hdl; 3080 free(hdlImpl->resource); 3081 free(hdlImpl); 3082 return (ret); 3083 } 3084 3085 /* 3086 * Convert a string of the form '100G' into a real number. Used when setting 3087 * the size of a logical unit. 3088 * Code lifted from libzfs_util.c 3089 */ 3090 static int 3091 niceStrToNum(const char *value, uint64_t *num) 3092 { 3093 char *end; 3094 int shift; 3095 3096 *num = 0; 3097 3098 /* Check to see if this looks like a number. */ 3099 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { 3100 return (-1); 3101 } 3102 3103 /* Rely on stroull() to process the numeric portion. */ 3104 errno = 0; 3105 *num = strtoull(value, &end, 10); 3106 3107 /* 3108 * Check for ERANGE, which indicates that the value is too large to fit 3109 * in a 64-bit value. 3110 */ 3111 if (errno == ERANGE) { 3112 return (-1); 3113 } 3114 3115 /* 3116 * If we have a decimal value, then do the computation with floating 3117 * point arithmetic. Otherwise, use standard arithmetic. 3118 */ 3119 if (*end == '.') { 3120 double fval = strtod(value, &end); 3121 3122 if ((shift = strToShift(end)) == -1) { 3123 return (-1); 3124 } 3125 3126 fval *= pow(2, shift); 3127 3128 if (fval > UINT64_MAX) { 3129 return (-1); 3130 } 3131 3132 *num = (uint64_t)fval; 3133 } else { 3134 if ((shift = strToShift(end)) == -1) { 3135 return (-1); 3136 } 3137 3138 /* Check for overflow */ 3139 if (shift >= 64 || (*num << shift) >> shift != *num) { 3140 return (-1); 3141 } 3142 3143 *num <<= shift; 3144 } 3145 3146 return (0); 3147 } 3148 3149 /* 3150 * stmfCreateTargetGroup 3151 * 3152 * Purpose: Create a local port group 3153 * 3154 * targetGroupName - name of local port group to create 3155 */ 3156 int 3157 stmfCreateTargetGroup(stmfGroupName *targetGroupName) 3158 { 3159 int ret; 3160 int fd; 3161 3162 if (targetGroupName == NULL || 3163 (strnlen((char *)targetGroupName, sizeof (stmfGroupName)) 3164 == sizeof (stmfGroupName))) { 3165 return (STMF_ERROR_INVALID_ARG); 3166 } 3167 3168 /* Check to ensure service exists */ 3169 if (psCheckService() != STMF_STATUS_SUCCESS) { 3170 return (STMF_ERROR_SERVICE_NOT_FOUND); 3171 } 3172 3173 /* call init */ 3174 ret = initializeConfig(); 3175 if (ret != STMF_STATUS_SUCCESS) { 3176 return (ret); 3177 } 3178 3179 /* 3180 * Open control node for stmf 3181 */ 3182 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3183 return (ret); 3184 3185 /* 3186 * Add the group to the driver 3187 */ 3188 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP, 3189 targetGroupName)) != STMF_STATUS_SUCCESS) { 3190 goto done; 3191 } 3192 3193 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 3194 goto done; 3195 } 3196 3197 /* 3198 * If the add to the driver was successful, add it to the persistent 3199 * store. 3200 */ 3201 ret = psCreateTargetGroup((char *)targetGroupName); 3202 switch (ret) { 3203 case STMF_PS_SUCCESS: 3204 ret = STMF_STATUS_SUCCESS; 3205 break; 3206 case STMF_PS_ERROR_EXISTS: 3207 ret = STMF_ERROR_EXISTS; 3208 break; 3209 case STMF_PS_ERROR_BUSY: 3210 ret = STMF_ERROR_BUSY; 3211 break; 3212 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3213 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3214 break; 3215 case STMF_PS_ERROR_VERSION_MISMATCH: 3216 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3217 break; 3218 default: 3219 syslog(LOG_DEBUG, 3220 "stmfCreateTargetGroup:psCreateTargetGroup" 3221 ":error(%d)", ret); 3222 ret = STMF_STATUS_ERROR; 3223 break; 3224 } 3225 3226 done: 3227 (void) close(fd); 3228 return (ret); 3229 } 3230 3231 /* 3232 * stmfDeleteHostGroup 3233 * 3234 * Purpose: Delete an initiator or local port group 3235 * 3236 * hostGroupName - group to delete 3237 */ 3238 int 3239 stmfDeleteHostGroup(stmfGroupName *hostGroupName) 3240 { 3241 int ret; 3242 int fd; 3243 3244 if (hostGroupName == NULL) { 3245 return (STMF_ERROR_INVALID_ARG); 3246 } 3247 3248 /* Check to ensure service exists */ 3249 if (psCheckService() != STMF_STATUS_SUCCESS) { 3250 return (STMF_ERROR_SERVICE_NOT_FOUND); 3251 } 3252 3253 /* call init */ 3254 ret = initializeConfig(); 3255 if (ret != STMF_STATUS_SUCCESS) { 3256 return (ret); 3257 } 3258 3259 /* 3260 * Open control node for stmf 3261 */ 3262 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3263 return (ret); 3264 3265 /* 3266 * Remove the group from the driver 3267 */ 3268 if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP, 3269 hostGroupName)) != STMF_STATUS_SUCCESS) { 3270 goto done; 3271 } 3272 3273 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 3274 goto done; 3275 } 3276 3277 /* 3278 * If the remove from the driver was successful, remove it from the 3279 * persistent store. 3280 */ 3281 ret = psDeleteHostGroup((char *)hostGroupName); 3282 switch (ret) { 3283 case STMF_PS_SUCCESS: 3284 ret = STMF_STATUS_SUCCESS; 3285 break; 3286 case STMF_PS_ERROR_NOT_FOUND: 3287 ret = STMF_ERROR_NOT_FOUND; 3288 break; 3289 case STMF_PS_ERROR_BUSY: 3290 ret = STMF_ERROR_BUSY; 3291 break; 3292 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3293 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3294 break; 3295 case STMF_PS_ERROR_VERSION_MISMATCH: 3296 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3297 break; 3298 default: 3299 syslog(LOG_DEBUG, 3300 "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)", 3301 ret); 3302 ret = STMF_STATUS_ERROR; 3303 break; 3304 } 3305 3306 done: 3307 (void) close(fd); 3308 return (ret); 3309 } 3310 3311 /* 3312 * stmfDeleteTargetGroup 3313 * 3314 * Purpose: Delete an initiator or local port group 3315 * 3316 * targetGroupName - group to delete 3317 */ 3318 int 3319 stmfDeleteTargetGroup(stmfGroupName *targetGroupName) 3320 { 3321 int ret = STMF_STATUS_SUCCESS; 3322 int fd; 3323 3324 if (targetGroupName == NULL) { 3325 return (STMF_ERROR_INVALID_ARG); 3326 } 3327 3328 /* Check to ensure service exists */ 3329 if (psCheckService() != STMF_STATUS_SUCCESS) { 3330 return (STMF_ERROR_SERVICE_NOT_FOUND); 3331 } 3332 3333 /* call init */ 3334 ret = initializeConfig(); 3335 if (ret != STMF_STATUS_SUCCESS) { 3336 return (ret); 3337 } 3338 3339 /* 3340 * Open control node for stmf 3341 */ 3342 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3343 return (ret); 3344 3345 /* 3346 * Remove the group from the driver 3347 */ 3348 if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP, 3349 targetGroupName)) != STMF_STATUS_SUCCESS) { 3350 goto done; 3351 } 3352 3353 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 3354 goto done; 3355 } 3356 3357 /* 3358 * If the remove from the driver was successful, remove it from the 3359 * persistent store. 3360 */ 3361 ret = psDeleteTargetGroup((char *)targetGroupName); 3362 switch (ret) { 3363 case STMF_PS_SUCCESS: 3364 ret = STMF_STATUS_SUCCESS; 3365 break; 3366 case STMF_PS_ERROR_NOT_FOUND: 3367 ret = STMF_ERROR_NOT_FOUND; 3368 break; 3369 case STMF_PS_ERROR_BUSY: 3370 ret = STMF_ERROR_BUSY; 3371 break; 3372 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3373 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3374 break; 3375 case STMF_PS_ERROR_VERSION_MISMATCH: 3376 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3377 break; 3378 default: 3379 syslog(LOG_DEBUG, 3380 "stmfDeleteTargetGroup:psDeleteTargetGroup" 3381 ":error(%d)", ret); 3382 ret = STMF_STATUS_ERROR; 3383 break; 3384 } 3385 3386 done: 3387 (void) close(fd); 3388 return (ret); 3389 } 3390 3391 /* 3392 * stmfDevidFromIscsiName 3393 * 3394 * Purpose: convert an iSCSI name to an stmf devid 3395 * 3396 * iscsiName - unicode nul terminated utf-8 encoded iSCSI name 3397 * devid - on success, contains the converted iscsi name 3398 */ 3399 int 3400 stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid) 3401 { 3402 if (devid == NULL || iscsiName == NULL) 3403 return (STMF_ERROR_INVALID_ARG); 3404 3405 bzero(devid, sizeof (stmfDevid)); 3406 3407 /* Validate size of target */ 3408 if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME || 3409 devid->identLength < strlen(EUI) || 3410 devid->identLength < strlen(IQN)) { 3411 return (STMF_ERROR_INVALID_ARG); 3412 } 3413 3414 if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) && 3415 strncmp(iscsiName, IQN, strlen(IQN)) != 0) { 3416 return (STMF_ERROR_INVALID_ARG); 3417 } 3418 3419 /* copy UTF-8 bytes to ident */ 3420 bcopy(iscsiName, devid->ident, devid->identLength); 3421 3422 return (STMF_STATUS_SUCCESS); 3423 } 3424 3425 /* 3426 * stmfDevidFromWwn 3427 * 3428 * Purpose: convert a WWN to an stmf devid 3429 * 3430 * wwn - 8-byte wwn identifier 3431 * devid - on success, contains the converted wwn 3432 */ 3433 int 3434 stmfDevidFromWwn(uchar_t *wwn, stmfDevid *devid) 3435 { 3436 if (wwn == NULL || devid == NULL) 3437 return (STMF_ERROR_INVALID_ARG); 3438 3439 bzero(devid, sizeof (stmfDevid)); 3440 3441 /* Copy eui prefix */ 3442 (void) bcopy(WWN, devid->ident, strlen(WWN)); 3443 3444 /* Convert to ASCII uppercase hexadecimal string */ 3445 (void) snprintf((char *)&devid->ident[strlen(WWN)], 3446 sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X", 3447 wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 3448 3449 devid->identLength = strlen((char *)devid->ident); 3450 3451 return (STMF_STATUS_SUCCESS); 3452 } 3453 3454 /* 3455 * stmfFreeMemory 3456 * 3457 * Purpose: Free memory allocated by this library 3458 * 3459 * memory - previously allocated pointer of memory managed by library 3460 */ 3461 void 3462 stmfFreeMemory(void *memory) 3463 { 3464 free(memory); 3465 } 3466 3467 /* 3468 * get host group, target group list from stmf 3469 * 3470 * groupType - HOST_GROUP, TARGET_GROUP 3471 */ 3472 static int 3473 groupListIoctl(stmfGroupList **groupList, int groupType) 3474 { 3475 int ret; 3476 int fd; 3477 int ioctlRet; 3478 int i; 3479 int cmd; 3480 stmf_iocdata_t stmfIoctl; 3481 /* framework group list */ 3482 stmf_group_name_t *iGroupList = NULL; 3483 uint32_t groupListSize; 3484 3485 if (groupList == NULL) { 3486 return (STMF_ERROR_INVALID_ARG); 3487 } 3488 3489 if (groupType == HOST_GROUP) { 3490 cmd = STMF_IOCTL_GET_HG_LIST; 3491 } else if (groupType == TARGET_GROUP) { 3492 cmd = STMF_IOCTL_GET_TG_LIST; 3493 } else { 3494 return (STMF_ERROR_INVALID_ARG); 3495 } 3496 3497 /* call init */ 3498 ret = initializeConfig(); 3499 if (ret != STMF_STATUS_SUCCESS) { 3500 return (ret); 3501 } 3502 3503 /* 3504 * Open control node for stmf 3505 */ 3506 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3507 return (ret); 3508 3509 /* 3510 * Allocate ioctl input buffer 3511 */ 3512 groupListSize = ALLOC_GROUP; 3513 groupListSize = groupListSize * (sizeof (stmf_group_name_t)); 3514 iGroupList = (stmf_group_name_t *)calloc(1, groupListSize); 3515 if (iGroupList == NULL) { 3516 ret = STMF_ERROR_NOMEM; 3517 goto done; 3518 } 3519 3520 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3521 /* 3522 * Issue ioctl to get the group list 3523 */ 3524 stmfIoctl.stmf_version = STMF_VERSION_1; 3525 stmfIoctl.stmf_obuf_size = groupListSize; 3526 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList; 3527 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3528 if (ioctlRet != 0) { 3529 switch (errno) { 3530 case EBUSY: 3531 ret = STMF_ERROR_BUSY; 3532 break; 3533 case EPERM: 3534 case EACCES: 3535 ret = STMF_ERROR_PERM; 3536 break; 3537 default: 3538 syslog(LOG_DEBUG, 3539 "groupListIoctl:ioctl errno(%d)", 3540 errno); 3541 ret = STMF_STATUS_ERROR; 3542 break; 3543 } 3544 goto done; 3545 } 3546 /* 3547 * Check whether input buffer was large enough 3548 */ 3549 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GROUP) { 3550 groupListSize = stmfIoctl.stmf_obuf_max_nentries * 3551 sizeof (stmf_group_name_t); 3552 iGroupList = realloc(iGroupList, groupListSize); 3553 if (iGroupList == NULL) { 3554 ret = STMF_ERROR_NOMEM; 3555 goto done; 3556 } 3557 stmfIoctl.stmf_obuf_size = groupListSize; 3558 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList; 3559 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3560 if (ioctlRet != 0) { 3561 switch (errno) { 3562 case EBUSY: 3563 ret = STMF_ERROR_BUSY; 3564 break; 3565 case EPERM: 3566 case EACCES: 3567 ret = STMF_ERROR_PERM; 3568 break; 3569 default: 3570 syslog(LOG_DEBUG, 3571 "groupListIoctl:ioctl errno(%d)", 3572 errno); 3573 ret = STMF_STATUS_ERROR; 3574 break; 3575 } 3576 goto done; 3577 } 3578 } 3579 3580 /* allocate and copy to caller's buffer */ 3581 *groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) + 3582 sizeof (stmfGroupName) * stmfIoctl.stmf_obuf_nentries); 3583 if (*groupList == NULL) { 3584 ret = STMF_ERROR_NOMEM; 3585 goto done; 3586 } 3587 (*groupList)->cnt = stmfIoctl.stmf_obuf_nentries; 3588 for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) { 3589 bcopy(iGroupList[i].name, (*groupList)->name[i], 3590 sizeof (stmfGroupName)); 3591 } 3592 3593 done: 3594 free(iGroupList); 3595 (void) close(fd); 3596 return (ret); 3597 } 3598 3599 /* 3600 * get host group members, target group members from stmf 3601 * 3602 * groupProps - allocated on success 3603 * 3604 * groupType - HOST_GROUP, TARGET_GROUP 3605 */ 3606 static int 3607 groupMemberListIoctl(stmfGroupName *groupName, stmfGroupProperties **groupProps, 3608 int groupType) 3609 { 3610 int ret; 3611 int fd; 3612 int ioctlRet; 3613 int i; 3614 int cmd; 3615 stmf_iocdata_t stmfIoctl; 3616 /* framework group list */ 3617 stmf_group_name_t iGroupName; 3618 stmf_ge_ident_t *iGroupMembers; 3619 uint32_t groupListSize; 3620 3621 if (groupName == NULL) { 3622 return (STMF_ERROR_INVALID_ARG); 3623 } 3624 3625 if (groupType == HOST_GROUP) { 3626 cmd = STMF_IOCTL_GET_HG_ENTRIES; 3627 } else if (groupType == TARGET_GROUP) { 3628 cmd = STMF_IOCTL_GET_TG_ENTRIES; 3629 } else { 3630 return (STMF_ERROR_INVALID_ARG); 3631 } 3632 3633 /* call init */ 3634 ret = initializeConfig(); 3635 if (ret != STMF_STATUS_SUCCESS) { 3636 return (ret); 3637 } 3638 3639 /* 3640 * Open control node for stmf 3641 */ 3642 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3643 return (ret); 3644 3645 bzero(&iGroupName, sizeof (iGroupName)); 3646 3647 bcopy(groupName, &iGroupName.name, strlen((char *)groupName)); 3648 3649 iGroupName.name_size = strlen((char *)groupName); 3650 3651 /* 3652 * Allocate ioctl input buffer 3653 */ 3654 groupListSize = ALLOC_GRP_MEMBER; 3655 groupListSize = groupListSize * (sizeof (stmf_ge_ident_t)); 3656 iGroupMembers = (stmf_ge_ident_t *)calloc(1, groupListSize); 3657 if (iGroupMembers == NULL) { 3658 ret = STMF_ERROR_NOMEM; 3659 goto done; 3660 } 3661 3662 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3663 /* 3664 * Issue ioctl to get the group list 3665 */ 3666 stmfIoctl.stmf_version = STMF_VERSION_1; 3667 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName; 3668 stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t); 3669 stmfIoctl.stmf_obuf_size = groupListSize; 3670 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers; 3671 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3672 if (ioctlRet != 0) { 3673 switch (errno) { 3674 case EBUSY: 3675 ret = STMF_ERROR_BUSY; 3676 break; 3677 case EPERM: 3678 case EACCES: 3679 ret = STMF_ERROR_PERM; 3680 break; 3681 default: 3682 syslog(LOG_DEBUG, 3683 "groupListIoctl:ioctl errno(%d)", 3684 errno); 3685 ret = STMF_STATUS_ERROR; 3686 break; 3687 } 3688 goto done; 3689 } 3690 /* 3691 * Check whether input buffer was large enough 3692 */ 3693 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GRP_MEMBER) { 3694 groupListSize = stmfIoctl.stmf_obuf_max_nentries * 3695 sizeof (stmf_ge_ident_t); 3696 iGroupMembers = realloc(iGroupMembers, groupListSize); 3697 if (iGroupMembers == NULL) { 3698 ret = STMF_ERROR_NOMEM; 3699 goto done; 3700 } 3701 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName; 3702 stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t); 3703 stmfIoctl.stmf_obuf_size = groupListSize; 3704 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers; 3705 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3706 if (ioctlRet != 0) { 3707 switch (errno) { 3708 case EBUSY: 3709 ret = STMF_ERROR_BUSY; 3710 break; 3711 case EPERM: 3712 case EACCES: 3713 ret = STMF_ERROR_PERM; 3714 break; 3715 default: 3716 syslog(LOG_DEBUG, 3717 "groupListIoctl:ioctl errno(%d)", 3718 errno); 3719 ret = STMF_STATUS_ERROR; 3720 break; 3721 } 3722 goto done; 3723 } 3724 } 3725 3726 /* allocate and copy to caller's buffer */ 3727 *groupProps = (stmfGroupProperties *)calloc(1, 3728 sizeof (stmfGroupProperties) + 3729 sizeof (stmfDevid) * stmfIoctl.stmf_obuf_nentries); 3730 if (*groupProps == NULL) { 3731 ret = STMF_ERROR_NOMEM; 3732 goto done; 3733 } 3734 (*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries; 3735 for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) { 3736 (*groupProps)->name[i].identLength = 3737 iGroupMembers[i].ident_size; 3738 bcopy(iGroupMembers[i].ident, (*groupProps)->name[i].ident, 3739 iGroupMembers[i].ident_size); 3740 } 3741 3742 done: 3743 free(iGroupMembers); 3744 (void) close(fd); 3745 return (ret); 3746 } 3747 3748 /* 3749 * Purpose: access persistent config data for host groups and target groups 3750 */ 3751 static int 3752 iLoadGroupFromPs(stmfGroupList **groupList, int type) 3753 { 3754 int ret; 3755 3756 if (groupList == NULL) { 3757 return (STMF_ERROR_INVALID_ARG); 3758 } 3759 3760 if (type == HOST_GROUP) { 3761 ret = psGetHostGroupList(groupList); 3762 } else if (type == TARGET_GROUP) { 3763 ret = psGetTargetGroupList(groupList); 3764 } else { 3765 return (STMF_ERROR_INVALID_ARG); 3766 } 3767 switch (ret) { 3768 case STMF_PS_SUCCESS: 3769 ret = STMF_STATUS_SUCCESS; 3770 break; 3771 case STMF_PS_ERROR_NOT_FOUND: 3772 ret = STMF_ERROR_NOT_FOUND; 3773 break; 3774 case STMF_PS_ERROR_BUSY: 3775 ret = STMF_ERROR_BUSY; 3776 break; 3777 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3778 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3779 break; 3780 case STMF_PS_ERROR_VERSION_MISMATCH: 3781 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3782 break; 3783 default: 3784 syslog(LOG_DEBUG, 3785 "stmfGetHostGroupList:psGetHostGroupList:error(%d)", 3786 ret); 3787 ret = STMF_STATUS_ERROR; 3788 break; 3789 } 3790 3791 return (ret); 3792 } 3793 3794 /* 3795 * stmfGetHostGroupList 3796 * 3797 * Purpose: Retrieves the list of initiator group oids 3798 * 3799 * hostGroupList - pointer to pointer to hostGroupList structure 3800 * on success, this contains the host group list. 3801 */ 3802 int 3803 stmfGetHostGroupList(stmfGroupList **hostGroupList) 3804 { 3805 int ret = STMF_STATUS_ERROR; 3806 3807 if (hostGroupList == NULL) { 3808 return (STMF_ERROR_INVALID_ARG); 3809 } 3810 3811 ret = groupListIoctl(hostGroupList, HOST_GROUP); 3812 return (ret); 3813 } 3814 3815 3816 /* 3817 * Purpose: access persistent config data for host groups and target groups 3818 */ 3819 static int 3820 iLoadGroupMembersFromPs(stmfGroupName *groupName, 3821 stmfGroupProperties **groupProp, int type) 3822 { 3823 int ret; 3824 3825 if (groupName == NULL) { 3826 return (STMF_ERROR_INVALID_ARG); 3827 } 3828 3829 if (type == HOST_GROUP) { 3830 ret = psGetHostGroupMemberList((char *)groupName, groupProp); 3831 } else if (type == TARGET_GROUP) { 3832 ret = psGetTargetGroupMemberList((char *)groupName, groupProp); 3833 } else { 3834 return (STMF_ERROR_INVALID_ARG); 3835 } 3836 switch (ret) { 3837 case STMF_PS_SUCCESS: 3838 ret = STMF_STATUS_SUCCESS; 3839 break; 3840 case STMF_PS_ERROR_NOT_FOUND: 3841 ret = STMF_ERROR_NOT_FOUND; 3842 break; 3843 case STMF_PS_ERROR_BUSY: 3844 ret = STMF_ERROR_BUSY; 3845 break; 3846 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3847 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3848 break; 3849 case STMF_PS_ERROR_VERSION_MISMATCH: 3850 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3851 break; 3852 default: 3853 syslog(LOG_DEBUG, 3854 "iLoadGroupMembersFromPs:psGetHostGroupList:" 3855 "error(%d)", ret); 3856 ret = STMF_STATUS_ERROR; 3857 break; 3858 } 3859 3860 return (ret); 3861 } 3862 3863 /* 3864 * stmfGetHostGroupMembers 3865 * 3866 * Purpose: Retrieves the group properties for a host group 3867 * 3868 * groupName - name of group for which to retrieve host group members. 3869 * groupProp - pointer to pointer to stmfGroupProperties structure 3870 * on success, this contains the list of group members. 3871 */ 3872 int 3873 stmfGetHostGroupMembers(stmfGroupName *groupName, 3874 stmfGroupProperties **groupProp) 3875 { 3876 int ret; 3877 3878 if (groupName == NULL || groupProp == NULL) { 3879 return (STMF_ERROR_INVALID_ARG); 3880 } 3881 3882 ret = groupMemberListIoctl(groupName, groupProp, HOST_GROUP); 3883 3884 return (ret); 3885 } 3886 3887 /* 3888 * stmfGetProviderData 3889 * 3890 * Purpose: Get provider data list 3891 * 3892 * providerName - name of provider for which to retrieve the data 3893 * nvl - pointer to nvlist_t pointer which will contain the nvlist data 3894 * retrieved. 3895 * providerType - type of provider for which to retrieve data. 3896 * STMF_LU_PROVIDER_TYPE 3897 * STMF_PORT_PROVIDER_TYPE 3898 */ 3899 int 3900 stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType) 3901 { 3902 return (stmfGetProviderDataProt(providerName, nvl, providerType, 3903 NULL)); 3904 } 3905 3906 /* 3907 * stmfGetProviderDataProt 3908 * 3909 * Purpose: Get provider data list with token 3910 * 3911 * providerName - name of provider for which to retrieve the data 3912 * nvl - pointer to nvlist_t pointer which will contain the nvlist data 3913 * retrieved. 3914 * providerType - type of provider for which to retrieve data. 3915 * STMF_LU_PROVIDER_TYPE 3916 * STMF_PORT_PROVIDER_TYPE 3917 * setToken - Returns the stale data token 3918 */ 3919 int 3920 stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType, 3921 uint64_t *setToken) 3922 { 3923 int ret; 3924 3925 if (providerName == NULL || nvl == NULL) { 3926 return (STMF_ERROR_INVALID_ARG); 3927 } 3928 if (providerType != STMF_LU_PROVIDER_TYPE && 3929 providerType != STMF_PORT_PROVIDER_TYPE) { 3930 return (STMF_ERROR_INVALID_ARG); 3931 } 3932 /* call init */ 3933 ret = initializeConfig(); 3934 if (ret != STMF_STATUS_SUCCESS) { 3935 return (ret); 3936 } 3937 return (getProviderData(providerName, nvl, providerType, setToken)); 3938 } 3939 3940 /* 3941 * stmfGetProviderDataList 3942 * 3943 * Purpose: Get the list of providers currently persisting data 3944 * 3945 * providerList - pointer to pointer to an stmfProviderList structure allocated 3946 * by the caller. Will contain the list of providers on success. 3947 */ 3948 int 3949 stmfGetProviderDataList(stmfProviderList **providerList) 3950 { 3951 int ret; 3952 3953 ret = psGetProviderDataList(providerList); 3954 switch (ret) { 3955 case STMF_PS_SUCCESS: 3956 ret = STMF_STATUS_SUCCESS; 3957 break; 3958 case STMF_PS_ERROR_BUSY: 3959 ret = STMF_ERROR_BUSY; 3960 break; 3961 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3962 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3963 break; 3964 case STMF_PS_ERROR_VERSION_MISMATCH: 3965 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3966 break; 3967 default: 3968 syslog(LOG_DEBUG, 3969 "stmfGetProviderDataList:psGetProviderDataList" 3970 ":error(%d)", ret); 3971 ret = STMF_STATUS_ERROR; 3972 break; 3973 } 3974 3975 return (ret); 3976 } 3977 3978 3979 /* 3980 * stmfGetSessionList 3981 * 3982 * Purpose: Retrieves the session list for a target (devid) 3983 * 3984 * devid - devid of target for which to retrieve session information. 3985 * sessionList - pointer to pointer to stmfSessionList structure 3986 * on success, this contains the list of initiator sessions. 3987 */ 3988 int 3989 stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList) 3990 { 3991 int ret = STMF_STATUS_SUCCESS; 3992 int fd; 3993 int ioctlRet; 3994 int cmd = STMF_IOCTL_SESSION_LIST; 3995 int i; 3996 stmf_iocdata_t stmfIoctl; 3997 slist_scsi_session_t *fSessionList, *fSessionListP = NULL; 3998 uint8_t ident[260]; 3999 uint32_t fSessionListSize; 4000 4001 if (sessionList == NULL || devid == NULL) { 4002 ret = STMF_ERROR_INVALID_ARG; 4003 } 4004 4005 /* call init */ 4006 ret = initializeConfig(); 4007 if (ret != STMF_STATUS_SUCCESS) { 4008 return (ret); 4009 } 4010 4011 /* 4012 * Open control node for stmf 4013 */ 4014 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4015 return (ret); 4016 4017 /* 4018 * Allocate ioctl input buffer 4019 */ 4020 fSessionListSize = ALLOC_SESSION; 4021 fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t)); 4022 fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize); 4023 fSessionListP = fSessionList; 4024 if (fSessionList == NULL) { 4025 ret = STMF_ERROR_NOMEM; 4026 goto done; 4027 } 4028 4029 ident[IDENT_LENGTH_BYTE] = devid->identLength; 4030 bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1], 4031 devid->identLength); 4032 4033 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4034 /* 4035 * Issue ioctl to get the session list 4036 */ 4037 stmfIoctl.stmf_version = STMF_VERSION_1; 4038 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident; 4039 stmfIoctl.stmf_ibuf_size = sizeof (ident); 4040 stmfIoctl.stmf_obuf_size = fSessionListSize; 4041 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList; 4042 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4043 if (ioctlRet != 0) { 4044 switch (errno) { 4045 case EBUSY: 4046 ret = STMF_ERROR_BUSY; 4047 break; 4048 case EPERM: 4049 case EACCES: 4050 ret = STMF_ERROR_PERM; 4051 break; 4052 default: 4053 syslog(LOG_DEBUG, 4054 "stmfGetSessionList:ioctl errno(%d)", 4055 errno); 4056 ret = STMF_STATUS_ERROR; 4057 break; 4058 } 4059 goto done; 4060 } 4061 /* 4062 * Check whether input buffer was large enough 4063 */ 4064 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_SESSION) { 4065 fSessionListSize = stmfIoctl.stmf_obuf_max_nentries * 4066 sizeof (slist_scsi_session_t); 4067 fSessionList = realloc(fSessionList, fSessionListSize); 4068 if (fSessionList == NULL) { 4069 ret = STMF_ERROR_NOMEM; 4070 goto done; 4071 } 4072 fSessionListP = fSessionList; 4073 stmfIoctl.stmf_obuf_size = fSessionListSize; 4074 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList; 4075 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4076 if (ioctlRet != 0) { 4077 switch (errno) { 4078 case EBUSY: 4079 ret = STMF_ERROR_BUSY; 4080 break; 4081 case EPERM: 4082 case EACCES: 4083 ret = STMF_ERROR_PERM; 4084 break; 4085 default: 4086 syslog(LOG_DEBUG, 4087 "stmfGetSessionList:ioctl " 4088 "errno(%d)", errno); 4089 ret = STMF_STATUS_ERROR; 4090 break; 4091 } 4092 goto done; 4093 } 4094 } 4095 4096 /* 4097 * allocate caller's buffer with the final size 4098 */ 4099 *sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) + 4100 stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession)); 4101 if (*sessionList == NULL) { 4102 ret = STMF_ERROR_NOMEM; 4103 free(sessionList); 4104 goto done; 4105 } 4106 4107 (*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries; 4108 4109 /* 4110 * copy session info to caller's buffer 4111 */ 4112 for (i = 0; i < (*sessionList)->cnt; i++) { 4113 (*sessionList)->session[i].initiator.identLength = 4114 fSessionList->initiator[IDENT_LENGTH_BYTE]; 4115 bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]), 4116 (*sessionList)->session[i].initiator.ident, 4117 STMF_IDENT_LENGTH); 4118 bcopy(&(fSessionList->alias), 4119 &((*sessionList)->session[i].alias), 4120 sizeof ((*sessionList)->session[i].alias)); 4121 bcopy(&(fSessionList++->creation_time), 4122 &((*sessionList)->session[i].creationTime), 4123 sizeof (time_t)); 4124 } 4125 done: 4126 (void) close(fd); 4127 free(fSessionListP); 4128 return (ret); 4129 } 4130 4131 /* 4132 * stmfGetTargetGroupList 4133 * 4134 * Purpose: Retrieves the list of target groups 4135 * 4136 * targetGroupList - pointer to a pointer to an stmfGroupList structure. On 4137 * success, it contains the list of target groups. 4138 */ 4139 int 4140 stmfGetTargetGroupList(stmfGroupList **targetGroupList) 4141 { 4142 int ret; 4143 4144 if (targetGroupList == NULL) { 4145 return (STMF_ERROR_INVALID_ARG); 4146 } 4147 4148 ret = groupListIoctl(targetGroupList, TARGET_GROUP); 4149 return (ret); 4150 } 4151 4152 /* 4153 * stmfGetTargetGroupMembers 4154 * 4155 * Purpose: Retrieves the group members for a target group 4156 * 4157 * groupName - name of target group for which to retrieve members. 4158 * groupProp - pointer to pointer to stmfGroupProperties structure 4159 * on success, this contains the list of group members. 4160 */ 4161 int 4162 stmfGetTargetGroupMembers(stmfGroupName *groupName, 4163 stmfGroupProperties **groupProp) 4164 { 4165 int ret; 4166 4167 if (groupName == NULL || groupProp == NULL) { 4168 return (STMF_ERROR_INVALID_ARG); 4169 } 4170 4171 ret = groupMemberListIoctl(groupName, groupProp, TARGET_GROUP); 4172 4173 return (ret); 4174 } 4175 4176 /* 4177 * stmfGetTargetList 4178 * 4179 * Purpose: Retrieves the list of target ports 4180 * 4181 * targetList - pointer to a pointer to an stmfDevidList structure. 4182 * On success, it contains the list of local ports (target). 4183 */ 4184 int 4185 stmfGetTargetList(stmfDevidList **targetList) 4186 { 4187 int ret; 4188 int fd; 4189 int ioctlRet; 4190 int i; 4191 stmf_iocdata_t stmfIoctl; 4192 /* framework target port list */ 4193 slist_target_port_t *fTargetList, *fTargetListP = NULL; 4194 uint32_t fTargetListSize; 4195 4196 if (targetList == NULL) { 4197 return (STMF_ERROR_INVALID_ARG); 4198 } 4199 4200 /* call init */ 4201 ret = initializeConfig(); 4202 if (ret != STMF_STATUS_SUCCESS) { 4203 return (ret); 4204 } 4205 4206 /* 4207 * Open control node for stmf 4208 */ 4209 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4210 return (ret); 4211 4212 /* 4213 * Allocate ioctl input buffer 4214 */ 4215 fTargetListSize = ALLOC_TARGET_PORT * sizeof (slist_target_port_t); 4216 fTargetListP = fTargetList = 4217 (slist_target_port_t *)calloc(1, fTargetListSize); 4218 if (fTargetList == NULL) { 4219 ret = STMF_ERROR_NOMEM; 4220 goto done; 4221 } 4222 4223 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4224 /* 4225 * Issue ioctl to retrieve target list 4226 */ 4227 stmfIoctl.stmf_version = STMF_VERSION_1; 4228 stmfIoctl.stmf_obuf_size = fTargetListSize; 4229 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList; 4230 ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl); 4231 if (ioctlRet != 0) { 4232 switch (errno) { 4233 case EBUSY: 4234 ret = STMF_ERROR_BUSY; 4235 break; 4236 case EPERM: 4237 case EACCES: 4238 ret = STMF_ERROR_PERM; 4239 break; 4240 default: 4241 syslog(LOG_DEBUG, 4242 "stmfGetTargetList:ioctl errno(%d)", errno); 4243 ret = STMF_STATUS_ERROR; 4244 break; 4245 } 4246 goto done; 4247 } 4248 /* 4249 * Check whether input buffer was large enough 4250 */ 4251 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_TARGET_PORT) { 4252 fTargetListSize = stmfIoctl.stmf_obuf_max_nentries * 4253 sizeof (slist_target_port_t); 4254 fTargetListP = fTargetList = 4255 realloc(fTargetList, fTargetListSize); 4256 if (fTargetList == NULL) { 4257 ret = STMF_ERROR_NOMEM; 4258 goto done; 4259 } 4260 stmfIoctl.stmf_obuf_size = fTargetListSize; 4261 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList; 4262 ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, 4263 &stmfIoctl); 4264 if (ioctlRet != 0) { 4265 switch (errno) { 4266 case EBUSY: 4267 ret = STMF_ERROR_BUSY; 4268 break; 4269 case EPERM: 4270 case EACCES: 4271 ret = STMF_ERROR_PERM; 4272 break; 4273 default: 4274 syslog(LOG_DEBUG, 4275 "stmfGetTargetList:ioctl errno(%d)", 4276 errno); 4277 ret = STMF_STATUS_ERROR; 4278 break; 4279 } 4280 goto done; 4281 } 4282 } 4283 4284 *targetList = (stmfDevidList *)calloc(1, 4285 stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) + 4286 sizeof (stmfDevidList)); 4287 if (*targetList == NULL) { 4288 ret = STMF_ERROR_NOMEM; 4289 goto done; 4290 } 4291 4292 (*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries; 4293 for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) { 4294 (*targetList)->devid[i].identLength = 4295 fTargetList->target[IDENT_LENGTH_BYTE]; 4296 bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1], 4297 &(*targetList)->devid[i].ident, 4298 fTargetList->target[IDENT_LENGTH_BYTE]); 4299 } 4300 4301 done: 4302 (void) close(fd); 4303 free(fTargetListP); 4304 return (ret); 4305 } 4306 4307 /* 4308 * stmfGetTargetProperties 4309 * 4310 * Purpose: Retrieves the properties for a logical unit 4311 * 4312 * devid - devid of the target for which to retrieve properties 4313 * targetProps - pointer to an stmfTargetProperties structure. 4314 * On success, it contains the target properties for 4315 * the specified devid. 4316 */ 4317 int 4318 stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps) 4319 { 4320 int ret = STMF_STATUS_SUCCESS; 4321 int fd; 4322 int ioctlRet; 4323 stmf_iocdata_t stmfIoctl; 4324 sioc_target_port_props_t targetProperties; 4325 scsi_devid_desc_t *scsiDevid; 4326 4327 if (devid == NULL || targetProps == NULL) { 4328 return (STMF_ERROR_INVALID_ARG); 4329 } 4330 4331 /* call init */ 4332 ret = initializeConfig(); 4333 if (ret != STMF_STATUS_SUCCESS) { 4334 return (ret); 4335 } 4336 4337 /* 4338 * Open control node for stmf 4339 */ 4340 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4341 return (ret); 4342 4343 targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength; 4344 bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1], 4345 devid->identLength); 4346 4347 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4348 /* 4349 * Issue ioctl to add to the host group 4350 */ 4351 stmfIoctl.stmf_version = STMF_VERSION_1; 4352 stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id); 4353 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id; 4354 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties; 4355 stmfIoctl.stmf_obuf_size = sizeof (targetProperties); 4356 ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES, 4357 &stmfIoctl); 4358 if (ioctlRet != 0) { 4359 switch (errno) { 4360 case EBUSY: 4361 ret = STMF_ERROR_BUSY; 4362 break; 4363 case EPERM: 4364 case EACCES: 4365 ret = STMF_ERROR_PERM; 4366 break; 4367 case ENOENT: 4368 ret = STMF_ERROR_NOT_FOUND; 4369 break; 4370 default: 4371 syslog(LOG_DEBUG, 4372 "stmfGetTargetProperties:ioctl errno(%d)", 4373 errno); 4374 ret = STMF_STATUS_ERROR; 4375 break; 4376 } 4377 goto done; 4378 } 4379 4380 bcopy(targetProperties.tgt_provider_name, targetProps->providerName, 4381 sizeof (targetProperties.tgt_provider_name)); 4382 if (targetProperties.tgt_state == STMF_STATE_ONLINE) { 4383 targetProps->status = STMF_TARGET_PORT_ONLINE; 4384 } else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) { 4385 targetProps->status = STMF_TARGET_PORT_OFFLINE; 4386 } else if (targetProperties.tgt_state == STMF_STATE_ONLINING) { 4387 targetProps->status = STMF_TARGET_PORT_ONLINING; 4388 } else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) { 4389 targetProps->status = STMF_TARGET_PORT_OFFLINING; 4390 } 4391 bcopy(targetProperties.tgt_alias, targetProps->alias, 4392 sizeof (targetProps->alias)); 4393 4394 scsiDevid = (scsi_devid_desc_t *)&targetProperties.tgt_id; 4395 targetProps->protocol = scsiDevid->protocol_id; 4396 4397 done: 4398 (void) close(fd); 4399 return (ret); 4400 } 4401 4402 /* 4403 * stmfGetLogicalUnitList 4404 * 4405 * Purpose: Retrieves list of logical unit Object IDs 4406 * 4407 * luList - pointer to a pointer to a stmfGuidList structure. On success, 4408 * it contains the list of logical unit guids. 4409 * 4410 */ 4411 int 4412 stmfGetLogicalUnitList(stmfGuidList **luList) 4413 { 4414 int ret; 4415 int fd; 4416 int ioctlRet; 4417 int cmd = STMF_IOCTL_LU_LIST; 4418 int i; 4419 stmf_iocdata_t stmfIoctl; 4420 slist_lu_t *fLuList; 4421 uint32_t fLuListSize; 4422 uint32_t listCnt; 4423 4424 if (luList == NULL) { 4425 return (STMF_ERROR_INVALID_ARG); 4426 } 4427 4428 /* call init */ 4429 ret = initializeConfig(); 4430 if (ret != STMF_STATUS_SUCCESS) { 4431 return (ret); 4432 } 4433 4434 /* 4435 * Open control node for stmf 4436 */ 4437 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4438 return (ret); 4439 4440 /* 4441 * Allocate ioctl input buffer 4442 */ 4443 fLuListSize = ALLOC_LU; 4444 fLuListSize = fLuListSize * (sizeof (slist_lu_t)); 4445 fLuList = (slist_lu_t *)calloc(1, fLuListSize); 4446 if (fLuList == NULL) { 4447 ret = STMF_ERROR_NOMEM; 4448 goto done; 4449 } 4450 4451 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4452 /* 4453 * Issue ioctl to get the LU list 4454 */ 4455 stmfIoctl.stmf_version = STMF_VERSION_1; 4456 stmfIoctl.stmf_obuf_size = fLuListSize; 4457 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList; 4458 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4459 if (ioctlRet != 0) { 4460 switch (errno) { 4461 case EBUSY: 4462 ret = STMF_ERROR_BUSY; 4463 break; 4464 case EPERM: 4465 case EACCES: 4466 ret = STMF_ERROR_PERM; 4467 break; 4468 default: 4469 syslog(LOG_DEBUG, 4470 "stmfGetLogicalUnitList:ioctl errno(%d)", 4471 errno); 4472 ret = STMF_STATUS_ERROR; 4473 break; 4474 } 4475 goto done; 4476 } 4477 /* 4478 * Check whether input buffer was large enough 4479 */ 4480 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_LU) { 4481 fLuListSize = stmfIoctl.stmf_obuf_max_nentries * 4482 sizeof (slist_lu_t); 4483 free(fLuList); 4484 fLuList = (slist_lu_t *)calloc(1, fLuListSize); 4485 if (fLuList == NULL) { 4486 ret = STMF_ERROR_NOMEM; 4487 goto done; 4488 } 4489 stmfIoctl.stmf_obuf_size = fLuListSize; 4490 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList; 4491 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4492 if (ioctlRet != 0) { 4493 switch (errno) { 4494 case EBUSY: 4495 ret = STMF_ERROR_BUSY; 4496 break; 4497 case EPERM: 4498 case EACCES: 4499 ret = STMF_ERROR_PERM; 4500 break; 4501 default: 4502 syslog(LOG_DEBUG, 4503 "stmfGetLogicalUnitList:" 4504 "ioctl errno(%d)", errno); 4505 ret = STMF_STATUS_ERROR; 4506 break; 4507 } 4508 goto done; 4509 } 4510 } 4511 4512 if (ret != STMF_STATUS_SUCCESS) { 4513 goto done; 4514 } 4515 4516 listCnt = stmfIoctl.stmf_obuf_nentries; 4517 4518 /* 4519 * allocate caller's buffer with the final size 4520 */ 4521 *luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) + 4522 listCnt * sizeof (stmfGuid)); 4523 if (*luList == NULL) { 4524 ret = STMF_ERROR_NOMEM; 4525 goto done; 4526 } 4527 4528 (*luList)->cnt = listCnt; 4529 4530 /* copy to caller's buffer */ 4531 for (i = 0; i < listCnt; i++) { 4532 bcopy(&fLuList[i].lu_guid, (*luList)->guid[i].guid, 4533 sizeof (stmfGuid)); 4534 } 4535 4536 /* 4537 * sort the list. This gives a consistent view across gets 4538 */ 4539 qsort((void *)&((*luList)->guid[0]), (*luList)->cnt, 4540 sizeof (stmfGuid), guidCompare); 4541 4542 done: 4543 (void) close(fd); 4544 /* 4545 * free internal buffers 4546 */ 4547 free(fLuList); 4548 return (ret); 4549 } 4550 4551 /* 4552 * stmfGetLogicalUnitProperties 4553 * 4554 * Purpose: Retrieves the properties for a logical unit 4555 * 4556 * lu - guid of the logical unit for which to retrieve properties 4557 * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success, 4558 * it contains the logical unit properties for the specified guid. 4559 */ 4560 int 4561 stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps) 4562 { 4563 int ret = STMF_STATUS_SUCCESS; 4564 int stmfRet; 4565 int fd; 4566 int ioctlRet; 4567 int cmd = STMF_IOCTL_GET_LU_PROPERTIES; 4568 stmfViewEntryList *viewEntryList = NULL; 4569 stmf_iocdata_t stmfIoctl; 4570 sioc_lu_props_t fLuProps; 4571 4572 if (lu == NULL || luProps == NULL) { 4573 return (STMF_ERROR_INVALID_ARG); 4574 } 4575 4576 bzero(luProps, sizeof (stmfLogicalUnitProperties)); 4577 4578 /* call init */ 4579 ret = initializeConfig(); 4580 if (ret != STMF_STATUS_SUCCESS) { 4581 return (ret); 4582 } 4583 4584 /* 4585 * Open control node for stmf 4586 */ 4587 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4588 return (ret); 4589 4590 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4591 /* 4592 * Issue ioctl to add to the host group 4593 */ 4594 stmfIoctl.stmf_version = STMF_VERSION_1; 4595 stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid); 4596 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu; 4597 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps; 4598 stmfIoctl.stmf_obuf_size = sizeof (fLuProps); 4599 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4600 if (ioctlRet != 0) { 4601 switch (errno) { 4602 case EBUSY: 4603 ret = STMF_ERROR_BUSY; 4604 break; 4605 case EPERM: 4606 case EACCES: 4607 ret = STMF_ERROR_PERM; 4608 break; 4609 case ENOENT: 4610 stmfRet = stmfGetViewEntryList(lu, 4611 &viewEntryList); 4612 if (stmfRet == STMF_STATUS_SUCCESS) { 4613 luProps->status = 4614 STMF_LOGICAL_UNIT_UNREGISTERED; 4615 if (viewEntryList->cnt > 0) { 4616 ret = STMF_STATUS_SUCCESS; 4617 } else { 4618 ret = STMF_ERROR_NOT_FOUND; 4619 } 4620 } else { 4621 ret = STMF_ERROR_NOT_FOUND; 4622 } 4623 stmfFreeMemory(viewEntryList); 4624 break; 4625 default: 4626 syslog(LOG_DEBUG, 4627 "stmfGetLogicalUnit:ioctl errno(%d)", 4628 errno); 4629 ret = STMF_STATUS_ERROR; 4630 break; 4631 } 4632 goto done; 4633 } 4634 4635 bcopy(fLuProps.lu_provider_name, luProps->providerName, 4636 sizeof (fLuProps.lu_provider_name)); 4637 if (fLuProps.lu_state == STMF_STATE_ONLINE) { 4638 luProps->status = STMF_LOGICAL_UNIT_ONLINE; 4639 } else if (fLuProps.lu_state == STMF_STATE_OFFLINE) { 4640 luProps->status = STMF_LOGICAL_UNIT_OFFLINE; 4641 } else if (fLuProps.lu_state == STMF_STATE_ONLINING) { 4642 luProps->status = STMF_LOGICAL_UNIT_ONLINING; 4643 } else if (fLuProps.lu_state == STMF_STATE_OFFLINING) { 4644 luProps->status = STMF_LOGICAL_UNIT_OFFLINING; 4645 } 4646 bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias)); 4647 done: 4648 (void) close(fd); 4649 return (ret); 4650 } 4651 4652 /* 4653 * stmfGetState 4654 * 4655 * Purpose: retrieve the current state of the stmf module 4656 * 4657 * state - pointer to stmfState structure allocated by the caller 4658 * On success, contains the state of stmf 4659 */ 4660 int 4661 stmfGetState(stmfState *state) 4662 { 4663 int ret; 4664 stmf_state_desc_t iState; 4665 4666 if (state == NULL) { 4667 return (STMF_ERROR_INVALID_ARG); 4668 } 4669 4670 ret = getStmfState(&iState); 4671 if (ret != STMF_STATUS_SUCCESS) { 4672 return (ret); 4673 } 4674 switch (iState.state) { 4675 case STMF_STATE_ONLINE: 4676 state->operationalState = 4677 STMF_SERVICE_STATE_ONLINE; 4678 break; 4679 case STMF_STATE_OFFLINE: 4680 state->operationalState = 4681 STMF_SERVICE_STATE_OFFLINE; 4682 break; 4683 case STMF_STATE_ONLINING: 4684 state->operationalState = 4685 STMF_SERVICE_STATE_ONLINING; 4686 break; 4687 case STMF_STATE_OFFLINING: 4688 state->operationalState = 4689 STMF_SERVICE_STATE_OFFLINING; 4690 break; 4691 default: 4692 state->operationalState = 4693 STMF_SERVICE_STATE_UNKNOWN; 4694 break; 4695 } 4696 switch (iState.config_state) { 4697 case STMF_CONFIG_NONE: 4698 state->configState = STMF_CONFIG_STATE_NONE; 4699 break; 4700 case STMF_CONFIG_INIT: 4701 state->configState = STMF_CONFIG_STATE_INIT; 4702 break; 4703 case STMF_CONFIG_INIT_DONE: 4704 state->configState = 4705 STMF_CONFIG_STATE_INIT_DONE; 4706 break; 4707 default: 4708 state->configState = 4709 STMF_CONFIG_STATE_UNKNOWN; 4710 break; 4711 } 4712 return (STMF_STATUS_SUCCESS); 4713 } 4714 4715 /* 4716 * stmfGetViewEntryList 4717 * 4718 * Purpose: Retrieves the list of view entries for the specified 4719 * logical unit. 4720 * 4721 * lu - the guid of the logical unit for which to retrieve the view entry list 4722 * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On 4723 * success, contains the list of view entries. 4724 */ 4725 int 4726 stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList) 4727 { 4728 int ret; 4729 int fd; 4730 int ioctlRet; 4731 int cmd = STMF_IOCTL_LU_VE_LIST; 4732 int i; 4733 stmf_iocdata_t stmfIoctl; 4734 stmf_view_op_entry_t *fVeList; 4735 uint32_t fVeListSize; 4736 uint32_t listCnt; 4737 4738 if (lu == NULL || viewEntryList == NULL) { 4739 return (STMF_ERROR_INVALID_ARG); 4740 } 4741 4742 /* call init */ 4743 ret = initializeConfig(); 4744 if (ret != STMF_STATUS_SUCCESS) { 4745 return (ret); 4746 } 4747 4748 /* 4749 * Open control node for stmf 4750 */ 4751 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4752 return (ret); 4753 4754 /* 4755 * Allocate ioctl input buffer 4756 */ 4757 fVeListSize = ALLOC_VE; 4758 fVeListSize = fVeListSize * (sizeof (stmf_view_op_entry_t)); 4759 fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize); 4760 if (fVeList == NULL) { 4761 ret = STMF_ERROR_NOMEM; 4762 goto done; 4763 } 4764 4765 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4766 /* 4767 * Issue ioctl to get the LU list 4768 */ 4769 stmfIoctl.stmf_version = STMF_VERSION_1; 4770 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu; 4771 stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid); 4772 stmfIoctl.stmf_obuf_size = fVeListSize; 4773 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList; 4774 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4775 if (ioctlRet != 0) { 4776 switch (errno) { 4777 case EBUSY: 4778 ret = STMF_ERROR_BUSY; 4779 break; 4780 case EPERM: 4781 case EACCES: 4782 ret = STMF_ERROR_PERM; 4783 break; 4784 default: 4785 syslog(LOG_DEBUG, 4786 "stmfGetViewEntryList:ioctl errno(%d)", 4787 errno); 4788 ret = STMF_STATUS_ERROR; 4789 break; 4790 } 4791 goto done; 4792 } 4793 /* 4794 * Check whether input buffer was large enough 4795 */ 4796 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_VE) { 4797 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4798 fVeListSize = stmfIoctl.stmf_obuf_max_nentries * 4799 sizeof (stmf_view_op_entry_t); 4800 free(fVeList); 4801 fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize); 4802 if (fVeList == NULL) { 4803 return (STMF_ERROR_NOMEM); 4804 } 4805 stmfIoctl.stmf_obuf_size = fVeListSize; 4806 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList; 4807 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4808 if (ioctlRet != 0) { 4809 switch (errno) { 4810 case EBUSY: 4811 ret = STMF_ERROR_BUSY; 4812 break; 4813 case EPERM: 4814 case EACCES: 4815 ret = STMF_ERROR_PERM; 4816 break; 4817 default: 4818 syslog(LOG_DEBUG, 4819 "stmfGetLogicalUnitList:" 4820 "ioctl errno(%d)", errno); 4821 ret = STMF_STATUS_ERROR; 4822 break; 4823 } 4824 goto done; 4825 } 4826 } 4827 4828 if (ret != STMF_STATUS_SUCCESS) { 4829 goto done; 4830 } 4831 4832 listCnt = stmfIoctl.stmf_obuf_nentries; 4833 4834 /* 4835 * allocate caller's buffer with the final size 4836 */ 4837 *viewEntryList = (stmfViewEntryList *)calloc(1, 4838 sizeof (stmfViewEntryList) + listCnt * sizeof (stmfViewEntry)); 4839 if (*viewEntryList == NULL) { 4840 ret = STMF_ERROR_NOMEM; 4841 goto done; 4842 } 4843 4844 (*viewEntryList)->cnt = listCnt; 4845 4846 /* copy to caller's buffer */ 4847 for (i = 0; i < listCnt; i++) { 4848 (*viewEntryList)->ve[i].veIndexValid = B_TRUE; 4849 (*viewEntryList)->ve[i].veIndex = fVeList[i].ve_ndx; 4850 if (fVeList[i].ve_all_hosts == 1) { 4851 (*viewEntryList)->ve[i].allHosts = B_TRUE; 4852 } else { 4853 bcopy(fVeList[i].ve_host_group.name, 4854 (*viewEntryList)->ve[i].hostGroup, 4855 fVeList[i].ve_host_group.name_size); 4856 } 4857 if (fVeList[i].ve_all_targets == 1) { 4858 (*viewEntryList)->ve[i].allTargets = B_TRUE; 4859 } else { 4860 bcopy(fVeList[i].ve_target_group.name, 4861 (*viewEntryList)->ve[i].targetGroup, 4862 fVeList[i].ve_target_group.name_size); 4863 } 4864 bcopy(fVeList[i].ve_lu_nbr, (*viewEntryList)->ve[i].luNbr, 4865 sizeof ((*viewEntryList)->ve[i].luNbr)); 4866 (*viewEntryList)->ve[i].luNbrValid = B_TRUE; 4867 } 4868 4869 /* 4870 * sort the list. This gives a consistent view across gets 4871 */ 4872 qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt, 4873 sizeof (stmfViewEntry), viewEntryCompare); 4874 4875 done: 4876 (void) close(fd); 4877 /* 4878 * free internal buffers 4879 */ 4880 free(fVeList); 4881 return (ret); 4882 } 4883 4884 4885 /* 4886 * loadHostGroups 4887 * 4888 * Purpose - issues the ioctl to load the host groups into stmf 4889 * 4890 * fd - file descriptor for the control node of stmf. 4891 * groupList - populated host group list 4892 */ 4893 static int 4894 loadHostGroups(int fd, stmfGroupList *groupList) 4895 { 4896 int i, j; 4897 int ret = STMF_STATUS_SUCCESS; 4898 stmfGroupProperties *groupProps = NULL; 4899 4900 for (i = 0; i < groupList->cnt; i++) { 4901 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP, 4902 &(groupList->name[i]))) != STMF_STATUS_SUCCESS) { 4903 goto out; 4904 } 4905 ret = iLoadGroupMembersFromPs(&(groupList->name[i]), 4906 &groupProps, HOST_GROUP); 4907 for (j = 0; j < groupProps->cnt; j++) { 4908 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, 4909 &(groupList->name[i]), &(groupProps->name[j]))) 4910 != STMF_STATUS_SUCCESS) { 4911 goto out; 4912 } 4913 } 4914 } 4915 4916 4917 out: 4918 stmfFreeMemory(groupProps); 4919 return (ret); 4920 } 4921 4922 /* 4923 * loadTargetGroups 4924 * 4925 * Purpose - issues the ioctl to load the target groups into stmf 4926 * 4927 * fd - file descriptor for the control node of stmf. 4928 * groupList - populated target group list. 4929 */ 4930 static int 4931 loadTargetGroups(int fd, stmfGroupList *groupList) 4932 { 4933 int i, j; 4934 int ret = STMF_STATUS_SUCCESS; 4935 stmfGroupProperties *groupProps = NULL; 4936 4937 for (i = 0; i < groupList->cnt; i++) { 4938 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP, 4939 &(groupList->name[i]))) != STMF_STATUS_SUCCESS) { 4940 goto out; 4941 } 4942 ret = iLoadGroupMembersFromPs(&(groupList->name[i]), 4943 &groupProps, TARGET_GROUP); 4944 for (j = 0; j < groupProps->cnt; j++) { 4945 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY, 4946 &(groupList->name[i]), &(groupProps->name[j]))) 4947 != STMF_STATUS_SUCCESS) { 4948 goto out; 4949 } 4950 } 4951 } 4952 4953 4954 out: 4955 stmfFreeMemory(groupProps); 4956 return (ret); 4957 } 4958 4959 4960 /* 4961 * loadStore 4962 * 4963 * Purpose: Load the configuration data from the store 4964 * 4965 * First load the host groups and target groups, then the view entries 4966 * and finally the provider data 4967 * 4968 * fd - file descriptor of control node for stmf. 4969 */ 4970 static int 4971 loadStore(int fd) 4972 { 4973 int ret; 4974 int i, j; 4975 stmfGroupList *groupList = NULL; 4976 stmfGuidList *guidList = NULL; 4977 stmfViewEntryList *viewEntryList = NULL; 4978 stmfProviderList *providerList = NULL; 4979 int providerType; 4980 nvlist_t *nvl = NULL; 4981 4982 4983 4984 /* load host groups */ 4985 ret = iLoadGroupFromPs(&groupList, HOST_GROUP); 4986 if (ret != STMF_STATUS_SUCCESS) { 4987 return (ret); 4988 } 4989 ret = loadHostGroups(fd, groupList); 4990 if (ret != STMF_STATUS_SUCCESS) { 4991 goto out; 4992 } 4993 4994 stmfFreeMemory(groupList); 4995 groupList = NULL; 4996 4997 /* load target groups */ 4998 ret = iLoadGroupFromPs(&groupList, TARGET_GROUP); 4999 if (ret != STMF_STATUS_SUCCESS) { 5000 goto out; 5001 } 5002 ret = loadTargetGroups(fd, groupList); 5003 if (ret != STMF_STATUS_SUCCESS) { 5004 goto out; 5005 } 5006 5007 stmfFreeMemory(groupList); 5008 groupList = NULL; 5009 5010 /* Get the guid list */ 5011 ret = psGetLogicalUnitList(&guidList); 5012 switch (ret) { 5013 case STMF_PS_SUCCESS: 5014 ret = STMF_STATUS_SUCCESS; 5015 break; 5016 case STMF_PS_ERROR_NOT_FOUND: 5017 ret = STMF_ERROR_NOT_FOUND; 5018 break; 5019 case STMF_PS_ERROR_BUSY: 5020 ret = STMF_ERROR_BUSY; 5021 break; 5022 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5023 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5024 break; 5025 case STMF_PS_ERROR_VERSION_MISMATCH: 5026 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5027 break; 5028 default: 5029 ret = STMF_STATUS_ERROR; 5030 break; 5031 } 5032 5033 if (ret != STMF_STATUS_SUCCESS) { 5034 goto out; 5035 } 5036 5037 /* 5038 * We have the guid list, now get the corresponding 5039 * view entries for each guid 5040 */ 5041 for (i = 0; i < guidList->cnt; i++) { 5042 ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList); 5043 switch (ret) { 5044 case STMF_PS_SUCCESS: 5045 ret = STMF_STATUS_SUCCESS; 5046 break; 5047 case STMF_PS_ERROR_NOT_FOUND: 5048 ret = STMF_ERROR_NOT_FOUND; 5049 break; 5050 case STMF_PS_ERROR_BUSY: 5051 ret = STMF_ERROR_BUSY; 5052 break; 5053 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5054 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5055 break; 5056 case STMF_PS_ERROR_VERSION_MISMATCH: 5057 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5058 break; 5059 default: 5060 ret = STMF_STATUS_ERROR; 5061 break; 5062 } 5063 if (ret != STMF_STATUS_SUCCESS) { 5064 goto out; 5065 } 5066 for (j = 0; j < viewEntryList->cnt; j++) { 5067 ret = addViewEntryIoctl(fd, &guidList->guid[i], 5068 &viewEntryList->ve[j]); 5069 if (ret != STMF_STATUS_SUCCESS) { 5070 goto out; 5071 } 5072 } 5073 } 5074 5075 /* get the list of providers that have data */ 5076 ret = psGetProviderDataList(&providerList); 5077 switch (ret) { 5078 case STMF_PS_SUCCESS: 5079 ret = STMF_STATUS_SUCCESS; 5080 break; 5081 case STMF_PS_ERROR_NOT_FOUND: 5082 ret = STMF_ERROR_NOT_FOUND; 5083 break; 5084 case STMF_PS_ERROR_BUSY: 5085 ret = STMF_ERROR_BUSY; 5086 break; 5087 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5088 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5089 break; 5090 case STMF_PS_ERROR_VERSION_MISMATCH: 5091 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5092 break; 5093 default: 5094 ret = STMF_STATUS_ERROR; 5095 break; 5096 } 5097 if (ret != STMF_STATUS_SUCCESS) { 5098 goto out; 5099 } 5100 5101 for (i = 0; i < providerList->cnt; i++) { 5102 providerType = providerList->provider[i].providerType; 5103 ret = psGetProviderData(providerList->provider[i].name, 5104 &nvl, providerType, NULL); 5105 switch (ret) { 5106 case STMF_PS_SUCCESS: 5107 ret = STMF_STATUS_SUCCESS; 5108 break; 5109 case STMF_PS_ERROR_NOT_FOUND: 5110 ret = STMF_ERROR_NOT_FOUND; 5111 break; 5112 case STMF_PS_ERROR_BUSY: 5113 ret = STMF_ERROR_BUSY; 5114 break; 5115 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5116 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5117 break; 5118 case STMF_PS_ERROR_VERSION_MISMATCH: 5119 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5120 break; 5121 default: 5122 ret = STMF_STATUS_ERROR; 5123 break; 5124 } 5125 if (ret != STMF_STATUS_SUCCESS) { 5126 goto out; 5127 } 5128 5129 /* call setProviderData */ 5130 ret = setProviderData(fd, providerList->provider[i].name, nvl, 5131 providerType, NULL); 5132 switch (ret) { 5133 case STMF_PS_SUCCESS: 5134 ret = STMF_STATUS_SUCCESS; 5135 break; 5136 case STMF_PS_ERROR_NOT_FOUND: 5137 ret = STMF_ERROR_NOT_FOUND; 5138 break; 5139 case STMF_PS_ERROR_BUSY: 5140 ret = STMF_ERROR_BUSY; 5141 break; 5142 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5143 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5144 break; 5145 case STMF_PS_ERROR_VERSION_MISMATCH: 5146 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5147 break; 5148 default: 5149 ret = STMF_STATUS_ERROR; 5150 break; 5151 } 5152 if (ret != STMF_STATUS_SUCCESS) { 5153 goto out; 5154 } 5155 5156 nvlist_free(nvl); 5157 nvl = NULL; 5158 } 5159 out: 5160 if (groupList != NULL) { 5161 free(groupList); 5162 } 5163 if (guidList != NULL) { 5164 free(guidList); 5165 } 5166 if (viewEntryList != NULL) { 5167 free(viewEntryList); 5168 } 5169 if (nvl != NULL) { 5170 nvlist_free(nvl); 5171 } 5172 return (ret); 5173 } 5174 5175 /* 5176 * stmfGetAluaState 5177 * 5178 * Purpose - Get the alua state 5179 * 5180 */ 5181 int 5182 stmfGetAluaState(boolean_t *enabled, uint32_t *node) 5183 { 5184 int ret = STMF_STATUS_SUCCESS; 5185 int fd; 5186 stmf_iocdata_t stmfIoctl = {0}; 5187 stmf_alua_state_desc_t alua_state = {0}; 5188 int ioctlRet; 5189 5190 if (enabled == NULL || node == NULL) { 5191 return (STMF_ERROR_INVALID_ARG); 5192 } 5193 5194 /* 5195 * Open control node for stmf 5196 */ 5197 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5198 return (ret); 5199 5200 /* 5201 * Issue ioctl to get the stmf state 5202 */ 5203 stmfIoctl.stmf_version = STMF_VERSION_1; 5204 stmfIoctl.stmf_obuf_size = sizeof (alua_state); 5205 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&alua_state; 5206 ioctlRet = ioctl(fd, STMF_IOCTL_GET_ALUA_STATE, &stmfIoctl); 5207 5208 (void) close(fd); 5209 5210 if (ioctlRet != 0) { 5211 switch (errno) { 5212 case EBUSY: 5213 ret = STMF_ERROR_BUSY; 5214 break; 5215 case EPERM: 5216 case EACCES: 5217 ret = STMF_ERROR_PERM; 5218 break; 5219 default: 5220 syslog(LOG_DEBUG, 5221 "getStmfState:ioctl errno(%d)", errno); 5222 ret = STMF_STATUS_ERROR; 5223 break; 5224 } 5225 } else { 5226 if (alua_state.alua_state == 1) { 5227 *enabled = B_TRUE; 5228 } else { 5229 *enabled = B_FALSE; 5230 } 5231 *node = alua_state.alua_node; 5232 } 5233 5234 return (ret); 5235 } 5236 5237 /* 5238 * stmfSetAluaState 5239 * 5240 * Purpose - set the alua state to enabled/disabled 5241 * 5242 */ 5243 int 5244 stmfSetAluaState(boolean_t enabled, uint32_t node) 5245 { 5246 int ret = STMF_STATUS_SUCCESS; 5247 int fd; 5248 stmf_iocdata_t stmfIoctl = {0}; 5249 stmf_alua_state_desc_t alua_state = {0}; 5250 int ioctlRet; 5251 5252 if ((enabled != B_TRUE && enabled != B_FALSE) || (node > 1)) { 5253 return (STMF_ERROR_INVALID_ARG); 5254 } 5255 5256 if (enabled) { 5257 alua_state.alua_state = 1; 5258 } 5259 5260 alua_state.alua_node = node; 5261 5262 /* 5263 * Open control node for stmf 5264 */ 5265 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5266 return (ret); 5267 5268 /* 5269 * Issue ioctl to get the stmf state 5270 */ 5271 stmfIoctl.stmf_version = STMF_VERSION_1; 5272 stmfIoctl.stmf_ibuf_size = sizeof (alua_state); 5273 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&alua_state; 5274 ioctlRet = ioctl(fd, STMF_IOCTL_SET_ALUA_STATE, &stmfIoctl); 5275 5276 (void) close(fd); 5277 5278 if (ioctlRet != 0) { 5279 switch (errno) { 5280 case EBUSY: 5281 ret = STMF_ERROR_BUSY; 5282 break; 5283 case EPERM: 5284 case EACCES: 5285 ret = STMF_ERROR_PERM; 5286 break; 5287 default: 5288 syslog(LOG_DEBUG, 5289 "getStmfState:ioctl errno(%d)", errno); 5290 ret = STMF_STATUS_ERROR; 5291 break; 5292 } 5293 } 5294 if (!enabled && ret == STMF_STATUS_SUCCESS) { 5295 deleteNonActiveLus(); 5296 } 5297 5298 return (ret); 5299 } 5300 5301 static void 5302 deleteNonActiveLus() 5303 { 5304 int stmfRet; 5305 int i; 5306 stmfGuidList *luList; 5307 luResource hdl = NULL; 5308 char propVal[10]; 5309 size_t propValSize = sizeof (propVal); 5310 5311 stmfRet = stmfGetLogicalUnitList(&luList); 5312 if (stmfRet != STMF_STATUS_SUCCESS) { 5313 return; 5314 } 5315 5316 for (i = 0; i < luList->cnt; i++) { 5317 stmfRet = stmfGetLuResource(&luList->guid[i], &hdl); 5318 if (stmfRet != STMF_STATUS_SUCCESS) { 5319 goto err; 5320 } 5321 stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_ACCESS_STATE, propVal, 5322 &propValSize); 5323 if (stmfRet != STMF_STATUS_SUCCESS) { 5324 goto err; 5325 } 5326 if (propVal[0] == '0') { 5327 (void) stmfFreeLuResource(hdl); 5328 hdl = NULL; 5329 continue; 5330 } 5331 (void) stmfDeleteLu(&luList->guid[i]); 5332 (void) stmfFreeLuResource(hdl); 5333 hdl = NULL; 5334 } 5335 5336 err: 5337 stmfFreeMemory(luList); 5338 (void) stmfFreeLuResource(hdl); 5339 } 5340 5341 /* 5342 * stmfLoadConfig 5343 * 5344 * Purpose - load the configuration data from smf into stmf 5345 * 5346 */ 5347 int 5348 stmfLoadConfig(void) 5349 { 5350 int ret = STMF_STATUS_SUCCESS; 5351 int fd; 5352 stmf_state_desc_t stmfStateSet; 5353 stmfState state; 5354 5355 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5356 stmfStateSet.state = STMF_STATE_OFFLINE; 5357 5358 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) 5359 != STMF_STATUS_SUCCESS) { 5360 return (ret); 5361 } 5362 /* 5363 * Configuration not stored persistently; nothing to 5364 * initialize so do not set to STMF_CONFIG_INIT. 5365 */ 5366 stmfStateSet.config_state = STMF_CONFIG_INIT_DONE; 5367 goto done; 5368 } 5369 5370 /* Check to ensure service exists */ 5371 if (psCheckService() != STMF_STATUS_SUCCESS) { 5372 return (STMF_ERROR_SERVICE_NOT_FOUND); 5373 } 5374 5375 ret = stmfGetState(&state); 5376 if (ret == STMF_STATUS_SUCCESS) { 5377 if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) { 5378 return (STMF_ERROR_SERVICE_ONLINE); 5379 } 5380 } else { 5381 return (STMF_STATUS_ERROR); 5382 } 5383 5384 5385 stmfStateSet.state = STMF_STATE_OFFLINE; 5386 stmfStateSet.config_state = STMF_CONFIG_INIT; 5387 5388 /* 5389 * Open control node for stmf 5390 */ 5391 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5392 return (ret); 5393 5394 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE); 5395 if (ret != STMF_STATUS_SUCCESS) { 5396 goto done; 5397 } 5398 5399 /* Load the persistent configuration data */ 5400 ret = loadStore(fd); 5401 if (ret != 0) { 5402 goto done; 5403 } 5404 5405 stmfStateSet.state = STMF_STATE_OFFLINE; 5406 stmfStateSet.config_state = STMF_CONFIG_INIT_DONE; 5407 5408 done: 5409 if (ret == STMF_STATUS_SUCCESS) { 5410 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE); 5411 } 5412 (void) close(fd); 5413 return (ret); 5414 } 5415 5416 5417 /* 5418 * getStmfState 5419 * 5420 * stmfState - pointer to stmf_state_desc_t structure. Will contain the state 5421 * information of the stmf service on success. 5422 */ 5423 static int 5424 getStmfState(stmf_state_desc_t *stmfState) 5425 { 5426 int ret = STMF_STATUS_SUCCESS; 5427 int fd; 5428 int ioctlRet; 5429 stmf_iocdata_t stmfIoctl; 5430 5431 /* 5432 * Open control node for stmf 5433 */ 5434 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5435 return (ret); 5436 5437 bzero(&stmfIoctl, sizeof (stmfIoctl)); 5438 /* 5439 * Issue ioctl to get the stmf state 5440 */ 5441 stmfIoctl.stmf_version = STMF_VERSION_1; 5442 stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t); 5443 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState; 5444 stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t); 5445 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState; 5446 ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl); 5447 5448 (void) close(fd); 5449 5450 if (ioctlRet != 0) { 5451 switch (errno) { 5452 case EBUSY: 5453 ret = STMF_ERROR_BUSY; 5454 break; 5455 case EPERM: 5456 case EACCES: 5457 ret = STMF_ERROR_PERM; 5458 break; 5459 default: 5460 syslog(LOG_DEBUG, 5461 "getStmfState:ioctl errno(%d)", errno); 5462 ret = STMF_STATUS_ERROR; 5463 break; 5464 } 5465 } 5466 return (ret); 5467 } 5468 5469 5470 /* 5471 * setStmfState 5472 * 5473 * stmfState - pointer to caller set state structure 5474 * objectType - one of: 5475 * LOGICAL_UNIT_TYPE 5476 * TARGET_TYPE 5477 * STMF_SERVICE_TYPE 5478 */ 5479 static int 5480 setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType) 5481 { 5482 int ret = STMF_STATUS_SUCCESS; 5483 int ioctlRet; 5484 int cmd; 5485 stmf_iocdata_t stmfIoctl; 5486 5487 switch (objectType) { 5488 case LOGICAL_UNIT_TYPE: 5489 cmd = STMF_IOCTL_SET_LU_STATE; 5490 break; 5491 case TARGET_TYPE: 5492 cmd = STMF_IOCTL_SET_TARGET_PORT_STATE; 5493 break; 5494 case STMF_SERVICE_TYPE: 5495 cmd = STMF_IOCTL_SET_STMF_STATE; 5496 break; 5497 default: 5498 ret = STMF_STATUS_ERROR; 5499 goto done; 5500 } 5501 5502 bzero(&stmfIoctl, sizeof (stmfIoctl)); 5503 /* 5504 * Issue ioctl to set the stmf state 5505 */ 5506 stmfIoctl.stmf_version = STMF_VERSION_1; 5507 stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t); 5508 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState; 5509 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 5510 if (ioctlRet != 0) { 5511 switch (errno) { 5512 case EBUSY: 5513 ret = STMF_ERROR_BUSY; 5514 break; 5515 case EPERM: 5516 case EACCES: 5517 ret = STMF_ERROR_PERM; 5518 break; 5519 case ENOENT: 5520 ret = STMF_ERROR_NOT_FOUND; 5521 break; 5522 default: 5523 syslog(LOG_DEBUG, 5524 "setStmfState:ioctl errno(%d)", errno); 5525 ret = STMF_STATUS_ERROR; 5526 break; 5527 } 5528 } 5529 done: 5530 return (ret); 5531 } 5532 5533 /* 5534 * stmfOnline 5535 * 5536 * Purpose: Online stmf service 5537 * 5538 */ 5539 int 5540 stmfOnline(void) 5541 { 5542 int ret; 5543 int fd; 5544 stmfState state; 5545 stmf_state_desc_t iState; 5546 5547 ret = stmfGetState(&state); 5548 if (ret == STMF_STATUS_SUCCESS) { 5549 if (state.operationalState == STMF_SERVICE_STATE_ONLINE) { 5550 return (STMF_ERROR_SERVICE_ONLINE); 5551 } 5552 } else { 5553 return (STMF_STATUS_ERROR); 5554 } 5555 iState.state = STMF_STATE_ONLINE; 5556 iState.config_state = STMF_CONFIG_NONE; 5557 /* 5558 * Open control node for stmf 5559 * to make call to setStmfState() 5560 */ 5561 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5562 return (ret); 5563 ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE); 5564 (void) close(fd); 5565 return (ret); 5566 } 5567 5568 /* 5569 * stmfOffline 5570 * 5571 * Purpose: Offline stmf service 5572 * 5573 */ 5574 int 5575 stmfOffline(void) 5576 { 5577 int ret; 5578 int fd; 5579 stmfState state; 5580 stmf_state_desc_t iState; 5581 5582 ret = stmfGetState(&state); 5583 if (ret == STMF_STATUS_SUCCESS) { 5584 if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) { 5585 return (STMF_ERROR_SERVICE_OFFLINE); 5586 } 5587 } else { 5588 return (STMF_STATUS_ERROR); 5589 } 5590 iState.state = STMF_STATE_OFFLINE; 5591 iState.config_state = STMF_CONFIG_NONE; 5592 5593 /* 5594 * Open control node for stmf 5595 * to make call to setStmfState() 5596 */ 5597 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5598 return (ret); 5599 ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE); 5600 (void) close(fd); 5601 return (ret); 5602 } 5603 5604 5605 /* 5606 * stmfOfflineTarget 5607 * 5608 * Purpose: Change state of target to offline 5609 * 5610 * devid - devid of the target to offline 5611 */ 5612 int 5613 stmfOfflineTarget(stmfDevid *devid) 5614 { 5615 stmf_state_desc_t targetState; 5616 int ret = STMF_STATUS_SUCCESS; 5617 int fd; 5618 5619 if (devid == NULL) { 5620 return (STMF_ERROR_INVALID_ARG); 5621 } 5622 bzero(&targetState, sizeof (targetState)); 5623 5624 targetState.state = STMF_STATE_OFFLINE; 5625 targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength; 5626 bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1], 5627 devid->identLength); 5628 /* 5629 * Open control node for stmf 5630 * to make call to setStmfState() 5631 */ 5632 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5633 return (ret); 5634 ret = setStmfState(fd, &targetState, TARGET_TYPE); 5635 (void) close(fd); 5636 return (ret); 5637 } 5638 5639 /* 5640 * stmfOfflineLogicalUnit 5641 * 5642 * Purpose: Change state of logical unit to offline 5643 * 5644 * lu - guid of the logical unit to offline 5645 */ 5646 int 5647 stmfOfflineLogicalUnit(stmfGuid *lu) 5648 { 5649 stmf_state_desc_t luState; 5650 int ret = STMF_STATUS_SUCCESS; 5651 int fd; 5652 5653 if (lu == NULL) { 5654 return (STMF_ERROR_INVALID_ARG); 5655 } 5656 5657 bzero(&luState, sizeof (luState)); 5658 5659 luState.state = STMF_STATE_OFFLINE; 5660 bcopy(lu, &luState.ident, sizeof (stmfGuid)); 5661 /* 5662 * Open control node for stmf 5663 * to make call to setStmfState() 5664 */ 5665 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5666 return (ret); 5667 ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE); 5668 (void) close(fd); 5669 return (ret); 5670 } 5671 5672 /* 5673 * stmfOnlineTarget 5674 * 5675 * Purpose: Change state of target to online 5676 * 5677 * devid - devid of the target to online 5678 */ 5679 int 5680 stmfOnlineTarget(stmfDevid *devid) 5681 { 5682 stmf_state_desc_t targetState; 5683 int ret = STMF_STATUS_SUCCESS; 5684 int fd; 5685 5686 if (devid == NULL) { 5687 return (STMF_ERROR_INVALID_ARG); 5688 } 5689 bzero(&targetState, sizeof (targetState)); 5690 5691 targetState.state = STMF_STATE_ONLINE; 5692 targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength; 5693 bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1], 5694 devid->identLength); 5695 /* 5696 * Open control node for stmf 5697 * to make call to setStmfState() 5698 */ 5699 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5700 return (ret); 5701 ret = setStmfState(fd, &targetState, TARGET_TYPE); 5702 (void) close(fd); 5703 return (ret); 5704 } 5705 5706 /* 5707 * stmfOnlineLogicalUnit 5708 * 5709 * Purpose: Change state of logical unit to online 5710 * 5711 * lu - guid of the logical unit to online 5712 */ 5713 int 5714 stmfOnlineLogicalUnit(stmfGuid *lu) 5715 { 5716 stmf_state_desc_t luState; 5717 int ret = STMF_STATUS_SUCCESS; 5718 int fd; 5719 5720 if (lu == NULL) { 5721 return (STMF_ERROR_INVALID_ARG); 5722 } 5723 5724 bzero(&luState, sizeof (luState)); 5725 5726 luState.state = STMF_STATE_ONLINE; 5727 bcopy(lu, &luState.ident, sizeof (stmfGuid)); 5728 /* 5729 * Open control node for stmf 5730 * to make call to setStmfState() 5731 */ 5732 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5733 return (ret); 5734 ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE); 5735 (void) close(fd); 5736 return (ret); 5737 } 5738 5739 /* 5740 * stmfRemoveFromHostGroup 5741 * 5742 * Purpose: Removes an initiator from an initiator group 5743 * 5744 * hostGroupName - name of an initiator group 5745 * hostName - name of host group member to remove 5746 */ 5747 int 5748 stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName) 5749 { 5750 int ret; 5751 int fd; 5752 5753 if (hostGroupName == NULL || 5754 (strnlen((char *)hostGroupName, sizeof (stmfGroupName)) 5755 == sizeof (stmfGroupName)) || hostName == NULL) { 5756 return (STMF_ERROR_INVALID_ARG); 5757 } 5758 5759 /* call init */ 5760 ret = initializeConfig(); 5761 if (ret != STMF_STATUS_SUCCESS) { 5762 return (ret); 5763 } 5764 5765 /* 5766 * Open control node for stmf 5767 */ 5768 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5769 return (ret); 5770 5771 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY, 5772 hostGroupName, hostName)) != STMF_STATUS_SUCCESS) { 5773 goto done; 5774 } 5775 5776 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5777 goto done; 5778 } 5779 5780 ret = psRemoveHostGroupMember((char *)hostGroupName, 5781 (char *)hostName->ident); 5782 switch (ret) { 5783 case STMF_PS_SUCCESS: 5784 ret = STMF_STATUS_SUCCESS; 5785 break; 5786 case STMF_PS_ERROR_MEMBER_NOT_FOUND: 5787 ret = STMF_ERROR_MEMBER_NOT_FOUND; 5788 break; 5789 case STMF_PS_ERROR_GROUP_NOT_FOUND: 5790 ret = STMF_ERROR_GROUP_NOT_FOUND; 5791 break; 5792 case STMF_PS_ERROR_BUSY: 5793 ret = STMF_ERROR_BUSY; 5794 break; 5795 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5796 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5797 break; 5798 case STMF_PS_ERROR_VERSION_MISMATCH: 5799 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5800 break; 5801 default: 5802 syslog(LOG_DEBUG, 5803 "stmfRemoveFromHostGroup" 5804 "psRemoveHostGroupMember:error(%d)", ret); 5805 ret = STMF_STATUS_ERROR; 5806 break; 5807 } 5808 5809 done: 5810 (void) close(fd); 5811 return (ret); 5812 } 5813 5814 /* 5815 * stmfRemoveFromTargetGroup 5816 * 5817 * Purpose: Removes a local port from a local port group 5818 * 5819 * targetGroupName - name of a target group 5820 * targetName - name of target to remove 5821 */ 5822 int 5823 stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName) 5824 { 5825 int ret; 5826 int fd; 5827 5828 if (targetGroupName == NULL || 5829 (strnlen((char *)targetGroupName, sizeof (stmfGroupName)) 5830 == sizeof (stmfGroupName)) || targetName == NULL) { 5831 return (STMF_ERROR_INVALID_ARG); 5832 } 5833 5834 /* call init */ 5835 ret = initializeConfig(); 5836 if (ret != STMF_STATUS_SUCCESS) { 5837 return (ret); 5838 } 5839 5840 /* 5841 * Open control node for stmf 5842 */ 5843 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5844 return (ret); 5845 5846 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY, 5847 targetGroupName, targetName)) != STMF_STATUS_SUCCESS) { 5848 goto done; 5849 } 5850 5851 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5852 goto done; 5853 } 5854 5855 ret = psRemoveTargetGroupMember((char *)targetGroupName, 5856 (char *)targetName->ident); 5857 switch (ret) { 5858 case STMF_PS_SUCCESS: 5859 ret = STMF_STATUS_SUCCESS; 5860 break; 5861 case STMF_PS_ERROR_MEMBER_NOT_FOUND: 5862 ret = STMF_ERROR_MEMBER_NOT_FOUND; 5863 break; 5864 case STMF_PS_ERROR_GROUP_NOT_FOUND: 5865 ret = STMF_ERROR_GROUP_NOT_FOUND; 5866 break; 5867 case STMF_PS_ERROR_BUSY: 5868 ret = STMF_ERROR_BUSY; 5869 break; 5870 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5871 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5872 break; 5873 case STMF_PS_ERROR_VERSION_MISMATCH: 5874 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5875 break; 5876 default: 5877 syslog(LOG_DEBUG, 5878 "stmfRemoveFromTargetGroup" 5879 "psRemoveTargetGroupMember:error(%d)", ret); 5880 ret = STMF_STATUS_ERROR; 5881 break; 5882 } 5883 5884 done: 5885 (void) close(fd); 5886 return (ret); 5887 } 5888 5889 /* 5890 * stmfRemoveViewEntry 5891 * 5892 * Purpose: Removes a view entry from a logical unit 5893 * 5894 * lu - guid of lu for which view entry is being removed 5895 * viewEntryIndex - index of view entry to remove 5896 * 5897 */ 5898 int 5899 stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex) 5900 { 5901 int ret = STMF_STATUS_SUCCESS; 5902 int fd; 5903 int ioctlRet; 5904 stmf_iocdata_t stmfIoctl; 5905 stmf_view_op_entry_t ioctlViewEntry; 5906 5907 if (lu == NULL) { 5908 return (STMF_ERROR_INVALID_ARG); 5909 } 5910 5911 /* call init */ 5912 ret = initializeConfig(); 5913 if (ret != STMF_STATUS_SUCCESS) { 5914 return (ret); 5915 } 5916 5917 /* 5918 * Open control node for stmf 5919 */ 5920 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5921 return (ret); 5922 5923 bzero(&ioctlViewEntry, sizeof (ioctlViewEntry)); 5924 ioctlViewEntry.ve_ndx_valid = B_TRUE; 5925 ioctlViewEntry.ve_ndx = viewEntryIndex; 5926 bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid)); 5927 5928 bzero(&stmfIoctl, sizeof (stmfIoctl)); 5929 /* 5930 * Issue ioctl to add to the view entry 5931 */ 5932 stmfIoctl.stmf_version = STMF_VERSION_1; 5933 stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry); 5934 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry; 5935 ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl); 5936 if (ioctlRet != 0) { 5937 switch (errno) { 5938 case EBUSY: 5939 ret = STMF_ERROR_BUSY; 5940 break; 5941 case EPERM: 5942 ret = STMF_ERROR_PERM; 5943 break; 5944 case EACCES: 5945 switch (stmfIoctl.stmf_error) { 5946 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 5947 ret = STMF_ERROR_CONFIG_NONE; 5948 break; 5949 default: 5950 ret = STMF_ERROR_PERM; 5951 break; 5952 } 5953 break; 5954 case ENODEV: 5955 case ENOENT: 5956 ret = STMF_ERROR_NOT_FOUND; 5957 break; 5958 default: 5959 syslog(LOG_DEBUG, 5960 "stmfRemoveViewEntry:ioctl errno(%d)", 5961 errno); 5962 ret = STMF_STATUS_ERROR; 5963 break; 5964 } 5965 goto done; 5966 } 5967 5968 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5969 goto done; 5970 } 5971 5972 ret = psRemoveViewEntry(lu, viewEntryIndex); 5973 switch (ret) { 5974 case STMF_PS_SUCCESS: 5975 ret = STMF_STATUS_SUCCESS; 5976 break; 5977 case STMF_PS_ERROR_NOT_FOUND: 5978 ret = STMF_ERROR_NOT_FOUND; 5979 break; 5980 case STMF_PS_ERROR_BUSY: 5981 ret = STMF_ERROR_BUSY; 5982 break; 5983 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5984 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5985 break; 5986 case STMF_PS_ERROR_VERSION_MISMATCH: 5987 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5988 break; 5989 default: 5990 syslog(LOG_DEBUG, 5991 "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)", 5992 ret); 5993 ret = STMF_STATUS_ERROR; 5994 break; 5995 } 5996 5997 done: 5998 (void) close(fd); 5999 return (ret); 6000 } 6001 6002 /* 6003 * stmfSetProviderData 6004 * 6005 * Purpose: set the provider data 6006 * 6007 * providerName - unique name of provider 6008 * nvl - nvlist to set 6009 * providerType - type of provider for which to set data 6010 * STMF_LU_PROVIDER_TYPE 6011 * STMF_PORT_PROVIDER_TYPE 6012 */ 6013 int 6014 stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType) 6015 { 6016 return (stmfSetProviderDataProt(providerName, nvl, providerType, 6017 NULL)); 6018 } 6019 6020 /* 6021 * stmfSetProviderDataProt 6022 * 6023 * Purpose: set the provider data 6024 * 6025 * providerName - unique name of provider 6026 * nvl - nvlist to set 6027 * providerType - type of provider for which to set data 6028 * STMF_LU_PROVIDER_TYPE 6029 * STMF_PORT_PROVIDER_TYPE 6030 * setToken - Stale data token returned in the stmfGetProviderDataProt() 6031 * call or NULL. 6032 */ 6033 int 6034 stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType, 6035 uint64_t *setToken) 6036 { 6037 int ret; 6038 int fd; 6039 6040 if (providerName == NULL || nvl == NULL) { 6041 return (STMF_ERROR_INVALID_ARG); 6042 } 6043 6044 if (providerType != STMF_LU_PROVIDER_TYPE && 6045 providerType != STMF_PORT_PROVIDER_TYPE) { 6046 return (STMF_ERROR_INVALID_ARG); 6047 } 6048 6049 /* call init */ 6050 ret = initializeConfig(); 6051 if (ret != STMF_STATUS_SUCCESS) { 6052 return (ret); 6053 } 6054 6055 /* 6056 * Open control node for stmf 6057 */ 6058 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 6059 return (ret); 6060 6061 ret = setProviderData(fd, providerName, nvl, providerType, setToken); 6062 6063 (void) close(fd); 6064 6065 if (ret != STMF_STATUS_SUCCESS) { 6066 goto done; 6067 } 6068 6069 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 6070 goto done; 6071 } 6072 6073 /* setting driver provider data successful. Now persist it */ 6074 ret = psSetProviderData(providerName, nvl, providerType, NULL); 6075 switch (ret) { 6076 case STMF_PS_SUCCESS: 6077 ret = STMF_STATUS_SUCCESS; 6078 break; 6079 case STMF_PS_ERROR_EXISTS: 6080 ret = STMF_ERROR_EXISTS; 6081 break; 6082 case STMF_PS_ERROR_BUSY: 6083 ret = STMF_ERROR_BUSY; 6084 break; 6085 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 6086 ret = STMF_ERROR_SERVICE_NOT_FOUND; 6087 break; 6088 case STMF_PS_ERROR_VERSION_MISMATCH: 6089 ret = STMF_ERROR_SERVICE_DATA_VERSION; 6090 break; 6091 case STMF_PS_ERROR_PROV_DATA_STALE: 6092 ret = STMF_ERROR_PROV_DATA_STALE; 6093 break; 6094 default: 6095 syslog(LOG_DEBUG, 6096 "stmfSetProviderData" 6097 "psSetProviderData:error(%d)", ret); 6098 ret = STMF_STATUS_ERROR; 6099 break; 6100 } 6101 6102 done: 6103 return (ret); 6104 } 6105 6106 /* 6107 * getProviderData 6108 * 6109 * Purpose: set the provider data from stmf 6110 * 6111 * providerName - unique name of provider 6112 * nvl - nvlist to load/retrieve 6113 * providerType - logical unit or port provider 6114 * setToken - returned stale data token 6115 */ 6116 int 6117 getProviderData(char *providerName, nvlist_t **nvl, int providerType, 6118 uint64_t *setToken) 6119 { 6120 int ret = STMF_STATUS_SUCCESS; 6121 int fd; 6122 int ioctlRet; 6123 size_t nvlistSize = ALLOC_PP_DATA_SIZE; 6124 int retryCnt = 0; 6125 int retryCntMax = MAX_PROVIDER_RETRY; 6126 stmf_ppioctl_data_t ppi = {0}, *ppi_out = NULL; 6127 boolean_t retry = B_TRUE; 6128 stmf_iocdata_t stmfIoctl; 6129 6130 if (providerName == NULL) { 6131 return (STMF_ERROR_INVALID_ARG); 6132 } 6133 6134 /* 6135 * Open control node for stmf 6136 */ 6137 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 6138 return (ret); 6139 6140 /* set provider name and provider type */ 6141 if (strlcpy(ppi.ppi_name, providerName, 6142 sizeof (ppi.ppi_name)) >= 6143 sizeof (ppi.ppi_name)) { 6144 ret = STMF_ERROR_INVALID_ARG; 6145 goto done; 6146 } 6147 switch (providerType) { 6148 case STMF_LU_PROVIDER_TYPE: 6149 ppi.ppi_lu_provider = 1; 6150 break; 6151 case STMF_PORT_PROVIDER_TYPE: 6152 ppi.ppi_port_provider = 1; 6153 break; 6154 default: 6155 ret = STMF_ERROR_INVALID_ARG; 6156 goto done; 6157 } 6158 6159 do { 6160 /* allocate memory for ioctl */ 6161 ppi_out = (stmf_ppioctl_data_t *)calloc(1, nvlistSize + 6162 sizeof (stmf_ppioctl_data_t)); 6163 if (ppi_out == NULL) { 6164 ret = STMF_ERROR_NOMEM; 6165 goto done; 6166 6167 } 6168 6169 /* set the size of the ioctl data to allocated buffer */ 6170 ppi.ppi_data_size = nvlistSize; 6171 6172 bzero(&stmfIoctl, sizeof (stmfIoctl)); 6173 6174 stmfIoctl.stmf_version = STMF_VERSION_1; 6175 stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t); 6176 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi; 6177 stmfIoctl.stmf_obuf_size = sizeof (stmf_ppioctl_data_t) + 6178 nvlistSize; 6179 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)ppi_out; 6180 ioctlRet = ioctl(fd, STMF_IOCTL_GET_PP_DATA, &stmfIoctl); 6181 if (ioctlRet != 0) { 6182 switch (errno) { 6183 case EBUSY: 6184 ret = STMF_ERROR_BUSY; 6185 break; 6186 case EPERM: 6187 case EACCES: 6188 ret = STMF_ERROR_PERM; 6189 break; 6190 case EINVAL: 6191 if (stmfIoctl.stmf_error == 6192 STMF_IOCERR_INSUFFICIENT_BUF) { 6193 nvlistSize = 6194 ppi_out->ppi_data_size; 6195 free(ppi_out); 6196 ppi_out = NULL; 6197 if (retryCnt++ > retryCntMax) { 6198 retry = B_FALSE; 6199 ret = STMF_ERROR_BUSY; 6200 } else { 6201 ret = 6202 STMF_STATUS_SUCCESS; 6203 } 6204 } else { 6205 syslog(LOG_DEBUG, 6206 "getProviderData:ioctl" 6207 "unable to retrieve " 6208 "nvlist"); 6209 ret = STMF_STATUS_ERROR; 6210 } 6211 break; 6212 case ENOENT: 6213 ret = STMF_ERROR_NOT_FOUND; 6214 break; 6215 default: 6216 syslog(LOG_DEBUG, 6217 "getProviderData:ioctl errno(%d)", 6218 errno); 6219 ret = STMF_STATUS_ERROR; 6220 break; 6221 } 6222 if (ret != STMF_STATUS_SUCCESS) 6223 goto done; 6224 } 6225 } while (retry && stmfIoctl.stmf_error == STMF_IOCERR_INSUFFICIENT_BUF); 6226 6227 if ((ret = nvlist_unpack((char *)ppi_out->ppi_data, 6228 ppi_out->ppi_data_size, nvl, 0)) != 0) { 6229 ret = STMF_STATUS_ERROR; 6230 goto done; 6231 } 6232 6233 /* caller has asked for new token */ 6234 if (setToken) { 6235 *setToken = ppi_out->ppi_token; 6236 } 6237 done: 6238 free(ppi_out); 6239 (void) close(fd); 6240 return (ret); 6241 } 6242 6243 /* 6244 * setProviderData 6245 * 6246 * Purpose: set the provider data in stmf 6247 * 6248 * providerName - unique name of provider 6249 * nvl - nvlist to set 6250 * providerType - logical unit or port provider 6251 * setToken - stale data token to check if not NULL 6252 */ 6253 static int 6254 setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType, 6255 uint64_t *setToken) 6256 { 6257 int ret = STMF_STATUS_SUCCESS; 6258 int ioctlRet; 6259 size_t nvlistEncodedSize; 6260 stmf_ppioctl_data_t *ppi = NULL; 6261 uint64_t outToken; 6262 char *allocatedNvBuffer; 6263 stmf_iocdata_t stmfIoctl; 6264 6265 if (providerName == NULL) { 6266 return (STMF_ERROR_INVALID_ARG); 6267 } 6268 6269 /* get size of encoded nvlist */ 6270 if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) { 6271 return (STMF_STATUS_ERROR); 6272 } 6273 6274 /* allocate memory for ioctl */ 6275 ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize + 6276 sizeof (stmf_ppioctl_data_t)); 6277 if (ppi == NULL) { 6278 return (STMF_ERROR_NOMEM); 6279 } 6280 6281 if (setToken) { 6282 ppi->ppi_token_valid = 1; 6283 ppi->ppi_token = *setToken; 6284 } 6285 6286 allocatedNvBuffer = (char *)&ppi->ppi_data; 6287 if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize, 6288 NV_ENCODE_XDR, 0) != 0) { 6289 return (STMF_STATUS_ERROR); 6290 } 6291 6292 /* set provider name and provider type */ 6293 (void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name)); 6294 switch (providerType) { 6295 case STMF_LU_PROVIDER_TYPE: 6296 ppi->ppi_lu_provider = 1; 6297 break; 6298 case STMF_PORT_PROVIDER_TYPE: 6299 ppi->ppi_port_provider = 1; 6300 break; 6301 default: 6302 return (STMF_ERROR_INVALID_ARG); 6303 } 6304 6305 /* set the size of the ioctl data to packed data size */ 6306 ppi->ppi_data_size = nvlistEncodedSize; 6307 6308 bzero(&stmfIoctl, sizeof (stmfIoctl)); 6309 6310 stmfIoctl.stmf_version = STMF_VERSION_1; 6311 /* 6312 * Subtracting 8 from the size as that is the size of the last member 6313 * of the structure where the packed data resides 6314 */ 6315 stmfIoctl.stmf_ibuf_size = nvlistEncodedSize + 6316 sizeof (stmf_ppioctl_data_t) - 8; 6317 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi; 6318 stmfIoctl.stmf_obuf_size = sizeof (uint64_t); 6319 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&outToken; 6320 ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl); 6321 if (ioctlRet != 0) { 6322 switch (errno) { 6323 case EBUSY: 6324 ret = STMF_ERROR_BUSY; 6325 break; 6326 case EPERM: 6327 case EACCES: 6328 ret = STMF_ERROR_PERM; 6329 break; 6330 case EINVAL: 6331 if (stmfIoctl.stmf_error == 6332 STMF_IOCERR_PPD_UPDATED) { 6333 ret = STMF_ERROR_PROV_DATA_STALE; 6334 } else { 6335 ret = STMF_STATUS_ERROR; 6336 } 6337 break; 6338 default: 6339 syslog(LOG_DEBUG, 6340 "setProviderData:ioctl errno(%d)", errno); 6341 ret = STMF_STATUS_ERROR; 6342 break; 6343 } 6344 if (ret != STMF_STATUS_SUCCESS) 6345 goto done; 6346 } 6347 6348 /* caller has asked for new token */ 6349 if (setToken) { 6350 *setToken = outToken; 6351 } 6352 done: 6353 free(ppi); 6354 return (ret); 6355 } 6356 6357 /* 6358 * set the persistence method in the library only or library and service 6359 */ 6360 int 6361 stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet) 6362 { 6363 int ret = STMF_STATUS_SUCCESS; 6364 int oldPersist; 6365 6366 (void) pthread_mutex_lock(&persistenceTypeLock); 6367 oldPersist = iPersistType; 6368 if (persistType == STMF_PERSIST_NONE || 6369 persistType == STMF_PERSIST_SMF) { 6370 iLibSetPersist = B_TRUE; 6371 iPersistType = persistType; 6372 } else { 6373 (void) pthread_mutex_unlock(&persistenceTypeLock); 6374 return (STMF_ERROR_INVALID_ARG); 6375 } 6376 /* Is this for this library open or in SMF */ 6377 if (serviceSet == B_TRUE) { 6378 ret = psSetServicePersist(persistType); 6379 if (ret != STMF_PS_SUCCESS) { 6380 ret = STMF_ERROR_PERSIST_TYPE; 6381 /* Set to old value */ 6382 iPersistType = oldPersist; 6383 } 6384 } 6385 (void) pthread_mutex_unlock(&persistenceTypeLock); 6386 6387 return (ret); 6388 } 6389 6390 /* 6391 * Only returns internal state for persist. If unset, goes to ps. If that 6392 * fails, returns default setting 6393 */ 6394 static uint8_t 6395 iGetPersistMethod() 6396 { 6397 6398 uint8_t persistType = 0; 6399 6400 (void) pthread_mutex_lock(&persistenceTypeLock); 6401 if (iLibSetPersist) { 6402 persistType = iPersistType; 6403 } else { 6404 int ret; 6405 ret = psGetServicePersist(&persistType); 6406 if (ret != STMF_PS_SUCCESS) { 6407 /* set to default */ 6408 persistType = STMF_DEFAULT_PERSIST; 6409 } 6410 } 6411 (void) pthread_mutex_unlock(&persistenceTypeLock); 6412 return (persistType); 6413 } 6414 6415 /* 6416 * Returns either library state or persistent config state depending on 6417 * serviceState 6418 */ 6419 int 6420 stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState) 6421 { 6422 int ret = STMF_STATUS_SUCCESS; 6423 6424 if (persistType == NULL) { 6425 return (STMF_ERROR_INVALID_ARG); 6426 } 6427 if (serviceState) { 6428 ret = psGetServicePersist(persistType); 6429 if (ret != STMF_PS_SUCCESS) { 6430 ret = STMF_ERROR_PERSIST_TYPE; 6431 } 6432 } else { 6433 (void) pthread_mutex_lock(&persistenceTypeLock); 6434 if (iLibSetPersist) { 6435 *persistType = iPersistType; 6436 } else { 6437 *persistType = STMF_DEFAULT_PERSIST; 6438 } 6439 (void) pthread_mutex_unlock(&persistenceTypeLock); 6440 } 6441 6442 return (ret); 6443 } 6444 6445 /* 6446 * stmfPostProxyMsg 6447 * 6448 * Purpose: Post a message to the proxy port provider 6449 * 6450 * buf - buffer containing message to post 6451 * buflen - buffer length 6452 */ 6453 int 6454 stmfPostProxyMsg(int hdl, void *buf, uint32_t buflen) 6455 { 6456 int ret = STMF_STATUS_SUCCESS; 6457 int ioctlRet; 6458 pppt_iocdata_t ppptIoctl = {0}; 6459 6460 if (buf == NULL) { 6461 return (STMF_ERROR_INVALID_ARG); 6462 } 6463 6464 /* 6465 * Issue ioctl to post the message 6466 */ 6467 ppptIoctl.pppt_version = PPPT_VERSION_1; 6468 ppptIoctl.pppt_buf_size = buflen; 6469 ppptIoctl.pppt_buf = (uint64_t)(unsigned long)buf; 6470 ioctlRet = ioctl(hdl, PPPT_MESSAGE, &ppptIoctl); 6471 if (ioctlRet != 0) { 6472 switch (errno) { 6473 case EPERM: 6474 case EACCES: 6475 ret = STMF_ERROR_PERM; 6476 break; 6477 default: 6478 ret = STMF_ERROR_POST_MSG_FAILED; 6479 break; 6480 } 6481 } 6482 6483 return (ret); 6484 } 6485 6486 /* 6487 * stmfInitProxyDoor 6488 * 6489 * Purpose: Install door in proxy 6490 * 6491 * hdl - pointer to returned handle 6492 * fd - door from door_create() 6493 */ 6494 int 6495 stmfInitProxyDoor(int *hdl, int door) 6496 { 6497 int ret = STMF_STATUS_SUCCESS; 6498 int ioctlRet; 6499 int fd; 6500 pppt_iocdata_t ppptIoctl = {0}; 6501 6502 if (hdl == NULL) { 6503 return (STMF_ERROR_INVALID_ARG); 6504 } 6505 6506 /* 6507 * Open control node for pppt 6508 */ 6509 if ((ret = openPppt(OPEN_PPPT, &fd)) != STMF_STATUS_SUCCESS) { 6510 return (ret); 6511 } 6512 6513 /* 6514 * Issue ioctl to install the door 6515 */ 6516 ppptIoctl.pppt_version = PPPT_VERSION_1; 6517 ppptIoctl.pppt_door_fd = (uint32_t)door; 6518 ioctlRet = ioctl(fd, PPPT_INSTALL_DOOR, &ppptIoctl); 6519 if (ioctlRet != 0) { 6520 switch (errno) { 6521 case EPERM: 6522 case EACCES: 6523 ret = STMF_ERROR_PERM; 6524 break; 6525 case EINVAL: 6526 ret = STMF_ERROR_INVALID_ARG; 6527 break; 6528 case EBUSY: 6529 ret = STMF_ERROR_DOOR_INSTALLED; 6530 break; 6531 default: 6532 ret = STMF_STATUS_ERROR; 6533 break; 6534 } 6535 } 6536 6537 /* return driver fd to caller */ 6538 *hdl = fd; 6539 return (ret); 6540 } 6541 6542 void 6543 stmfDestroyProxyDoor(int hdl) 6544 { 6545 (void) close(hdl); 6546 } 6547 6548 /* 6549 * validateLunNumIoctl 6550 * 6551 * Purpose: Issues ioctl to check and get available lun# in view entry 6552 * 6553 * viewEntry - view entry to use 6554 */ 6555 static int 6556 validateLunNumIoctl(int fd, stmfViewEntry *viewEntry) 6557 { 6558 int ret = STMF_STATUS_SUCCESS; 6559 int ioctlRet; 6560 stmf_iocdata_t stmfIoctl; 6561 stmf_view_op_entry_t ioctlViewEntry; 6562 6563 bzero(&ioctlViewEntry, sizeof (ioctlViewEntry)); 6564 /* 6565 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be 6566 * false on input 6567 */ 6568 ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid; 6569 ioctlViewEntry.ve_all_hosts = viewEntry->allHosts; 6570 ioctlViewEntry.ve_all_targets = viewEntry->allTargets; 6571 6572 if (viewEntry->allHosts == B_FALSE) { 6573 bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name, 6574 sizeof (stmfGroupName)); 6575 ioctlViewEntry.ve_host_group.name_size = 6576 strlen((char *)viewEntry->hostGroup); 6577 } 6578 if (viewEntry->allTargets == B_FALSE) { 6579 bcopy(viewEntry->targetGroup, 6580 &ioctlViewEntry.ve_target_group.name, 6581 sizeof (stmfGroupName)); 6582 ioctlViewEntry.ve_target_group.name_size = 6583 strlen((char *)viewEntry->targetGroup); 6584 } 6585 /* Validating the lun number */ 6586 if (viewEntry->luNbrValid) { 6587 bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr, 6588 sizeof (ioctlViewEntry.ve_lu_nbr)); 6589 } 6590 6591 bzero(&stmfIoctl, sizeof (stmfIoctl)); 6592 /* 6593 * Issue ioctl to validate lun# in the view entry 6594 */ 6595 stmfIoctl.stmf_version = STMF_VERSION_1; 6596 stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry); 6597 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry; 6598 stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry); 6599 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry; 6600 ioctlRet = ioctl(fd, STMF_IOCTL_VALIDATE_VIEW, &stmfIoctl); 6601 6602 /* save available lun number */ 6603 if (!viewEntry->luNbrValid) { 6604 bcopy(ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr, 6605 sizeof (ioctlViewEntry.ve_lu_nbr)); 6606 } 6607 if (ioctlRet != 0) { 6608 switch (errno) { 6609 case EBUSY: 6610 ret = STMF_ERROR_BUSY; 6611 break; 6612 case EPERM: 6613 ret = STMF_ERROR_PERM; 6614 break; 6615 case EACCES: 6616 switch (stmfIoctl.stmf_error) { 6617 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 6618 ret = STMF_ERROR_CONFIG_NONE; 6619 break; 6620 default: 6621 ret = STMF_ERROR_PERM; 6622 break; 6623 } 6624 break; 6625 default: 6626 switch (stmfIoctl.stmf_error) { 6627 case STMF_IOCERR_LU_NUMBER_IN_USE: 6628 ret = STMF_ERROR_LUN_IN_USE; 6629 break; 6630 case STMF_IOCERR_VIEW_ENTRY_CONFLICT: 6631 ret = STMF_ERROR_VE_CONFLICT; 6632 break; 6633 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 6634 ret = STMF_ERROR_CONFIG_NONE; 6635 break; 6636 case STMF_IOCERR_INVALID_HG: 6637 ret = STMF_ERROR_INVALID_HG; 6638 break; 6639 case STMF_IOCERR_INVALID_TG: 6640 ret = STMF_ERROR_INVALID_TG; 6641 break; 6642 default: 6643 syslog(LOG_DEBUG, 6644 "addViewEntryIoctl" 6645 ":error(%d)", 6646 stmfIoctl.stmf_error); 6647 ret = STMF_STATUS_ERROR; 6648 break; 6649 } 6650 break; 6651 } 6652 } 6653 return (ret); 6654 } 6655 6656 /* 6657 * stmfValidateView 6658 * 6659 * Purpose: Validate or get lun # base on TG, HG of view entry 6660 * 6661 * viewEntry - view entry structure to use 6662 */ 6663 int 6664 stmfValidateView(stmfViewEntry *viewEntry) 6665 { 6666 int ret; 6667 int fd; 6668 stmfViewEntry iViewEntry; 6669 6670 if (viewEntry == NULL) { 6671 return (STMF_ERROR_INVALID_ARG); 6672 } 6673 6674 /* initialize and set internal view entry */ 6675 bzero(&iViewEntry, sizeof (iViewEntry)); 6676 6677 if (!viewEntry->allHosts) { 6678 bcopy(viewEntry->hostGroup, iViewEntry.hostGroup, 6679 sizeof (iViewEntry.hostGroup)); 6680 } else { 6681 iViewEntry.allHosts = B_TRUE; 6682 } 6683 6684 if (!viewEntry->allTargets) { 6685 bcopy(viewEntry->targetGroup, iViewEntry.targetGroup, 6686 sizeof (iViewEntry.targetGroup)); 6687 } else { 6688 iViewEntry.allTargets = B_TRUE; 6689 } 6690 6691 if (viewEntry->luNbrValid) { 6692 iViewEntry.luNbrValid = B_TRUE; 6693 bcopy(viewEntry->luNbr, iViewEntry.luNbr, 6694 sizeof (iViewEntry.luNbr)); 6695 } 6696 6697 /* 6698 * set users return view entry index valid flag to false 6699 * in case of failure 6700 */ 6701 viewEntry->veIndexValid = B_FALSE; 6702 6703 /* Check to ensure service exists */ 6704 if (psCheckService() != STMF_STATUS_SUCCESS) { 6705 return (STMF_ERROR_SERVICE_NOT_FOUND); 6706 } 6707 6708 /* call init */ 6709 ret = initializeConfig(); 6710 if (ret != STMF_STATUS_SUCCESS) { 6711 return (ret); 6712 } 6713 6714 /* 6715 * Open control node for stmf 6716 */ 6717 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 6718 return (ret); 6719 6720 /* 6721 * Validate lun# in the view entry from the driver 6722 */ 6723 ret = validateLunNumIoctl(fd, &iViewEntry); 6724 (void) close(fd); 6725 6726 /* save available lun number */ 6727 if (!viewEntry->luNbrValid) { 6728 bcopy(iViewEntry.luNbr, viewEntry->luNbr, 6729 sizeof (iViewEntry.luNbr)); 6730 } 6731 6732 return (ret); 6733 } 6734