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