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