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