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