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