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