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