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