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