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