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