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 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) * stmfIoctl.stmf_obuf_nentries); 3276 if (*groupProps == NULL) { 3277 ret = STMF_ERROR_NOMEM; 3278 goto done; 3279 } 3280 (*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries; 3281 for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) { 3282 (*groupProps)->name[i].identLength = 3283 iGroupMembers[i].ident_size; 3284 bcopy(iGroupMembers[i].ident, (*groupProps)->name[i].ident, 3285 iGroupMembers[i].ident_size); 3286 } 3287 3288 done: 3289 free(iGroupMembers); 3290 (void) close(fd); 3291 return (ret); 3292 } 3293 3294 /* 3295 * Purpose: access persistent config data for host groups and target groups 3296 */ 3297 static int 3298 iLoadGroupFromPs(stmfGroupList **groupList, int type) 3299 { 3300 int ret; 3301 3302 if (groupList == NULL) { 3303 return (STMF_ERROR_INVALID_ARG); 3304 } 3305 3306 if (type == HOST_GROUP) { 3307 ret = psGetHostGroupList(groupList); 3308 } else if (type == TARGET_GROUP) { 3309 ret = psGetTargetGroupList(groupList); 3310 } else { 3311 return (STMF_ERROR_INVALID_ARG); 3312 } 3313 switch (ret) { 3314 case STMF_PS_SUCCESS: 3315 ret = STMF_STATUS_SUCCESS; 3316 break; 3317 case STMF_PS_ERROR_NOT_FOUND: 3318 ret = STMF_ERROR_NOT_FOUND; 3319 break; 3320 case STMF_PS_ERROR_BUSY: 3321 ret = STMF_ERROR_BUSY; 3322 break; 3323 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3324 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3325 break; 3326 case STMF_PS_ERROR_VERSION_MISMATCH: 3327 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3328 break; 3329 default: 3330 syslog(LOG_DEBUG, 3331 "stmfGetHostGroupList:psGetHostGroupList:error(%d)", 3332 ret); 3333 ret = STMF_STATUS_ERROR; 3334 break; 3335 } 3336 3337 return (ret); 3338 } 3339 3340 /* 3341 * stmfGetHostGroupList 3342 * 3343 * Purpose: Retrieves the list of initiator group oids 3344 * 3345 * hostGroupList - pointer to pointer to hostGroupList structure 3346 * on success, this contains the host group list. 3347 */ 3348 int 3349 stmfGetHostGroupList(stmfGroupList **hostGroupList) 3350 { 3351 int ret = STMF_STATUS_ERROR; 3352 3353 if (hostGroupList == NULL) { 3354 return (STMF_ERROR_INVALID_ARG); 3355 } 3356 3357 ret = groupListIoctl(hostGroupList, HOST_GROUP); 3358 return (ret); 3359 } 3360 3361 3362 /* 3363 * Purpose: access persistent config data for host groups and target groups 3364 */ 3365 static int 3366 iLoadGroupMembersFromPs(stmfGroupName *groupName, 3367 stmfGroupProperties **groupProp, int type) 3368 { 3369 int ret; 3370 3371 if (groupName == NULL) { 3372 return (STMF_ERROR_INVALID_ARG); 3373 } 3374 3375 if (type == HOST_GROUP) { 3376 ret = psGetHostGroupMemberList((char *)groupName, groupProp); 3377 } else if (type == TARGET_GROUP) { 3378 ret = psGetTargetGroupMemberList((char *)groupName, groupProp); 3379 } else { 3380 return (STMF_ERROR_INVALID_ARG); 3381 } 3382 switch (ret) { 3383 case STMF_PS_SUCCESS: 3384 ret = STMF_STATUS_SUCCESS; 3385 break; 3386 case STMF_PS_ERROR_NOT_FOUND: 3387 ret = STMF_ERROR_NOT_FOUND; 3388 break; 3389 case STMF_PS_ERROR_BUSY: 3390 ret = STMF_ERROR_BUSY; 3391 break; 3392 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3393 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3394 break; 3395 case STMF_PS_ERROR_VERSION_MISMATCH: 3396 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3397 break; 3398 default: 3399 syslog(LOG_DEBUG, 3400 "iLoadGroupMembersFromPs:psGetHostGroupList:" 3401 "error(%d)", ret); 3402 ret = STMF_STATUS_ERROR; 3403 break; 3404 } 3405 3406 return (ret); 3407 } 3408 3409 /* 3410 * stmfGetHostGroupMembers 3411 * 3412 * Purpose: Retrieves the group properties for a host group 3413 * 3414 * groupName - name of group for which to retrieve host group members. 3415 * groupProp - pointer to pointer to stmfGroupProperties structure 3416 * on success, this contains the list of group members. 3417 */ 3418 int 3419 stmfGetHostGroupMembers(stmfGroupName *groupName, 3420 stmfGroupProperties **groupProp) 3421 { 3422 int ret; 3423 3424 if (groupName == NULL || groupProp == NULL) { 3425 return (STMF_ERROR_INVALID_ARG); 3426 } 3427 3428 ret = groupMemberListIoctl(groupName, groupProp, HOST_GROUP); 3429 3430 return (ret); 3431 } 3432 3433 /* 3434 * stmfGetProviderData 3435 * 3436 * Purpose: Get provider data list 3437 * 3438 * providerName - name of provider for which to retrieve the data 3439 * nvl - pointer to nvlist_t pointer which will contain the nvlist data 3440 * retrieved. 3441 * providerType - type of provider for which to retrieve data. 3442 * STMF_LU_PROVIDER_TYPE 3443 * STMF_PORT_PROVIDER_TYPE 3444 */ 3445 int 3446 stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType) 3447 { 3448 return (stmfGetProviderDataProt(providerName, nvl, providerType, 3449 NULL)); 3450 } 3451 3452 /* 3453 * stmfGetProviderDataProt 3454 * 3455 * Purpose: Get provider data list with token 3456 * 3457 * providerName - name of provider for which to retrieve the data 3458 * nvl - pointer to nvlist_t pointer which will contain the nvlist data 3459 * retrieved. 3460 * providerType - type of provider for which to retrieve data. 3461 * STMF_LU_PROVIDER_TYPE 3462 * STMF_PORT_PROVIDER_TYPE 3463 * setToken - Returns the stale data token 3464 */ 3465 int 3466 stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType, 3467 uint64_t *setToken) 3468 { 3469 int ret; 3470 3471 if (providerName == NULL || nvl == NULL) { 3472 return (STMF_ERROR_INVALID_ARG); 3473 } 3474 if (providerType != STMF_LU_PROVIDER_TYPE && 3475 providerType != STMF_PORT_PROVIDER_TYPE) { 3476 return (STMF_ERROR_INVALID_ARG); 3477 } 3478 /* call init */ 3479 ret = initializeConfig(); 3480 if (ret != STMF_STATUS_SUCCESS) { 3481 return (ret); 3482 } 3483 return (getProviderData(providerName, nvl, providerType, setToken)); 3484 } 3485 3486 /* 3487 * stmfGetProviderDataList 3488 * 3489 * Purpose: Get the list of providers currently persisting data 3490 * 3491 * providerList - pointer to pointer to an stmfProviderList structure allocated 3492 * by the caller. Will contain the list of providers on success. 3493 */ 3494 int 3495 stmfGetProviderDataList(stmfProviderList **providerList) 3496 { 3497 int ret; 3498 3499 ret = psGetProviderDataList(providerList); 3500 switch (ret) { 3501 case STMF_PS_SUCCESS: 3502 ret = STMF_STATUS_SUCCESS; 3503 break; 3504 case STMF_PS_ERROR_BUSY: 3505 ret = STMF_ERROR_BUSY; 3506 break; 3507 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 3508 ret = STMF_ERROR_SERVICE_NOT_FOUND; 3509 break; 3510 case STMF_PS_ERROR_VERSION_MISMATCH: 3511 ret = STMF_ERROR_SERVICE_DATA_VERSION; 3512 break; 3513 default: 3514 syslog(LOG_DEBUG, 3515 "stmfGetProviderDataList:psGetProviderDataList" 3516 ":error(%d)", ret); 3517 ret = STMF_STATUS_ERROR; 3518 break; 3519 } 3520 3521 return (ret); 3522 } 3523 3524 3525 /* 3526 * stmfGetSessionList 3527 * 3528 * Purpose: Retrieves the session list for a target (devid) 3529 * 3530 * devid - devid of target for which to retrieve session information. 3531 * sessionList - pointer to pointer to stmfSessionList structure 3532 * on success, this contains the list of initiator sessions. 3533 */ 3534 int 3535 stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList) 3536 { 3537 int ret = STMF_STATUS_SUCCESS; 3538 int fd; 3539 int ioctlRet; 3540 int cmd = STMF_IOCTL_SESSION_LIST; 3541 int i; 3542 stmf_iocdata_t stmfIoctl; 3543 slist_scsi_session_t *fSessionList; 3544 uint8_t ident[260]; 3545 uint32_t fSessionListSize; 3546 3547 if (sessionList == NULL || devid == NULL) { 3548 ret = STMF_ERROR_INVALID_ARG; 3549 } 3550 3551 /* call init */ 3552 ret = initializeConfig(); 3553 if (ret != STMF_STATUS_SUCCESS) { 3554 return (ret); 3555 } 3556 3557 /* 3558 * Open control node for stmf 3559 */ 3560 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3561 return (ret); 3562 3563 /* 3564 * Allocate ioctl input buffer 3565 */ 3566 fSessionListSize = ALLOC_SESSION; 3567 fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t)); 3568 fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize); 3569 if (fSessionList == NULL) { 3570 return (STMF_ERROR_NOMEM); 3571 } 3572 3573 ident[IDENT_LENGTH_BYTE] = devid->identLength; 3574 bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1], 3575 devid->identLength); 3576 3577 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3578 /* 3579 * Issue ioctl to get the session list 3580 */ 3581 stmfIoctl.stmf_version = STMF_VERSION_1; 3582 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident; 3583 stmfIoctl.stmf_ibuf_size = sizeof (ident); 3584 stmfIoctl.stmf_obuf_size = fSessionListSize; 3585 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList; 3586 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3587 if (ioctlRet != 0) { 3588 switch (errno) { 3589 case EBUSY: 3590 ret = STMF_ERROR_BUSY; 3591 break; 3592 case EPERM: 3593 case EACCES: 3594 ret = STMF_ERROR_PERM; 3595 break; 3596 default: 3597 syslog(LOG_DEBUG, 3598 "stmfGetSessionList:ioctl errno(%d)", 3599 errno); 3600 ret = STMF_STATUS_ERROR; 3601 break; 3602 } 3603 goto done; 3604 } 3605 /* 3606 * Check whether input buffer was large enough 3607 */ 3608 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_SESSION) { 3609 fSessionListSize = stmfIoctl.stmf_obuf_max_nentries * 3610 sizeof (slist_scsi_session_t); 3611 fSessionList = realloc(fSessionList, fSessionListSize); 3612 if (fSessionList == NULL) { 3613 return (STMF_ERROR_NOMEM); 3614 } 3615 stmfIoctl.stmf_obuf_size = fSessionListSize; 3616 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList; 3617 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3618 if (ioctlRet != 0) { 3619 switch (errno) { 3620 case EBUSY: 3621 ret = STMF_ERROR_BUSY; 3622 break; 3623 case EPERM: 3624 case EACCES: 3625 ret = STMF_ERROR_PERM; 3626 break; 3627 default: 3628 syslog(LOG_DEBUG, 3629 "stmfGetSessionList:ioctl " 3630 "errno(%d)", errno); 3631 ret = STMF_STATUS_ERROR; 3632 break; 3633 } 3634 goto done; 3635 } 3636 } 3637 3638 /* 3639 * allocate caller's buffer with the final size 3640 */ 3641 *sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) + 3642 stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession)); 3643 if (*sessionList == NULL) { 3644 ret = STMF_ERROR_NOMEM; 3645 free(sessionList); 3646 goto done; 3647 } 3648 3649 (*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries; 3650 3651 /* 3652 * copy session info to caller's buffer 3653 */ 3654 for (i = 0; i < (*sessionList)->cnt; i++) { 3655 (*sessionList)->session[i].initiator.identLength = 3656 fSessionList->initiator[IDENT_LENGTH_BYTE]; 3657 bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]), 3658 (*sessionList)->session[i].initiator.ident, 3659 STMF_IDENT_LENGTH); 3660 bcopy(&(fSessionList->alias), 3661 &((*sessionList)->session[i].alias), 3662 sizeof ((*sessionList)->session[i].alias)); 3663 bcopy(&(fSessionList++->creation_time), 3664 &((*sessionList)->session[i].creationTime), 3665 sizeof (time_t)); 3666 } 3667 done: 3668 (void) close(fd); 3669 return (ret); 3670 } 3671 3672 /* 3673 * stmfGetTargetGroupList 3674 * 3675 * Purpose: Retrieves the list of target groups 3676 * 3677 * targetGroupList - pointer to a pointer to an stmfGroupList structure. On 3678 * success, it contains the list of target groups. 3679 */ 3680 int 3681 stmfGetTargetGroupList(stmfGroupList **targetGroupList) 3682 { 3683 int ret; 3684 3685 if (targetGroupList == NULL) { 3686 return (STMF_ERROR_INVALID_ARG); 3687 } 3688 3689 ret = groupListIoctl(targetGroupList, TARGET_GROUP); 3690 return (ret); 3691 } 3692 3693 /* 3694 * stmfGetTargetGroupMembers 3695 * 3696 * Purpose: Retrieves the group members for a target group 3697 * 3698 * groupName - name of target group for which to retrieve members. 3699 * groupProp - pointer to pointer to stmfGroupProperties structure 3700 * on success, this contains the list of group members. 3701 */ 3702 int 3703 stmfGetTargetGroupMembers(stmfGroupName *groupName, 3704 stmfGroupProperties **groupProp) 3705 { 3706 int ret; 3707 3708 if (groupName == NULL || groupProp == NULL) { 3709 return (STMF_ERROR_INVALID_ARG); 3710 } 3711 3712 ret = groupMemberListIoctl(groupName, groupProp, TARGET_GROUP); 3713 3714 return (ret); 3715 } 3716 3717 /* 3718 * stmfGetTargetList 3719 * 3720 * Purpose: Retrieves the list of target ports 3721 * 3722 * targetList - pointer to a pointer to an stmfDevidList structure. 3723 * On success, it contains the list of local ports (target). 3724 */ 3725 int 3726 stmfGetTargetList(stmfDevidList **targetList) 3727 { 3728 int ret; 3729 int fd; 3730 int ioctlRet; 3731 int i; 3732 stmf_iocdata_t stmfIoctl; 3733 /* framework target port list */ 3734 slist_target_port_t *fTargetList, *fTargetListP = NULL; 3735 uint32_t fTargetListSize; 3736 3737 if (targetList == NULL) { 3738 return (STMF_ERROR_INVALID_ARG); 3739 } 3740 3741 /* call init */ 3742 ret = initializeConfig(); 3743 if (ret != STMF_STATUS_SUCCESS) { 3744 return (ret); 3745 } 3746 3747 /* 3748 * Open control node for stmf 3749 */ 3750 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3751 return (ret); 3752 3753 /* 3754 * Allocate ioctl input buffer 3755 */ 3756 fTargetListSize = ALLOC_TARGET_PORT * sizeof (slist_target_port_t); 3757 fTargetListP = fTargetList = 3758 (slist_target_port_t *)calloc(1, fTargetListSize); 3759 if (fTargetList == NULL) { 3760 ret = STMF_ERROR_NOMEM; 3761 goto done; 3762 } 3763 3764 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3765 /* 3766 * Issue ioctl to retrieve target list 3767 */ 3768 stmfIoctl.stmf_version = STMF_VERSION_1; 3769 stmfIoctl.stmf_obuf_size = fTargetListSize; 3770 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList; 3771 ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl); 3772 if (ioctlRet != 0) { 3773 switch (errno) { 3774 case EBUSY: 3775 ret = STMF_ERROR_BUSY; 3776 break; 3777 case EPERM: 3778 case EACCES: 3779 ret = STMF_ERROR_PERM; 3780 break; 3781 default: 3782 syslog(LOG_DEBUG, 3783 "stmfGetTargetList:ioctl errno(%d)", errno); 3784 ret = STMF_STATUS_ERROR; 3785 break; 3786 } 3787 goto done; 3788 } 3789 /* 3790 * Check whether input buffer was large enough 3791 */ 3792 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_TARGET_PORT) { 3793 fTargetListSize = stmfIoctl.stmf_obuf_max_nentries * 3794 sizeof (slist_target_port_t); 3795 fTargetListP = fTargetList = 3796 realloc(fTargetList, fTargetListSize); 3797 if (fTargetList == NULL) { 3798 ret = STMF_ERROR_NOMEM; 3799 goto done; 3800 } 3801 stmfIoctl.stmf_obuf_size = fTargetListSize; 3802 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList; 3803 ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, 3804 &stmfIoctl); 3805 if (ioctlRet != 0) { 3806 switch (errno) { 3807 case EBUSY: 3808 ret = STMF_ERROR_BUSY; 3809 break; 3810 case EPERM: 3811 case EACCES: 3812 ret = STMF_ERROR_PERM; 3813 break; 3814 default: 3815 syslog(LOG_DEBUG, 3816 "stmfGetTargetList:ioctl errno(%d)", 3817 errno); 3818 ret = STMF_STATUS_ERROR; 3819 break; 3820 } 3821 goto done; 3822 } 3823 } 3824 3825 *targetList = (stmfDevidList *)calloc(1, 3826 stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) + 3827 sizeof (stmfDevidList)); 3828 if (*targetList == NULL) { 3829 ret = STMF_ERROR_NOMEM; 3830 goto done; 3831 } 3832 3833 (*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries; 3834 for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) { 3835 (*targetList)->devid[i].identLength = 3836 fTargetList->target[IDENT_LENGTH_BYTE]; 3837 bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1], 3838 &(*targetList)->devid[i].ident, 3839 fTargetList->target[IDENT_LENGTH_BYTE]); 3840 } 3841 3842 done: 3843 (void) close(fd); 3844 free(fTargetListP); 3845 return (ret); 3846 } 3847 3848 /* 3849 * stmfGetTargetProperties 3850 * 3851 * Purpose: Retrieves the properties for a logical unit 3852 * 3853 * devid - devid of the target for which to retrieve properties 3854 * targetProps - pointer to an stmfTargetProperties structure. 3855 * On success, it contains the target properties for 3856 * the specified devid. 3857 */ 3858 int 3859 stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps) 3860 { 3861 int ret = STMF_STATUS_SUCCESS; 3862 int fd; 3863 int ioctlRet; 3864 stmf_iocdata_t stmfIoctl; 3865 sioc_target_port_props_t targetProperties; 3866 3867 if (devid == NULL || targetProps == NULL) { 3868 return (STMF_ERROR_INVALID_ARG); 3869 } 3870 3871 /* call init */ 3872 ret = initializeConfig(); 3873 if (ret != STMF_STATUS_SUCCESS) { 3874 return (ret); 3875 } 3876 3877 /* 3878 * Open control node for stmf 3879 */ 3880 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3881 return (ret); 3882 3883 targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength; 3884 bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1], 3885 devid->identLength); 3886 3887 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3888 /* 3889 * Issue ioctl to add to the host group 3890 */ 3891 stmfIoctl.stmf_version = STMF_VERSION_1; 3892 stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id); 3893 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id; 3894 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties; 3895 stmfIoctl.stmf_obuf_size = sizeof (targetProperties); 3896 ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES, 3897 &stmfIoctl); 3898 if (ioctlRet != 0) { 3899 switch (errno) { 3900 case EBUSY: 3901 ret = STMF_ERROR_BUSY; 3902 break; 3903 case EPERM: 3904 case EACCES: 3905 ret = STMF_ERROR_PERM; 3906 break; 3907 case ENOENT: 3908 ret = STMF_ERROR_NOT_FOUND; 3909 break; 3910 default: 3911 syslog(LOG_DEBUG, 3912 "stmfGetTargetProperties:ioctl errno(%d)", 3913 errno); 3914 ret = STMF_STATUS_ERROR; 3915 break; 3916 } 3917 goto done; 3918 } 3919 3920 bcopy(targetProperties.tgt_provider_name, targetProps->providerName, 3921 sizeof (targetProperties.tgt_provider_name)); 3922 if (targetProperties.tgt_state == STMF_STATE_ONLINE) { 3923 targetProps->status = STMF_TARGET_PORT_ONLINE; 3924 } else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) { 3925 targetProps->status = STMF_TARGET_PORT_OFFLINE; 3926 } else if (targetProperties.tgt_state == STMF_STATE_ONLINING) { 3927 targetProps->status = STMF_TARGET_PORT_ONLINING; 3928 } else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) { 3929 targetProps->status = STMF_TARGET_PORT_OFFLINING; 3930 } 3931 bcopy(targetProperties.tgt_alias, targetProps->alias, 3932 sizeof (targetProps->alias)); 3933 done: 3934 (void) close(fd); 3935 return (ret); 3936 } 3937 3938 /* 3939 * stmfGetLogicalUnitList 3940 * 3941 * Purpose: Retrieves list of logical unit Object IDs 3942 * 3943 * luList - pointer to a pointer to a stmfGuidList structure. On success, 3944 * it contains the list of logical unit guids. 3945 * 3946 */ 3947 int 3948 stmfGetLogicalUnitList(stmfGuidList **luList) 3949 { 3950 int ret; 3951 int fd; 3952 int ioctlRet; 3953 int cmd = STMF_IOCTL_LU_LIST; 3954 int i; 3955 stmf_iocdata_t stmfIoctl; 3956 slist_lu_t *fLuList; 3957 uint32_t fLuListSize; 3958 uint32_t listCnt; 3959 3960 if (luList == NULL) { 3961 return (STMF_ERROR_INVALID_ARG); 3962 } 3963 3964 /* call init */ 3965 ret = initializeConfig(); 3966 if (ret != STMF_STATUS_SUCCESS) { 3967 return (ret); 3968 } 3969 3970 /* 3971 * Open control node for stmf 3972 */ 3973 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 3974 return (ret); 3975 3976 /* 3977 * Allocate ioctl input buffer 3978 */ 3979 fLuListSize = ALLOC_LU; 3980 fLuListSize = fLuListSize * (sizeof (slist_lu_t)); 3981 fLuList = (slist_lu_t *)calloc(1, fLuListSize); 3982 if (fLuList == NULL) { 3983 ret = STMF_ERROR_NOMEM; 3984 goto done; 3985 } 3986 3987 bzero(&stmfIoctl, sizeof (stmfIoctl)); 3988 /* 3989 * Issue ioctl to get the LU list 3990 */ 3991 stmfIoctl.stmf_version = STMF_VERSION_1; 3992 stmfIoctl.stmf_obuf_size = fLuListSize; 3993 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList; 3994 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 3995 if (ioctlRet != 0) { 3996 switch (errno) { 3997 case EBUSY: 3998 ret = STMF_ERROR_BUSY; 3999 break; 4000 case EPERM: 4001 case EACCES: 4002 ret = STMF_ERROR_PERM; 4003 break; 4004 default: 4005 syslog(LOG_DEBUG, 4006 "stmfGetLogicalUnitList:ioctl errno(%d)", 4007 errno); 4008 ret = STMF_STATUS_ERROR; 4009 break; 4010 } 4011 goto done; 4012 } 4013 /* 4014 * Check whether input buffer was large enough 4015 */ 4016 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_LU) { 4017 fLuListSize = stmfIoctl.stmf_obuf_max_nentries * 4018 sizeof (slist_lu_t); 4019 free(fLuList); 4020 fLuList = (slist_lu_t *)calloc(1, fLuListSize); 4021 if (fLuList == NULL) { 4022 ret = STMF_ERROR_NOMEM; 4023 goto done; 4024 } 4025 stmfIoctl.stmf_obuf_size = fLuListSize; 4026 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList; 4027 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4028 if (ioctlRet != 0) { 4029 switch (errno) { 4030 case EBUSY: 4031 ret = STMF_ERROR_BUSY; 4032 break; 4033 case EPERM: 4034 case EACCES: 4035 ret = STMF_ERROR_PERM; 4036 break; 4037 default: 4038 syslog(LOG_DEBUG, 4039 "stmfGetLogicalUnitList:" 4040 "ioctl errno(%d)", errno); 4041 ret = STMF_STATUS_ERROR; 4042 break; 4043 } 4044 goto done; 4045 } 4046 } 4047 4048 if (ret != STMF_STATUS_SUCCESS) { 4049 goto done; 4050 } 4051 4052 listCnt = stmfIoctl.stmf_obuf_nentries; 4053 4054 /* 4055 * allocate caller's buffer with the final size 4056 */ 4057 *luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) + 4058 listCnt * sizeof (stmfGuid)); 4059 if (*luList == NULL) { 4060 ret = STMF_ERROR_NOMEM; 4061 goto done; 4062 } 4063 4064 (*luList)->cnt = listCnt; 4065 4066 /* copy to caller's buffer */ 4067 for (i = 0; i < listCnt; i++) { 4068 bcopy(&fLuList[i].lu_guid, (*luList)->guid[i].guid, 4069 sizeof (stmfGuid)); 4070 } 4071 4072 /* 4073 * sort the list. This gives a consistent view across gets 4074 */ 4075 qsort((void *)&((*luList)->guid[0]), (*luList)->cnt, 4076 sizeof (stmfGuid), guidCompare); 4077 4078 done: 4079 (void) close(fd); 4080 /* 4081 * free internal buffers 4082 */ 4083 free(fLuList); 4084 return (ret); 4085 } 4086 4087 /* 4088 * stmfGetLogicalUnitProperties 4089 * 4090 * Purpose: Retrieves the properties for a logical unit 4091 * 4092 * lu - guid of the logical unit for which to retrieve properties 4093 * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success, 4094 * it contains the logical unit properties for the specified guid. 4095 */ 4096 int 4097 stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps) 4098 { 4099 int ret = STMF_STATUS_SUCCESS; 4100 int stmfRet; 4101 int fd; 4102 int ioctlRet; 4103 int cmd = STMF_IOCTL_GET_LU_PROPERTIES; 4104 stmfViewEntryList *viewEntryList = NULL; 4105 stmf_iocdata_t stmfIoctl; 4106 sioc_lu_props_t fLuProps; 4107 4108 if (lu == NULL || luProps == NULL) { 4109 return (STMF_ERROR_INVALID_ARG); 4110 } 4111 4112 bzero(luProps, sizeof (stmfLogicalUnitProperties)); 4113 4114 /* call init */ 4115 ret = initializeConfig(); 4116 if (ret != STMF_STATUS_SUCCESS) { 4117 return (ret); 4118 } 4119 4120 /* 4121 * Open control node for stmf 4122 */ 4123 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4124 return (ret); 4125 4126 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4127 /* 4128 * Issue ioctl to add to the host group 4129 */ 4130 stmfIoctl.stmf_version = STMF_VERSION_1; 4131 stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid); 4132 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu; 4133 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps; 4134 stmfIoctl.stmf_obuf_size = sizeof (fLuProps); 4135 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4136 if (ioctlRet != 0) { 4137 switch (errno) { 4138 case EBUSY: 4139 ret = STMF_ERROR_BUSY; 4140 break; 4141 case EPERM: 4142 case EACCES: 4143 ret = STMF_ERROR_PERM; 4144 break; 4145 case ENOENT: 4146 stmfRet = stmfGetViewEntryList(lu, 4147 &viewEntryList); 4148 if (stmfRet == STMF_STATUS_SUCCESS) { 4149 luProps->status = 4150 STMF_LOGICAL_UNIT_UNREGISTERED; 4151 if (viewEntryList->cnt > 0) { 4152 ret = STMF_STATUS_SUCCESS; 4153 } else { 4154 ret = STMF_ERROR_NOT_FOUND; 4155 } 4156 } else { 4157 ret = STMF_ERROR_NOT_FOUND; 4158 } 4159 stmfFreeMemory(viewEntryList); 4160 break; 4161 default: 4162 syslog(LOG_DEBUG, 4163 "stmfGetLogicalUnit:ioctl errno(%d)", 4164 errno); 4165 ret = STMF_STATUS_ERROR; 4166 break; 4167 } 4168 goto done; 4169 } 4170 4171 bcopy(fLuProps.lu_provider_name, luProps->providerName, 4172 sizeof (fLuProps.lu_provider_name)); 4173 if (fLuProps.lu_state == STMF_STATE_ONLINE) { 4174 luProps->status = STMF_LOGICAL_UNIT_ONLINE; 4175 } else if (fLuProps.lu_state == STMF_STATE_OFFLINE) { 4176 luProps->status = STMF_LOGICAL_UNIT_OFFLINE; 4177 } else if (fLuProps.lu_state == STMF_STATE_ONLINING) { 4178 luProps->status = STMF_LOGICAL_UNIT_ONLINING; 4179 } else if (fLuProps.lu_state == STMF_STATE_OFFLINING) { 4180 luProps->status = STMF_LOGICAL_UNIT_OFFLINING; 4181 } 4182 bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias)); 4183 done: 4184 (void) close(fd); 4185 return (ret); 4186 } 4187 4188 /* 4189 * stmfGetState 4190 * 4191 * Purpose: retrieve the current state of the stmf module 4192 * 4193 * state - pointer to stmfState structure allocated by the caller 4194 * On success, contains the state of stmf 4195 */ 4196 int 4197 stmfGetState(stmfState *state) 4198 { 4199 int ret; 4200 stmf_state_desc_t iState; 4201 4202 if (state == NULL) { 4203 return (STMF_ERROR_INVALID_ARG); 4204 } 4205 4206 ret = getStmfState(&iState); 4207 if (ret != STMF_STATUS_SUCCESS) { 4208 return (ret); 4209 } 4210 switch (iState.state) { 4211 case STMF_STATE_ONLINE: 4212 state->operationalState = 4213 STMF_SERVICE_STATE_ONLINE; 4214 break; 4215 case STMF_STATE_OFFLINE: 4216 state->operationalState = 4217 STMF_SERVICE_STATE_OFFLINE; 4218 break; 4219 case STMF_STATE_ONLINING: 4220 state->operationalState = 4221 STMF_SERVICE_STATE_ONLINING; 4222 break; 4223 case STMF_STATE_OFFLINING: 4224 state->operationalState = 4225 STMF_SERVICE_STATE_OFFLINING; 4226 break; 4227 default: 4228 state->operationalState = 4229 STMF_SERVICE_STATE_UNKNOWN; 4230 break; 4231 } 4232 switch (iState.config_state) { 4233 case STMF_CONFIG_NONE: 4234 state->configState = STMF_CONFIG_STATE_NONE; 4235 break; 4236 case STMF_CONFIG_INIT: 4237 state->configState = STMF_CONFIG_STATE_INIT; 4238 break; 4239 case STMF_CONFIG_INIT_DONE: 4240 state->configState = 4241 STMF_CONFIG_STATE_INIT_DONE; 4242 break; 4243 default: 4244 state->configState = 4245 STMF_CONFIG_STATE_UNKNOWN; 4246 break; 4247 } 4248 return (STMF_STATUS_SUCCESS); 4249 } 4250 4251 /* 4252 * stmfGetViewEntryList 4253 * 4254 * Purpose: Retrieves the list of view entries for the specified 4255 * logical unit. 4256 * 4257 * lu - the guid of the logical unit for which to retrieve the view entry list 4258 * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On 4259 * success, contains the list of view entries. 4260 */ 4261 int 4262 stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList) 4263 { 4264 int ret; 4265 int fd; 4266 int ioctlRet; 4267 int cmd = STMF_IOCTL_LU_VE_LIST; 4268 int i; 4269 stmf_iocdata_t stmfIoctl; 4270 stmf_view_op_entry_t *fVeList; 4271 uint32_t fVeListSize; 4272 uint32_t listCnt; 4273 4274 if (lu == NULL || viewEntryList == NULL) { 4275 return (STMF_ERROR_INVALID_ARG); 4276 } 4277 4278 /* call init */ 4279 ret = initializeConfig(); 4280 if (ret != STMF_STATUS_SUCCESS) { 4281 return (ret); 4282 } 4283 4284 /* 4285 * Open control node for stmf 4286 */ 4287 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4288 return (ret); 4289 4290 /* 4291 * Allocate ioctl input buffer 4292 */ 4293 fVeListSize = ALLOC_VE; 4294 fVeListSize = fVeListSize * (sizeof (stmf_view_op_entry_t)); 4295 fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize); 4296 if (fVeList == NULL) { 4297 ret = STMF_ERROR_NOMEM; 4298 goto done; 4299 } 4300 4301 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4302 /* 4303 * Issue ioctl to get the LU list 4304 */ 4305 stmfIoctl.stmf_version = STMF_VERSION_1; 4306 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu; 4307 stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid); 4308 stmfIoctl.stmf_obuf_size = fVeListSize; 4309 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList; 4310 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4311 if (ioctlRet != 0) { 4312 switch (errno) { 4313 case EBUSY: 4314 ret = STMF_ERROR_BUSY; 4315 break; 4316 case EPERM: 4317 case EACCES: 4318 ret = STMF_ERROR_PERM; 4319 break; 4320 default: 4321 syslog(LOG_DEBUG, 4322 "stmfGetViewEntryList:ioctl errno(%d)", 4323 errno); 4324 ret = STMF_STATUS_ERROR; 4325 break; 4326 } 4327 goto done; 4328 } 4329 /* 4330 * Check whether input buffer was large enough 4331 */ 4332 if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_VE) { 4333 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4334 fVeListSize = stmfIoctl.stmf_obuf_max_nentries * 4335 sizeof (stmf_view_op_entry_t); 4336 free(fVeList); 4337 fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize); 4338 if (fVeList == NULL) { 4339 return (STMF_ERROR_NOMEM); 4340 } 4341 stmfIoctl.stmf_obuf_size = fVeListSize; 4342 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList; 4343 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4344 if (ioctlRet != 0) { 4345 switch (errno) { 4346 case EBUSY: 4347 ret = STMF_ERROR_BUSY; 4348 break; 4349 case EPERM: 4350 case EACCES: 4351 ret = STMF_ERROR_PERM; 4352 break; 4353 default: 4354 syslog(LOG_DEBUG, 4355 "stmfGetLogicalUnitList:" 4356 "ioctl errno(%d)", errno); 4357 ret = STMF_STATUS_ERROR; 4358 break; 4359 } 4360 goto done; 4361 } 4362 } 4363 4364 if (ret != STMF_STATUS_SUCCESS) { 4365 goto done; 4366 } 4367 4368 if (stmfIoctl.stmf_obuf_nentries == 0) { 4369 ret = STMF_ERROR_NOT_FOUND; 4370 goto done; 4371 } 4372 4373 listCnt = stmfIoctl.stmf_obuf_nentries; 4374 4375 /* 4376 * allocate caller's buffer with the final size 4377 */ 4378 *viewEntryList = (stmfViewEntryList *)calloc(1, 4379 sizeof (stmfViewEntryList) + listCnt * sizeof (stmfViewEntry)); 4380 if (*viewEntryList == NULL) { 4381 ret = STMF_ERROR_NOMEM; 4382 goto done; 4383 } 4384 4385 (*viewEntryList)->cnt = listCnt; 4386 4387 /* copy to caller's buffer */ 4388 for (i = 0; i < listCnt; i++) { 4389 (*viewEntryList)->ve[i].veIndexValid = B_TRUE; 4390 (*viewEntryList)->ve[i].veIndex = fVeList[i].ve_ndx; 4391 if (fVeList[i].ve_all_hosts == 1) { 4392 (*viewEntryList)->ve[i].allHosts = B_TRUE; 4393 } else { 4394 bcopy(fVeList[i].ve_host_group.name, 4395 (*viewEntryList)->ve[i].hostGroup, 4396 fVeList[i].ve_host_group.name_size); 4397 } 4398 if (fVeList[i].ve_all_targets == 1) { 4399 (*viewEntryList)->ve[i].allTargets = B_TRUE; 4400 } else { 4401 bcopy(fVeList[i].ve_target_group.name, 4402 (*viewEntryList)->ve[i].targetGroup, 4403 fVeList[i].ve_target_group.name_size); 4404 } 4405 bcopy(fVeList[i].ve_lu_nbr, (*viewEntryList)->ve[i].luNbr, 4406 sizeof ((*viewEntryList)->ve[i].luNbr)); 4407 (*viewEntryList)->ve[i].luNbrValid = B_TRUE; 4408 } 4409 4410 /* 4411 * sort the list. This gives a consistent view across gets 4412 */ 4413 qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt, 4414 sizeof (stmfViewEntry), viewEntryCompare); 4415 4416 done: 4417 (void) close(fd); 4418 /* 4419 * free internal buffers 4420 */ 4421 free(fVeList); 4422 return (ret); 4423 } 4424 4425 4426 /* 4427 * loadHostGroups 4428 * 4429 * Purpose - issues the ioctl to load the host groups into stmf 4430 * 4431 * fd - file descriptor for the control node of stmf. 4432 * groupList - populated host group list 4433 */ 4434 static int 4435 loadHostGroups(int fd, stmfGroupList *groupList) 4436 { 4437 int i, j; 4438 int ret = STMF_STATUS_SUCCESS; 4439 stmfGroupProperties *groupProps = NULL; 4440 4441 for (i = 0; i < groupList->cnt; i++) { 4442 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP, 4443 &(groupList->name[i]))) != STMF_STATUS_SUCCESS) { 4444 goto out; 4445 } 4446 ret = iLoadGroupMembersFromPs(&(groupList->name[i]), 4447 &groupProps, HOST_GROUP); 4448 for (j = 0; j < groupProps->cnt; j++) { 4449 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, 4450 &(groupList->name[i]), &(groupProps->name[j]))) 4451 != STMF_STATUS_SUCCESS) { 4452 goto out; 4453 } 4454 } 4455 } 4456 4457 4458 out: 4459 stmfFreeMemory(groupProps); 4460 return (ret); 4461 } 4462 4463 /* 4464 * loadTargetGroups 4465 * 4466 * Purpose - issues the ioctl to load the target groups into stmf 4467 * 4468 * fd - file descriptor for the control node of stmf. 4469 * groupList - populated target group list. 4470 */ 4471 static int 4472 loadTargetGroups(int fd, stmfGroupList *groupList) 4473 { 4474 int i, j; 4475 int ret = STMF_STATUS_SUCCESS; 4476 stmfGroupProperties *groupProps = NULL; 4477 4478 for (i = 0; i < groupList->cnt; i++) { 4479 if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP, 4480 &(groupList->name[i]))) != STMF_STATUS_SUCCESS) { 4481 goto out; 4482 } 4483 ret = iLoadGroupMembersFromPs(&(groupList->name[i]), 4484 &groupProps, TARGET_GROUP); 4485 for (j = 0; j < groupProps->cnt; j++) { 4486 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY, 4487 &(groupList->name[i]), &(groupProps->name[j]))) 4488 != STMF_STATUS_SUCCESS) { 4489 goto out; 4490 } 4491 } 4492 } 4493 4494 4495 out: 4496 stmfFreeMemory(groupProps); 4497 return (ret); 4498 } 4499 4500 4501 /* 4502 * loadStore 4503 * 4504 * Purpose: Load the configuration data from the store 4505 * 4506 * First load the host groups and target groups, then the view entries 4507 * and finally the provider data 4508 * 4509 * fd - file descriptor of control node for stmf. 4510 */ 4511 static int 4512 loadStore(int fd) 4513 { 4514 int ret; 4515 int i, j; 4516 stmfGroupList *groupList = NULL; 4517 stmfGuidList *guidList = NULL; 4518 stmfViewEntryList *viewEntryList = NULL; 4519 stmfProviderList *providerList = NULL; 4520 int providerType; 4521 nvlist_t *nvl = NULL; 4522 4523 4524 4525 /* load host groups */ 4526 ret = iLoadGroupFromPs(&groupList, HOST_GROUP); 4527 if (ret != STMF_STATUS_SUCCESS) { 4528 return (ret); 4529 } 4530 ret = loadHostGroups(fd, groupList); 4531 if (ret != STMF_STATUS_SUCCESS) { 4532 goto out; 4533 } 4534 4535 stmfFreeMemory(groupList); 4536 groupList = NULL; 4537 4538 /* load target groups */ 4539 ret = iLoadGroupFromPs(&groupList, TARGET_GROUP); 4540 if (ret != STMF_STATUS_SUCCESS) { 4541 goto out; 4542 } 4543 ret = loadTargetGroups(fd, groupList); 4544 if (ret != STMF_STATUS_SUCCESS) { 4545 goto out; 4546 } 4547 4548 stmfFreeMemory(groupList); 4549 groupList = NULL; 4550 4551 /* Get the guid list */ 4552 ret = psGetLogicalUnitList(&guidList); 4553 switch (ret) { 4554 case STMF_PS_SUCCESS: 4555 ret = STMF_STATUS_SUCCESS; 4556 break; 4557 case STMF_PS_ERROR_NOT_FOUND: 4558 ret = STMF_ERROR_NOT_FOUND; 4559 break; 4560 case STMF_PS_ERROR_BUSY: 4561 ret = STMF_ERROR_BUSY; 4562 break; 4563 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 4564 ret = STMF_ERROR_SERVICE_NOT_FOUND; 4565 break; 4566 case STMF_PS_ERROR_VERSION_MISMATCH: 4567 ret = STMF_ERROR_SERVICE_DATA_VERSION; 4568 break; 4569 default: 4570 ret = STMF_STATUS_ERROR; 4571 break; 4572 } 4573 4574 if (ret != STMF_STATUS_SUCCESS) { 4575 goto out; 4576 } 4577 4578 /* 4579 * We have the guid list, now get the corresponding 4580 * view entries for each guid 4581 */ 4582 for (i = 0; i < guidList->cnt; i++) { 4583 ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList); 4584 switch (ret) { 4585 case STMF_PS_SUCCESS: 4586 ret = STMF_STATUS_SUCCESS; 4587 break; 4588 case STMF_PS_ERROR_NOT_FOUND: 4589 ret = STMF_ERROR_NOT_FOUND; 4590 break; 4591 case STMF_PS_ERROR_BUSY: 4592 ret = STMF_ERROR_BUSY; 4593 break; 4594 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 4595 ret = STMF_ERROR_SERVICE_NOT_FOUND; 4596 break; 4597 case STMF_PS_ERROR_VERSION_MISMATCH: 4598 ret = STMF_ERROR_SERVICE_DATA_VERSION; 4599 break; 4600 default: 4601 ret = STMF_STATUS_ERROR; 4602 break; 4603 } 4604 if (ret != STMF_STATUS_SUCCESS) { 4605 goto out; 4606 } 4607 for (j = 0; j < viewEntryList->cnt; j++) { 4608 ret = addViewEntryIoctl(fd, &guidList->guid[i], 4609 &viewEntryList->ve[j]); 4610 if (ret != STMF_STATUS_SUCCESS) { 4611 goto out; 4612 } 4613 } 4614 } 4615 4616 /* get the list of providers that have data */ 4617 ret = psGetProviderDataList(&providerList); 4618 switch (ret) { 4619 case STMF_PS_SUCCESS: 4620 ret = STMF_STATUS_SUCCESS; 4621 break; 4622 case STMF_PS_ERROR_NOT_FOUND: 4623 ret = STMF_ERROR_NOT_FOUND; 4624 break; 4625 case STMF_PS_ERROR_BUSY: 4626 ret = STMF_ERROR_BUSY; 4627 break; 4628 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 4629 ret = STMF_ERROR_SERVICE_NOT_FOUND; 4630 break; 4631 case STMF_PS_ERROR_VERSION_MISMATCH: 4632 ret = STMF_ERROR_SERVICE_DATA_VERSION; 4633 break; 4634 default: 4635 ret = STMF_STATUS_ERROR; 4636 break; 4637 } 4638 if (ret != STMF_STATUS_SUCCESS) { 4639 goto out; 4640 } 4641 4642 for (i = 0; i < providerList->cnt; i++) { 4643 providerType = providerList->provider[i].providerType; 4644 ret = psGetProviderData(providerList->provider[i].name, 4645 &nvl, providerType, NULL); 4646 switch (ret) { 4647 case STMF_PS_SUCCESS: 4648 ret = STMF_STATUS_SUCCESS; 4649 break; 4650 case STMF_PS_ERROR_NOT_FOUND: 4651 ret = STMF_ERROR_NOT_FOUND; 4652 break; 4653 case STMF_PS_ERROR_BUSY: 4654 ret = STMF_ERROR_BUSY; 4655 break; 4656 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 4657 ret = STMF_ERROR_SERVICE_NOT_FOUND; 4658 break; 4659 case STMF_PS_ERROR_VERSION_MISMATCH: 4660 ret = STMF_ERROR_SERVICE_DATA_VERSION; 4661 break; 4662 default: 4663 ret = STMF_STATUS_ERROR; 4664 break; 4665 } 4666 if (ret != STMF_STATUS_SUCCESS) { 4667 goto out; 4668 } 4669 4670 /* call setProviderData */ 4671 ret = setProviderData(fd, providerList->provider[i].name, nvl, 4672 providerType, NULL); 4673 switch (ret) { 4674 case STMF_PS_SUCCESS: 4675 ret = STMF_STATUS_SUCCESS; 4676 break; 4677 case STMF_PS_ERROR_NOT_FOUND: 4678 ret = STMF_ERROR_NOT_FOUND; 4679 break; 4680 case STMF_PS_ERROR_BUSY: 4681 ret = STMF_ERROR_BUSY; 4682 break; 4683 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 4684 ret = STMF_ERROR_SERVICE_NOT_FOUND; 4685 break; 4686 case STMF_PS_ERROR_VERSION_MISMATCH: 4687 ret = STMF_ERROR_SERVICE_DATA_VERSION; 4688 break; 4689 default: 4690 ret = STMF_STATUS_ERROR; 4691 break; 4692 } 4693 if (ret != STMF_STATUS_SUCCESS) { 4694 goto out; 4695 } 4696 4697 nvlist_free(nvl); 4698 nvl = NULL; 4699 } 4700 out: 4701 if (groupList != NULL) { 4702 free(groupList); 4703 } 4704 if (guidList != NULL) { 4705 free(guidList); 4706 } 4707 if (viewEntryList != NULL) { 4708 free(viewEntryList); 4709 } 4710 if (nvl != NULL) { 4711 nvlist_free(nvl); 4712 } 4713 return (ret); 4714 } 4715 4716 /* 4717 * stmfLoadConfig 4718 * 4719 * Purpose - load the configuration data from smf into stmf 4720 * 4721 */ 4722 int 4723 stmfLoadConfig(void) 4724 { 4725 int ret = STMF_STATUS_SUCCESS; 4726 int fd; 4727 stmf_state_desc_t stmfStateSet; 4728 stmfState state; 4729 4730 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 4731 stmfStateSet.state = STMF_STATE_OFFLINE; 4732 stmfStateSet.config_state = STMF_CONFIG_INIT; 4733 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) 4734 != STMF_STATUS_SUCCESS) { 4735 return (ret); 4736 } 4737 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE); 4738 if (ret != STMF_STATUS_SUCCESS) { 4739 goto done; 4740 } 4741 stmfStateSet.config_state = STMF_CONFIG_INIT_DONE; 4742 goto done; 4743 } 4744 4745 /* Check to ensure service exists */ 4746 if (psCheckService() != STMF_STATUS_SUCCESS) { 4747 return (STMF_ERROR_SERVICE_NOT_FOUND); 4748 } 4749 4750 ret = stmfGetState(&state); 4751 if (ret == STMF_STATUS_SUCCESS) { 4752 if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) { 4753 return (STMF_ERROR_SERVICE_ONLINE); 4754 } 4755 } else { 4756 return (STMF_STATUS_ERROR); 4757 } 4758 4759 4760 stmfStateSet.state = STMF_STATE_OFFLINE; 4761 stmfStateSet.config_state = STMF_CONFIG_INIT; 4762 4763 /* 4764 * Open control node for stmf 4765 */ 4766 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 4767 return (ret); 4768 4769 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE); 4770 if (ret != STMF_STATUS_SUCCESS) { 4771 goto done; 4772 } 4773 4774 /* Load the persistent configuration data */ 4775 ret = loadStore(fd); 4776 if (ret != 0) { 4777 goto done; 4778 } 4779 4780 stmfStateSet.state = STMF_STATE_OFFLINE; 4781 stmfStateSet.config_state = STMF_CONFIG_INIT_DONE; 4782 4783 done: 4784 if (ret == STMF_STATUS_SUCCESS) { 4785 ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE); 4786 } 4787 (void) close(fd); 4788 return (ret); 4789 } 4790 4791 4792 /* 4793 * getStmfState 4794 * 4795 * stmfState - pointer to stmf_state_desc_t structure. Will contain the state 4796 * information of the stmf service on success. 4797 */ 4798 static int 4799 getStmfState(stmf_state_desc_t *stmfState) 4800 { 4801 int ret = STMF_STATUS_SUCCESS; 4802 int fd; 4803 int ioctlRet; 4804 stmf_iocdata_t stmfIoctl; 4805 4806 /* 4807 * Open control node for stmf 4808 */ 4809 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 4810 return (ret); 4811 4812 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4813 /* 4814 * Issue ioctl to get the stmf state 4815 */ 4816 stmfIoctl.stmf_version = STMF_VERSION_1; 4817 stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t); 4818 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState; 4819 stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t); 4820 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState; 4821 ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl); 4822 4823 (void) close(fd); 4824 4825 if (ioctlRet != 0) { 4826 switch (errno) { 4827 case EBUSY: 4828 ret = STMF_ERROR_BUSY; 4829 break; 4830 case EPERM: 4831 case EACCES: 4832 ret = STMF_ERROR_PERM; 4833 break; 4834 default: 4835 syslog(LOG_DEBUG, 4836 "getStmfState:ioctl errno(%d)", errno); 4837 ret = STMF_STATUS_ERROR; 4838 break; 4839 } 4840 } 4841 return (ret); 4842 } 4843 4844 4845 /* 4846 * setStmfState 4847 * 4848 * stmfState - pointer to caller set state structure 4849 * objectType - one of: 4850 * LOGICAL_UNIT_TYPE 4851 * TARGET_TYPE 4852 * STMF_SERVICE_TYPE 4853 */ 4854 static int 4855 setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType) 4856 { 4857 int ret = STMF_STATUS_SUCCESS; 4858 int ioctlRet; 4859 int cmd; 4860 stmf_iocdata_t stmfIoctl; 4861 4862 switch (objectType) { 4863 case LOGICAL_UNIT_TYPE: 4864 cmd = STMF_IOCTL_SET_LU_STATE; 4865 break; 4866 case TARGET_TYPE: 4867 cmd = STMF_IOCTL_SET_TARGET_PORT_STATE; 4868 break; 4869 case STMF_SERVICE_TYPE: 4870 cmd = STMF_IOCTL_SET_STMF_STATE; 4871 break; 4872 default: 4873 ret = STMF_STATUS_ERROR; 4874 goto done; 4875 } 4876 4877 bzero(&stmfIoctl, sizeof (stmfIoctl)); 4878 /* 4879 * Issue ioctl to set the stmf state 4880 */ 4881 stmfIoctl.stmf_version = STMF_VERSION_1; 4882 stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t); 4883 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState; 4884 ioctlRet = ioctl(fd, cmd, &stmfIoctl); 4885 if (ioctlRet != 0) { 4886 switch (errno) { 4887 case EBUSY: 4888 ret = STMF_ERROR_BUSY; 4889 break; 4890 case EPERM: 4891 case EACCES: 4892 ret = STMF_ERROR_PERM; 4893 break; 4894 case ENOENT: 4895 ret = STMF_ERROR_NOT_FOUND; 4896 break; 4897 default: 4898 syslog(LOG_DEBUG, 4899 "setStmfState:ioctl errno(%d)", errno); 4900 ret = STMF_STATUS_ERROR; 4901 break; 4902 } 4903 } 4904 done: 4905 return (ret); 4906 } 4907 4908 /* 4909 * stmfOnline 4910 * 4911 * Purpose: Online stmf service 4912 * 4913 */ 4914 int 4915 stmfOnline(void) 4916 { 4917 int ret; 4918 int fd; 4919 stmfState state; 4920 stmf_state_desc_t iState; 4921 4922 ret = stmfGetState(&state); 4923 if (ret == STMF_STATUS_SUCCESS) { 4924 if (state.operationalState == STMF_SERVICE_STATE_ONLINE) { 4925 return (STMF_ERROR_SERVICE_ONLINE); 4926 } 4927 } else { 4928 return (STMF_STATUS_ERROR); 4929 } 4930 iState.state = STMF_STATE_ONLINE; 4931 iState.config_state = STMF_CONFIG_NONE; 4932 /* 4933 * Open control node for stmf 4934 * to make call to setStmfState() 4935 */ 4936 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 4937 return (ret); 4938 ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE); 4939 (void) close(fd); 4940 return (ret); 4941 } 4942 4943 /* 4944 * stmfOffline 4945 * 4946 * Purpose: Offline stmf service 4947 * 4948 */ 4949 int 4950 stmfOffline(void) 4951 { 4952 int ret; 4953 int fd; 4954 stmfState state; 4955 stmf_state_desc_t iState; 4956 4957 ret = stmfGetState(&state); 4958 if (ret == STMF_STATUS_SUCCESS) { 4959 if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) { 4960 return (STMF_ERROR_SERVICE_OFFLINE); 4961 } 4962 } else { 4963 return (STMF_STATUS_ERROR); 4964 } 4965 iState.state = STMF_STATE_OFFLINE; 4966 iState.config_state = STMF_CONFIG_NONE; 4967 4968 /* 4969 * Open control node for stmf 4970 * to make call to setStmfState() 4971 */ 4972 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 4973 return (ret); 4974 ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE); 4975 (void) close(fd); 4976 return (ret); 4977 } 4978 4979 4980 /* 4981 * stmfOfflineTarget 4982 * 4983 * Purpose: Change state of target to offline 4984 * 4985 * devid - devid of the target to offline 4986 */ 4987 int 4988 stmfOfflineTarget(stmfDevid *devid) 4989 { 4990 stmf_state_desc_t targetState; 4991 int ret = STMF_STATUS_SUCCESS; 4992 int fd; 4993 4994 if (devid == NULL) { 4995 return (STMF_ERROR_INVALID_ARG); 4996 } 4997 bzero(&targetState, sizeof (targetState)); 4998 4999 targetState.state = STMF_STATE_OFFLINE; 5000 targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength; 5001 bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1], 5002 devid->identLength); 5003 /* 5004 * Open control node for stmf 5005 * to make call to setStmfState() 5006 */ 5007 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5008 return (ret); 5009 ret = setStmfState(fd, &targetState, TARGET_TYPE); 5010 (void) close(fd); 5011 return (ret); 5012 } 5013 5014 /* 5015 * stmfOfflineLogicalUnit 5016 * 5017 * Purpose: Change state of logical unit to offline 5018 * 5019 * lu - guid of the logical unit to offline 5020 */ 5021 int 5022 stmfOfflineLogicalUnit(stmfGuid *lu) 5023 { 5024 stmf_state_desc_t luState; 5025 int ret = STMF_STATUS_SUCCESS; 5026 int fd; 5027 5028 if (lu == NULL) { 5029 return (STMF_ERROR_INVALID_ARG); 5030 } 5031 5032 bzero(&luState, sizeof (luState)); 5033 5034 luState.state = STMF_STATE_OFFLINE; 5035 bcopy(lu, &luState.ident, sizeof (stmfGuid)); 5036 /* 5037 * Open control node for stmf 5038 * to make call to setStmfState() 5039 */ 5040 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5041 return (ret); 5042 ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE); 5043 (void) close(fd); 5044 return (ret); 5045 } 5046 5047 /* 5048 * stmfOnlineTarget 5049 * 5050 * Purpose: Change state of target to online 5051 * 5052 * devid - devid of the target to online 5053 */ 5054 int 5055 stmfOnlineTarget(stmfDevid *devid) 5056 { 5057 stmf_state_desc_t targetState; 5058 int ret = STMF_STATUS_SUCCESS; 5059 int fd; 5060 5061 if (devid == NULL) { 5062 return (STMF_ERROR_INVALID_ARG); 5063 } 5064 bzero(&targetState, sizeof (targetState)); 5065 5066 targetState.state = STMF_STATE_ONLINE; 5067 targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength; 5068 bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1], 5069 devid->identLength); 5070 /* 5071 * Open control node for stmf 5072 * to make call to setStmfState() 5073 */ 5074 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5075 return (ret); 5076 ret = setStmfState(fd, &targetState, TARGET_TYPE); 5077 (void) close(fd); 5078 return (ret); 5079 } 5080 5081 /* 5082 * stmfOnlineLogicalUnit 5083 * 5084 * Purpose: Change state of logical unit to online 5085 * 5086 * lu - guid of the logical unit to online 5087 */ 5088 int 5089 stmfOnlineLogicalUnit(stmfGuid *lu) 5090 { 5091 stmf_state_desc_t luState; 5092 int ret = STMF_STATUS_SUCCESS; 5093 int fd; 5094 5095 if (lu == NULL) { 5096 return (STMF_ERROR_INVALID_ARG); 5097 } 5098 5099 bzero(&luState, sizeof (luState)); 5100 5101 luState.state = STMF_STATE_ONLINE; 5102 bcopy(lu, &luState.ident, sizeof (stmfGuid)); 5103 /* 5104 * Open control node for stmf 5105 * to make call to setStmfState() 5106 */ 5107 if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS) 5108 return (ret); 5109 ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE); 5110 (void) close(fd); 5111 return (ret); 5112 } 5113 5114 /* 5115 * stmfRemoveFromHostGroup 5116 * 5117 * Purpose: Removes an initiator from an initiator group 5118 * 5119 * hostGroupName - name of an initiator group 5120 * hostName - name of host group member to remove 5121 */ 5122 int 5123 stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName) 5124 { 5125 int ret; 5126 int fd; 5127 5128 if (hostGroupName == NULL || 5129 (strnlen((char *)hostGroupName, sizeof (stmfGroupName)) 5130 == sizeof (stmfGroupName)) || hostName == NULL) { 5131 return (STMF_ERROR_INVALID_ARG); 5132 } 5133 5134 /* call init */ 5135 ret = initializeConfig(); 5136 if (ret != STMF_STATUS_SUCCESS) { 5137 return (ret); 5138 } 5139 5140 /* 5141 * Open control node for stmf 5142 */ 5143 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5144 return (ret); 5145 5146 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY, 5147 hostGroupName, hostName)) != STMF_STATUS_SUCCESS) { 5148 goto done; 5149 } 5150 5151 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5152 goto done; 5153 } 5154 5155 ret = psRemoveHostGroupMember((char *)hostGroupName, 5156 (char *)hostName->ident); 5157 switch (ret) { 5158 case STMF_PS_SUCCESS: 5159 ret = STMF_STATUS_SUCCESS; 5160 break; 5161 case STMF_PS_ERROR_MEMBER_NOT_FOUND: 5162 ret = STMF_ERROR_MEMBER_NOT_FOUND; 5163 break; 5164 case STMF_PS_ERROR_GROUP_NOT_FOUND: 5165 ret = STMF_ERROR_GROUP_NOT_FOUND; 5166 break; 5167 case STMF_PS_ERROR_BUSY: 5168 ret = STMF_ERROR_BUSY; 5169 break; 5170 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5171 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5172 break; 5173 case STMF_PS_ERROR_VERSION_MISMATCH: 5174 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5175 break; 5176 default: 5177 syslog(LOG_DEBUG, 5178 "stmfRemoveFromHostGroup" 5179 "psRemoveHostGroupMember:error(%d)", ret); 5180 ret = STMF_STATUS_ERROR; 5181 break; 5182 } 5183 5184 done: 5185 (void) close(fd); 5186 return (ret); 5187 } 5188 5189 /* 5190 * stmfRemoveFromTargetGroup 5191 * 5192 * Purpose: Removes a local port from a local port group 5193 * 5194 * targetGroupName - name of a target group 5195 * targetName - name of target to remove 5196 */ 5197 int 5198 stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName) 5199 { 5200 int ret; 5201 int fd; 5202 5203 if (targetGroupName == NULL || 5204 (strnlen((char *)targetGroupName, sizeof (stmfGroupName)) 5205 == sizeof (stmfGroupName)) || targetName == NULL) { 5206 return (STMF_ERROR_INVALID_ARG); 5207 } 5208 5209 /* call init */ 5210 ret = initializeConfig(); 5211 if (ret != STMF_STATUS_SUCCESS) { 5212 return (ret); 5213 } 5214 5215 /* 5216 * Open control node for stmf 5217 */ 5218 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5219 return (ret); 5220 5221 if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY, 5222 targetGroupName, targetName)) != STMF_STATUS_SUCCESS) { 5223 goto done; 5224 } 5225 5226 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5227 goto done; 5228 } 5229 5230 ret = psRemoveTargetGroupMember((char *)targetGroupName, 5231 (char *)targetName->ident); 5232 switch (ret) { 5233 case STMF_PS_SUCCESS: 5234 ret = STMF_STATUS_SUCCESS; 5235 break; 5236 case STMF_PS_ERROR_MEMBER_NOT_FOUND: 5237 ret = STMF_ERROR_MEMBER_NOT_FOUND; 5238 break; 5239 case STMF_PS_ERROR_GROUP_NOT_FOUND: 5240 ret = STMF_ERROR_GROUP_NOT_FOUND; 5241 break; 5242 case STMF_PS_ERROR_BUSY: 5243 ret = STMF_ERROR_BUSY; 5244 break; 5245 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5246 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5247 break; 5248 case STMF_PS_ERROR_VERSION_MISMATCH: 5249 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5250 break; 5251 default: 5252 syslog(LOG_DEBUG, 5253 "stmfRemoveFromTargetGroup" 5254 "psRemoveTargetGroupMember:error(%d)", ret); 5255 ret = STMF_STATUS_ERROR; 5256 break; 5257 } 5258 5259 done: 5260 (void) close(fd); 5261 return (ret); 5262 } 5263 5264 /* 5265 * stmfRemoveViewEntry 5266 * 5267 * Purpose: Removes a view entry from a logical unit 5268 * 5269 * lu - guid of lu for which view entry is being removed 5270 * viewEntryIndex - index of view entry to remove 5271 * 5272 */ 5273 int 5274 stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex) 5275 { 5276 int ret = STMF_STATUS_SUCCESS; 5277 int fd; 5278 int ioctlRet; 5279 stmf_iocdata_t stmfIoctl; 5280 stmf_view_op_entry_t ioctlViewEntry; 5281 5282 if (lu == NULL) { 5283 return (STMF_ERROR_INVALID_ARG); 5284 } 5285 5286 /* call init */ 5287 ret = initializeConfig(); 5288 if (ret != STMF_STATUS_SUCCESS) { 5289 return (ret); 5290 } 5291 5292 /* 5293 * Open control node for stmf 5294 */ 5295 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5296 return (ret); 5297 5298 bzero(&ioctlViewEntry, sizeof (ioctlViewEntry)); 5299 ioctlViewEntry.ve_ndx_valid = B_TRUE; 5300 ioctlViewEntry.ve_ndx = viewEntryIndex; 5301 bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid)); 5302 5303 bzero(&stmfIoctl, sizeof (stmfIoctl)); 5304 /* 5305 * Issue ioctl to add to the view entry 5306 */ 5307 stmfIoctl.stmf_version = STMF_VERSION_1; 5308 stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry); 5309 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry; 5310 ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl); 5311 if (ioctlRet != 0) { 5312 switch (errno) { 5313 case EBUSY: 5314 ret = STMF_ERROR_BUSY; 5315 break; 5316 case EPERM: 5317 ret = STMF_ERROR_PERM; 5318 break; 5319 case EACCES: 5320 switch (stmfIoctl.stmf_error) { 5321 case STMF_IOCERR_UPDATE_NEED_CFG_INIT: 5322 ret = STMF_ERROR_CONFIG_NONE; 5323 break; 5324 default: 5325 ret = STMF_ERROR_PERM; 5326 break; 5327 } 5328 break; 5329 case ENODEV: 5330 case ENOENT: 5331 ret = STMF_ERROR_NOT_FOUND; 5332 break; 5333 default: 5334 syslog(LOG_DEBUG, 5335 "stmfRemoveViewEntry:ioctl errno(%d)", 5336 errno); 5337 ret = STMF_STATUS_ERROR; 5338 break; 5339 } 5340 goto done; 5341 } 5342 5343 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5344 goto done; 5345 } 5346 5347 ret = psRemoveViewEntry(lu, viewEntryIndex); 5348 switch (ret) { 5349 case STMF_PS_SUCCESS: 5350 ret = STMF_STATUS_SUCCESS; 5351 break; 5352 case STMF_PS_ERROR_NOT_FOUND: 5353 ret = STMF_ERROR_NOT_FOUND; 5354 break; 5355 case STMF_PS_ERROR_BUSY: 5356 ret = STMF_ERROR_BUSY; 5357 break; 5358 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5359 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5360 break; 5361 case STMF_PS_ERROR_VERSION_MISMATCH: 5362 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5363 break; 5364 default: 5365 syslog(LOG_DEBUG, 5366 "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)", 5367 ret); 5368 ret = STMF_STATUS_ERROR; 5369 break; 5370 } 5371 5372 done: 5373 (void) close(fd); 5374 return (ret); 5375 } 5376 5377 /* 5378 * stmfSetProviderData 5379 * 5380 * Purpose: set the provider data 5381 * 5382 * providerName - unique name of provider 5383 * nvl - nvlist to set 5384 * providerType - type of provider for which to set data 5385 * STMF_LU_PROVIDER_TYPE 5386 * STMF_PORT_PROVIDER_TYPE 5387 */ 5388 int 5389 stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType) 5390 { 5391 return (stmfSetProviderDataProt(providerName, nvl, providerType, 5392 NULL)); 5393 } 5394 5395 /* 5396 * stmfSetProviderDataProt 5397 * 5398 * Purpose: set the provider data 5399 * 5400 * providerName - unique name of provider 5401 * nvl - nvlist to set 5402 * providerType - type of provider for which to set data 5403 * STMF_LU_PROVIDER_TYPE 5404 * STMF_PORT_PROVIDER_TYPE 5405 * setToken - Stale data token returned in the stmfGetProviderDataProt() 5406 * call or NULL. 5407 */ 5408 int 5409 stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType, 5410 uint64_t *setToken) 5411 { 5412 int ret; 5413 int fd; 5414 5415 if (providerName == NULL || nvl == NULL) { 5416 return (STMF_ERROR_INVALID_ARG); 5417 } 5418 5419 if (providerType != STMF_LU_PROVIDER_TYPE && 5420 providerType != STMF_PORT_PROVIDER_TYPE) { 5421 return (STMF_ERROR_INVALID_ARG); 5422 } 5423 5424 /* call init */ 5425 ret = initializeConfig(); 5426 if (ret != STMF_STATUS_SUCCESS) { 5427 return (ret); 5428 } 5429 5430 /* 5431 * Open control node for stmf 5432 */ 5433 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5434 return (ret); 5435 5436 ret = setProviderData(fd, providerName, nvl, providerType, setToken); 5437 5438 (void) close(fd); 5439 5440 if (ret != STMF_STATUS_SUCCESS) { 5441 goto done; 5442 } 5443 5444 if (iGetPersistMethod() == STMF_PERSIST_NONE) { 5445 goto done; 5446 } 5447 5448 /* setting driver provider data successful. Now persist it */ 5449 ret = psSetProviderData(providerName, nvl, providerType, NULL); 5450 switch (ret) { 5451 case STMF_PS_SUCCESS: 5452 ret = STMF_STATUS_SUCCESS; 5453 break; 5454 case STMF_PS_ERROR_EXISTS: 5455 ret = STMF_ERROR_EXISTS; 5456 break; 5457 case STMF_PS_ERROR_BUSY: 5458 ret = STMF_ERROR_BUSY; 5459 break; 5460 case STMF_PS_ERROR_SERVICE_NOT_FOUND: 5461 ret = STMF_ERROR_SERVICE_NOT_FOUND; 5462 break; 5463 case STMF_PS_ERROR_VERSION_MISMATCH: 5464 ret = STMF_ERROR_SERVICE_DATA_VERSION; 5465 break; 5466 case STMF_PS_ERROR_PROV_DATA_STALE: 5467 ret = STMF_ERROR_PROV_DATA_STALE; 5468 break; 5469 default: 5470 syslog(LOG_DEBUG, 5471 "stmfSetProviderData" 5472 "psSetProviderData:error(%d)", ret); 5473 ret = STMF_STATUS_ERROR; 5474 break; 5475 } 5476 5477 done: 5478 return (ret); 5479 } 5480 5481 /* 5482 * getProviderData 5483 * 5484 * Purpose: set the provider data from stmf 5485 * 5486 * providerName - unique name of provider 5487 * nvl - nvlist to load/retrieve 5488 * providerType - logical unit or port provider 5489 * setToken - returned stale data token 5490 */ 5491 int 5492 getProviderData(char *providerName, nvlist_t **nvl, int providerType, 5493 uint64_t *setToken) 5494 { 5495 int ret = STMF_STATUS_SUCCESS; 5496 int fd; 5497 int ioctlRet; 5498 size_t nvlistSize = ALLOC_PP_DATA_SIZE; 5499 int retryCnt = 0; 5500 int retryCntMax = MAX_PROVIDER_RETRY; 5501 stmf_ppioctl_data_t ppi = {0}, *ppi_out = NULL; 5502 boolean_t retry = B_TRUE; 5503 stmf_iocdata_t stmfIoctl; 5504 5505 if (providerName == NULL) { 5506 return (STMF_ERROR_INVALID_ARG); 5507 } 5508 5509 /* 5510 * Open control node for stmf 5511 */ 5512 if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS) 5513 return (ret); 5514 5515 /* set provider name and provider type */ 5516 if (strlcpy(ppi.ppi_name, providerName, 5517 sizeof (ppi.ppi_name)) >= 5518 sizeof (ppi.ppi_name)) { 5519 ret = STMF_ERROR_INVALID_ARG; 5520 goto done; 5521 } 5522 switch (providerType) { 5523 case STMF_LU_PROVIDER_TYPE: 5524 ppi.ppi_lu_provider = 1; 5525 break; 5526 case STMF_PORT_PROVIDER_TYPE: 5527 ppi.ppi_port_provider = 1; 5528 break; 5529 default: 5530 ret = STMF_ERROR_INVALID_ARG; 5531 goto done; 5532 } 5533 5534 do { 5535 /* allocate memory for ioctl */ 5536 ppi_out = (stmf_ppioctl_data_t *)calloc(1, nvlistSize + 5537 sizeof (stmf_ppioctl_data_t)); 5538 if (ppi_out == NULL) { 5539 ret = STMF_ERROR_NOMEM; 5540 goto done; 5541 5542 } 5543 5544 /* set the size of the ioctl data to allocated buffer */ 5545 ppi.ppi_data_size = nvlistSize; 5546 5547 bzero(&stmfIoctl, sizeof (stmfIoctl)); 5548 5549 stmfIoctl.stmf_version = STMF_VERSION_1; 5550 stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t); 5551 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi; 5552 stmfIoctl.stmf_obuf_size = sizeof (stmf_ppioctl_data_t) + 5553 nvlistSize; 5554 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)ppi_out; 5555 ioctlRet = ioctl(fd, STMF_IOCTL_GET_PP_DATA, &stmfIoctl); 5556 if (ioctlRet != 0) { 5557 switch (errno) { 5558 case EBUSY: 5559 ret = STMF_ERROR_BUSY; 5560 break; 5561 case EPERM: 5562 case EACCES: 5563 ret = STMF_ERROR_PERM; 5564 break; 5565 case EINVAL: 5566 if (stmfIoctl.stmf_error == 5567 STMF_IOCERR_INSUFFICIENT_BUF) { 5568 nvlistSize = 5569 ppi_out->ppi_data_size; 5570 free(ppi_out); 5571 ppi_out = NULL; 5572 if (retryCnt++ > retryCntMax) { 5573 retry = B_FALSE; 5574 ret = STMF_ERROR_BUSY; 5575 } else { 5576 ret = 5577 STMF_STATUS_SUCCESS; 5578 } 5579 } else { 5580 syslog(LOG_DEBUG, 5581 "getProviderData:ioctl" 5582 "unable to retrieve " 5583 "nvlist"); 5584 ret = STMF_STATUS_ERROR; 5585 } 5586 break; 5587 case ENOENT: 5588 ret = STMF_ERROR_NOT_FOUND; 5589 break; 5590 default: 5591 syslog(LOG_DEBUG, 5592 "getProviderData:ioctl errno(%d)", 5593 errno); 5594 ret = STMF_STATUS_ERROR; 5595 break; 5596 } 5597 if (ret != STMF_STATUS_SUCCESS) 5598 goto done; 5599 } 5600 } while (retry && stmfIoctl.stmf_error == STMF_IOCERR_INSUFFICIENT_BUF); 5601 5602 if ((ret = nvlist_unpack((char *)ppi_out->ppi_data, 5603 ppi_out->ppi_data_size, nvl, 0)) != 0) { 5604 ret = STMF_STATUS_ERROR; 5605 goto done; 5606 } 5607 5608 /* caller has asked for new token */ 5609 if (setToken) { 5610 *setToken = ppi_out->ppi_token; 5611 } 5612 done: 5613 free(ppi_out); 5614 (void) close(fd); 5615 return (ret); 5616 } 5617 5618 /* 5619 * setProviderData 5620 * 5621 * Purpose: set the provider data in stmf 5622 * 5623 * providerName - unique name of provider 5624 * nvl - nvlist to set 5625 * providerType - logical unit or port provider 5626 * setToken - stale data token to check if not NULL 5627 */ 5628 static int 5629 setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType, 5630 uint64_t *setToken) 5631 { 5632 int ret = STMF_STATUS_SUCCESS; 5633 int ioctlRet; 5634 size_t nvlistEncodedSize; 5635 stmf_ppioctl_data_t *ppi = NULL; 5636 uint64_t outToken; 5637 char *allocatedNvBuffer; 5638 stmf_iocdata_t stmfIoctl; 5639 5640 if (providerName == NULL) { 5641 return (STMF_ERROR_INVALID_ARG); 5642 } 5643 5644 /* get size of encoded nvlist */ 5645 if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) { 5646 return (STMF_STATUS_ERROR); 5647 } 5648 5649 /* allocate memory for ioctl */ 5650 ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize + 5651 sizeof (stmf_ppioctl_data_t)); 5652 if (ppi == NULL) { 5653 return (STMF_ERROR_NOMEM); 5654 } 5655 5656 if (setToken) { 5657 ppi->ppi_token_valid = 1; 5658 ppi->ppi_token = *setToken; 5659 } 5660 5661 allocatedNvBuffer = (char *)&ppi->ppi_data; 5662 if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize, 5663 NV_ENCODE_XDR, 0) != 0) { 5664 return (STMF_STATUS_ERROR); 5665 } 5666 5667 /* set provider name and provider type */ 5668 (void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name)); 5669 switch (providerType) { 5670 case STMF_LU_PROVIDER_TYPE: 5671 ppi->ppi_lu_provider = 1; 5672 break; 5673 case STMF_PORT_PROVIDER_TYPE: 5674 ppi->ppi_port_provider = 1; 5675 break; 5676 default: 5677 return (STMF_ERROR_INVALID_ARG); 5678 } 5679 5680 /* set the size of the ioctl data to packed data size */ 5681 ppi->ppi_data_size = nvlistEncodedSize; 5682 5683 bzero(&stmfIoctl, sizeof (stmfIoctl)); 5684 5685 stmfIoctl.stmf_version = STMF_VERSION_1; 5686 /* 5687 * Subtracting 8 from the size as that is the size of the last member 5688 * of the structure where the packed data resides 5689 */ 5690 stmfIoctl.stmf_ibuf_size = nvlistEncodedSize + 5691 sizeof (stmf_ppioctl_data_t) - 8; 5692 stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi; 5693 stmfIoctl.stmf_obuf_size = sizeof (uint64_t); 5694 stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&outToken; 5695 ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl); 5696 if (ioctlRet != 0) { 5697 switch (errno) { 5698 case EBUSY: 5699 ret = STMF_ERROR_BUSY; 5700 break; 5701 case EPERM: 5702 case EACCES: 5703 ret = STMF_ERROR_PERM; 5704 break; 5705 case EINVAL: 5706 if (stmfIoctl.stmf_error == 5707 STMF_IOCERR_PPD_UPDATED) { 5708 ret = STMF_ERROR_PROV_DATA_STALE; 5709 } else { 5710 ret = STMF_STATUS_ERROR; 5711 } 5712 break; 5713 default: 5714 syslog(LOG_DEBUG, 5715 "setProviderData:ioctl errno(%d)", errno); 5716 ret = STMF_STATUS_ERROR; 5717 break; 5718 } 5719 if (ret != STMF_STATUS_SUCCESS) 5720 goto done; 5721 } 5722 5723 /* caller has asked for new token */ 5724 if (setToken) { 5725 *setToken = outToken; 5726 } 5727 done: 5728 free(ppi); 5729 return (ret); 5730 } 5731 5732 /* 5733 * set the persistence method in the library only or library and service 5734 */ 5735 int 5736 stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet) 5737 { 5738 int ret = STMF_STATUS_SUCCESS; 5739 int oldPersist; 5740 5741 (void) pthread_mutex_lock(&persistenceTypeLock); 5742 oldPersist = iPersistType; 5743 if (persistType == STMF_PERSIST_NONE || 5744 persistType == STMF_PERSIST_SMF) { 5745 iLibSetPersist = B_TRUE; 5746 iPersistType = persistType; 5747 } else { 5748 (void) pthread_mutex_unlock(&persistenceTypeLock); 5749 return (STMF_ERROR_INVALID_ARG); 5750 } 5751 /* Is this for this library open or in SMF */ 5752 if (serviceSet == B_TRUE) { 5753 ret = psSetServicePersist(persistType); 5754 if (ret != STMF_PS_SUCCESS) { 5755 ret = STMF_ERROR_PERSIST_TYPE; 5756 /* Set to old value */ 5757 iPersistType = oldPersist; 5758 } 5759 } 5760 (void) pthread_mutex_unlock(&persistenceTypeLock); 5761 5762 return (ret); 5763 } 5764 5765 /* 5766 * Only returns internal state for persist. If unset, goes to ps. If that 5767 * fails, returns default setting 5768 */ 5769 static uint8_t 5770 iGetPersistMethod() 5771 { 5772 5773 uint8_t persistType = 0; 5774 5775 (void) pthread_mutex_lock(&persistenceTypeLock); 5776 if (iLibSetPersist) { 5777 persistType = iPersistType; 5778 } else { 5779 int ret; 5780 ret = psGetServicePersist(&persistType); 5781 if (ret != STMF_PS_SUCCESS) { 5782 /* set to default */ 5783 persistType = STMF_DEFAULT_PERSIST; 5784 } 5785 } 5786 (void) pthread_mutex_unlock(&persistenceTypeLock); 5787 return (persistType); 5788 } 5789 5790 /* 5791 * Returns either library state or persistent config state depending on 5792 * serviceState 5793 */ 5794 int 5795 stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState) 5796 { 5797 int ret = STMF_STATUS_SUCCESS; 5798 5799 if (persistType == NULL) { 5800 return (STMF_ERROR_INVALID_ARG); 5801 } 5802 if (serviceState) { 5803 ret = psGetServicePersist(persistType); 5804 if (ret != STMF_PS_SUCCESS) { 5805 ret = STMF_ERROR_PERSIST_TYPE; 5806 } 5807 } else { 5808 (void) pthread_mutex_lock(&persistenceTypeLock); 5809 if (iLibSetPersist) { 5810 *persistType = iPersistType; 5811 } else { 5812 *persistType = STMF_DEFAULT_PERSIST; 5813 } 5814 (void) pthread_mutex_unlock(&persistenceTypeLock); 5815 } 5816 5817 return (ret); 5818 } 5819