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